| 12345678910111213141516171819202122 |
- import assert from 'node:assert/strict'
- import {readFileSync} from 'node:fs'
- import {enuToGeodetic} from './roof-geodesy.mjs'
- const identity=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]
- // Analytic WGS84 forward coordinates are independent of the Bowring inverse.
- let maxAngleError=0,maxHeightError=0
- for(const lon of [110.32875,110.395,110.46578])for(const lat of [28.39172,28.454,28.4913])for(const height of [0,150,450]){
- const L=lon*Math.PI/180,P=lat*Math.PI/180,a=6378137,e2=6.6943799901413165e-3,N=a/Math.sqrt(1-e2*Math.sin(P)**2)
- const X=(N+height)*Math.cos(P)*Math.cos(L),Y=(N+height)*Math.cos(P)*Math.sin(L),Z=(N*(1-e2)+height)*Math.sin(P)
- const actual=enuToGeodetic(identity,X,Y,Z)
- maxAngleError=Math.max(maxAngleError,Math.abs(actual.longitude-L),Math.abs(actual.latitude-P));maxHeightError=Math.max(maxHeightError,Math.abs(actual.height-height))
- assert.ok(Math.abs(actual.latitude-P)<1e-10&&Math.abs(actual.longitude-L)<1e-10)
- assert.ok(Math.abs(actual.height-height)<.001)
- }
- const input=JSON.parse(readFileSync('tools/city-massing/city/cad-bim/instanced-active-input.json'))
- const origin=enuToGeodetic(input.transform,0,0,0)
- assert.ok(Math.abs(origin.longitude*180/Math.PI-input.origin.lon)<1e-8&&Math.abs(origin.latitude*180/Math.PI-input.origin.lat)<1e-8)
- for(const point of [[1400,-1200,150],[3000,-6000,200],[-3000,3000,100]]){
- const m=input.transform,[x,y,z]=point,X=m[0]*x+m[4]*y+m[8]*z+m[12],Y=m[1]*x+m[5]*y+m[9]*z+m[13],Z=m[2]*x+m[6]*y+m[10]*z+m[14]
- assert.deepEqual(enuToGeodetic(m,x,y,z),enuToGeodetic(identity,X,Y,Z))
- }
- console.log(JSON.stringify({passed:true,analyticWgs84RoundTrips:27,maxAngleErrorRad:maxAngleError,maxHeightErrorM:maxHeightError,transformChecked:true}))
|