deck.gl渲染PointCloudLayer点云图层
目录
效果图
在线地址
deck.gl渲染PointCloudLayer点云图层
https://tool.giserdqy.com/deckgl/point-cloud-layer.html
功能说明
本实例实现了deck.gl加载底图,基于PointCloudLayer渲染自定义生成的100万个点立方范围内玫瑰花朵形状构成的点云数据。
数据结构
position: 点云的空间坐标
normal:点云的法向量
color: rgb色彩信息
{
position: [x,y,z],
normal: [nx, ny, nz],
color: [u *128, v *128, p[2] * 255]
}
代码解析
- 此部分是引入在线deck.gl包,mapboxgl底图,设置了基本的css样式
<html>
<head>
<title>deck.gl PointCloudLayer Example</title>
<script src="https://unpkg.com/deck.gl@^8.8.0/dist.min.js"></script>
<style type="text/css">
body {
width: 100vw;
height: 100vh;
margin: 0;
background: #000;
}
</style>
</head>
- 这部分初始化调整文本字体面板
<head>
<title>deck.gl PointCloudLayer Example</title>
<script src="https://unpkg.com/deck.gl@^8.8.0/dist.min.js"></script>
<style type="text/css">
body {
width: 100vw;
height: 100vh;
margin: 0;
background: #000;
}
</style>
</head>
- 这部分是es6写法,引入需要的模块DeckGL、PointCloudLayer、OrbitView
<script type="text/javascript">
const {DeckGL, OrbitView, PointCloudLayer, COORDINATE_SYSTEM} = deck;
</script>
- 该部分代码生成玫瑰形状点云数据
// One million points
const SAMPLE_SIZE = 1e6;
const SURFACE_EQUATION = (x, y) => Math.sin(x * x + y * y) * x / Math.PI;
const EPSILON = 1e-4;
const points = [];
const dim = Math.sqrt(SAMPLE_SIZE);
function getPosition(u, v) {
const x = (u - 1/2) * Math.PI * 2;
const y = (v - 1/2) * Math.PI * 2;
const z = SURFACE_EQUATION(x, y);
return [x, y, z];
}
function getNormal(u, v) {
const p0 = getPosition(u - EPSILON, v - EPSILON);
const p1 = getPosition(u + EPSILON, v + EPSILON);
const nx = (p1[1] - p0[1]) * (p1[2] - p0[2]);
const ny = (p1[2] - p0[2]) * (p1[0] - p0[0]);
const nz = (p1[0] - p0[0]) * (p1[1] - p0[1]);
return [nx, ny, nz];
}
for (let i = 0; i < dim; i++) {
for (let j = 0; j < dim; j++) {
const u = i / (dim - 1);
const v = j / (dim - 1);
const p = getPosition(u, v);
const n = getNormal(u, v);
points.push({
position: p,
normal: n,
color: [u *128, v *128, p[2] * 255]
});
}
}
- 初始化DeckGL,PointCloudLayer图层,设置View为OrbitView
new DeckGL({
views: [new OrbitView()], // 指定3d视图,该视图特点是Camera沿着一个方向面对着固定的点,围着目标旋转
initialViewState: {rotationX: 45, rotationOrbit: -45, zoom: 5},// 视图初始状态
controller: true, // 与用户操作同步
layers: [
new PointCloudLayer({// 点云图层初始化
id: 'pointCloud', // 唯一id
data: points, // 指定数据
getPosition: d => d.position, // 动态获取位置
getNormal: d => d.normal, // 动态获取法向量
getColor: d => d.color, // 动态设置颜色
radiusPixels: 1 // 点云像素半径
})
]
});
源代码
拷贝到html文件中可直接用浏览器打开
<html>
<head>
<title>deck.gl PointCloudLayer Example</title>
<script src="https://unpkg.com/deck.gl@^8.8.0/dist.min.js"></script>
<style type="text/css">
body {
width: 100vw;
height: 100vh;
margin: 0;
background: #000;
}
</style>
</head>
<body></body>
<script type="text/javascript">
const {DeckGL, OrbitView, PointCloudLayer, COORDINATE_SYSTEM} = deck;
// One million points
const SAMPLE_SIZE = 1e6;
const SURFACE_EQUATION = (x, y) => Math.sin(x * x + y * y) * x / Math.PI;
const EPSILON = 1e-4;
const points = [];
const dim = Math.sqrt(SAMPLE_SIZE);
function getPosition(u, v) {
const x = (u - 1/2) * Math.PI * 2;
const y = (v - 1/2) * Math.PI * 2;
const z = SURFACE_EQUATION(x, y);
return [x, y, z];
}
function getNormal(u, v) {
const p0 = getPosition(u - EPSILON, v - EPSILON);
const p1 = getPosition(u + EPSILON, v + EPSILON);
const nx = (p1[1] - p0[1]) * (p1[2] - p0[2]);
const ny = (p1[2] - p0[2]) * (p1[0] - p0[0]);
const nz = (p1[0] - p0[0]) * (p1[1] - p0[1]);
return [nx, ny, nz];
}
for (let i = 0; i < dim; i++) {
for (let j = 0; j < dim; j++) {
const u = i / (dim - 1);
const v = j / (dim - 1);
const p = getPosition(u, v);
const n = getNormal(u, v);
points.push({
position: p,
normal: n,
color: [u *128, v *128, p[2] * 255]
});
}
}
new DeckGL({
views: [new OrbitView()],
initialViewState: {rotationX: 45, rotationOrbit: -45, zoom: 5},
controller: true,
layers: [
new PointCloudLayer({
id: 'pointCloud',
data: points,
getPosition: d => d.position,
getNormal: d => d.normal,
getColor: d => d.color,
radiusPixels: 1
})
]
});
</script>
</html>