@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.
Files changed (259) hide show
  1. package/Math/{angle-calculation.ts → angle-calculation.js} +14 -18
  2. package/Math/{arc-cdf-points.ts → arc-cdf-points.js} +272 -329
  3. package/Math/{arc-generate-points-exponantial.ts → arc-generate-points-exponantial.js} +254 -299
  4. package/Math/{arc.ts → arc.js} +292 -421
  5. package/Math/bounds/line-bbox.js +186 -225
  6. package/Math/{circle-cdf-points.ts → circle-cdf-points.js} +78 -143
  7. package/Math/{circle.ts → circle.js} +33 -49
  8. package/Math/{constants.ts → constants.js} +4 -12
  9. package/Math/contour/{quadtreecontours.ts → quadtreecontours.js} +300 -371
  10. package/Math/contour/quadtreecontours1.js +298 -336
  11. package/Math/{finite-line-2d.ts → finite-line-2d.js} +58 -68
  12. package/Math/{haversine.ts → haversine.js} +22 -33
  13. package/Math/index.js +1 -0
  14. package/Math/juction/{arc-plane.ts → arc-plane.js} +143 -203
  15. package/Math/juction/{line-sphere.ts → line-sphere.js} +22 -32
  16. package/Math/juction/{plane-plane.ts → plane-plane.js} +53 -62
  17. package/Math/{line.ts → line.js} +52 -84
  18. package/Math/matrix4.js +1 -0
  19. package/Math/{methods.ts → methods.js} +126 -182
  20. package/Math/{plane.ts → plane.js} +56 -92
  21. package/Math/{quaternion.ts → quaternion.js} +106 -128
  22. package/Math/templete-shapes/{grid-visually-equal.ts → grid-visually-equal.js} +65 -118
  23. package/Math/tessellation/constants.js +1 -0
  24. package/Math/tessellation/{methods.ts → methods.js} +49 -79
  25. package/Math/tessellation/{nearest-value-padding.ts → nearest-value-padding.js} +112 -147
  26. package/Math/tessellation/{spherical-triangle-area.ts → spherical-triangle-area.js} +99 -127
  27. package/Math/tessellation/{tile-merger.ts → tile-merger.js} +429 -578
  28. package/Math/tessellation/{triangle-tessellation.ts → triangle-tessellation.js} +386 -533
  29. package/Math/tessellation/types.js +1 -0
  30. package/Math/types.js +1 -0
  31. package/Math/utils.js +2 -3
  32. package/Math/{vec3.ts → vec3.js} +155 -227
  33. package/Math/{xyz-tile.ts → xyz-tile.js} +18 -26
  34. package/algorithms/search-binary.js +16 -14
  35. package/altitude-locator/adaptors.js +1 -0
  36. package/altitude-locator/keymethod.js +1 -0
  37. package/altitude-locator/plugin.js +344 -445
  38. package/altitude-locator/types.js +21 -26
  39. package/compass-rose/compass-rose-padding-flat.js +230 -274
  40. package/compass-rose/{compass-text-writer.ts → compass-text-writer.js} +155 -210
  41. package/compass-rose/index.js +3 -3
  42. package/{constants.ts → constants.js} +6 -8
  43. package/heatwave/datamanager.js +149 -168
  44. package/heatwave/heatwave.js +206 -261
  45. package/heatwave/index.js +5 -5
  46. package/heatwave/isobar.js +303 -340
  47. package/heatwave/{texture-point-sampler.ts → texture-point-sampler.js} +187 -220
  48. package/investigation-tools/draw/tiles/adapters.js +67 -0
  49. package/investigation-tools/draw/tiles/{tiles.ts → tiles.js} +128 -162
  50. package/jest.config.js +7 -6
  51. package/package.json +1 -1
  52. package/pin/pin-object-array1.js +300 -381
  53. package/pin/pin-point-totem1.js +60 -77
  54. package/programs/arrowfield/arrow-field.js +60 -89
  55. package/programs/arrowfield/logic.js +141 -173
  56. package/programs/data2legend/density-to-legend.js +68 -86
  57. package/programs/data2legend/point-to-density-texture.js +67 -84
  58. package/programs/float2legendwithratio/index.js +2 -3
  59. package/programs/float2legendwithratio/logic.js +118 -144
  60. package/programs/float2legendwithratio/object.js +104 -141
  61. package/programs/helpers/blender.js +58 -73
  62. package/programs/helpers/{fadeaway.ts → fadeaway.js} +60 -73
  63. package/programs/index.js +20 -19
  64. package/programs/line-on-globe/circle-accurate-3d.js +85 -112
  65. package/programs/line-on-globe/circle-accurate-flat.js +148 -200
  66. package/programs/line-on-globe/degree-padding-around-circle-3d.js +102 -134
  67. package/programs/line-on-globe/index.js +1 -0
  68. package/programs/line-on-globe/lines-color-instanced-flat.js +80 -99
  69. package/programs/line-on-globe/linestrip/data.js +4 -0
  70. package/programs/line-on-globe/linestrip/{linestrip.ts → linestrip.js} +93 -152
  71. package/programs/line-on-globe/{naive-accurate-flexible.ts → naive-accurate-flexible.js} +126 -175
  72. package/programs/line-on-globe/util.js +5 -8
  73. package/programs/picking/pickable-polygon-renderer.js +98 -129
  74. package/programs/picking/pickable-renderer.js +98 -130
  75. package/programs/point-on-globe/element-globe-surface-glow.js +93 -122
  76. package/programs/point-on-globe/element-point-glow.js +80 -114
  77. package/programs/point-on-globe/square-pixel-point.js +121 -139
  78. package/programs/polygon-on-globe/{texture-dem-triangles.ts → texture-dem-triangles.js} +163 -207
  79. package/programs/{programcache.ts → programcache.js} +126 -134
  80. package/programs/rings/index.js +1 -1
  81. package/programs/rings/partial-ring/{piece-of-pie.ts → piece-of-pie.js} +152 -222
  82. package/programs/totems/camera-totem-attactment-interface.js +1 -0
  83. package/programs/totems/{camerauniformblock.ts → camerauniformblock.js} +225 -310
  84. package/programs/totems/{canvas-webglobe-info.ts → canvas-webglobe-info.js} +132 -147
  85. package/programs/totems/{dem-textures-manager.ts → dem-textures-manager.js} +257 -360
  86. package/programs/totems/{globe-changes.ts → globe-changes.js} +59 -79
  87. package/programs/totems/gpu-selection-uniform-block.js +99 -127
  88. package/programs/totems/{index.ts → index.js} +2 -2
  89. package/programs/two-d/pixel-padding-for-compass.js +87 -101
  90. package/programs/util.js +14 -19
  91. package/programs/vectorfields/logics/{constants.ts → constants.js} +4 -5
  92. package/programs/vectorfields/logics/{drawrectangleparticles.ts → drawrectangleparticles.js} +80 -115
  93. package/programs/vectorfields/logics/index.js +2 -4
  94. package/programs/vectorfields/logics/particle-ubo.js +16 -0
  95. package/programs/vectorfields/logics/{pixelbased.ts → pixelbased.js} +86 -115
  96. package/programs/vectorfields/logics/ubo.js +51 -57
  97. package/programs/vectorfields/{pingpongbuffermanager.ts → pingpongbuffermanager.js} +99 -113
  98. package/range-tools-on-terrain/bearing-line/{adapters.ts → adapters.js} +114 -154
  99. package/range-tools-on-terrain/bearing-line/{plugin.ts → plugin.js} +457 -569
  100. package/range-tools-on-terrain/bearing-line/types.js +1 -0
  101. package/range-tools-on-terrain/circle-line-chain/{adapters.ts → adapters.js} +85 -104
  102. package/range-tools-on-terrain/circle-line-chain/{chain-list-map.ts → chain-list-map.js} +382 -446
  103. package/range-tools-on-terrain/circle-line-chain/{plugin.ts → plugin.js} +464 -607
  104. package/range-tools-on-terrain/circle-line-chain/types.js +1 -0
  105. package/range-tools-on-terrain/range-ring/{adapters.ts → adapters.js} +93 -114
  106. package/range-tools-on-terrain/range-ring/{enum.ts → enum.js} +2 -2
  107. package/range-tools-on-terrain/range-ring/{plugin.ts → plugin.js} +377 -444
  108. package/range-tools-on-terrain/range-ring/rangeringangletext.js +331 -0
  109. package/range-tools-on-terrain/range-ring/types.js +9 -0
  110. package/semiplugins/interface.js +1 -0
  111. package/semiplugins/lightweight/{line-plugin.ts → line-plugin.js} +221 -342
  112. package/semiplugins/lightweight/{piece-of-pie-plugin.ts → piece-of-pie-plugin.js} +200 -275
  113. package/semiplugins/shape-on-terrain/{arc-plugin.ts → arc-plugin.js} +481 -616
  114. package/semiplugins/shape-on-terrain/{circle-plugin.ts → circle-plugin.js} +444 -588
  115. package/semiplugins/shape-on-terrain/{padding-1-degree.ts → padding-1-degree.js} +539 -713
  116. package/semiplugins/shape-on-terrain/terrain-polygon/{adapters.ts → adapters.js} +55 -69
  117. package/semiplugins/shape-on-terrain/terrain-polygon/data/{cache.ts → cache.js} +102 -149
  118. package/semiplugins/shape-on-terrain/terrain-polygon/data/{index-polygon-map.ts → index-polygon-map.js} +45 -58
  119. package/semiplugins/shape-on-terrain/terrain-polygon/data/{manager.ts → manager.js} +4 -4
  120. package/semiplugins/shape-on-terrain/terrain-polygon/data/master-worker.js +177 -196
  121. package/semiplugins/shape-on-terrain/terrain-polygon/data/{polygon-to-triangles.ts → polygon-to-triangles.js} +100 -144
  122. package/semiplugins/shape-on-terrain/terrain-polygon/data/{random.ts → random.js} +121 -165
  123. package/semiplugins/shape-on-terrain/terrain-polygon/data/types.js +1 -0
  124. package/semiplugins/shape-on-terrain/terrain-polygon/data/{worker-contact.ts → worker-contact.js} +63 -81
  125. package/semiplugins/shape-on-terrain/terrain-polygon/data/worker.js +125 -146
  126. package/semiplugins/shape-on-terrain/terrain-polygon/{terrain-polygon.ts → terrain-polygon.js} +219 -265
  127. package/semiplugins/shape-on-terrain/terrain-polygon/types.js +8 -0
  128. package/semiplugins/shell/bbox-renderer/index.js +2 -0
  129. package/semiplugins/shell/bbox-renderer/{logic.ts → logic.js} +209 -273
  130. package/semiplugins/shell/bbox-renderer/object.js +75 -0
  131. package/semiplugins/type.js +1 -0
  132. package/semiplugins/utility/{container-plugin.ts → container-plugin.js} +94 -126
  133. package/semiplugins/utility/{object-pass-container-plugin.ts → object-pass-container-plugin.js} +80 -101
  134. package/shaders/fragment-toy/firework.js +1 -1
  135. package/shaders/fragment-toy/singularity.js +2 -5
  136. package/tracks/point-heat-map/adaptors/timetracksplugin-format-to-this.js +63 -78
  137. package/tracks/point-heat-map/index.js +1 -0
  138. package/tracks/point-heat-map/plugin-webworker.js +121 -148
  139. package/tracks/point-heat-map/point-to-heat-map-flow.js +121 -150
  140. package/tracks/point-tracks/key-methods.js +2 -3
  141. package/tracks/point-tracks/plugin.js +401 -487
  142. package/tracks/timetracks/adaptors-line-strip.js +65 -79
  143. package/tracks/timetracks/plugin-line-strip.js +240 -295
  144. package/tracks/timetracks/program-line-strip.js +411 -495
  145. package/tracks/timetracks/programpoint-line-strip.js +109 -137
  146. package/types.js +19 -0
  147. package/util/account/bufferoffsetmanager.js +176 -209
  148. package/util/account/create-buffermap-orchastration.js +39 -0
  149. package/util/account/index.js +3 -6
  150. package/util/account/single-attribute-buffer-management/{buffer-manager.ts → buffer-manager.js} +119 -151
  151. package/util/account/single-attribute-buffer-management/{buffer-orchestrator.ts → buffer-orchestrator.js} +212 -238
  152. package/util/account/single-attribute-buffer-management/{buffer-orchestrator1.ts → buffer-orchestrator1.js} +159 -184
  153. package/util/account/single-attribute-buffer-management/{index.ts → index.js} +4 -11
  154. package/util/account/single-attribute-buffer-management/{object-store.ts → object-store.js} +55 -76
  155. package/util/account/single-attribute-buffer-management/types.js +1 -0
  156. package/util/account/util.js +18 -22
  157. package/util/algorithms/index.js +1 -0
  158. package/util/algorithms/search-binary.js +25 -26
  159. package/util/build-strategy/{static-dynamic.ts → static-dynamic.js} +41 -50
  160. package/util/check/index.js +1 -0
  161. package/util/check/typecheck.js +66 -0
  162. package/util/{frame-counter-trigger.ts → frame-counter-trigger.js} +84 -99
  163. package/util/geometry/{index.ts → index.js} +121 -155
  164. package/util/gl-util/buffer/{attribute-loader.ts → attribute-loader.js} +62 -84
  165. package/util/gl-util/buffer/{index.ts → index.js} +3 -6
  166. package/util/gl-util/draw-options/{methods.ts → methods.js} +32 -47
  167. package/util/gl-util/uniform-block/{manager.ts → manager.js} +200 -232
  168. package/util/{globe-default-gl-states.ts → globe-default-gl-states.js} +4 -5
  169. package/util/{helper-methods.ts → helper-methods.js} +8 -9
  170. package/util/index.js +10 -9
  171. package/util/interpolation/index.js +1 -0
  172. package/util/interpolation/timetrack/index.js +2 -9
  173. package/util/interpolation/timetrack/timetrack-interpolator.js +79 -94
  174. package/util/interpolation/timetrack/web-worker.js +46 -51
  175. package/util/picking/{fence.ts → fence.js} +43 -47
  176. package/util/picking/{picker-displayer.ts → picker-displayer.js} +176 -226
  177. package/util/programs/draw-from-pixel-coords.js +164 -201
  178. package/util/programs/{draw-texture-on-canvas.ts → draw-texture-on-canvas.js} +69 -91
  179. package/util/programs/supersampletotextures.js +97 -130
  180. package/util/programs/texturetoglobe.js +128 -153
  181. package/util/shaderfunctions/{geometrytransformations.ts → geometrytransformations.js} +44 -106
  182. package/util/shaderfunctions/index.js +2 -2
  183. package/util/shaderfunctions/nodata.js +2 -4
  184. package/util/shaderfunctions/noisefunctions.js +7 -10
  185. package/util/{webglobjectbuilders.ts → webglobjectbuilders.js} +358 -446
  186. package/vectorfield/arrowfield/adaptor.js +11 -11
  187. package/vectorfield/arrowfield/index.js +3 -3
  188. package/vectorfield/arrowfield/plugin.js +83 -128
  189. package/vectorfield/waveparticles/adaptor.js +15 -16
  190. package/vectorfield/waveparticles/index.js +3 -3
  191. package/vectorfield/waveparticles/{plugin.ts → plugin.js} +415 -506
  192. package/vectorfield/wind/adapters/{image-to-fields.ts → image-to-fields.js} +61 -74
  193. package/vectorfield/wind/adapters/types.js +1 -0
  194. package/vectorfield/wind/{imagetovectorfieldandmagnitude.ts → imagetovectorfieldandmagnitude.js} +53 -78
  195. package/vectorfield/wind/index.js +5 -5
  196. package/vectorfield/wind/{plugin-persistant copy.ts → plugin-persistant copy.js } +364 -461
  197. package/vectorfield/wind/{plugin-persistant.ts → plugin-persistant.js} +375 -483
  198. package/vectorfield/wind/plugin.js +685 -883
  199. package/vectorfield/wind/vectorfieldimage.js +23 -27
  200. package/write-text/{context-text-bulk.ts → context-text-bulk.js} +200 -285
  201. package/write-text/context-text3.js +167 -0
  202. package/write-text/{context-text4.ts → context-text4.js} +146 -231
  203. package/write-text/context-textDELETE.js +94 -125
  204. package/write-text/objectarraylabels/{index.ts → index.js} +2 -2
  205. package/write-text/objectarraylabels/objectarraylabels.js +200 -247
  206. package/Math/matrix4.ts +0 -0
  207. package/Math/mesh/mapbox-delaunay.d.ts +0 -74
  208. package/Math/roadmap.md +0 -10
  209. package/Math/tessellation/constants.ts +0 -1
  210. package/Math/tessellation/roadmap.md +0 -48
  211. package/Math/tessellation/types.ts +0 -1
  212. package/Math/types.ts +0 -68
  213. package/investigation-tools/draw/tiles/adapters.ts +0 -133
  214. package/programs/line-on-globe/linestrip/data.ts +0 -29
  215. package/programs/polygon-on-globe/roadmap.md +0 -8
  216. package/programs/totems/camera-totem-attactment-interface.ts +0 -4
  217. package/programs/vectorfields/logics/particle-ubo.ts +0 -23
  218. package/publish.bat +0 -62
  219. package/range-tools-on-terrain/bearing-line/types.ts +0 -65
  220. package/range-tools-on-terrain/circle-line-chain/types.ts +0 -43
  221. package/range-tools-on-terrain/range-ring/rangeringangletext.ts +0 -396
  222. package/range-tools-on-terrain/range-ring/types.ts +0 -30
  223. package/semiplugins/interface.ts +0 -14
  224. package/semiplugins/shape-on-terrain/goal.md +0 -12
  225. package/semiplugins/shape-on-terrain/terrain-polygon/data/cache-shortcuts.md +0 -20
  226. package/semiplugins/shape-on-terrain/terrain-polygon/data/master-worker.ts +0 -209
  227. package/semiplugins/shape-on-terrain/terrain-polygon/data/readme.md +0 -5
  228. package/semiplugins/shape-on-terrain/terrain-polygon/data/types.ts +0 -37
  229. package/semiplugins/shape-on-terrain/terrain-polygon/notes.md +0 -90
  230. package/semiplugins/shape-on-terrain/terrain-polygon/types.ts +0 -69
  231. package/semiplugins/shell/bbox-renderer/index.ts +0 -2
  232. package/semiplugins/shell/bbox-renderer/object.ts +0 -129
  233. package/semiplugins/type.ts +0 -8
  234. package/terrain-plugin.mmd +0 -83
  235. package/tests/Math/arc-sampling-test.js +0 -367
  236. package/tests/Math/arc-sampling-test.ts +0 -429
  237. package/tests/Math/arc.test.ts +0 -77
  238. package/tests/Math/junction/arc-limit.test.ts +0 -7
  239. package/tests/Math/junction/arc-plane-points.test.ts +0 -196
  240. package/tests/Math/junction/arc-plane.test.ts +0 -172
  241. package/tests/Math/junction/line-sphere.test.ts +0 -127
  242. package/tests/Math/junction/plane-plane.test.ts +0 -91
  243. package/tests/Math/plane-test.ts +0 -17
  244. package/tests/Math/plane.test.ts +0 -43
  245. package/tests/Math/vec3.test.ts +0 -33
  246. package/tracks/point-heat-map/readme.md +0 -15
  247. package/tracks/timetracks/readme.md +0 -1
  248. package/tsconfig.json +0 -22
  249. package/types/@pirireis/webglobe.d.ts +0 -102
  250. package/types/delaunator.d.ts +0 -40
  251. package/types/earcut.d.ts +0 -11
  252. package/types/rbush.d.ts +0 -57
  253. package/types.ts +0 -319
  254. package/util/account/create-buffermap-orchastration.ts +0 -85
  255. package/util/account/single-attribute-buffer-management/types.ts +0 -43
  256. package/util/check/typecheck.ts +0 -74
  257. package/vectorfield/wind/adapters/types.ts +0 -12
  258. package/write-text/context-text3.ts +0 -252
  259. package/write-text/objectarraylabels/objectarraylabels.d.ts +0 -72
