123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- import * as THREE from "../../libs/three.js/build/three.module.js";
- import {PointCloudOctreeGeometry, PointCloudOctreeGeometryNode} from "../PointCloudOctreeGeometry.js";
- import {Version} from "../Version.js";
- import {XHRFactory} from "../XHRFactory.js";
- import {LasLazLoader} from "./LasLazLoader.js";
- import {BinaryLoader} from "./BinaryLoader.js";
- import {Utils} from "../utils.js";
- import {PointAttribute, PointAttributes, PointAttributeTypes} from "./PointAttributes.js";
- var transformFrom4dkk = function(name){
- var jsAttribute = PointAttribute[name]
- return jsAttribute
- /* if(name == "POSITION_CARTESIAN"){
- jsAttribute = {
- description: "",
- elementSize: 4,
- elements: 3,
- name: "POSITION_CARTESIAN",
- size: 12,
- type: "int32",
- }
- }else if(name == "COLOR_PACKED"){
- jsAttribute = {
- description: "" ,
- elementSize: 1,
- elements: 4,
- name: "RGBA",
- size: 4,
- type: 'int8',
- }
- }else if(name == "NORMAL_OCT16"){
-
- jsAttribute = {
- description: "" ,
- elementSize: 4,
- elements: 2,
- name: "NORMAL_OCT16",
- size: 12,
- type: "uint8",
- }
- } */
- /* var Q = q(L.COLOR_PACKED, K.DATA_TYPE_INT8, 4)
- POSITION_CARTESIAN: q(L.POSITION_CARTESIAN, K.DATA_TYPE_FLOAT, 3),
- RGBA_PACKED: Q,
- COLOR_PACKED: Q,
- RGB_PACKED: q(L.COLOR_PACKED, K.DATA_TYPE_INT8, 3),
- NORMAL_FLOATS: q(L.NORMAL_FLOATS, K.DATA_TYPE_FLOAT, 3),
- FILLER_1B: q(L.FILLER, K.DATA_TYPE_UINT8, 1),
- INTENSITY: q(L.INTENSITY, K.DATA_TYPE_UINT16, 1),
- CLASSIFICATION: q(L.CLASSIFICATION, K.DATA_TYPE_UINT8, 1),
- NORMAL_SPHEREMAPPED: q(L.NORMAL_SPHEREMAPPED, K.DATA_TYPE_UINT8, 2),
- NORMAL_OCT16: q(L.NORMAL_OCT16, K.DATA_TYPE_UINT8, 2),
- NORMAL: q(L.NORMAL, K.DATA_TYPE_FLOAT, 3) */
-
- }
-
- function parseAttributes(cloudjs){
- let version = new Version(cloudjs.version);
- const replacements = {
- "COLOR_PACKED": "rgba",
- "RGBA": "rgba",
- "INTENSITY": "intensity",
- "CLASSIFICATION": "classification",
- "GPS_TIME": "gps-time",
- };
- const replaceOldNames = (old) => {
- if(replacements[old]){
- return replacements[old];
- }else{
- return old;
- }
- };
- const pointAttributes = [];
- if(version.upTo('1.7')){
-
- for(let attributeName of cloudjs.pointAttributes){
- const oldAttribute = PointAttribute[attributeName];
- const attribute = {
- name: oldAttribute.name,
- size: oldAttribute.byteSize,
- elements: oldAttribute.numElements,
- elementSize: oldAttribute.byteSize / oldAttribute.numElements,
- type: oldAttribute.type.name,
- description: "",
- };
- pointAttributes.push(attribute);
- }
- }else{
- pointAttributes.push(...cloudjs.pointAttributes);
- }
- {
- const attributes = new PointAttributes();
- const typeConversion = {
- int8: PointAttributeTypes.DATA_TYPE_INT8,
- int16: PointAttributeTypes.DATA_TYPE_INT16,
- int32: PointAttributeTypes.DATA_TYPE_INT32,
- int64: PointAttributeTypes.DATA_TYPE_INT64,
- uint8: PointAttributeTypes.DATA_TYPE_UINT8,
- uint16: PointAttributeTypes.DATA_TYPE_UINT16,
- uint32: PointAttributeTypes.DATA_TYPE_UINT32,
- uint64: PointAttributeTypes.DATA_TYPE_UINT64,
- double: PointAttributeTypes.DATA_TYPE_DOUBLE,
- float: PointAttributeTypes.DATA_TYPE_FLOAT,
- };
- for(let jsAttribute of pointAttributes){
-
- if(jsAttribute.name == void 0){//是来自四维看看的数据
- //attribute = transformFrom4dkk(jsAttribute)
- var attribute_ = PointAttribute[jsAttribute]
- attributes.add(attribute_);
- continue;
- }
-
- const name = replaceOldNames(jsAttribute.name);
- const type = typeConversion[jsAttribute.type];
- const numElements = jsAttribute.elements;
- const description = jsAttribute.description;
- const attribute = new PointAttribute(name, type, numElements);
- attributes.add(attribute);
- }
- {
- // check if it has normals
- let hasNormals =
- pointAttributes.find(a => a.name === "NormalX") !== undefined &&
- pointAttributes.find(a => a.name === "NormalY") !== undefined &&
- pointAttributes.find(a => a.name === "NormalZ") !== undefined;
- if(hasNormals){
- let vector = {
- name: "NORMAL",
- attributes: ["NormalX", "NormalY", "NormalZ"],
- };
- attributes.addVector(vector);
- }
- }
- return attributes;
- }
- }
- function lasLazAttributes(fMno){
- const attributes = new PointAttributes();
- attributes.add(PointAttribute.POSITION_CARTESIAN);
- attributes.add(new PointAttribute("rgba", PointAttributeTypes.DATA_TYPE_UINT8, 4));
- attributes.add(new PointAttribute("intensity", PointAttributeTypes.DATA_TYPE_UINT16, 1));
- attributes.add(new PointAttribute("classification", PointAttributeTypes.DATA_TYPE_UINT8, 1));
- attributes.add(new PointAttribute("gps-time", PointAttributeTypes.DATA_TYPE_DOUBLE, 1));
- attributes.add(new PointAttribute("number of returns", PointAttributeTypes.DATA_TYPE_UINT8, 1));
- attributes.add(new PointAttribute("return number", PointAttributeTypes.DATA_TYPE_UINT8, 1));
- attributes.add(new PointAttribute("source id", PointAttributeTypes.DATA_TYPE_UINT16, 1));
- //attributes.add(new PointAttribute("pointSourceID", PointAttributeTypes.DATA_TYPE_INT8, 4));
- return attributes;
- }
- export class POCLoader {
- static load(url, timeStamp, callback){ //add timeStamp
- try {
- let pco = new PointCloudOctreeGeometry();
- pco.timeStamp = timeStamp
-
- pco.url = url;
- let xhr = XHRFactory.createXMLHttpRequest();
- xhr.open('GET', url+'?m='+timeStamp, true);
- xhr.onreadystatechange = function () {
- if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 0)) {
- let fMno = JSON.parse(xhr.responseText);
- let version = new Version(fMno.version);
- // assume octreeDir is absolute if it starts with http
- if (fMno.octreeDir.indexOf('http') === 0) {
- pco.octreeDir = fMno.octreeDir;
- } else {
- pco.octreeDir = url + '/../' + fMno.octreeDir;
- }
- pco.spacing = fMno.spacing;
- pco.hierarchyStepSize = fMno.hierarchyStepSize;
- pco.pointAttributes = fMno.pointAttributes;
- let min = new THREE.Vector3(fMno.boundingBox.lx, fMno.boundingBox.ly, fMno.boundingBox.lz);
- let max = new THREE.Vector3(fMno.boundingBox.ux, fMno.boundingBox.uy, fMno.boundingBox.uz);
- let boundingBox = new THREE.Box3(min, max);
- let tightBoundingBox = boundingBox.clone();
- if (fMno.tightBoundingBox) {//这个才是真实的bounding,前面那个bounding的size是个正方体,似乎取了最长边作为边长
- tightBoundingBox.min.copy(new THREE.Vector3(fMno.tightBoundingBox.lx, fMno.tightBoundingBox.ly, fMno.tightBoundingBox.lz));
- tightBoundingBox.max.copy(new THREE.Vector3(fMno.tightBoundingBox.ux, fMno.tightBoundingBox.uy, fMno.tightBoundingBox.uz));
- }
-
- let offset = min.clone(); //将成为点云的position,被我用作旋转中心(但在点云中不那么居中,navvis也是这样, 这样可能是为了让模型在这数据的bounding上)
- boundingBox.min.sub(offset); //点云的真实坐标的min都是0,0,0吗(我看案例是,因绕角落旋转,也就是原点)
-
- boundingBox.max.sub(offset);
- tightBoundingBox.min.sub(offset);
- tightBoundingBox.max.sub(offset);
- //改
- //pco.projection = fMno.projection || "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs ",
- //"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" //给地图
-
- pco.boundingBox = boundingBox;
- pco.tightBoundingBox = tightBoundingBox;
- pco.boundingSphere = boundingBox.getBoundingSphere(new THREE.Sphere());
- pco.tightBoundingSphere = tightBoundingBox.getBoundingSphere(new THREE.Sphere());
- pco.offset = offset;
- if (fMno.pointAttributes === 'LAS') {
- pco.loader = new LasLazLoader(fMno.version, "las");
- pco.pointAttributes = lasLazAttributes(fMno);
- } else if (fMno.pointAttributes === 'LAZ') {
- pco.loader = new LasLazLoader(fMno.version, "laz");
- pco.pointAttributes = lasLazAttributes(fMno);
- } else {
- pco.loader = new BinaryLoader(fMno.version, boundingBox, fMno.scale);
- pco.pointAttributes = parseAttributes(fMno);
- }
- let nodes = {};
- { // load root
- let name = 'r';
- let root = new PointCloudOctreeGeometryNode(name, pco, boundingBox);
- root.level = 0;
- root.hasChildren = true;
- root.spacing = pco.spacing;
- if (version.upTo('1.5')) {
- root.numPoints = fMno.hierarchy[0][1];
- } else {
- root.numPoints = 0;
- }
- pco.root = root;
- pco.root.load();
- nodes[name] = root;
- }
- // load remaining hierarchy
- if (version.upTo('1.4')) {
- for (let i = 1; i < fMno.hierarchy.length; i++) {
- let name = fMno.hierarchy[i][0];
- let numPoints = fMno.hierarchy[i][1];
- let index = parseInt(name.charAt(name.length - 1));
- let parentName = name.substring(0, name.length - 1);
- let parentNode = nodes[parentName];
- let level = name.length - 1;
- //let boundingBox = POCLoader.createChildAABB(parentNode.boundingBox, index);
- let boundingBox = Utils.createChildAABB(parentNode.boundingBox, index);
- let node = new PointCloudOctreeGeometryNode(name, pco, boundingBox);
- node.level = level;
- node.numPoints = numPoints;
- node.spacing = pco.spacing / Math.pow(2, level);
- parentNode.addChild(node);
- nodes[name] = node;
- }
- }
- pco.nodes = nodes;
- callback(pco);
- }
- };
- xhr.send(null);
- } catch (e) {
- console.log("loading failed: '" + url + "'");
- console.log(e);
- callback();
- }
- }
- loadPointAttributes(mno){
- let fpa = mno.pointAttributes;
- let pa = new PointAttributes();
- for (let i = 0; i < fpa.length; i++) {
- let pointAttribute = PointAttribute[fpa[i]];
- pa.add(pointAttribute);
- }
- return pa;
- }
- createChildAABB(aabb, index){
- let min = aabb.min.clone();
- let max = aabb.max.clone();
- let size = new THREE.Vector3().subVectors(max, min);
- if ((index & 0b0001) > 0) {
- min.z += size.z / 2;
- } else {
- max.z -= size.z / 2;
- }
- if ((index & 0b0010) > 0) {
- min.y += size.y / 2;
- } else {
- max.y -= size.y / 2;
- }
- if ((index & 0b0100) > 0) {
- min.x += size.x / 2;
- } else {
- max.x -= size.x / 2;
- }
- return new THREE.Box3(min, max);
- }
- }
|