赞
踩
通过第三方的软件,网上有很多可以使用的,将las数据切片成3dtiles,3dtiles的介绍可以去网上搜索,也很多。
cesium加载3dtiles并依据点云的强度属性来控制颜色带的显示,通过调整阈值,动态调整颜色带与点云的颜色。
依据相机与可视域内的tile的距离,再通过距离与pointSize大小的线性变化,计算tile的pointSize的大小,赋值给tile瓦片实现动态调整点云点的大小。
1、点击某一点云,通过读取该点云所在的tile块的原始数据(pnts),解析pnts中的点云的点 并计算cesium点选的那个点与pnts中点云集中距离最近的那个点即为被选中的点
2、输出选中的点云点的属性信息(如 xyz,强度等)
部分代码如下:
- let transformPos = {x: -518467.65, y: -2537603.97, z: -42.13};
- let blhPos = [116.46000, 39.90002];
- this.initPointCloudCheck(transformPos, blhPos);
其中transformPos为点云数据的自身坐标系的参考点坐标,blhPos为该参考点对应的经纬度坐标系下的经纬度坐标,即模型的某一点transformPos=经纬度坐标的blhPos 。目的是为了切片时坐标系转换。
3dtiles二进制文件的格式如下:
- /**
- * 鼠标点击处的屏幕坐标转换成笛卡尔坐标
- * @param {screen position from mouse} viewer
- * @param {screen position from mouse} movement
- */
- function getCartesian3fromPick(viewer, movement) {
- let position = movement.position;
- if (!Cesium.defined(position)) {
- return;
- }
- let worldPosition = viewer.scene.pickPosition(position);
- if (!Cesium.defined(worldPosition)) {
- return;
- }
- return worldPosition;
- }
-
- /**
- * 读取点云pnts的源数据
- * @param {Object} arrayBuffer
- * @param {Object} pickId 选中的tile Id
- * @param {Object} pickedCar3 选中car3坐标
- * @param {Object} pointLength 选中的tile 所包含的点数量
- * @param {Object} transformPos
- * @param {Object} blhPos
- */
- processPntsData(arrayBuffer, pickId, pickedCar3, pointLength, transformPos, blhPos) {
-
- let pickedOriginalPos = this.transFormLocalPosition(pickedCar3, transformPos, blhPos);
-
- let uint8Array = new Uint8Array(arrayBuffer);
- let view = new DataView(arrayBuffer);
-
- let sizeOfUint32 = 4;
-
- //偏移字节数byteOffset 默认为4,TILE中的前4个字节为magic标识 值为pnts
- //getUint32(n)方法从DataView读取开始索引为n的一个32-bit数即4个字节
- //第二个值为tile的版本 值为1
- //具体可查看官网的 3D tile的数据结构
- //https://github.com/CesiumGS/3d-tiles/blob/main/specification/TileFormats/PointCloud/README.md
- let byteOffset = 0;
- let magicArray = [view.getUint8(byteOffset), view.getUint8(byteOffset + 1), view.getUint8(byteOffset + 2), view.getUint8(byteOffset + 3)];
-
- let magic = byteToString(magicArray);
-
- byteOffset += sizeOfUint32; // Skip magic
-
- let version = view.getUint32(byteOffset, true);
- //继续往下移动
- byteOffset += sizeOfUint32; // Skip version
- //得到byteLength的长度
- let byteLength = view.getUint32(byteOffset, true);
- //继续往下移动
- byteOffset += sizeOfUint32; // Skip byteLength
- //得到featuretableJSON字节长度
- let featureTableJsonByteLength = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- //得到featuretable 二进制字节长度
- let featureTableBinaryByteLength = view.getUint32(byteOffset, true);
- //得到bathTableJson字节长度
- let batchTableJSONByteLength = view.getUint32(20, true);
- //得到bathTable 二进制字节长度
- let batchTableBinaryByteLength = view.getUint32(24, true);
-
- //获取body的内容,从28开始是因为pnts的头部长度为28,b3dm与i3dm是其他的固定值
-
- //转换到featuretable的buffer中
- let featureTableJson = new Uint8Array(arrayBuffer, 28, featureTableJsonByteLength);
- let featureTableJsonStr = this.Uint8ArrayToString(featureTableJson);
- let featureTableJsonObj = JSON.parse(featureTableJsonStr);
- //通过offset与相关内容区的长度,可以直接读取对应的内容
- let featureTableBinary = new Uint8Array(arrayBuffer, 28 + featureTableJsonByteLength, featureTableBinaryByteLength);
- let featureTable = new Cesium.Cesium3DTileFeatureTable(featureTableJsonObj, featureTableBinary);
- let positions = featureTable.getPropertyArray('POSITION_QUANTIZED', Cesium.ComponentDatatype.UNSIGNED_SHORT, 3);
- // getPropertyArray 函数中调用getTypedArrayFromBinary,
- // 在调用 typedArray = ComponentDatatype.createArrayBufferView(componentType, featureTable.buffer.buffer, featureTable.buffer.byteOffset + byteOffset, count * componentLength);
-
- let batchTableJSON = new Uint8Array(arrayBuffer, 28 + featureTableJsonByteLength + featureTableBinaryByteLength, batchTableJSONByteLength);
- let batchTableJSONStr = this.Uint8ArrayToString(batchTableJSON);
- let batchTableJSONObj = JSON.parse(batchTableJSONStr);
- let batchTableBinary = new Uint8Array(arrayBuffer, 28 + featureTableJsonByteLength + featureTableBinaryByteLength + batchTableJSONByteLength, batchTableBinaryByteLength);
- let batchTable = new Cesium.Cesium3DTileFeatureTable(batchTableJSONObj, batchTableBinary);
- let intensity = batchTable.getPropertyArray('Intensity', Cesium.ComponentDatatype.UNSIGNED_SHORT, 3);
-
- let referpointOriginalXYZ = [-518444.65, -2537603.97, -42.13];
- let referpointBLH = [116.46, 39.90002, 0];
- let referpointCar3 = [1, 1, 1];
- let referpointCartian3 = cesiumCommon.lonlat2Cartesian([referpointBLH[0], referpointBLH[1]], referpointBLH[2]);
-
- this.createEntity(referpointCartian3, Cesium.Color.RED);
-
- //header+featureTableJsonByteLength+featureTableBinaryByteLength+batchTableJSONByteLength
- //到二进制数据的位置
- let pickIdPre = 28 + featureTableJsonByteLength + featureTableBinaryByteLength + batchTableJSONByteLength;
- // let intensityValue = view.getUint16(pickIdPre, true);
-
- //byteOffset 表示字段在arraybuffer在body中的偏移
- let xIndex = pickIdPre + batchTableJSONObj.x.byteOffset;
- let yIndex = pickIdPre + batchTableJSONObj.y.byteOffset;
- let zIndex = pickIdPre + batchTableJSONObj.z.byteOffset;
-
- // let x = view.getFloat32(xIndex, true);
- // let y = view.getFloat32(yIndex, true);
- // let z = view.getFloat32(zIndex, true);
- // alert("强度值:" + intensityValue + "\n" + "x:" + x + ",y:" + y + ",z:" + z);
-
- //强度值
- let intensitycompentType = batchTableJSONObj.Intensity.componentType;
- let intensitytype = batchTableJSONObj.Intensity.type;
- let intensityIndex = pickIdPre + batchTableJSONObj.Intensity.byteOffset;
- let intensityStep = Cesium.ComponentDatatype.getSizeInBytes(Cesium.ComponentDatatype.fromName(intensitycompentType)) * Cesium.numberOfComponentsForType(intensitytype);
-
- //x y z
- let xcompentType = batchTableJSONObj.x.componentType;
- let xtype = batchTableJSONObj.x.type;
- //compentType与type 决定了x字段的占位长度
- let xStep = Cesium.ComponentDatatype.getSizeInBytes(Cesium.ComponentDatatype.fromName(xcompentType)) * Cesium.numberOfComponentsForType(xtype);
-
- let distanceArray = [];
-
- //一个pnts可能有成千上万个点的数据,pointLength就是该pnts对应的点的个数(todo)
- for (let i = 0; i < pointLength; i++) {
- //强度值
- let eachIntensity = intensityIndex + i * intensityStep;
- //float 每一个值占4位 double 每一个值占8位
- let eachX = xIndex + i * xStep;
- let eachY = yIndex + i * xStep;
- let eachZ = zIndex + i * xStep;
-
- let thisIntensity = 0;
-
- switch (intensitycompentType) {
- case "FLOAT":
- thisIntensity = view.getFloat32(eachIntensity, true);
- break;
- case "DOUBLE":
- thisIntensity = view.getFloat64(eachIntensity, true);
- break;
- }
-
-
- let thisX = 0;
- let thisY = 0;
- let thisZ = 0;
-
- switch (xcompentType) {
- case "FLOAT":
- thisX = view.getFloat32(eachX, true);
- thisY = view.getFloat32(eachY, true);
- thisZ = view.getFloat32(eachZ, true);
- break;
- case "DOUBLE":
- thisX = view.getFloat64(eachX, true);
- thisY = view.getFloat64(eachY, true);
- thisZ = view.getFloat64(eachZ, true);
- break;
- }
-
- let checkCartian3 = new Cesium.Cartesian3(thisX, thisY, thisZ);
-
- let distance = Cesium.Cartesian3.distance(checkCartian3, pickedOriginalPos);
-
- let checkedPoint = {
- Intensity: thisIntensity,
- x: thisX,
- y: thisY,
- z: thisZ,
- cartesian3: checkCartian3
- };
-
- distanceArray.push({distance: distance, point: checkedPoint});
- console.log(JSON.stringify(checkedPoint));
- }
-
- let minOne = this.sortByDistance(distanceArray);
-
- //let minOneCar3 = minOne.point.cartesian3;
- //this.createEntity(minOneCar3, Cesium.Color.WHITE);
-
- alert(JSON.stringify(minOne));
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。