@pirireis/webglobeplugins 0.8.15-alpha → 0.8.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Math/arc.ts ADDED
@@ -0,0 +1,239 @@
1
+
2
+ import { Vector3D } from "./vector3d";
3
+ import { Plane } from "./plane";
4
+ import { Quaternion } from "./quaternion";
5
+ import { Radians } from "./types";
6
+ import { Ray } from "./ray";
7
+
8
+ const _quaternion = /*@__PURE__*/ new Quaternion(0, 0, 0, 0);
9
+ const _ray = /*@__PURE__*/ new Ray(new Vector3D(0, 0, 0), new Vector3D(0, 0, 0));
10
+ const _0vector = /*@__PURE__*/ new Vector3D(0, 0, 0);
11
+ const _0plane = /*@__PURE__*/ new Plane(_0vector, 0);
12
+
13
+ const _A_x_otherA = /*@__PURE__*/ new Vector3D(0, 0, 0);
14
+ const _A_x_otherB = /*@__PURE__*/ new Vector3D(0, 0, 0);
15
+ const _AxB = /*@__PURE__*/ new Vector3D(0, 0, 0);
16
+
17
+
18
+
19
+
20
+
21
+ export class Arc {
22
+ pointA: Vector3D;
23
+ pointB: Vector3D;
24
+ _dot: number;
25
+ _AxB: Vector3D;
26
+ _theta: Radians;
27
+ _imageinaryPlane: Plane;
28
+ constructor(
29
+ pointA: Vector3D,
30
+ pointB: Vector3D,
31
+ ) {
32
+ this.pointA = pointA.normalize();
33
+ this.pointB = pointB.normalize();
34
+ this._AxB = pointA.clone().cross(pointB);
35
+ this._dot = this.pointA.dot(this.pointB);
36
+ this._theta = Math.acos(this._dot);
37
+ this._imageinaryPlane = new Plane(this._AxB.clone().normalize(), 0);
38
+ }
39
+
40
+
41
+ copy(arc: Arc): Arc {
42
+ this.pointA.copy(arc.pointA);
43
+ this.pointB.copy(arc.pointB);
44
+ this._AxB.copy(arc._AxB);
45
+ this._dot = arc._dot;
46
+ this._theta = arc._theta;
47
+ this._imageinaryPlane.copy(arc._imageinaryPlane);
48
+ return this;
49
+ }
50
+
51
+
52
+ clone(): Arc {
53
+ return new Arc(this.pointA.clone(), this.pointB.clone());
54
+ }
55
+
56
+
57
+ equals(arc: Arc): boolean {
58
+ return (this.pointA.equals(arc.pointA) && this.pointB.equals(arc.pointB)) || (this.pointA.equals(arc.pointB) && this.pointB.equals(arc.pointA));
59
+ }
60
+
61
+
62
+ slerp(t: number): Vector3D {
63
+
64
+ const pointA = this.pointA;
65
+ const pointB = this.pointB;
66
+
67
+ const step = t / this._theta;
68
+ const sinTheta = Math.sin(this._theta);
69
+ const sinStep = Math.sin(step * this._theta);
70
+ const sinOneMinusStep = Math.sin((1 - step) * this._theta);
71
+
72
+ const x = (sinOneMinusStep * pointA[0] + sinStep * pointB[0]) / sinTheta;
73
+ const y = (sinOneMinusStep * pointA[1] + sinStep * pointB[1]) / sinTheta;
74
+ const z = (sinOneMinusStep * pointA[2] + sinStep * pointB[2]) / sinTheta;
75
+
76
+ return new Vector3D(x, y, z);
77
+
78
+ }
79
+
80
+
81
+
82
+
83
+ // TODO: EDGE CASE: the points are on same location
84
+ intersectionMedium(medium: Plane, target: Arc | null = null): Arc | null {
85
+ // Orianted in right hand rule
86
+ if (this.pointA.equals(this.pointB)) return null; // arc is too short
87
+
88
+ const result = this._imageinaryPlane.intersectionPlane(medium);
89
+ if (result instanceof Plane) {
90
+ return this.clone();
91
+ }
92
+
93
+ if (result === null) { console.log("null intersection"); return null; } // planes are parallel
94
+
95
+ const intersectionPoints = _ray.set(result.origin, result.direction).intersectionSphere(_0vector.set(0, 0, 0), 1);
96
+ if (intersectionPoints === null) {
97
+ return null; // no intersection
98
+ }
99
+
100
+ const [A, B] = (() => {
101
+ Vector3D.crossVectors(...intersectionPoints, _AxB);
102
+ if (_AxB.dot(this._AxB) >= 0) {
103
+ return [intersectionPoints[0], intersectionPoints[1]];
104
+ } else {
105
+ return [intersectionPoints[1], intersectionPoints[0]];
106
+ }
107
+ })();
108
+
109
+
110
+ Vector3D.crossVectors(this.pointA, A, _A_x_otherA);
111
+ Vector3D.crossVectors(this.pointA, B, _A_x_otherB);
112
+ // think as this.pointA is on y=1 on a x-y space. this.pointB is on the x>0 part of the space.
113
+ // any point on x<0 is outside. Any point y<this._dot is outside.
114
+ const _yA = this.pointA.dot(A);
115
+ const _yB = this.pointA.dot(B);
116
+
117
+ const _xA = _A_x_otherA.dot(this._AxB);
118
+ const _xB = _A_x_otherB.dot(this._AxB);
119
+
120
+
121
+ if (_xA < 0 && _xB < 0) {
122
+ return null; // no intersection
123
+ }
124
+ if (_yA < this._dot && _yB < this._dot) {
125
+ return null; // no intersection
126
+ }
127
+
128
+ const resultPoints: [Vector3D, Vector3D] = [
129
+ _xA < 0 ? this.pointA.clone() : A,
130
+ _yB <= this._dot ? this.pointB.clone() : B
131
+ ];
132
+ if (target === null) {
133
+ target = new Arc(...resultPoints);
134
+ } else {
135
+ target.setFromUnitVectors(...resultPoints);
136
+ }
137
+
138
+ return target;
139
+ }
140
+
141
+
142
+
143
+
144
+ setFromUnitVectors(
145
+ pointA: Vector3D,
146
+ pointB: Vector3D,
147
+ ) {
148
+
149
+ // following values might be calculated lazily
150
+ this.pointA.copy(pointA).normalize();
151
+ this.pointB.copy(pointB).normalize();
152
+ this._AxB = pointA.clone().cross(pointB);
153
+ this._dot = this.pointA.dot(this.pointB);
154
+ this._theta = Math.acos(this._dot);
155
+ this._imageinaryPlane = new Plane(this._AxB.clone().normalize(), 0);
156
+ }
157
+
158
+
159
+
160
+ populatePoints3D(pointCount: number, startProportion: number = 0, endProportion: number = 1): Float32Array {
161
+
162
+ const points3D = new Float32Array(pointCount * 3);
163
+ const step = (endProportion - startProportion) / (pointCount - 1);
164
+ const _AxBnormalized = this._AxB.clone().normalize();
165
+
166
+ _0vector.copy(this.pointA);
167
+
168
+ if (startProportion > 0) {
169
+ _quaternion.setFromAxisAngle(_AxBnormalized, this._theta * startProportion);
170
+ _0vector.applyQuaternion(_quaternion);
171
+ }
172
+ _quaternion.setFromAxisAngle(_AxBnormalized, this._theta * step);
173
+ let index = 0;
174
+ for (let i = 0; i < pointCount; i++) {
175
+ points3D[index++] = _0vector.x;
176
+ points3D[index++] = _0vector.y;
177
+ points3D[index++] = _0vector.z;
178
+ _0vector.applyQuaternion(_quaternion);
179
+ }
180
+
181
+ return points3D;
182
+ }
183
+ // cutBoundingBoxes(dotStep: number = 0.025): { minX: number, minY: number, maxX: number, maxY: number }[] {
184
+ // const pointA = this.pointA;
185
+ // const to = this.pointB;
186
+ // const a = [pointA.x, pointA.y, pointA.z];
187
+ // const b = [to.x, to.y, to.z];
188
+
189
+ // const theta = Math.acos(a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
190
+ // const step = dotStep / theta;
191
+
192
+ // if (step >= 1) {
193
+ // return [{ minX: Math.min(pointA.x, to.x), minY: Math.min(pointA.y, to.y), maxX: Math.max(pointA.x, to.x), maxY: Math.max(pointA.y, to.y) }];
194
+ // }
195
+
196
+ // let points = [pointA] as Vector3D[];
197
+ // let currentStep = 0;
198
+ // while (currentStep < 1) {
199
+ // currentStep += step;
200
+ // points.push(this.slerp(currentStep, currentStep + step, 1)[0]);
201
+ // }
202
+
203
+ // return points.map(point => ({ minX: point.x, minY: point.y, maxX: point.x, maxY: point.y }));
204
+ // }
205
+
206
+ // boundingBox(): { minLon: Radians, minLat: Radians, maxLon: Radians, maxLat: Radians } {
207
+
208
+ // // Do two poınts remaın on the same half when the circle is cut by Z axis?
209
+ // const Z = Math.sign(this.pointA.z + this.pointB.z);
210
+ // _0vector.set(0, 0, Z);
211
+ // const zDot = this.greatCirclePlaneNormalVector.dot(_0vector);
212
+ // const zDif = Math.abs(this.pointA.z - this.pointB.z);
213
+ // const minPossibleZDistanceIfOnTheSameHalf = (1 - this.dot) * zDot;
214
+
215
+ // const aLonLat = this.pointA.toLonLat();
216
+ // const bLonLat = this.pointB.toLonLat();
217
+
218
+ // if (zDif >= minPossibleZDistanceIfOnTheSameHalf) {
219
+ // return {
220
+ // minLon: Math.min(aLonLat.lon, bLonLat.lon),
221
+ // minLat: Math.min(aLonLat.lat, bLonLat.lat),
222
+ // maxLon: Math.max(aLonLat.lon, bLonLat.lon),
223
+ // maxLat: Math.max(aLonLat.lat, bLonLat.lat)
224
+ // }
225
+ // }
226
+
227
+ // // if not, we need to calculate Z peek of the arc
228
+ // const z = Math.asin(zDot * Z);
229
+ // return {
230
+ // minLon: Math.min(aLonLat.lon, bLonLat.lon),
231
+ // minLat: Math.min(aLonLat.lat, bLonLat.lat, z),
232
+ // maxLon: Math.max(aLonLat.lon, bLonLat.lon),
233
+ // maxLat: Math.max(aLonLat.lat, bLonLat.lat, z)
234
+
235
+ // }
236
+ // }
237
+
238
+ }
239
+
@@ -0,0 +1,225 @@
1
+ function isClose(a, b, rtol = 1e-5, atol = 1e-8) {
2
+ // JavaScript equivalent of NumPy's isclose
3
+ return Math.abs(a - b) <= (atol + rtol * Math.abs(b));
4
+ }
5
+
6
+ function mod(n, m) {
7
+ // Proper modulo operation that handles negative numbers
8
+ return ((n % m) + m) % m;
9
+ }
10
+
11
+ function calculateInitialBearing(phi1, lambda1, phi2, lambda2) {
12
+ // Calculates the initial bearing (forward azimuth) from point 1 to point 2
13
+ if (isClose(Math.cos(phi1), 0)) { // Starting from a pole
14
+ if (phi1 > 0) { // North pole
15
+ return Math.PI; // Bearing is South
16
+ } else { // South pole
17
+ return 0; // Bearing is North
18
+ }
19
+ }
20
+
21
+ const deltaLambda = lambda2 - lambda1;
22
+ const y = Math.sin(deltaLambda) * Math.cos(phi2);
23
+ const x = Math.cos(phi1) * Math.sin(phi2) - Math.sin(phi1) * Math.cos(phi2) * Math.cos(deltaLambda);
24
+ const theta = Math.atan2(y, x);
25
+ return theta;
26
+ }
27
+
28
+ function getGreatCircleArcBBox(phi1Rad, lambda1Rad, phi2Rad, lambda2Rad) {
29
+ // Calculates the bounding box around the great circle arc between two points
30
+ // on a spherical surface, handling edge cases like poles and antimeridian crossing.
31
+ // Args: Latitudes and longitudes in radians
32
+ // Returns: [phiMin, phiMax, lambdaMin, lambdaMax] in radians
33
+
34
+ // === Edge Case: Same Points ===
35
+ if (isClose(phi1Rad, phi2Rad) && isClose(lambda1Rad, lambda2Rad)) {
36
+ return [phi1Rad, phi1Rad, lambda1Rad, lambda1Rad];
37
+ }
38
+
39
+ // === Edge Case: Antipodal Points ===
40
+ const deltaLambdaNorm = mod(lambda1Rad - lambda2Rad + Math.PI, 2 * Math.PI) - Math.PI;
41
+ if (isClose(phi1Rad, -phi2Rad) && isClose(Math.abs(deltaLambdaNorm), Math.PI)) {
42
+ // Path covers all longitudes and passes through poles
43
+ return [-Math.PI / 2, Math.PI / 2, -Math.PI, Math.PI];
44
+ }
45
+
46
+ // === Longitude Bounds ===
47
+ let lambda1Adj = lambda1Rad;
48
+ let lambda2Adj = lambda2Rad;
49
+
50
+ // Handle antimeridian crossing
51
+ let deltaLambda = lambda2Rad - lambda1Rad;
52
+ if (deltaLambda > Math.PI) {
53
+ deltaLambda -= 2 * Math.PI;
54
+ } else if (deltaLambda <= -Math.PI) {
55
+ deltaLambda += 2 * Math.PI;
56
+ }
57
+
58
+ const crossesAntimeridian = Math.abs(lambda2Rad - lambda1Rad) > Math.PI;
59
+
60
+ if (crossesAntimeridian) {
61
+ // Add 2*pi to the smaller longitude
62
+ if (lambda1Rad < lambda2Rad) {
63
+ lambda1Adj += 2 * Math.PI;
64
+ } else {
65
+ lambda2Adj += 2 * Math.PI;
66
+ }
67
+ }
68
+
69
+ const lambdaMin = Math.min(lambda1Adj, lambda2Adj);
70
+ const lambdaMax = Math.max(lambda1Adj, lambda2Adj);
71
+
72
+ // === Latitude Bounds ===
73
+ let phiMin = Math.min(phi1Rad, phi2Rad);
74
+ let phiMax = Math.max(phi1Rad, phi2Rad);
75
+
76
+ // === Vertex Check ===
77
+ // Check the maximum/minimum latitude reached by the great circle
78
+ const theta12 = calculateInitialBearing(phi1Rad, lambda1Rad, phi2Rad, lambda2Rad);
79
+ const theta21 = calculateInitialBearing(phi2Rad, lambda2Rad, phi1Rad, lambda1Rad);
80
+
81
+ const cosPhi1 = Math.cos(phi1Rad);
82
+ if (!isClose(cosPhi1, 0)) { // Starting point is not a pole
83
+ // Compute the absolute latitude of the vertex
84
+ const argAcos = Math.abs(Math.sin(theta12) * cosPhi1);
85
+ const phiVtxAbs = Math.acos(Math.min(Math.max(argAcos, -1.0), 1.0));
86
+
87
+ // Check if the path crosses the northern vertex
88
+ if (isClose(theta12, 0) && phiVtxAbs > phiMax) { // Starting due north
89
+ phiMax = phiVtxAbs;
90
+ } else if (isClose(Math.abs(theta12), Math.PI) && -phiVtxAbs < phiMin) { // Starting due south
91
+ phiMin = -phiVtxAbs;
92
+ } else {
93
+ // General case: Check if the path crosses the vertex
94
+ const finalBearingAtP2 = mod(theta21 + Math.PI + Math.PI, 2 * Math.PI) - Math.PI;
95
+
96
+ // Northern vertex check
97
+ if ((-Math.PI / 2 < theta12 && theta12 < Math.PI / 2) &&
98
+ !(finalBearingAtP2 >= -Math.PI / 2 && finalBearingAtP2 <= Math.PI / 2)) {
99
+ if (phiVtxAbs > phiMax) {
100
+ phiMax = phiVtxAbs;
101
+ }
102
+ }
103
+
104
+ // Southern vertex check
105
+ if (!(theta12 >= -Math.PI / 2 && theta12 <= Math.PI / 2) &&
106
+ (-Math.PI / 2 < finalBearingAtP2 && finalBearingAtP2 < Math.PI / 2)) {
107
+ if (-phiVtxAbs < phiMin) {
108
+ phiMin = -phiVtxAbs;
109
+ }
110
+ }
111
+ }
112
+ }
113
+
114
+ return [phiMin, phiMax, lambdaMin, lambdaMax];
115
+ }
116
+
117
+
118
+
119
+
120
+ // --- Example Usage ---
121
+ function degreesToRadians(deg) {
122
+ return deg * Math.PI / 180;
123
+ }
124
+
125
+ function radiansToDegrees(rad) {
126
+ return rad * 180 / Math.PI;
127
+ }
128
+
129
+
130
+ export { getGreatCircleArcBBox };
131
+
132
+ // Test Case 1: London to Tokyo
133
+ const lat1Deg = 51.5, lon1Deg = -0.1;
134
+ const lat2Deg = 35.7, lon2Deg = 139.7;
135
+
136
+ const phi1 = degreesToRadians(lat1Deg);
137
+ const lambda1 = degreesToRadians(lon1Deg);
138
+ const phi2 = degreesToRadians(lat2Deg);
139
+ const lambda2 = degreesToRadians(lon2Deg);
140
+
141
+ const [phiMinRad, phiMaxRad, lambdaMinRad, lambdaMaxRad] = getGreatCircleArcBBox(phi1, lambda1, phi2, lambda2);
142
+
143
+ const phiMinDeg = radiansToDegrees(phiMinRad);
144
+ const phiMaxDeg = radiansToDegrees(phiMaxRad);
145
+ const lambdaMinDeg = radiansToDegrees(lambdaMinRad);
146
+ const lambdaMaxDeg = radiansToDegrees(lambdaMaxRad);
147
+
148
+ console.log("Input Points (Radians):");
149
+ console.log(` P1: Latitude=${lat1Deg}, Longitude=${lon1Deg}`);
150
+ console.log(` P2: Latitude=${lat2Deg}, Longitude=${lon2Deg}`);
151
+ console.log(` P1: Latitude=${phi1.toFixed(4)}, Longitude=${lambda1.toFixed(4)}`);
152
+ console.log(` P2: Latitude=${phi2.toFixed(4)}, Longitude=${lambda2.toFixed(4)}`);
153
+ console.log("-".repeat(20));
154
+ console.log("Bounding Box (Radians):");
155
+ // console phys://console.log(` Minimum Latitude (phi_min): ${phiMinRad.toFixed(4)}`);
156
+ console.log(` Maximum Latitude (phi_max): ${phiMaxRad.toFixed(4)}`);
157
+ console.log(` Minimum Longitude (lambda_min): ${lambdaMinRad.toFixed(4)}`);
158
+ console.log(` Maximum Longitude (lambda_max): ${lambdaMaxRad.toFixed(4)}`);
159
+ console.log("-".repeat(20));
160
+ console.log("Bounding Box (Degrees):");
161
+ console.log(` Minimum Latitude: ${phiMinDeg.toFixed(2)}°`);
162
+ console.log(` Maximum Latitude: ${phiMaxDeg.toFixed(2)}°`);
163
+ console.log(` Minimum Longitude: ${lambdaMinDeg.toFixed(2)}°`);
164
+ console.log(` Maximum Longitude: ${lambdaMaxDeg.toFixed(2)}°`);
165
+
166
+ // --- Antimeridian Crossing Test ---
167
+ console.log("\n" + "=".repeat(30));
168
+ console.log("Antimeridian Crossing Test");
169
+ const lat1DegAm = -18, lon1DegAm = 178;
170
+ const lat2DegAm = -14, lon2DegAm = -172;
171
+
172
+ const phi1Am = degreesToRadians(lat1DegAm);
173
+ const lambda1Am = degreesToRadians(lon1DegAm);
174
+ const phi2Am = degreesToRadians(lat2DegAm);
175
+ const lambda2Am = degreesToRadians(lon2DegAm);
176
+
177
+ const [phiMinRadAm, phiMaxRadAm, lambdaMinRadAm, lambdaMaxRadAm] = getGreatCircleArcBBox(phi1Am, lambda1Am, phi2Am, lambda2Am);
178
+
179
+ const phiMinDegAm = radiansToDegrees(phiMinRadAm);
180
+ const phiMaxDegAm = radiansToDegrees(phiMaxRadAm);
181
+ const lambdaMinDegAm = radiansToDegrees(lambdaMinRadAm);
182
+ const lambdaMaxDegAm = radiansToDegrees(lambdaMaxRadAm);
183
+
184
+ console.log(`Input Points (Degrees): P1=(${lat1DegAm}, ${lon1DegAm}), P2=(${lat2DegAm}, ${lon2DegAm})`);
185
+ console.log("Bounding Box (Radians):");
186
+ console.log(` phi_min=${phiMinRadAm.toFixed(4)}, phi_max=${phiMaxRadAm.toFixed(4)}`);
187
+ console.log(` lambda_min=${lambdaMinRadAm.toFixed(4)}, lambda_max=${lambdaMaxRadAm.toFixed(4)}`);
188
+ console.log("Bounding Box (Degrees):");
189
+ console.log(` Min Latitude: ${phiMinDegAm.toFixed(2)}°`);
190
+ console.log(` Max Latitude: ${phiMaxDegAm.toFixed(2)}°`);
191
+ console.log(` Min Longitude: ${lambdaMinDegAm.toFixed(2)}° (178° expected)`);
192
+ console.log(` Max Longitude: ${lambdaMaxDegAm.toFixed(2)}° (188° expected, which is -172° + 360°)`);
193
+
194
+ // --- Polar Crossing Test ---
195
+ console.log("\n" + "=".repeat(30));
196
+ console.log("Polar Crossing Test");
197
+ const lat1DegP = 80, lon1DegP = 20;
198
+ const lat2DegP = 80, lon2DegP = -100;
199
+
200
+ const phi1P = degreesToRadians(lat1DegP);
201
+ const lambda1P = degreesToRadians(lon1DegP);
202
+ const phi2P = degreesToRadians(lat2DegP);
203
+ const lambda2P = degreesToRadians(lon2DegP);
204
+
205
+ const [phiMinRadP, phiMaxRadP, lambdaMinRadP, lambdaMaxRadP] = getGreatCircleArcBBox(phi1P, lambda1P, phi2P, lambda2P);
206
+
207
+ const phiMinDegP = radiansToDegrees(phiMinRadP);
208
+ const phiMaxDegP = radiansToDegrees(phiMaxRadP);
209
+ const lambdaMinDegP = radiansToDegrees(lambdaMinRadP);
210
+ const lambdaMaxDegP = radiansToDegrees(lambdaMaxRadP);
211
+
212
+ console.log(`Input Points (Degrees): P1=(${lat1DegP}, ${lon1DegP}), P2=(${lat2DegP}, ${lon2DegP})`);
213
+ console.log("Bounding Box (Radians):");
214
+ console.log(` phi_min=${phiMinRadP.toFixed(4)}, phi_max=${phiMaxRadP.toFixed(4)}`);
215
+ console.log(` lambda_min=${lambdaMinRadP.toFixed(4)}, lambda_max=${lambdaMaxRadP.toFixed(4)}`);
216
+ console.log("Bounding Box (Degrees):");
217
+ console.log(` Min Latitude: ${phiMinDegP.toFixed(2)}°`);
218
+ console.log(` Max Latitude: ${phiMaxDegP.toFixed(2)}° (Should be close to North Pole > 80°)`);
219
+ console.log(` Min Longitude: ${lambdaMinDegP.toFixed(2)}°`);
220
+ console.log(` Max Longitude: ${lambdaMaxDegP.toFixed(2)}°`);
221
+
222
+
223
+
224
+ // --- line points intersection with bbox ---
225
+
@@ -0,0 +1,8 @@
1
+ const WORLD_RADIUS_3D = 6378.137;
2
+ const WORLD_RADIUS_MERCATOR = 6378136.99911;
3
+
4
+ export {
5
+ WORLD_RADIUS_3D,
6
+ WORLD_RADIUS_MERCATOR
7
+ }
8
+
@@ -0,0 +1,47 @@
1
+ import { Plane } from "../plane";
2
+ import { Vector3D } from "../vector3d";
3
+ import { Arc } from "../arc";
4
+
5
+
6
+
7
+ const Radians = Math.PI / 180;
8
+
9
+ export class ArcPartOnScreen {
10
+ private _oldLookInfo: { CenterLong: number, CenterLat: number, Distance: number, Tilt: number, NorthAng: number };
11
+ private _boundPlane: Plane;
12
+
13
+ constructor() {
14
+ this._boundPlane = new Plane(new Vector3D(0, 0, 0), 0);
15
+ this._oldLookInfo = { CenterLong: 0, CenterLat: -190, Distance: 0, Tilt: 0, NorthAng: 0 };
16
+ }
17
+
18
+
19
+ updateBoundPlane(lookInfo): boolean {
20
+ if (this._oldLookInfo && this._oldLookInfo.CenterLong === lookInfo.CenterLong && this._oldLookInfo.CenterLat === lookInfo.CenterLat) {
21
+ return false;
22
+ }
23
+ /**
24
+ * lookInfo {CenterLong: 47.75355881750585, CenterLat: 42.3417076206803, Distance: 2286603.4020860917, Tilt: 0.05, NorthAng: -13.829359965098265}
25
+ */
26
+ this._oldLookInfo.CenterLong = lookInfo.CenterLong;
27
+ this._oldLookInfo.CenterLat = lookInfo.CenterLat;
28
+ this._oldLookInfo.Distance = lookInfo.Distance;
29
+ this._oldLookInfo.Tilt = lookInfo.Tilt;
30
+ this._oldLookInfo.NorthAng = lookInfo.NorthAng;
31
+
32
+ Plane.fromGlobeLookInfo(Radians * lookInfo.CenterLong, Radians * lookInfo.CenterLat, lookInfo.Distance, this._boundPlane);
33
+ return true;
34
+ }
35
+
36
+
37
+
38
+ getArcPartOnScreen(arc: Arc, target: Arc): boolean {
39
+ // _imaginaryPlane.set(arc.greatCirclePlaneNormalVector, arc.pointA.dot(arc.greatCirclePlaneNormalVector));
40
+ // const intersection = _imaginaryPlane.intersectionPlane(this._boundPlane);
41
+ // if (!(intersection instanceof Ray)) return false;
42
+ // _ray.copy(intersection as Ray);
43
+ // const [point1, point2] = _ray.intersectionSphere(_unitShphereCenter, _unitShphereRadius) as [Vector3D, Vector3D];
44
+ const result = arc.intersectionMedium(this._boundPlane, target);
45
+ return !(result === null);
46
+ }
47
+ }
package/Math/methods.js CHANGED
@@ -1,6 +1,5 @@
1
1
 
2
- const WORLD_RADIUS_3D = 6378.137;
3
- const WORLD_RADIUS_MERCATOR = 6378136.99911;
2
+ import { WORLD_RADIUS_3D, WORLD_RADIUS_MERCATOR } from './constants.ts';
4
3
 
5
4
  /**
6
5
  * @typedef {Array<number>} vec3 [x, y, z]
@@ -193,7 +192,6 @@ const pixelXYLenghtToUnitVectorWithHeight = (pixelXYHeight) => {
193
192
 
194
193
  export {
195
194
  RADIANS,
196
- WORLD_RADIUS_3D,
197
195
  normalize3,
198
196
  dot3,
199
197
  length3,