@pirireis/webglobeplugins 1.0.2 → 1.0.3
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/{angle-calculation.ts → angle-calculation.js} +14 -18
- package/Math/{arc-cdf-points.ts → arc-cdf-points.js} +272 -329
- package/Math/{arc-generate-points-exponantial.ts → arc-generate-points-exponantial.js} +254 -299
- package/Math/{arc.ts → arc.js} +292 -421
- package/Math/bounds/line-bbox.js +186 -225
- package/Math/{circle-cdf-points.ts → circle-cdf-points.js} +78 -143
- package/Math/{circle.ts → circle.js} +33 -49
- package/Math/{constants.ts → constants.js} +4 -12
- package/Math/contour/{quadtreecontours.ts → quadtreecontours.js} +300 -371
- package/Math/contour/quadtreecontours1.js +298 -336
- package/Math/{finite-line-2d.ts → finite-line-2d.js} +58 -68
- package/Math/{haversine.ts → haversine.js} +22 -33
- package/Math/index.js +1 -0
- package/Math/juction/{arc-plane.ts → arc-plane.js} +143 -203
- package/Math/juction/{line-sphere.ts → line-sphere.js} +22 -32
- package/Math/juction/{plane-plane.ts → plane-plane.js} +53 -62
- package/Math/{line.ts → line.js} +52 -84
- package/Math/matrix4.js +1 -0
- package/Math/{methods.ts → methods.js} +126 -182
- package/Math/{plane.ts → plane.js} +56 -92
- package/Math/{quaternion.ts → quaternion.js} +106 -128
- package/Math/templete-shapes/{grid-visually-equal.ts → grid-visually-equal.js} +65 -118
- package/Math/tessellation/constants.js +1 -0
- package/Math/tessellation/{methods.ts → methods.js} +49 -79
- package/Math/tessellation/{nearest-value-padding.ts → nearest-value-padding.js} +112 -147
- package/Math/tessellation/{spherical-triangle-area.ts → spherical-triangle-area.js} +99 -127
- package/Math/tessellation/{tile-merger.ts → tile-merger.js} +429 -578
- package/Math/tessellation/{triangle-tessellation.ts → triangle-tessellation.js} +386 -533
- package/Math/tessellation/types.js +1 -0
- package/Math/types.js +1 -0
- package/Math/utils.js +2 -3
- package/Math/{vec3.ts → vec3.js} +155 -227
- package/Math/{xyz-tile.ts → xyz-tile.js} +18 -26
- package/algorithms/search-binary.js +16 -14
- package/altitude-locator/adaptors.js +1 -0
- package/altitude-locator/keymethod.js +1 -0
- package/altitude-locator/plugin.js +344 -445
- package/altitude-locator/types.js +21 -26
- package/compass-rose/compass-rose-padding-flat.js +230 -274
- package/compass-rose/{compass-text-writer.ts → compass-text-writer.js} +155 -210
- package/compass-rose/index.js +3 -3
- package/{constants.ts → constants.js} +6 -8
- package/heatwave/datamanager.js +149 -168
- package/heatwave/heatwave.js +206 -261
- package/heatwave/index.js +5 -5
- package/heatwave/isobar.js +303 -340
- package/heatwave/{texture-point-sampler.ts → texture-point-sampler.js} +187 -220
- package/investigation-tools/draw/tiles/adapters.js +67 -0
- package/investigation-tools/draw/tiles/{tiles.ts → tiles.js} +128 -162
- package/jest.config.js +7 -6
- package/package.json +1 -1
- package/pin/pin-object-array1.js +300 -381
- package/pin/pin-point-totem1.js +60 -77
- package/programs/arrowfield/arrow-field.js +60 -89
- package/programs/arrowfield/logic.js +141 -173
- package/programs/data2legend/density-to-legend.js +68 -86
- package/programs/data2legend/point-to-density-texture.js +67 -84
- package/programs/float2legendwithratio/index.js +2 -3
- package/programs/float2legendwithratio/logic.js +118 -144
- package/programs/float2legendwithratio/object.js +104 -141
- package/programs/helpers/blender.js +58 -73
- package/programs/helpers/{fadeaway.ts → fadeaway.js} +60 -73
- package/programs/index.js +20 -19
- package/programs/line-on-globe/circle-accurate-3d.js +85 -112
- package/programs/line-on-globe/circle-accurate-flat.js +148 -200
- package/programs/line-on-globe/degree-padding-around-circle-3d.js +102 -134
- package/programs/line-on-globe/index.js +1 -0
- package/programs/line-on-globe/lines-color-instanced-flat.js +80 -99
- package/programs/line-on-globe/linestrip/data.js +4 -0
- package/programs/line-on-globe/linestrip/{linestrip.ts → linestrip.js} +93 -152
- package/programs/line-on-globe/{naive-accurate-flexible.ts → naive-accurate-flexible.js} +126 -175
- package/programs/line-on-globe/util.js +5 -8
- package/programs/picking/pickable-polygon-renderer.js +98 -129
- package/programs/picking/pickable-renderer.js +98 -130
- package/programs/point-on-globe/element-globe-surface-glow.js +93 -122
- package/programs/point-on-globe/element-point-glow.js +80 -114
- package/programs/point-on-globe/square-pixel-point.js +121 -139
- package/programs/polygon-on-globe/{texture-dem-triangles.ts → texture-dem-triangles.js} +163 -207
- package/programs/{programcache.ts → programcache.js} +126 -134
- package/programs/rings/index.js +1 -1
- package/programs/rings/partial-ring/{piece-of-pie.ts → piece-of-pie.js} +152 -222
- package/programs/totems/camera-totem-attactment-interface.js +1 -0
- package/programs/totems/{camerauniformblock.ts → camerauniformblock.js} +225 -310
- package/programs/totems/{canvas-webglobe-info.ts → canvas-webglobe-info.js} +132 -147
- package/programs/totems/{dem-textures-manager.ts → dem-textures-manager.js} +257 -360
- package/programs/totems/{globe-changes.ts → globe-changes.js} +59 -79
- package/programs/totems/gpu-selection-uniform-block.js +99 -127
- package/programs/totems/{index.ts → index.js} +2 -2
- package/programs/two-d/pixel-padding-for-compass.js +87 -101
- package/programs/util.js +14 -19
- package/programs/vectorfields/logics/{constants.ts → constants.js} +4 -5
- package/programs/vectorfields/logics/{drawrectangleparticles.ts → drawrectangleparticles.js} +80 -115
- package/programs/vectorfields/logics/index.js +2 -4
- package/programs/vectorfields/logics/particle-ubo.js +16 -0
- package/programs/vectorfields/logics/{pixelbased.ts → pixelbased.js} +86 -115
- package/programs/vectorfields/logics/ubo.js +51 -57
- package/programs/vectorfields/{pingpongbuffermanager.ts → pingpongbuffermanager.js} +99 -113
- package/range-tools-on-terrain/bearing-line/{adapters.ts → adapters.js} +114 -154
- package/range-tools-on-terrain/bearing-line/{plugin.ts → plugin.js} +457 -569
- package/range-tools-on-terrain/bearing-line/types.js +1 -0
- package/range-tools-on-terrain/circle-line-chain/{adapters.ts → adapters.js} +85 -104
- package/range-tools-on-terrain/circle-line-chain/{chain-list-map.ts → chain-list-map.js} +382 -446
- package/range-tools-on-terrain/circle-line-chain/{plugin.ts → plugin.js} +464 -607
- package/range-tools-on-terrain/circle-line-chain/types.js +1 -0
- package/range-tools-on-terrain/range-ring/{adapters.ts → adapters.js} +93 -114
- package/range-tools-on-terrain/range-ring/{enum.ts → enum.js} +2 -2
- package/range-tools-on-terrain/range-ring/{plugin.ts → plugin.js} +377 -444
- package/range-tools-on-terrain/range-ring/rangeringangletext.js +331 -0
- package/range-tools-on-terrain/range-ring/types.js +9 -0
- package/semiplugins/interface.js +1 -0
- package/semiplugins/lightweight/{line-plugin.ts → line-plugin.js} +221 -342
- package/semiplugins/lightweight/{piece-of-pie-plugin.ts → piece-of-pie-plugin.js} +200 -275
- package/semiplugins/shape-on-terrain/{arc-plugin.ts → arc-plugin.js} +481 -616
- package/semiplugins/shape-on-terrain/{circle-plugin.ts → circle-plugin.js} +444 -588
- package/semiplugins/shape-on-terrain/{padding-1-degree.ts → padding-1-degree.js} +539 -713
- package/semiplugins/shape-on-terrain/terrain-polygon/{adapters.ts → adapters.js} +55 -69
- package/semiplugins/shape-on-terrain/terrain-polygon/data/{cache.ts → cache.js} +102 -149
- package/semiplugins/shape-on-terrain/terrain-polygon/data/{index-polygon-map.ts → index-polygon-map.js} +45 -58
- package/semiplugins/shape-on-terrain/terrain-polygon/data/{manager.ts → manager.js} +4 -4
- package/semiplugins/shape-on-terrain/terrain-polygon/data/master-worker.js +177 -196
- package/semiplugins/shape-on-terrain/terrain-polygon/data/{polygon-to-triangles.ts → polygon-to-triangles.js} +100 -144
- package/semiplugins/shape-on-terrain/terrain-polygon/data/{random.ts → random.js} +121 -165
- package/semiplugins/shape-on-terrain/terrain-polygon/data/types.js +1 -0
- package/semiplugins/shape-on-terrain/terrain-polygon/data/{worker-contact.ts → worker-contact.js} +63 -81
- package/semiplugins/shape-on-terrain/terrain-polygon/data/worker.js +125 -146
- package/semiplugins/shape-on-terrain/terrain-polygon/{terrain-polygon.ts → terrain-polygon.js} +219 -265
- package/semiplugins/shape-on-terrain/terrain-polygon/types.js +8 -0
- package/semiplugins/shell/bbox-renderer/index.js +2 -0
- package/semiplugins/shell/bbox-renderer/{logic.ts → logic.js} +209 -273
- package/semiplugins/shell/bbox-renderer/object.js +75 -0
- package/semiplugins/type.js +1 -0
- package/semiplugins/utility/{container-plugin.ts → container-plugin.js} +94 -126
- package/semiplugins/utility/{object-pass-container-plugin.ts → object-pass-container-plugin.js} +80 -101
- package/shaders/fragment-toy/firework.js +1 -1
- package/shaders/fragment-toy/singularity.js +2 -5
- package/tracks/point-heat-map/adaptors/timetracksplugin-format-to-this.js +63 -78
- package/tracks/point-heat-map/index.js +1 -0
- package/tracks/point-heat-map/plugin-webworker.js +121 -148
- package/tracks/point-heat-map/point-to-heat-map-flow.js +121 -150
- package/tracks/point-tracks/key-methods.js +2 -3
- package/tracks/point-tracks/plugin.js +401 -487
- package/tracks/timetracks/adaptors-line-strip.js +65 -79
- package/tracks/timetracks/plugin-line-strip.js +240 -295
- package/tracks/timetracks/program-line-strip.js +411 -495
- package/tracks/timetracks/programpoint-line-strip.js +109 -137
- package/types.js +19 -0
- package/util/account/bufferoffsetmanager.js +176 -209
- package/util/account/create-buffermap-orchastration.js +39 -0
- package/util/account/index.js +3 -6
- package/util/account/single-attribute-buffer-management/{buffer-manager.ts → buffer-manager.js} +119 -151
- package/util/account/single-attribute-buffer-management/{buffer-orchestrator.ts → buffer-orchestrator.js} +212 -238
- package/util/account/single-attribute-buffer-management/{buffer-orchestrator1.ts → buffer-orchestrator1.js} +159 -184
- package/util/account/single-attribute-buffer-management/{index.ts → index.js} +4 -11
- package/util/account/single-attribute-buffer-management/{object-store.ts → object-store.js} +55 -76
- package/util/account/single-attribute-buffer-management/types.js +1 -0
- package/util/account/util.js +18 -22
- package/util/algorithms/index.js +1 -0
- package/util/algorithms/search-binary.js +25 -26
- package/util/build-strategy/{static-dynamic.ts → static-dynamic.js} +41 -50
- package/util/check/index.js +1 -0
- package/util/check/typecheck.js +66 -0
- package/util/{frame-counter-trigger.ts → frame-counter-trigger.js} +84 -99
- package/util/geometry/{index.ts → index.js} +121 -155
- package/util/gl-util/buffer/{attribute-loader.ts → attribute-loader.js} +62 -84
- package/util/gl-util/buffer/{index.ts → index.js} +3 -6
- package/util/gl-util/draw-options/{methods.ts → methods.js} +32 -47
- package/util/gl-util/uniform-block/{manager.ts → manager.js} +200 -232
- package/util/{globe-default-gl-states.ts → globe-default-gl-states.js} +4 -5
- package/util/{helper-methods.ts → helper-methods.js} +8 -9
- package/util/index.js +10 -9
- package/util/interpolation/index.js +1 -0
- package/util/interpolation/timetrack/index.js +2 -9
- package/util/interpolation/timetrack/timetrack-interpolator.js +79 -94
- package/util/interpolation/timetrack/web-worker.js +46 -51
- package/util/picking/{fence.ts → fence.js} +43 -47
- package/util/picking/{picker-displayer.ts → picker-displayer.js} +176 -226
- package/util/programs/draw-from-pixel-coords.js +164 -201
- package/util/programs/{draw-texture-on-canvas.ts → draw-texture-on-canvas.js} +69 -91
- package/util/programs/supersampletotextures.js +97 -130
- package/util/programs/texturetoglobe.js +128 -153
- package/util/shaderfunctions/{geometrytransformations.ts → geometrytransformations.js} +44 -106
- package/util/shaderfunctions/index.js +2 -2
- package/util/shaderfunctions/nodata.js +2 -4
- package/util/shaderfunctions/noisefunctions.js +7 -10
- package/util/{webglobjectbuilders.ts → webglobjectbuilders.js} +358 -446
- package/vectorfield/arrowfield/adaptor.js +11 -11
- package/vectorfield/arrowfield/index.js +3 -3
- package/vectorfield/arrowfield/plugin.js +83 -128
- package/vectorfield/waveparticles/adaptor.js +15 -16
- package/vectorfield/waveparticles/index.js +3 -3
- package/vectorfield/waveparticles/{plugin.ts → plugin.js} +415 -506
- package/vectorfield/wind/adapters/{image-to-fields.ts → image-to-fields.js} +61 -74
- package/vectorfield/wind/adapters/types.js +1 -0
- package/vectorfield/wind/{imagetovectorfieldandmagnitude.ts → imagetovectorfieldandmagnitude.js} +53 -78
- package/vectorfield/wind/index.js +5 -5
- package/vectorfield/wind/{plugin-persistant copy.ts → plugin-persistant copy.js } +364 -461
- package/vectorfield/wind/{plugin-persistant.ts → plugin-persistant.js} +375 -483
- package/vectorfield/wind/plugin.js +685 -883
- package/vectorfield/wind/vectorfieldimage.js +23 -27
- package/write-text/{context-text-bulk.ts → context-text-bulk.js} +200 -285
- package/write-text/context-text3.js +167 -0
- package/write-text/{context-text4.ts → context-text4.js} +146 -231
- package/write-text/context-textDELETE.js +94 -125
- package/write-text/objectarraylabels/{index.ts → index.js} +2 -2
- package/write-text/objectarraylabels/objectarraylabels.js +200 -247
- package/Math/matrix4.ts +0 -0
- package/Math/mesh/mapbox-delaunay.d.ts +0 -74
- package/Math/roadmap.md +0 -10
- package/Math/tessellation/constants.ts +0 -1
- package/Math/tessellation/roadmap.md +0 -48
- package/Math/tessellation/types.ts +0 -1
- package/Math/types.ts +0 -68
- package/investigation-tools/draw/tiles/adapters.ts +0 -133
- package/programs/line-on-globe/linestrip/data.ts +0 -29
- package/programs/polygon-on-globe/roadmap.md +0 -8
- package/programs/totems/camera-totem-attactment-interface.ts +0 -4
- package/programs/vectorfields/logics/particle-ubo.ts +0 -23
- package/publish.bat +0 -62
- package/range-tools-on-terrain/bearing-line/types.ts +0 -65
- package/range-tools-on-terrain/circle-line-chain/types.ts +0 -43
- package/range-tools-on-terrain/range-ring/rangeringangletext.ts +0 -396
- package/range-tools-on-terrain/range-ring/types.ts +0 -30
- package/semiplugins/interface.ts +0 -14
- package/semiplugins/shape-on-terrain/goal.md +0 -12
- package/semiplugins/shape-on-terrain/terrain-polygon/data/cache-shortcuts.md +0 -20
- package/semiplugins/shape-on-terrain/terrain-polygon/data/master-worker.ts +0 -209
- package/semiplugins/shape-on-terrain/terrain-polygon/data/readme.md +0 -5
- package/semiplugins/shape-on-terrain/terrain-polygon/data/types.ts +0 -37
- package/semiplugins/shape-on-terrain/terrain-polygon/notes.md +0 -90
- package/semiplugins/shape-on-terrain/terrain-polygon/types.ts +0 -69
- package/semiplugins/shell/bbox-renderer/index.ts +0 -2
- package/semiplugins/shell/bbox-renderer/object.ts +0 -129
- package/semiplugins/type.ts +0 -8
- package/terrain-plugin.mmd +0 -83
- package/tests/Math/arc-sampling-test.js +0 -367
- package/tests/Math/arc-sampling-test.ts +0 -429
- package/tests/Math/arc.test.ts +0 -77
- package/tests/Math/junction/arc-limit.test.ts +0 -7
- package/tests/Math/junction/arc-plane-points.test.ts +0 -196
- package/tests/Math/junction/arc-plane.test.ts +0 -172
- package/tests/Math/junction/line-sphere.test.ts +0 -127
- package/tests/Math/junction/plane-plane.test.ts +0 -91
- package/tests/Math/plane-test.ts +0 -17
- package/tests/Math/plane.test.ts +0 -43
- package/tests/Math/vec3.test.ts +0 -33
- package/tracks/point-heat-map/readme.md +0 -15
- package/tracks/timetracks/readme.md +0 -1
- package/tsconfig.json +0 -22
- package/types/@pirireis/webglobe.d.ts +0 -102
- package/types/delaunator.d.ts +0 -40
- package/types/earcut.d.ts +0 -11
- package/types/rbush.d.ts +0 -57
- package/types.ts +0 -319
- package/util/account/create-buffermap-orchastration.ts +0 -85
- package/util/account/single-attribute-buffer-management/types.ts +0 -43
- package/util/check/typecheck.ts +0 -74
- package/vectorfield/wind/adapters/types.ts +0 -12
- package/write-text/context-text3.ts +0 -252
- package/write-text/objectarraylabels/objectarraylabels.d.ts +0 -72
package/Math/bounds/line-bbox.js
CHANGED
|
@@ -1,225 +1,186 @@
|
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// === Edge Case:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
const
|
|
145
|
-
const
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
console.log(
|
|
155
|
-
|
|
156
|
-
console.log(`
|
|
157
|
-
console.log(`
|
|
158
|
-
console.log(
|
|
159
|
-
console.log(
|
|
160
|
-
console.log(
|
|
161
|
-
console.log(`
|
|
162
|
-
console.log(`
|
|
163
|
-
|
|
164
|
-
console.log(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
const
|
|
174
|
-
const
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
console.log(`
|
|
185
|
-
console.log(
|
|
186
|
-
|
|
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
|
-
|
|
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
|
+
function mod(n, m) {
|
|
6
|
+
// Proper modulo operation that handles negative numbers
|
|
7
|
+
return ((n % m) + m) % m;
|
|
8
|
+
}
|
|
9
|
+
function calculateInitialBearing(phi1, lambda1, phi2, lambda2) {
|
|
10
|
+
// Calculates the initial bearing (forward azimuth) from point 1 to point 2
|
|
11
|
+
if (isClose(Math.cos(phi1), 0)) { // Starting from a pole
|
|
12
|
+
if (phi1 > 0) { // North pole
|
|
13
|
+
return Math.PI; // Bearing is South
|
|
14
|
+
}
|
|
15
|
+
else { // South pole
|
|
16
|
+
return 0; // Bearing is North
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const deltaLambda = lambda2 - lambda1;
|
|
20
|
+
const y = Math.sin(deltaLambda) * Math.cos(phi2);
|
|
21
|
+
const x = Math.cos(phi1) * Math.sin(phi2) - Math.sin(phi1) * Math.cos(phi2) * Math.cos(deltaLambda);
|
|
22
|
+
const theta = Math.atan2(y, x);
|
|
23
|
+
return theta;
|
|
24
|
+
}
|
|
25
|
+
function getGreatCircleArcBBox(phi1Rad, lambda1Rad, phi2Rad, lambda2Rad) {
|
|
26
|
+
// Calculates the bounding box around the great circle arc between two points
|
|
27
|
+
// on a spherical surface, handling edge cases like poles and antimeridian crossing.
|
|
28
|
+
// Args: Latitudes and longitudes in radians
|
|
29
|
+
// Returns: [phiMin, phiMax, lambdaMin, lambdaMax] in radians
|
|
30
|
+
// === Edge Case: Same Points ===
|
|
31
|
+
if (isClose(phi1Rad, phi2Rad) && isClose(lambda1Rad, lambda2Rad)) {
|
|
32
|
+
return [phi1Rad, phi1Rad, lambda1Rad, lambda1Rad];
|
|
33
|
+
}
|
|
34
|
+
// === Edge Case: Antipodal Points ===
|
|
35
|
+
const deltaLambdaNorm = mod(lambda1Rad - lambda2Rad + Math.PI, 2 * Math.PI) - Math.PI;
|
|
36
|
+
if (isClose(phi1Rad, -phi2Rad) && isClose(Math.abs(deltaLambdaNorm), Math.PI)) {
|
|
37
|
+
// Path covers all longitudes and passes through poles
|
|
38
|
+
return [-Math.PI / 2, Math.PI / 2, -Math.PI, Math.PI];
|
|
39
|
+
}
|
|
40
|
+
// === Longitude Bounds ===
|
|
41
|
+
let lambda1Adj = lambda1Rad;
|
|
42
|
+
let lambda2Adj = lambda2Rad;
|
|
43
|
+
// Handle antimeridian crossing
|
|
44
|
+
let deltaLambda = lambda2Rad - lambda1Rad;
|
|
45
|
+
if (deltaLambda > Math.PI) {
|
|
46
|
+
deltaLambda -= 2 * Math.PI;
|
|
47
|
+
}
|
|
48
|
+
else if (deltaLambda <= -Math.PI) {
|
|
49
|
+
deltaLambda += 2 * Math.PI;
|
|
50
|
+
}
|
|
51
|
+
const crossesAntimeridian = Math.abs(lambda2Rad - lambda1Rad) > Math.PI;
|
|
52
|
+
if (crossesAntimeridian) {
|
|
53
|
+
// Add 2*pi to the smaller longitude
|
|
54
|
+
if (lambda1Rad < lambda2Rad) {
|
|
55
|
+
lambda1Adj += 2 * Math.PI;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
lambda2Adj += 2 * Math.PI;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const lambdaMin = Math.min(lambda1Adj, lambda2Adj);
|
|
62
|
+
const lambdaMax = Math.max(lambda1Adj, lambda2Adj);
|
|
63
|
+
// === Latitude Bounds ===
|
|
64
|
+
let phiMin = Math.min(phi1Rad, phi2Rad);
|
|
65
|
+
let phiMax = Math.max(phi1Rad, phi2Rad);
|
|
66
|
+
// === Vertex Check ===
|
|
67
|
+
// Check the maximum/minimum latitude reached by the great circle
|
|
68
|
+
const theta12 = calculateInitialBearing(phi1Rad, lambda1Rad, phi2Rad, lambda2Rad);
|
|
69
|
+
const theta21 = calculateInitialBearing(phi2Rad, lambda2Rad, phi1Rad, lambda1Rad);
|
|
70
|
+
const cosPhi1 = Math.cos(phi1Rad);
|
|
71
|
+
if (!isClose(cosPhi1, 0)) { // Starting point is not a pole
|
|
72
|
+
// Compute the absolute latitude of the vertex
|
|
73
|
+
const argAcos = Math.abs(Math.sin(theta12) * cosPhi1);
|
|
74
|
+
const phiVtxAbs = Math.acos(Math.min(Math.max(argAcos, -1.0), 1.0));
|
|
75
|
+
// Check if the path crosses the northern vertex
|
|
76
|
+
if (isClose(theta12, 0) && phiVtxAbs > phiMax) { // Starting due north
|
|
77
|
+
phiMax = phiVtxAbs;
|
|
78
|
+
}
|
|
79
|
+
else if (isClose(Math.abs(theta12), Math.PI) && -phiVtxAbs < phiMin) { // Starting due south
|
|
80
|
+
phiMin = -phiVtxAbs;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
// General case: Check if the path crosses the vertex
|
|
84
|
+
const finalBearingAtP2 = mod(theta21 + Math.PI + Math.PI, 2 * Math.PI) - Math.PI;
|
|
85
|
+
// Northern vertex check
|
|
86
|
+
if ((-Math.PI / 2 < theta12 && theta12 < Math.PI / 2) &&
|
|
87
|
+
!(finalBearingAtP2 >= -Math.PI / 2 && finalBearingAtP2 <= Math.PI / 2)) {
|
|
88
|
+
if (phiVtxAbs > phiMax) {
|
|
89
|
+
phiMax = phiVtxAbs;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Southern vertex check
|
|
93
|
+
if (!(theta12 >= -Math.PI / 2 && theta12 <= Math.PI / 2) &&
|
|
94
|
+
(-Math.PI / 2 < finalBearingAtP2 && finalBearingAtP2 < Math.PI / 2)) {
|
|
95
|
+
if (-phiVtxAbs < phiMin) {
|
|
96
|
+
phiMin = -phiVtxAbs;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return [phiMin, phiMax, lambdaMin, lambdaMax];
|
|
102
|
+
}
|
|
103
|
+
// --- Example Usage ---
|
|
104
|
+
function degreesToRadians(deg) {
|
|
105
|
+
return deg * Math.PI / 180;
|
|
106
|
+
}
|
|
107
|
+
function radiansToDegrees(rad) {
|
|
108
|
+
return rad * 180 / Math.PI;
|
|
109
|
+
}
|
|
110
|
+
export { getGreatCircleArcBBox };
|
|
111
|
+
// Test Case 1: London to Tokyo
|
|
112
|
+
const lat1Deg = 51.5, lon1Deg = -0.1;
|
|
113
|
+
const lat2Deg = 35.7, lon2Deg = 139.7;
|
|
114
|
+
const phi1 = degreesToRadians(lat1Deg);
|
|
115
|
+
const lambda1 = degreesToRadians(lon1Deg);
|
|
116
|
+
const phi2 = degreesToRadians(lat2Deg);
|
|
117
|
+
const lambda2 = degreesToRadians(lon2Deg);
|
|
118
|
+
const [phiMinRad, phiMaxRad, lambdaMinRad, lambdaMaxRad] = getGreatCircleArcBBox(phi1, lambda1, phi2, lambda2);
|
|
119
|
+
const phiMinDeg = radiansToDegrees(phiMinRad);
|
|
120
|
+
const phiMaxDeg = radiansToDegrees(phiMaxRad);
|
|
121
|
+
const lambdaMinDeg = radiansToDegrees(lambdaMinRad);
|
|
122
|
+
const lambdaMaxDeg = radiansToDegrees(lambdaMaxRad);
|
|
123
|
+
console.log("Input Points (Radians):");
|
|
124
|
+
console.log(` P1: Latitude=${lat1Deg}, Longitude=${lon1Deg}`);
|
|
125
|
+
console.log(` P2: Latitude=${lat2Deg}, Longitude=${lon2Deg}`);
|
|
126
|
+
console.log(` P1: Latitude=${phi1.toFixed(4)}, Longitude=${lambda1.toFixed(4)}`);
|
|
127
|
+
console.log(` P2: Latitude=${phi2.toFixed(4)}, Longitude=${lambda2.toFixed(4)}`);
|
|
128
|
+
console.log("-".repeat(20));
|
|
129
|
+
console.log("Bounding Box (Radians):");
|
|
130
|
+
// console phys://console.log(` Minimum Latitude (phi_min): ${phiMinRad.toFixed(4)}`);
|
|
131
|
+
console.log(` Maximum Latitude (phi_max): ${phiMaxRad.toFixed(4)}`);
|
|
132
|
+
console.log(` Minimum Longitude (lambda_min): ${lambdaMinRad.toFixed(4)}`);
|
|
133
|
+
console.log(` Maximum Longitude (lambda_max): ${lambdaMaxRad.toFixed(4)}`);
|
|
134
|
+
console.log("-".repeat(20));
|
|
135
|
+
console.log("Bounding Box (Degrees):");
|
|
136
|
+
console.log(` Minimum Latitude: ${phiMinDeg.toFixed(2)}°`);
|
|
137
|
+
console.log(` Maximum Latitude: ${phiMaxDeg.toFixed(2)}°`);
|
|
138
|
+
console.log(` Minimum Longitude: ${lambdaMinDeg.toFixed(2)}°`);
|
|
139
|
+
console.log(` Maximum Longitude: ${lambdaMaxDeg.toFixed(2)}°`);
|
|
140
|
+
// --- Antimeridian Crossing Test ---
|
|
141
|
+
console.log("\n" + "=".repeat(30));
|
|
142
|
+
console.log("Antimeridian Crossing Test");
|
|
143
|
+
const lat1DegAm = -18, lon1DegAm = 178;
|
|
144
|
+
const lat2DegAm = -14, lon2DegAm = -172;
|
|
145
|
+
const phi1Am = degreesToRadians(lat1DegAm);
|
|
146
|
+
const lambda1Am = degreesToRadians(lon1DegAm);
|
|
147
|
+
const phi2Am = degreesToRadians(lat2DegAm);
|
|
148
|
+
const lambda2Am = degreesToRadians(lon2DegAm);
|
|
149
|
+
const [phiMinRadAm, phiMaxRadAm, lambdaMinRadAm, lambdaMaxRadAm] = getGreatCircleArcBBox(phi1Am, lambda1Am, phi2Am, lambda2Am);
|
|
150
|
+
const phiMinDegAm = radiansToDegrees(phiMinRadAm);
|
|
151
|
+
const phiMaxDegAm = radiansToDegrees(phiMaxRadAm);
|
|
152
|
+
const lambdaMinDegAm = radiansToDegrees(lambdaMinRadAm);
|
|
153
|
+
const lambdaMaxDegAm = radiansToDegrees(lambdaMaxRadAm);
|
|
154
|
+
console.log(`Input Points (Degrees): P1=(${lat1DegAm}, ${lon1DegAm}), P2=(${lat2DegAm}, ${lon2DegAm})`);
|
|
155
|
+
console.log("Bounding Box (Radians):");
|
|
156
|
+
console.log(` phi_min=${phiMinRadAm.toFixed(4)}, phi_max=${phiMaxRadAm.toFixed(4)}`);
|
|
157
|
+
console.log(` lambda_min=${lambdaMinRadAm.toFixed(4)}, lambda_max=${lambdaMaxRadAm.toFixed(4)}`);
|
|
158
|
+
console.log("Bounding Box (Degrees):");
|
|
159
|
+
console.log(` Min Latitude: ${phiMinDegAm.toFixed(2)}°`);
|
|
160
|
+
console.log(` Max Latitude: ${phiMaxDegAm.toFixed(2)}°`);
|
|
161
|
+
console.log(` Min Longitude: ${lambdaMinDegAm.toFixed(2)}° (178° expected)`);
|
|
162
|
+
console.log(` Max Longitude: ${lambdaMaxDegAm.toFixed(2)}° (188° expected, which is -172° + 360°)`);
|
|
163
|
+
// --- Polar Crossing Test ---
|
|
164
|
+
console.log("\n" + "=".repeat(30));
|
|
165
|
+
console.log("Polar Crossing Test");
|
|
166
|
+
const lat1DegP = 80, lon1DegP = 20;
|
|
167
|
+
const lat2DegP = 80, lon2DegP = -100;
|
|
168
|
+
const phi1P = degreesToRadians(lat1DegP);
|
|
169
|
+
const lambda1P = degreesToRadians(lon1DegP);
|
|
170
|
+
const phi2P = degreesToRadians(lat2DegP);
|
|
171
|
+
const lambda2P = degreesToRadians(lon2DegP);
|
|
172
|
+
const [phiMinRadP, phiMaxRadP, lambdaMinRadP, lambdaMaxRadP] = getGreatCircleArcBBox(phi1P, lambda1P, phi2P, lambda2P);
|
|
173
|
+
const phiMinDegP = radiansToDegrees(phiMinRadP);
|
|
174
|
+
const phiMaxDegP = radiansToDegrees(phiMaxRadP);
|
|
175
|
+
const lambdaMinDegP = radiansToDegrees(lambdaMinRadP);
|
|
176
|
+
const lambdaMaxDegP = radiansToDegrees(lambdaMaxRadP);
|
|
177
|
+
console.log(`Input Points (Degrees): P1=(${lat1DegP}, ${lon1DegP}), P2=(${lat2DegP}, ${lon2DegP})`);
|
|
178
|
+
console.log("Bounding Box (Radians):");
|
|
179
|
+
console.log(` phi_min=${phiMinRadP.toFixed(4)}, phi_max=${phiMaxRadP.toFixed(4)}`);
|
|
180
|
+
console.log(` lambda_min=${lambdaMinRadP.toFixed(4)}, lambda_max=${lambdaMaxRadP.toFixed(4)}`);
|
|
181
|
+
console.log("Bounding Box (Degrees):");
|
|
182
|
+
console.log(` Min Latitude: ${phiMinDegP.toFixed(2)}°`);
|
|
183
|
+
console.log(` Max Latitude: ${phiMaxDegP.toFixed(2)}° (Should be close to North Pole > 80°)`);
|
|
184
|
+
console.log(` Min Longitude: ${lambdaMinDegP.toFixed(2)}°`);
|
|
185
|
+
console.log(` Max Longitude: ${lambdaMaxDegP.toFixed(2)}°`);
|
|
186
|
+
// --- line points intersection with bbox ---
|