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]
}

代码解析

  1. 此部分是引入在线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>
  1. 这部分初始化调整文本字体面板
<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>
  1. 这部分是es6写法,引入需要的模块DeckGL、PointCloudLayer、OrbitView
    <script type="text/javascript">
       const {DeckGL, OrbitView, PointCloudLayer, COORDINATE_SYSTEM} = deck;
  </script>
  1. 该部分代码生成玫瑰形状点云数据
// 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]
        });
      }
    }
  1. 初始化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>

You may also like...