UNPKG

@csi-foxbyte/mesh-dem-to-terrain

Version:

A Node.js library that converts DEM meshes (DXF, GeoJSON, etc.) into Cesium Terrain Tiles (quantized-mesh or heightmap) with flexible zoom-level control and multi-threading support.

2 lines 4.03 kB
import {Logger,Document}from'@gltf-transform/core';import {dedup,flatten,join,weld,reorder}from'@gltf-transform/functions';import H from'delaunator';import {readFile}from'fs/promises';import Q from'lodash';import {MeshoptEncoder}from'meshoptimizer';import $ from'rbush';import {Box3,Vector3}from'three';import {parentPort}from'worker_threads';import {flipWindingOrder,resampleGrid,splitSharpEdges,betterWeld,expandWithExternalPolygons,cut,getSkirtIndicesFlat}from'./functions.js';import {QuantizedMesh}from'./quantizedMesh.js';import st from'path';if(Logger.DEFAULT_INSTANCE=new Logger(Logger.Verbosity.SILENT),!parentPort)throw new Error("Is not being called in a worker context!");let O=null,X=null,z=10;parentPort.on("message",async o=>{try{switch(o.type){case "init":O=new $().fromJSON(o.tree),parentPort.postMessage("ok"),X=o.outputFolder,z=o.skipLevel;break;case "work":if(!O)throw new Error("Worker is not initialized!");if(!X)throw new Error("No outputfolder set!");const[e,l,a,d]=at(o.x,o.y,o.zoom),r=new Document,u=r.createBuffer(),n=r.getRoot(),p=r.createScene();n.setDefaultScene(p);const y=r.createMaterial(),h=(a-e)*.1,x=(d-l)*.1,E=new Box3(new Vector3(e,l,-2e3),new Vector3(a,d,2e3)),A=o.zoom<z?[]:O.search({minX:e-h,minY:l-x,maxX:a+h,maxY:d+x});for(const{path:t}of A){const{gt:m,indices:g,vertices:b}=await it(t),I=r.createPrimitive(),w=r.createAccessor().setBuffer(u).setArray(b).setType("VEC3"),S=r.createAccessor().setBuffer(u).setArray(g).setType("SCALAR");I.setAttribute("POSITION",w),I.setIndices(S),I.setMaterial(y);const i=r.createNode();p.addChild(i),i.setTranslation(m.toArray());const f=r.createMesh();i.setMesh(f),f.addPrimitive(I);}if(A.length!==0){const t=new Vector3(...n.listNodes()?.[0]?.getTranslation()??[]);o.zoom<16?await r.transform(flipWindingOrder(),dedup(),flatten(),join(),weld({}),resampleGrid({minX:e-t.x,minY:l-t.y,maxX:a-t.x,maxY:d-t.y,offset:-100}),splitSharpEdges(),reorder({encoder:MeshoptEncoder})):await r.transform(flipWindingOrder(),dedup(),flatten(),join(),betterWeld(),expandWithExternalPolygons({minX:e-t.x,minY:l-t.y,maxX:a-t.x,maxY:d-t.y,offset:-100}),cut({minX:e-t.x,minY:l-t.y,maxX:a-t.x,maxY:d-t.y}),weld({}),splitSharpEdges(),reorder({encoder:MeshoptEncoder}));}const s=n.listMeshes().flatMap(t=>t.listPrimitives()).flatMap(t=>t.getAttribute("POSITION")?.getArray()?.byteLength),W=Q.sum(s);let c=[],L=[];if(W===0){const t=(a-e)/31,m=(d-l)/31;for(let i=0;i<32;i++)for(let f=0;f<32;f++)c.push(e+t*f,l+m*i,-100);const{triangles:g}=new H(c.filter((i,f)=>(f+1)%3!==0));g.reverse();const[b,I]=MeshoptEncoder.reorderMesh(g,!0,!1),w=new Array(I*3),S=new Map;for(let i=0;i<c.length/3;i++)if(b[i]!=4294967295){const f=i*3,N=b[i]*3;w[N]=c[f],w[N+1]=c[f+1],w[N+2]=c[f+2],S.set(i,b[i]);}c=w,L=Array.from(g);}else {c=Array.from(n.listMeshes().flatMap(m=>m.listPrimitives())[0].getAttribute("POSITION").getArray());const t=new Vector3(...n.listNodes()?.[0]?.getTranslation()??[]);for(let m=0;m<c.length;m+=3)c[m+0]+=t.x,c[m+1]+=t.y,c[m+2]+=t.z;L=Array.from(n.listMeshes().flatMap(m=>m.listPrimitives())[0].getIndices().getArray());}const{east:_,north:C,south:V,west:G}=getSkirtIndicesFlat(c,L,3,1e-6),j=await new QuantizedMesh(c,L,_,G,V,C,E).serialize();parentPort.postMessage({path:st.join(X,o.zoom.toString(),o.x.toString(),`${o.y}.terrain`),file:j});}}catch(e){console.error(e);}});async function it(o){const e=await readFile(o),l=new Vector3,a=e.readDoubleLE(0),d=e.readDoubleLE(8),r=e.readDoubleLE(16),u=24,n=e.readInt32LE(u),p=new Uint32Array(n),y=n>2**16,h=y?4:2;if(y)for(let s=0;s<n;s++)p[s]=e.readUint32LE(u+4+s*h);else for(let s=0;s<n;s++)p[s]=e.readUint16LE(u+4+s*h);const x=u+4+n*h,E=e.readInt32LE(x),A=new Float32Array(E);for(let s=0;s<E;s++)A[s]=e.readFloatLE(x+4+s*4);return l.set(a,d,r),{gt:l,indices:p,vertices:A}}function at(o,e,l,a=256){const r=2*Math.PI*6378137/2,n=2*Math.PI*6378137/a/Math.pow(2,l),p=o*a*n-r,y=e*a*n-r,h=(o+1)*a*n-r,x=(e+1)*a*n-r;return [p,y,h,x]}export{at as tmsTileToEPSG3857};//# sourceMappingURL=worker.js.map //# sourceMappingURL=worker.js.map