@@ -1,299 +1,254 @@
1
- import { Vec3 } from './types';
2
-
3
- // --- Utility Functions for 3D Vector Operations --- (Assumed to be the same as provided)
4
-
5
- /**
6
- * Normalizes a 3D vector to unit length.
7
- * @param v The input vector.
8
- * @returns The normalized vector. Returns [0,0,0] if the input vector is a zero vector.
9
- */
10
- function vec3Normalize(v: Vec3): Vec3 {
11
- const len = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
12
- if (len < 1e-9) { // Use a small epsilon to handle near-zero vectors
13
- return [0, 0, 0];
14
- }
15
- return [v[0] / len, v[1] / len, v[2] / len];
16
- }
17
-
18
- /**
19
- * Calculates the dot product of two 3D vectors.
20
- * @param v1 The first vector.
21
- * @param v2 The second vector.
22
- * @returns The dot product.
23
- */
24
- function vec3Dot(v1: Vec3, v2: Vec3): number {
25
- return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
26
- }
27
-
28
- /**
29
- * Calculates the cross product of two 3D vectors.
30
- * @param v1 The first vector.
31
- * @param v2 The second vector.
32
- * @returns The cross product vector.
33
- */
34
- function vec3Cross(v1: Vec3, v2: Vec3): Vec3 {
35
- return [
36
- v1[1] * v2[2] - v1[2] * v2[1],
37
- v1[2] * v2[0] - v1[0] * v2[2],
38
- v1[0] * v2[1] - v1[1] * v2[0]
39
- ];
40
- }
41
-
42
- /**
43
- * Scales a 3D vector by a scalar.
44
- * @param v The input vector.
45
- * @param s The scalar value.
46
- * @returns The scaled vector.
47
- */
48
- function vec3Scale(v: Vec3, s: number): Vec3 {
49
- return [v[0] * s, v[1] * s, v[2] * s];
50
- }
51
-
52
- /**
53
- * Adds two 3D vectors.
54
- * @param v1 The first vector.
55
- * @param v2 The second vector.
56
- * @returns The resulting vector.
57
- */
58
- function vec3Add(v1: Vec3, v2: Vec3): Vec3 {
59
- return [v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]];
60
- }
61
-
62
- /**
63
- * Subtracts the second 3D vector from the first.
64
- * @param v1 The first vector.
65
- * @param v2 The second vector.
66
- * @returns The resulting vector.
67
- */
68
- function vec3Sub(v1: Vec3, v2: Vec3): Vec3 {
69
- return [v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]];
70
- }
71
-
72
- /**
73
- * Clamps a numerical value within a specified range.
74
- * @param value The value to clamp.
75
- * @param min The minimum allowed value.
76
- * @param max The maximum allowed value.
77
- * @returns The clamped value.
78
- */
79
- function clamp(value: number, min: number, max: number): number {
80
- return Math.max(min, Math.min(value, max));
81
- }
82
-
83
-
84
- function vec3Distance(v1: Vec3, v2: Vec3): number {
85
- const dx = v1[0] - v2[0];
86
- const dy = v1[1] - v2[1];
87
- const dz = v1[2] - v2[2];
88
- return Math.sqrt(dx * dx + dy * dy + dz * dz);
89
- }
90
-
91
- /**
92
- * Rotates a vector around a given axis by a specified angle using Rodrigues' rotation formula.
93
- * The axis must be a unit vector for correct results.
94
- * @param v The vector to rotate.
95
- * @param axis The unit axis of rotation.
96
- * @param angle The angle of rotation in radians.
97
- * @returns The rotated vector.
98
- */
99
- function rotateVector(v: Vec3, axis: Vec3, angle: number): Vec3 {
100
- const cosAngle = Math.cos(angle);
101
- const sinAngle = Math.sin(angle);
102
- const oneMinusCos = 1.0 - cosAngle;
103
-
104
- const dotAxisV = vec3Dot(axis, v);
105
- const crossAxisV = vec3Cross(axis, v);
106
-
107
- // Rodrigues' rotation formula:
108
- // v' = v * cos(angle) + (axis x v) * sin(angle) + axis * (axis . v) * (1 - cos(angle))
109
- const term1 = vec3Scale(v, cosAngle);
110
- const term2 = vec3Scale(crossAxisV, sinAngle);
111
- const term3 = vec3Scale(axis, dotAxisV * oneMinusCos);
112
-
113
- return vec3Add(vec3Add(term1, term2), term3);
114
- }
115
-
116
- // --- Main Function for Arc Point Generation (CORRECTED) ---
117
-
118
- /**
119
- * Generates points on the shortest arc between p0 and p1 on a unit sphere.
120
- * The arc is formed by rotating p0 around axisA. The density of points
121
- * is higher closer to the attractionPoint, controlled by an exponential falloff.
122
- *
123
- * @param p0 The starting point of the arc (will be normalized).
124
- * @param p1 The ending point of the arc (will be normalized).
125
- * @param axisA The axis of rotation (will be normalized).
126
- * @param attractionPoint The point on the unit sphere that attracts sampled points (will be normalized).
127
- * @param pointCount The total number of points to generate on the arc, including p0 and p1.
128
- * @param attractionStrength Controls the density bias via exponential decay.
129
- * A value of 0 results in uniform sampling.
130
- * Higher positive values (e.g., 10, 50, 200) result in exponentially stronger attraction.
131
- * @returns An array of `Vec3` representing the deterministically sampled points on the arc.
132
- */
133
- export function generateArcPoints(
134
- p0: Vec3,
135
- p1: Vec3,
136
- axisA: Vec3,
137
- attractionPoint: Vec3,
138
- pointCount: number,
139
- attractionStrength: number
140
- ): Vec3[] {
141
- const sampledPoints: Vec3[] = [];
142
- const epsilon = 1e-9;
143
-
144
- // 1. Normalize all input vectors
145
- let nP0 = vec3Normalize(p0);
146
- let nP1 = vec3Normalize(p1);
147
- let nAxisA = vec3Normalize(axisA);
148
- let nAttractionPoint = vec3Normalize(attractionPoint);
149
-
150
- // Handle edge cases for pointCount
151
- if (pointCount < 1) return [];
152
- if (pointCount === 1) return [nP0];
153
-
154
- // 2. Determine the total rotation angle
155
- const p0Projected = vec3Sub(nP0, vec3Scale(nAxisA, vec3Dot(nP0, nAxisA)));
156
- const p1Projected = vec3Sub(nP1, vec3Scale(nAxisA, vec3Dot(nP1, nAxisA)));
157
-
158
- if (vec3Dot(p0Projected, p0Projected) < epsilon * epsilon || vec3Dot(p1Projected, p1Projected) < epsilon * epsilon) {
159
- console.warn("generateArcPoints: p0 or p1 is colinear with axisA. Cannot form a valid arc. Falling back to linear interpolation.");
160
- for (let i = 0; i < pointCount; i++) {
161
- const t = i / (pointCount - 1);
162
- sampledPoints.push(vec3Normalize(vec3Add(vec3Scale(nP0, 1 - t), vec3Scale(nP1, t))));
163
- }
164
- return sampledPoints;
165
- }
166
-
167
- const nP0Projected = vec3Normalize(p0Projected);
168
- const nP1Projected = vec3Normalize(p1Projected);
169
- const crossProj = vec3Cross(nP0Projected, nP1Projected);
170
- const totalRotationAngle = Math.atan2(vec3Dot(crossProj, nAxisA), vec3Dot(nP0Projected, nP1Projected));
171
-
172
- if (Math.abs(totalRotationAngle) < epsilon) {
173
- for (let i = 0; i < pointCount; i++) sampledPoints.push(nP0);
174
- return sampledPoints;
175
- }
176
-
177
- // 3. Find alpha_A: the angle parameter where the arc is closest to the attractionPoint
178
-
179
- const alpha_A = (() => {
180
- const dotProduct = vec3Dot(nP0, nAttractionPoint);
181
- return Math.acos(dotProduct);
182
- })()
183
-
184
- // let alpha_A = 0.0;
185
- // let minAngleToAttraction = Math.PI;
186
- // const testSteps = 1000;
187
- // for (let i = 0; i <= testSteps; i++) {
188
- // const t_test = i / testSteps;
189
- // const currentAlpha = totalRotationAngle * t_test;
190
- // const pArcTest = rotateVector(nP0, nAxisA, currentAlpha);
191
- // const dotProduct = clamp(vec3Dot(pArcTest, nAttractionPoint), -1.0, 1.0);
192
- // const currentAngle = Math.acos(dotProduct);
193
- // if (currentAngle < minAngleToAttraction) {
194
- // minAngleToAttraction = currentAngle;
195
- // alpha_A = currentAlpha;
196
- // }
197
- // }
198
-
199
- // 4. Define the PDF and CDF based on an exponential decay model
200
- const t_peak = totalRotationAngle !== 0 ? clamp(alpha_A / totalRotationAngle, 0, 1) : 0;
201
- const s = Math.max(0, attractionStrength);
202
-
203
- // 5. Generate deterministic points using inverse transform sampling
204
- for (let i = 0; i < pointCount; i++) {
205
- const u = (pointCount === 1) ? 0.5 : i / (pointCount - 1);
206
- let t_sampled: number;
207
-
208
- if (s < epsilon) {
209
- t_sampled = u;
210
- } else {
211
- // Correctly calculate the area under the two parts of the exponential PDF
212
- const area1 = (1 - Math.exp(-s * t_peak));
213
- const area2 = (1 - Math.exp(-s * (1 - t_peak)));
214
- const totalIntegratedArea = (area1 + area2) / s;
215
-
216
- if (totalIntegratedArea < epsilon) {
217
- t_sampled = u; // Fallback for extreme strength values
218
- } else {
219
- const cdfAtPeak = (area1 / s) / totalIntegratedArea;
220
-
221
- if (u <= cdfAtPeak) {
222
- // *** BUG FIX START ***
223
- // Correctly invert the CDF for the first part: [0, t_peak]
224
- const u_prime = u / cdfAtPeak;
225
- t_sampled = t_peak + Math.log(Math.exp(-s * t_peak) + u_prime * (1 - Math.exp(-s * t_peak))) / s;
226
- } else {
227
- // Correctly invert the CDF for the second part: [t_peak, 1]
228
- const u_double_prime = (u - cdfAtPeak) / (1 - cdfAtPeak);
229
- t_sampled = t_peak - Math.log(1 - u_double_prime * (1 - Math.exp(-s * (1 - t_peak)))) / s;
230
- }
231
- // *** BUG FIX END ***
232
- }
233
- }
234
-
235
- t_sampled = clamp(t_sampled, 0, 1);
236
- const actualRotationAngle = totalRotationAngle * t_sampled;
237
- const currentPoint = rotateVector(nP0, nAxisA, actualRotationAngle);
238
- sampledPoints.push(currentPoint);
239
- }
240
-
241
- return sampledPoints;
242
- }
243
-
244
-
245
-
246
-
247
- // // --- Example Usage (for demonstration and testing) ---
248
-
249
- // // Example 1: Basic arc, very strong attraction point in the middle
250
- // const p0_ex1: Vec3 = [1, 0, 0];
251
- // const p1_ex1: Vec3 = [0, 1, 0]; // 90 deg rotation around Z-axis
252
- // const axisA_ex1: Vec3 = [0, 0, 1];
253
- // const attractionPoint_ex1: Vec3 = [Math.sqrt(0.5), Math.sqrt(0.5), 0]; // On the arc, middle of P0-P1
254
- // const numPoints_ex1 = 21;
255
- // const strength_ex1 = 50.0; // Very strong attraction with the new exponential model
256
-
257
- // console.log("--- Example 1: Attraction point in the middle of the arc (Exponentially Strong) ---");
258
- // const points1 = generateArcPoints(p0_ex1, p1_ex1, axisA_ex1, attractionPoint_ex1, numPoints_ex1, strength_ex1);
259
- // console.log(`Generated ${points1.length} points.`);
260
- // // With high strength, points should be extremely clustered around the attraction point.
261
- // const sequentialDistances1 = points1.map((p, i) => {
262
- // if (i === 0) return 0;
263
- // return vec3Distance(points1[i - 1], p);
264
- // });
265
- // console.log("Distances near the start:", sequentialDistances1.slice(1, 5).map(d => d.toFixed(5)));
266
- // console.log("Distances near the middle (attraction point):", sequentialDistances1.slice(9, 13).map(d => d.toFixed(5)));
267
- // console.log("Distances near the end:", sequentialDistances1.slice(-4).map(d => d.toFixed(5)));
268
- // // Expected: Distances near the middle should be MUCH smaller than at the ends.
269
-
270
- // // Example 2: Attraction point near p0, very high strength
271
- // const p0_ex2: Vec3 = [1, 0, 0];
272
- // const p1_ex2: Vec3 = [0, 1, 0];
273
- // const axisA_ex2: Vec3 = [0, 0, 1];
274
- // const attractionPoint_ex2: Vec3 = [0.99, 0.01, 0]; // Very close to P0
275
- // const numPoints_ex2 = 10;
276
- // const strength_ex2 = 100.0; // Extremely strong attraction
277
-
278
- // console.log("\n--- Example 2: Attraction point near the start (p0) ---");
279
- // const points2 = generateArcPoints(p0_ex2, p1_ex2, axisA_ex2, attractionPoint_ex2, numPoints_ex2, strength_ex2);
280
- // console.log(`Generated ${points2.length} points.`);
281
- // console.log("First 5 points (should be very close to each other and p0):", points2.slice(0, 5).map(p => p.map(coord => coord.toFixed(5))));
282
- // console.log("Last 5 points (should be very spread out):", points2.slice(-5).map(p => p.map(coord => coord.toFixed(5))));
283
-
284
-
285
- // // Example 4: No attraction (uniform distribution)
286
- // const p0_ex4: Vec3 = [1, 0, 0];
287
- // const p1_ex4: Vec3 = [0, 1, 0];
288
- // const axisA_ex4: Vec3 = [0, 0, 1];
289
- // const attractionPoint_ex4: Vec3 = [1, 0, 0]; // Irrelevant when strength is 0
290
- // const numPoints_ex4 = 11;
291
- // const strength_ex4 = 0.0; // No attraction (uniform)
292
-
293
- // console.log("\n--- Example 4: Uniform distribution (strength = 0) ---");
294
- // const points4 = generateArcPoints(p0_ex4, p1_ex4, axisA_ex4, attractionPoint_ex4, numPoints_ex4, strength_ex4);
295
- // const sequentialDistances4 = points4.map((p, i) => {
296
- // if (i === 0) return 0;
297
- // return vec3Distance(points4[i - 1], p);
298
- // });
299
- // console.log("Sequential distances (should be almost identical):", sequentialDistances4.slice(1).map(d => d.toFixed(5)));
1
+ // --- Utility Functions for 3D Vector Operations --- (Assumed to be the same as provided)
2
+ /**
3
+ * Normalizes a 3D vector to unit length.
4
+ * @param v The input vector.
5
+ * @returns The normalized vector. Returns [0,0,0] if the input vector is a zero vector.
6
+ */
7
+ function vec3Normalize(v) {
8
+ const len = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
9
+ if (len < 1e-9) { // Use a small epsilon to handle near-zero vectors
10
+ return [0, 0, 0];
11
+ }
12
+ return [v[0] / len, v[1] / len, v[2] / len];
13
+ }
14
+ /**
15
+ * Calculates the dot product of two 3D vectors.
16
+ * @param v1 The first vector.
17
+ * @param v2 The second vector.
18
+ * @returns The dot product.
19
+ */
20
+ function vec3Dot(v1, v2) {
21
+ return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
22
+ }
23
+ /**
24
+ * Calculates the cross product of two 3D vectors.
25
+ * @param v1 The first vector.
26
+ * @param v2 The second vector.
27
+ * @returns The cross product vector.
28
+ */
29
+ function vec3Cross(v1, v2) {
30
+ return [
31
+ v1[1] * v2[2] - v1[2] * v2[1],
32
+ v1[2] * v2[0] - v1[0] * v2[2],
33
+ v1[0] * v2[1] - v1[1] * v2[0]
34
+ ];
35
+ }
36
+ /**
37
+ * Scales a 3D vector by a scalar.
38
+ * @param v The input vector.
39
+ * @param s The scalar value.
40
+ * @returns The scaled vector.
41
+ */
42
+ function vec3Scale(v, s) {
43
+ return [v[0] * s, v[1] * s, v[2] * s];
44
+ }
45
+ /**
46
+ * Adds two 3D vectors.
47
+ * @param v1 The first vector.
48
+ * @param v2 The second vector.
49
+ * @returns The resulting vector.
50
+ */
51
+ function vec3Add(v1, v2) {
52
+ return [v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]];
53
+ }
54
+ /**
55
+ * Subtracts the second 3D vector from the first.
56
+ * @param v1 The first vector.
57
+ * @param v2 The second vector.
58
+ * @returns The resulting vector.
59
+ */
60
+ function vec3Sub(v1, v2) {
61
+ return [v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]];
62
+ }
63
+ /**
64
+ * Clamps a numerical value within a specified range.
65
+ * @param value The value to clamp.
66
+ * @param min The minimum allowed value.
67
+ * @param max The maximum allowed value.
68
+ * @returns The clamped value.
69
+ */
70
+ function clamp(value, min, max) {
71
+ return Math.max(min, Math.min(value, max));
72
+ }
73
+ function vec3Distance(v1, v2) {
74
+ const dx = v1[0] - v2[0];
75
+ const dy = v1[1] - v2[1];
76
+ const dz = v1[2] - v2[2];
77
+ return Math.sqrt(dx * dx + dy * dy + dz * dz);
78
+ }
79
+ /**
80
+ * Rotates a vector around a given axis by a specified angle using Rodrigues' rotation formula.
81
+ * The axis must be a unit vector for correct results.
82
+ * @param v The vector to rotate.
83
+ * @param axis The unit axis of rotation.
84
+ * @param angle The angle of rotation in radians.
85
+ * @returns The rotated vector.
86
+ */
87
+ function rotateVector(v, axis, angle) {
88
+ const cosAngle = Math.cos(angle);
89
+ const sinAngle = Math.sin(angle);
90
+ const oneMinusCos = 1.0 - cosAngle;
91
+ const dotAxisV = vec3Dot(axis, v);
92
+ const crossAxisV = vec3Cross(axis, v);
93
+ // Rodrigues' rotation formula:
94
+ // v' = v * cos(angle) + (axis x v) * sin(angle) + axis * (axis . v) * (1 - cos(angle))
95
+ const term1 = vec3Scale(v, cosAngle);
96
+ const term2 = vec3Scale(crossAxisV, sinAngle);
97
+ const term3 = vec3Scale(axis, dotAxisV * oneMinusCos);
98
+ return vec3Add(vec3Add(term1, term2), term3);
99
+ }
100
+ // --- Main Function for Arc Point Generation (CORRECTED) ---
101
+ /**
102
+ * Generates points on the shortest arc between p0 and p1 on a unit sphere.
103
+ * The arc is formed by rotating p0 around axisA. The density of points
104
+ * is higher closer to the attractionPoint, controlled by an exponential falloff.
105
+ *
106
+ * @param p0 The starting point of the arc (will be normalized).
107
+ * @param p1 The ending point of the arc (will be normalized).
108
+ * @param axisA The axis of rotation (will be normalized).
109
+ * @param attractionPoint The point on the unit sphere that attracts sampled points (will be normalized).
110
+ * @param pointCount The total number of points to generate on the arc, including p0 and p1.
111
+ * @param attractionStrength Controls the density bias via exponential decay.
112
+ * A value of 0 results in uniform sampling.
113
+ * Higher positive values (e.g., 10, 50, 200) result in exponentially stronger attraction.
114
+ * @returns An array of `Vec3` representing the deterministically sampled points on the arc.
115
+ */
116
+ export function generateArcPoints(p0, p1, axisA, attractionPoint, pointCount, attractionStrength) {
117
+ const sampledPoints = [];
118
+ const epsilon = 1e-9;
119
+ // 1. Normalize all input vectors
120
+ let nP0 = vec3Normalize(p0);
121
+ let nP1 = vec3Normalize(p1);
122
+ let nAxisA = vec3Normalize(axisA);
123
+ let nAttractionPoint = vec3Normalize(attractionPoint);
124
+ // Handle edge cases for pointCount
125
+ if (pointCount < 1)
126
+ return [];
127
+ if (pointCount === 1)
128
+ return [nP0];
129
+ // 2. Determine the total rotation angle
130
+ const p0Projected = vec3Sub(nP0, vec3Scale(nAxisA, vec3Dot(nP0, nAxisA)));
131
+ const p1Projected = vec3Sub(nP1, vec3Scale(nAxisA, vec3Dot(nP1, nAxisA)));
132
+ if (vec3Dot(p0Projected, p0Projected) < epsilon * epsilon || vec3Dot(p1Projected, p1Projected) < epsilon * epsilon) {
133
+ console.warn("generateArcPoints: p0 or p1 is colinear with axisA. Cannot form a valid arc. Falling back to linear interpolation.");
134
+ for (let i = 0; i < pointCount; i++) {
135
+ const t = i / (pointCount - 1);
136
+ sampledPoints.push(vec3Normalize(vec3Add(vec3Scale(nP0, 1 - t), vec3Scale(nP1, t))));
137
+ }
138
+ return sampledPoints;
139
+ }
140
+ const nP0Projected = vec3Normalize(p0Projected);
141
+ const nP1Projected = vec3Normalize(p1Projected);
142
+ const crossProj = vec3Cross(nP0Projected, nP1Projected);
143
+ const totalRotationAngle = Math.atan2(vec3Dot(crossProj, nAxisA), vec3Dot(nP0Projected, nP1Projected));
144
+ if (Math.abs(totalRotationAngle) < epsilon) {
145
+ for (let i = 0; i < pointCount; i++)
146
+ sampledPoints.push(nP0);
147
+ return sampledPoints;
148
+ }
149
+ // 3. Find alpha_A: the angle parameter where the arc is closest to the attractionPoint
150
+ const alpha_A = (() => {
151
+ const dotProduct = vec3Dot(nP0, nAttractionPoint);
152
+ return Math.acos(dotProduct);
153
+ })();
154
+ // let alpha_A = 0.0;
155
+ // let minAngleToAttraction = Math.PI;
156
+ // const testSteps = 1000;
157
+ // for (let i = 0; i <= testSteps; i++) {
158
+ // const t_test = i / testSteps;
159
+ // const currentAlpha = totalRotationAngle * t_test;
160
+ // const pArcTest = rotateVector(nP0, nAxisA, currentAlpha);
161
+ // const dotProduct = clamp(vec3Dot(pArcTest, nAttractionPoint), -1.0, 1.0);
162
+ // const currentAngle = Math.acos(dotProduct);
163
+ // if (currentAngle < minAngleToAttraction) {
164
+ // minAngleToAttraction = currentAngle;
165
+ // alpha_A = currentAlpha;
166
+ // }
167
+ // }
168
+ // 4. Define the PDF and CDF based on an exponential decay model
169
+ const t_peak = totalRotationAngle !== 0 ? clamp(alpha_A / totalRotationAngle, 0, 1) : 0;
170
+ const s = Math.max(0, attractionStrength);
171
+ // 5. Generate deterministic points using inverse transform sampling
172
+ for (let i = 0; i < pointCount; i++) {
173
+ const u = (pointCount === 1) ? 0.5 : i / (pointCount - 1);
174
+ let t_sampled;
175
+ if (s < epsilon) {
176
+ t_sampled = u;
177
+ }
178
+ else {
179
+ // Correctly calculate the area under the two parts of the exponential PDF
180
+ const area1 = (1 - Math.exp(-s * t_peak));
181
+ const area2 = (1 - Math.exp(-s * (1 - t_peak)));
182
+ const totalIntegratedArea = (area1 + area2) / s;
183
+ if (totalIntegratedArea < epsilon) {
184
+ t_sampled = u; // Fallback for extreme strength values
185
+ }
186
+ else {
187
+ const cdfAtPeak = (area1 / s) / totalIntegratedArea;
188
+ if (u <= cdfAtPeak) {
189
+ // *** BUG FIX START ***
190
+ // Correctly invert the CDF for the first part: [0, t_peak]
191
+ const u_prime = u / cdfAtPeak;
192
+ t_sampled = t_peak + Math.log(Math.exp(-s * t_peak) + u_prime * (1 - Math.exp(-s * t_peak))) / s;
193
+ }
194
+ else {
195
+ // Correctly invert the CDF for the second part: [t_peak, 1]
196
+ const u_double_prime = (u - cdfAtPeak) / (1 - cdfAtPeak);
197
+ t_sampled = t_peak - Math.log(1 - u_double_prime * (1 - Math.exp(-s * (1 - t_peak)))) / s;
198
+ }
199
+ // *** BUG FIX END ***
200
+ }
201
+ }
202
+ t_sampled = clamp(t_sampled, 0, 1);
203
+ const actualRotationAngle = totalRotationAngle * t_sampled;
204
+ const currentPoint = rotateVector(nP0, nAxisA, actualRotationAngle);
205
+ sampledPoints.push(currentPoint);
206
+ }
207
+ return sampledPoints;
208
+ }
209
+ // // --- Example Usage (for demonstration and testing) ---
210
+ // // Example 1: Basic arc, very strong attraction point in the middle
211
+ // const p0_ex1: Vec3 = [1, 0, 0];
212
+ // const p1_ex1: Vec3 = [0, 1, 0]; // 90 deg rotation around Z-axis
213
+ // const axisA_ex1: Vec3 = [0, 0, 1];
214
+ // const attractionPoint_ex1: Vec3 = [Math.sqrt(0.5), Math.sqrt(0.5), 0]; // On the arc, middle of P0-P1
215
+ // const numPoints_ex1 = 21;
216
+ // const strength_ex1 = 50.0; // Very strong attraction with the new exponential model
217
+ // console.log("--- Example 1: Attraction point in the middle of the arc (Exponentially Strong) ---");
218
+ // const points1 = generateArcPoints(p0_ex1, p1_ex1, axisA_ex1, attractionPoint_ex1, numPoints_ex1, strength_ex1);
219
+ // console.log(`Generated ${points1.length} points.`);
220
+ // // With high strength, points should be extremely clustered around the attraction point.
221
+ // const sequentialDistances1 = points1.map((p, i) => {
222
+ // if (i === 0) return 0;
223
+ // return vec3Distance(points1[i - 1], p);
224
+ // });
225
+ // console.log("Distances near the start:", sequentialDistances1.slice(1, 5).map(d => d.toFixed(5)));
226
+ // console.log("Distances near the middle (attraction point):", sequentialDistances1.slice(9, 13).map(d => d.toFixed(5)));
227
+ // console.log("Distances near the end:", sequentialDistances1.slice(-4).map(d => d.toFixed(5)));
228
+ // // Expected: Distances near the middle should be MUCH smaller than at the ends.
229
+ // // Example 2: Attraction point near p0, very high strength
230
+ // const p0_ex2: Vec3 = [1, 0, 0];
231
+ // const p1_ex2: Vec3 = [0, 1, 0];
232
+ // const axisA_ex2: Vec3 = [0, 0, 1];
233
+ // const attractionPoint_ex2: Vec3 = [0.99, 0.01, 0]; // Very close to P0
234
+ // const numPoints_ex2 = 10;
235
+ // const strength_ex2 = 100.0; // Extremely strong attraction
236
+ // console.log("\n--- Example 2: Attraction point near the start (p0) ---");
237
+ // const points2 = generateArcPoints(p0_ex2, p1_ex2, axisA_ex2, attractionPoint_ex2, numPoints_ex2, strength_ex2);
238
+ // console.log(`Generated ${points2.length} points.`);
239
+ // console.log("First 5 points (should be very close to each other and p0):", points2.slice(0, 5).map(p => p.map(coord => coord.toFixed(5))));
240
+ // console.log("Last 5 points (should be very spread out):", points2.slice(-5).map(p => p.map(coord => coord.toFixed(5))));
241
+ // // Example 4: No attraction (uniform distribution)
242
+ // const p0_ex4: Vec3 = [1, 0, 0];
243
+ // const p1_ex4: Vec3 = [0, 1, 0];
244
+ // const axisA_ex4: Vec3 = [0, 0, 1];
245
+ // const attractionPoint_ex4: Vec3 = [1, 0, 0]; // Irrelevant when strength is 0
246
+ // const numPoints_ex4 = 11;
247
+ // const strength_ex4 = 0.0; // No attraction (uniform)
248
+ // console.log("\n--- Example 4: Uniform distribution (strength = 0) ---");
249
+ // const points4 = generateArcPoints(p0_ex4, p1_ex4, axisA_ex4, attractionPoint_ex4, numPoints_ex4, strength_ex4);
250
+ // const sequentialDistances4 = points4.map((p, i) => {
251
+ // if (i === 0) return 0;
252
+ // return vec3Distance(points4[i - 1], p);
253
+ // });
254
+ // console.log("Sequential distances (should be almost identical):", sequentialDistances4.slice(1).map(d => d.toFixed(5)));