当前位置:   article > 正文

Cesium之las数据生成3dtiles并选取单个点云_las 转 3dtiles 颜色丢失

las 转 3dtiles 颜色丢失
  • las数据转化成3dtiles(pnts)

通过第三方的软件,网上有很多可以使用的,将las数据切片成3dtiles,3dtiles的介绍可以去网上搜索,也很多。

  • cesium加载3dtiles

cesium加载3dtiles并依据点云的强度属性来控制颜色带的显示,通过调整阈值,动态调整颜色带与点云的颜色。

  • 依据可视域与相机的距离动态调整点云点的大小

依据相机与可视域内的tile的距离,再通过距离与pointSize大小的线性变化,计算tile的pointSize的大小,赋值给tile瓦片实现动态调整点云点的大小。

  • 点云点的选中

1、点击某一点云,通过读取该点云所在的tile块的原始数据(pnts),解析pnts中的点云的点 并计算cesium点选的那个点与pnts中点云集中距离最近的那个点即为被选中的点

2、输出选中的点云点的属性信息(如 xyz,强度等)

部分代码如下:

  1. let transformPos = {x: -518467.65, y: -2537603.97, z: -42.13};
  2. let blhPos = [116.46000, 39.90002];
  3. this.initPointCloudCheck(transformPos, blhPos);

其中transformPos为点云数据的自身坐标系的参考点坐标,blhPos为该参考点对应的经纬度坐标系下的经纬度坐标,即模型的某一点transformPos=经纬度坐标的blhPos 。目的是为了切片时坐标系转换。

3dtiles二进制文件的格式如下:

  1. /**
  2. * 鼠标点击处的屏幕坐标转换成笛卡尔坐标
  3. * @param {screen position from mouse} viewer
  4. * @param {screen position from mouse} movement
  5. */
  6. function getCartesian3fromPick(viewer, movement) {
  7. let position = movement.position;
  8. if (!Cesium.defined(position)) {
  9. return;
  10. }
  11. let worldPosition = viewer.scene.pickPosition(position);
  12. if (!Cesium.defined(worldPosition)) {
  13. return;
  14. }
  15. return worldPosition;
  16. }
  17. /**
  18. * 读取点云pnts的源数据
  19. * @param {Object} arrayBuffer
  20. * @param {Object} pickId 选中的tile Id
  21. * @param {Object} pickedCar3 选中car3坐标
  22. * @param {Object} pointLength 选中的tile 所包含的点数量
  23. * @param {Object} transformPos
  24. * @param {Object} blhPos
  25. */
  26. processPntsData(arrayBuffer, pickId, pickedCar3, pointLength, transformPos, blhPos) {
  27.     let pickedOriginalPos = this.transFormLocalPosition(pickedCar3, transformPos, blhPos);
  28.     let uint8Array = new Uint8Array(arrayBuffer);
  29.     let view = new DataView(arrayBuffer);
  30.     let sizeOfUint32 = 4;
  31.     //偏移字节数byteOffset 默认为4,TILE中的前4个字节为magic标识 值为pnts
  32.     //getUint32(n)方法从DataView读取开始索引为n的一个32-bit数即4个字节
  33. //第二个值为tile的版本 值为1
  34.     //具体可查看官网的 3D tile的数据结构
  35.     //https://github.com/CesiumGS/3d-tiles/blob/main/specification/TileFormats/PointCloud/README.md
  36.     let byteOffset = 0;
  37.     let magicArray = [view.getUint8(byteOffset), view.getUint8(byteOffset + 1), view.getUint8(byteOffset + 2), view.getUint8(byteOffset + 3)];
  38. let magic = byteToString(magicArray);
  39. byteOffset += sizeOfUint32; // Skip magic
  40.     let version = view.getUint32(byteOffset, true);
  41.     //继续往下移动
  42.     byteOffset += sizeOfUint32;  // Skip version
  43.     //得到byteLength的长度
  44.     let byteLength = view.getUint32(byteOffset, true);
  45.     //继续往下移动
  46.     byteOffset += sizeOfUint32;  // Skip byteLength
  47.     //得到featuretableJSON字节长度
  48.     let featureTableJsonByteLength = view.getUint32(byteOffset, true);
  49.     byteOffset += sizeOfUint32;
  50.     //得到featuretable 二进制字节长度
  51.     let featureTableBinaryByteLength = view.getUint32(byteOffset, true);
  52.     //得到bathTableJson字节长度
  53.     let batchTableJSONByteLength = view.getUint32(20, true);
  54.     //得到bathTable 二进制字节长度
  55.     let batchTableBinaryByteLength = view.getUint32(24, true);
  56.     //获取body的内容,从28开始是因为pnts的头部长度为28,b3dm与i3dm是其他的固定值
  57.     //转换到featuretable的buffer中
  58.     let featureTableJson = new Uint8Array(arrayBuffer, 28, featureTableJsonByteLength);
  59.     let featureTableJsonStr = this.Uint8ArrayToString(featureTableJson);
  60.     let featureTableJsonObj = JSON.parse(featureTableJsonStr);
  61.     //通过offset与相关内容区的长度,可以直接读取对应的内容
  62.     let featureTableBinary = new Uint8Array(arrayBuffer, 28 + featureTableJsonByteLength, featureTableBinaryByteLength);
  63.     let featureTable = new Cesium.Cesium3DTileFeatureTable(featureTableJsonObj, featureTableBinary);
  64.     let positions = featureTable.getPropertyArray('POSITION_QUANTIZED', Cesium.ComponentDatatype.UNSIGNED_SHORT, 3);
  65.     // getPropertyArray 函数中调用getTypedArrayFromBinary,
  66.     // 在调用 typedArray = ComponentDatatype.createArrayBufferView(componentType, featureTable.buffer.buffer, featureTable.buffer.byteOffset + byteOffset, count * componentLength);
  67.     let batchTableJSON = new Uint8Array(arrayBuffer, 28 + featureTableJsonByteLength + featureTableBinaryByteLength, batchTableJSONByteLength);
  68.     let batchTableJSONStr = this.Uint8ArrayToString(batchTableJSON);
  69.     let batchTableJSONObj = JSON.parse(batchTableJSONStr);
  70.     let batchTableBinary = new Uint8Array(arrayBuffer, 28 + featureTableJsonByteLength + featureTableBinaryByteLength + batchTableJSONByteLength, batchTableBinaryByteLength);
  71.     let batchTable = new Cesium.Cesium3DTileFeatureTable(batchTableJSONObj, batchTableBinary);
  72.     let intensity = batchTable.getPropertyArray('Intensity', Cesium.ComponentDatatype.UNSIGNED_SHORT, 3);
  73.     let referpointOriginalXYZ = [-518444.65, -2537603.97, -42.13];
  74.     let referpointBLH = [116.46, 39.90002, 0];
  75.     let referpointCar3 = [1, 1, 1];
  76.     let referpointCartian3 = cesiumCommon.lonlat2Cartesian([referpointBLH[0], referpointBLH[1]], referpointBLH[2]);
  77.     this.createEntity(referpointCartian3, Cesium.Color.RED);
  78.     //header+featureTableJsonByteLength+featureTableBinaryByteLength+batchTableJSONByteLength
  79.     //到二进制数据的位置
  80.     let pickIdPre = 28 + featureTableJsonByteLength + featureTableBinaryByteLength + batchTableJSONByteLength;
  81.     // let intensityValue = view.getUint16(pickIdPre, true);
  82.     //byteOffset 表示字段在arraybuffer在body中的偏移
  83.     let xIndex = pickIdPre + batchTableJSONObj.x.byteOffset;
  84.     let yIndex = pickIdPre + batchTableJSONObj.y.byteOffset;
  85.     let zIndex = pickIdPre + batchTableJSONObj.z.byteOffset;
  86.     // let x = view.getFloat32(xIndex, true);
  87.     // let y = view.getFloat32(yIndex, true);
  88.     // let z = view.getFloat32(zIndex, true);
  89.     // alert("强度值:" + intensityValue + "\n" + "x:" + x + ",y:" + y + ",z:" + z);
  90.     //强度值
  91.     let intensitycompentType = batchTableJSONObj.Intensity.componentType;
  92.     let intensitytype = batchTableJSONObj.Intensity.type;
  93.     let intensityIndex = pickIdPre + batchTableJSONObj.Intensity.byteOffset;
  94.     let intensityStep = Cesium.ComponentDatatype.getSizeInBytes(Cesium.ComponentDatatype.fromName(intensitycompentType)) * Cesium.numberOfComponentsForType(intensitytype);
  95.     //x y z
  96.     let xcompentType = batchTableJSONObj.x.componentType;
  97.     let xtype = batchTableJSONObj.x.type;
  98.     //compentType与type 决定了x字段的占位长度
  99.     let xStep = Cesium.ComponentDatatype.getSizeInBytes(Cesium.ComponentDatatype.fromName(xcompentType)) * Cesium.numberOfComponentsForType(xtype);
  100.     let distanceArray = [];
  101.     //一个pnts可能有成千上万个点的数据,pointLength就是该pnts对应的点的个数(todo)
  102.     for (let i = 0; i < pointLength; i++) {
  103. //强度值
  104. let eachIntensity = intensityIndex + i * intensityStep;
  105. //float 每一个值占4位 double 每一个值占8位
  106. let eachX = xIndex + i * xStep;
  107. let eachY = yIndex + i * xStep;
  108. let eachZ = zIndex + i * xStep;
  109. let thisIntensity = 0;
  110. switch (intensitycompentType) {
  111. case "FLOAT":
  112. thisIntensity = view.getFloat32(eachIntensity, true);
  113. break;
  114. case "DOUBLE":
  115. thisIntensity = view.getFloat64(eachIntensity, true);
  116. break;
  117. }
  118. let thisX = 0;
  119. let thisY = 0;
  120. let thisZ = 0;
  121. switch (xcompentType) {
  122. case "FLOAT":
  123. thisX = view.getFloat32(eachX, true);
  124. thisY = view.getFloat32(eachY, true);
  125. thisZ = view.getFloat32(eachZ, true);
  126. break;
  127. case "DOUBLE":
  128. thisX = view.getFloat64(eachX, true);
  129. thisY = view.getFloat64(eachY, true);
  130. thisZ = view.getFloat64(eachZ, true);
  131. break;
  132. }
  133.         let checkCartian3 = new Cesium.Cartesian3(thisX, thisY, thisZ);
  134.         let distance = Cesium.Cartesian3.distance(checkCartian3, pickedOriginalPos);
  135.         let checkedPoint = {
  136.             Intensity: thisIntensity,
  137.             x: thisX,
  138.             y: thisY,
  139.             z: thisZ,
  140.             cartesian3: checkCartian3
  141.         };
  142.         distanceArray.push({distance: distance, point: checkedPoint});
  143.         console.log(JSON.stringify(checkedPoint));
  144.     }
  145.     let minOne = this.sortByDistance(distanceArray);
  146.     //let minOneCar3 = minOne.point.cartesian3;
  147.     //this.createEntity(minOneCar3, Cesium.Color.WHITE);
  148.     alert(JSON.stringify(minOne));
  149. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/99739
推荐阅读
相关标签
  

闽ICP备14008679号