worldorbit 2.6.0 → 3.0.0

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 (196) hide show
  1. package/README.md +12 -5
  2. package/dist/browser/core/dist/atlas-edit.d.ts +11 -0
  3. package/dist/browser/core/dist/atlas-edit.js +347 -0
  4. package/dist/browser/core/dist/atlas-utils.d.ts +22 -0
  5. package/dist/browser/core/dist/atlas-utils.js +189 -0
  6. package/dist/browser/core/dist/atlas-validate.d.ts +2 -0
  7. package/dist/browser/core/dist/atlas-validate.js +488 -0
  8. package/dist/browser/core/dist/diagnostics.d.ts +10 -0
  9. package/dist/browser/core/dist/diagnostics.js +109 -0
  10. package/dist/browser/core/dist/draft-parse.d.ts +3 -0
  11. package/dist/browser/core/dist/draft-parse.js +1654 -0
  12. package/dist/browser/core/dist/draft.d.ts +21 -0
  13. package/dist/browser/core/dist/draft.js +482 -0
  14. package/dist/browser/core/dist/errors.d.ts +7 -0
  15. package/dist/browser/core/dist/errors.js +16 -0
  16. package/dist/browser/core/dist/format.d.ts +4 -0
  17. package/dist/browser/core/dist/format.js +613 -0
  18. package/dist/browser/core/dist/index.d.ts +29 -0
  19. package/dist/browser/core/dist/index.js +35 -6542
  20. package/dist/browser/core/dist/load.d.ts +4 -0
  21. package/dist/browser/core/dist/load.js +182 -0
  22. package/dist/browser/core/dist/markdown.d.ts +2 -0
  23. package/dist/browser/core/dist/markdown.js +37 -0
  24. package/dist/browser/core/dist/normalize.d.ts +2 -0
  25. package/dist/browser/core/dist/normalize.js +312 -0
  26. package/dist/browser/core/dist/parse.d.ts +2 -0
  27. package/dist/browser/core/dist/parse.js +133 -0
  28. package/dist/browser/core/dist/scene.d.ts +3 -0
  29. package/dist/browser/core/dist/scene.js +1901 -0
  30. package/dist/browser/core/dist/schema.d.ts +8 -0
  31. package/dist/browser/core/dist/schema.js +298 -0
  32. package/dist/browser/core/dist/spatial-scene.d.ts +3 -0
  33. package/dist/browser/core/dist/spatial-scene.js +420 -0
  34. package/dist/browser/core/dist/tokenize.d.ts +4 -0
  35. package/dist/browser/core/dist/tokenize.js +68 -0
  36. package/dist/browser/core/dist/types.d.ts +637 -0
  37. package/dist/browser/core/dist/types.js +1 -0
  38. package/dist/browser/core/dist/validate.d.ts +2 -0
  39. package/dist/browser/core/dist/validate.js +56 -0
  40. package/dist/browser/editor/dist/editor.d.ts +2 -0
  41. package/dist/browser/editor/dist/editor.js +3700 -0
  42. package/dist/browser/editor/dist/index.d.ts +2 -0
  43. package/dist/browser/editor/dist/index.js +1 -12250
  44. package/dist/browser/editor/dist/types.d.ts +59 -0
  45. package/dist/browser/editor/dist/types.js +1 -0
  46. package/dist/browser/markdown/dist/html.d.ts +3 -0
  47. package/dist/browser/markdown/dist/html.js +64 -0
  48. package/dist/browser/markdown/dist/index.d.ts +4 -0
  49. package/dist/browser/markdown/dist/index.js +3 -6179
  50. package/dist/browser/markdown/dist/rehype.d.ts +10 -0
  51. package/dist/browser/markdown/dist/rehype.js +49 -0
  52. package/dist/browser/markdown/dist/remark.d.ts +9 -0
  53. package/dist/browser/markdown/dist/remark.js +28 -0
  54. package/dist/browser/markdown/dist/types.d.ts +11 -0
  55. package/dist/browser/markdown/dist/types.js +1 -0
  56. package/dist/browser/viewer/dist/atlas-state.d.ts +12 -0
  57. package/dist/browser/viewer/dist/atlas-state.js +269 -0
  58. package/dist/browser/viewer/dist/atlas-viewer.d.ts +2 -0
  59. package/dist/browser/viewer/dist/atlas-viewer.js +495 -0
  60. package/dist/browser/viewer/dist/custom-element.d.ts +1 -0
  61. package/dist/browser/viewer/dist/custom-element.js +78 -0
  62. package/dist/browser/viewer/dist/embed.d.ts +24 -0
  63. package/dist/browser/viewer/dist/embed.js +172 -0
  64. package/dist/browser/viewer/dist/errors.d.ts +6 -0
  65. package/dist/browser/viewer/dist/errors.js +12 -0
  66. package/dist/browser/viewer/dist/index.d.ts +10 -0
  67. package/dist/browser/viewer/dist/index.js +9 -8334
  68. package/dist/browser/viewer/dist/minimap.d.ts +3 -0
  69. package/dist/browser/viewer/dist/minimap.js +63 -0
  70. package/dist/browser/viewer/dist/render.d.ts +6 -0
  71. package/dist/browser/viewer/dist/render.js +670 -0
  72. package/dist/browser/viewer/dist/runtime-3d.d.ts +19 -0
  73. package/dist/browser/viewer/dist/runtime-3d.js +494 -0
  74. package/dist/browser/viewer/dist/theme.d.ts +4 -0
  75. package/dist/browser/viewer/dist/theme.js +103 -0
  76. package/dist/browser/viewer/dist/tooltip.d.ts +3 -0
  77. package/dist/browser/viewer/dist/tooltip.js +198 -0
  78. package/dist/browser/viewer/dist/types.d.ts +292 -0
  79. package/dist/browser/viewer/dist/types.js +1 -0
  80. package/dist/browser/viewer/dist/vendor/three.module.js +53032 -0
  81. package/dist/browser/viewer/dist/viewer-state.d.ts +19 -0
  82. package/dist/browser/viewer/dist/viewer-state.js +162 -0
  83. package/dist/browser/viewer/dist/viewer.d.ts +2 -0
  84. package/dist/browser/viewer/dist/viewer.js +1662 -0
  85. package/dist/unpkg/core/dist/atlas-edit.d.ts +11 -0
  86. package/dist/unpkg/core/dist/atlas-edit.js +347 -0
  87. package/dist/unpkg/core/dist/atlas-utils.d.ts +22 -0
  88. package/dist/unpkg/core/dist/atlas-utils.js +189 -0
  89. package/dist/unpkg/core/dist/atlas-validate.d.ts +2 -0
  90. package/dist/unpkg/core/dist/atlas-validate.js +488 -0
  91. package/dist/unpkg/core/dist/diagnostics.d.ts +10 -0
  92. package/dist/unpkg/core/dist/diagnostics.js +109 -0
  93. package/dist/unpkg/core/dist/draft-parse.d.ts +3 -0
  94. package/dist/unpkg/core/dist/draft-parse.js +1654 -0
  95. package/dist/unpkg/core/dist/draft.d.ts +21 -0
  96. package/dist/unpkg/core/dist/draft.js +482 -0
  97. package/dist/unpkg/core/dist/errors.d.ts +7 -0
  98. package/dist/unpkg/core/dist/errors.js +16 -0
  99. package/dist/unpkg/core/dist/format.d.ts +4 -0
  100. package/dist/unpkg/core/dist/format.js +613 -0
  101. package/dist/unpkg/core/dist/index.d.ts +29 -0
  102. package/dist/unpkg/core/dist/index.js +35 -6614
  103. package/dist/unpkg/core/dist/load.d.ts +4 -0
  104. package/dist/unpkg/core/dist/load.js +182 -0
  105. package/dist/unpkg/core/dist/markdown.d.ts +2 -0
  106. package/dist/unpkg/core/dist/markdown.js +37 -0
  107. package/dist/unpkg/core/dist/normalize.d.ts +2 -0
  108. package/dist/unpkg/core/dist/normalize.js +312 -0
  109. package/dist/unpkg/core/dist/parse.d.ts +2 -0
  110. package/dist/unpkg/core/dist/parse.js +133 -0
  111. package/dist/unpkg/core/dist/scene.d.ts +3 -0
  112. package/dist/unpkg/core/dist/scene.js +1901 -0
  113. package/dist/unpkg/core/dist/schema.d.ts +8 -0
  114. package/dist/unpkg/core/dist/schema.js +298 -0
  115. package/dist/unpkg/core/dist/spatial-scene.d.ts +3 -0
  116. package/dist/unpkg/core/dist/spatial-scene.js +420 -0
  117. package/dist/unpkg/core/dist/tokenize.d.ts +4 -0
  118. package/dist/unpkg/core/dist/tokenize.js +68 -0
  119. package/dist/unpkg/core/dist/types.d.ts +637 -0
  120. package/dist/unpkg/core/dist/types.js +1 -0
  121. package/dist/unpkg/core/dist/validate.d.ts +2 -0
  122. package/dist/unpkg/core/dist/validate.js +56 -0
  123. package/dist/unpkg/editor/dist/editor.d.ts +2 -0
  124. package/dist/unpkg/editor/dist/editor.js +3700 -0
  125. package/dist/unpkg/editor/dist/index.d.ts +2 -0
  126. package/dist/unpkg/editor/dist/index.js +1 -12275
  127. package/dist/unpkg/editor/dist/types.d.ts +59 -0
  128. package/dist/unpkg/editor/dist/types.js +1 -0
  129. package/dist/unpkg/markdown/dist/html.d.ts +3 -0
  130. package/dist/unpkg/markdown/dist/html.js +64 -0
  131. package/dist/unpkg/markdown/dist/index.d.ts +4 -0
  132. package/dist/unpkg/markdown/dist/index.js +3 -6207
  133. package/dist/unpkg/markdown/dist/rehype.d.ts +10 -0
  134. package/dist/unpkg/markdown/dist/rehype.js +49 -0
  135. package/dist/unpkg/markdown/dist/remark.d.ts +9 -0
  136. package/dist/unpkg/markdown/dist/remark.js +28 -0
  137. package/dist/unpkg/markdown/dist/types.d.ts +11 -0
  138. package/dist/unpkg/markdown/dist/types.js +1 -0
  139. package/dist/unpkg/viewer/dist/atlas-state.d.ts +12 -0
  140. package/dist/unpkg/viewer/dist/atlas-state.js +269 -0
  141. package/dist/unpkg/viewer/dist/atlas-viewer.d.ts +2 -0
  142. package/dist/unpkg/viewer/dist/atlas-viewer.js +495 -0
  143. package/dist/unpkg/viewer/dist/custom-element.d.ts +1 -0
  144. package/dist/unpkg/viewer/dist/custom-element.js +78 -0
  145. package/dist/unpkg/viewer/dist/embed.d.ts +24 -0
  146. package/dist/unpkg/viewer/dist/embed.js +172 -0
  147. package/dist/unpkg/viewer/dist/errors.d.ts +6 -0
  148. package/dist/unpkg/viewer/dist/errors.js +12 -0
  149. package/dist/unpkg/viewer/dist/index.d.ts +10 -0
  150. package/dist/unpkg/viewer/dist/index.js +9 -8391
  151. package/dist/unpkg/viewer/dist/minimap.d.ts +3 -0
  152. package/dist/unpkg/viewer/dist/minimap.js +63 -0
  153. package/dist/unpkg/viewer/dist/render.d.ts +6 -0
  154. package/dist/unpkg/viewer/dist/render.js +670 -0
  155. package/dist/unpkg/viewer/dist/runtime-3d.d.ts +19 -0
  156. package/dist/unpkg/viewer/dist/runtime-3d.js +494 -0
  157. package/dist/unpkg/viewer/dist/theme.d.ts +4 -0
  158. package/dist/unpkg/viewer/dist/theme.js +103 -0
  159. package/dist/unpkg/viewer/dist/tooltip.d.ts +3 -0
  160. package/dist/unpkg/viewer/dist/tooltip.js +198 -0
  161. package/dist/unpkg/viewer/dist/types.d.ts +292 -0
  162. package/dist/unpkg/viewer/dist/types.js +1 -0
  163. package/dist/unpkg/viewer/dist/vendor/three.module.js +53032 -0
  164. package/dist/unpkg/viewer/dist/viewer-state.d.ts +19 -0
  165. package/dist/unpkg/viewer/dist/viewer-state.js +162 -0
  166. package/dist/unpkg/viewer/dist/viewer.d.ts +2 -0
  167. package/dist/unpkg/viewer/dist/viewer.js +1662 -0
  168. package/dist/unpkg/worldorbit-core.min.js +1 -12
  169. package/dist/unpkg/worldorbit-editor.min.js +1 -904
  170. package/dist/unpkg/worldorbit-markdown.min.js +1 -103
  171. package/dist/unpkg/worldorbit-viewer.min.js +1 -259
  172. package/dist/unpkg/worldorbit.js +2 -9704
  173. package/dist/unpkg/worldorbit.min.js +2 -263
  174. package/package.json +1 -1
  175. package/packages/core/dist/index.d.ts +1 -0
  176. package/packages/core/dist/index.js +1 -0
  177. package/packages/core/dist/spatial-scene.d.ts +3 -0
  178. package/packages/core/dist/spatial-scene.js +420 -0
  179. package/packages/core/dist/types.d.ts +105 -0
  180. package/packages/editor/dist/editor.js +25 -4
  181. package/packages/editor/dist/types.d.ts +4 -0
  182. package/packages/markdown/dist/html.js +10 -3
  183. package/packages/viewer/dist/atlas-state.js +3 -0
  184. package/packages/viewer/dist/atlas-viewer.js +1 -0
  185. package/packages/viewer/dist/custom-element.js +18 -4
  186. package/packages/viewer/dist/embed.d.ts +5 -1
  187. package/packages/viewer/dist/embed.js +58 -24
  188. package/packages/viewer/dist/errors.d.ts +6 -0
  189. package/packages/viewer/dist/errors.js +12 -0
  190. package/packages/viewer/dist/index.d.ts +1 -0
  191. package/packages/viewer/dist/index.js +1 -0
  192. package/packages/viewer/dist/runtime-3d.d.ts +19 -0
  193. package/packages/viewer/dist/runtime-3d.js +494 -0
  194. package/packages/viewer/dist/types.d.ts +21 -2
  195. package/packages/viewer/dist/vendor/three.module.js +53032 -0
  196. package/packages/viewer/dist/viewer.js +501 -41
@@ -0,0 +1,420 @@
1
+ import { renderDocumentToScene } from "./scene.js";
2
+ const DAY_IN_SECONDS = 86_400;
3
+ const YEAR_IN_SECONDS = DAY_IN_SECONDS * 365.25;
4
+ const FASTEST_VISIBLE_ORBIT_SECONDS = 18;
5
+ const SLOWEST_VISIBLE_ORBIT_SECONDS = 180;
6
+ export function renderDocumentToSpatialScene(document, options = {}) {
7
+ const renderOptions = {
8
+ width: options.width,
9
+ height: options.height,
10
+ padding: options.padding,
11
+ preset: options.preset,
12
+ projection: options.projection,
13
+ camera: options.camera,
14
+ scaleModel: options.scaleModel,
15
+ activeEventId: options.activeEventId,
16
+ };
17
+ const scene = renderDocumentToScene(document, renderOptions);
18
+ const scaleModel = resolveSpatialScaleModel(scene.layoutPreset, options.spatialScaleModel);
19
+ const sceneCenter = {
20
+ x: scene.contentBounds.centerX,
21
+ y: scene.contentBounds.centerY,
22
+ };
23
+ const objectMap = new Map(scene.objects.map((object) => [object.objectId, object]));
24
+ const orbitMap = new Map(scene.orbitVisuals.map((orbit) => [orbit.objectId, orbit]));
25
+ const rawMotionMetrics = new Map();
26
+ for (const object of scene.objects) {
27
+ const placement = object.object.placement;
28
+ if (!placement || placement.mode !== "orbit") {
29
+ continue;
30
+ }
31
+ rawMotionMetrics.set(object.objectId, resolveRawOrbitMetric(placement));
32
+ }
33
+ const minimumMotionMetric = Math.min(...[...rawMotionMetrics.values()].filter((value) => Number.isFinite(value) && value > 0)) || 1;
34
+ const positionCache = new Map();
35
+ const spatialObjects = scene.objects.map((entry) => createSpatialObject(entry, scene, sceneCenter, objectMap, orbitMap, scaleModel, positionCache, minimumMotionMetric));
36
+ const spatialObjectMap = new Map(spatialObjects.map((object) => [object.objectId, object]));
37
+ const spatialOrbits = scene.orbitVisuals.map((orbit) => createSpatialOrbit(orbit, spatialObjectMap, minimumMotionMetric, scene.activeEventId !== null));
38
+ const focusTargets = spatialObjects.map((object) => ({
39
+ objectId: object.objectId,
40
+ center: { ...object.position },
41
+ radius: object.visualRadius + scaleModel.focusPadding,
42
+ }));
43
+ return {
44
+ width: scene.width,
45
+ height: scene.height,
46
+ padding: scene.padding,
47
+ renderPreset: scene.renderPreset,
48
+ projection: scene.projection,
49
+ camera: scene.camera,
50
+ scaleModel,
51
+ title: scene.title,
52
+ subtitle: scene.subtitle,
53
+ systemId: scene.systemId,
54
+ viewMode: "3d",
55
+ layoutPreset: scene.layoutPreset,
56
+ metadata: {
57
+ ...scene.metadata,
58
+ "viewer.mode": "3d",
59
+ },
60
+ contentBounds: calculateSpatialBounds(spatialObjects),
61
+ semanticGroups: scene.semanticGroups,
62
+ viewpoints: scene.viewpoints,
63
+ activeEventId: scene.activeEventId,
64
+ timeFrozen: scene.activeEventId !== null,
65
+ objects: spatialObjects,
66
+ orbits: spatialOrbits,
67
+ focusTargets,
68
+ };
69
+ }
70
+ function createSpatialObject(entry, scene, sceneCenter, objectMap, orbitMap, scaleModel, positionCache, minimumMotionMetric) {
71
+ const position = resolveSpatialObjectPosition(entry, scene, sceneCenter, objectMap, orbitMap, positionCache);
72
+ const motion = createMotionModel(entry.object, orbitMap.get(entry.objectId), minimumMotionMetric, scene.activeEventId !== null);
73
+ return {
74
+ objectId: entry.objectId,
75
+ object: entry.object,
76
+ parentId: entry.parentId,
77
+ ancestorIds: entry.ancestorIds.slice(),
78
+ childIds: entry.childIds.slice(),
79
+ groupId: entry.groupId,
80
+ semanticGroupIds: entry.semanticGroupIds.slice(),
81
+ position,
82
+ radius: clampNumber(entry.radius * scaleModel.bodyRadiusMultiplier, scaleModel.minBodyRadius, scaleModel.maxBodyRadius),
83
+ visualRadius: clampNumber(entry.visualRadius * scaleModel.bodyRadiusMultiplier, scaleModel.minBodyRadius, scaleModel.maxBodyRadius + 24),
84
+ label: entry.label,
85
+ secondaryLabel: entry.secondaryLabel,
86
+ fillColor: entry.fillColor,
87
+ imageHref: entry.imageHref,
88
+ hidden: entry.hidden,
89
+ motion,
90
+ };
91
+ }
92
+ function createSpatialOrbit(orbit, objectMap, minimumMotionMetric, frozen) {
93
+ const owner = objectMap.get(orbit.objectId);
94
+ const parent = objectMap.get(orbit.parentId);
95
+ return {
96
+ objectId: orbit.objectId,
97
+ object: orbit.object,
98
+ parentId: orbit.parentId,
99
+ groupId: orbit.groupId,
100
+ semanticGroupIds: orbit.semanticGroupIds.slice(),
101
+ center: parent?.position ?? { x: 0, y: 0, z: 0 },
102
+ kind: orbit.kind,
103
+ radius: orbit.radius,
104
+ semiMajor: orbit.radius ?? orbit.rx ?? 0,
105
+ semiMinor: orbit.radius ?? orbit.ry ?? 0,
106
+ rotationDeg: orbit.rotationDeg,
107
+ inclinationDeg: owner?.motion?.inclinationDeg ??
108
+ unitValueToDegrees(orbit.object.placement?.mode === "orbit"
109
+ ? orbit.object.placement.inclination
110
+ : undefined) ??
111
+ 0,
112
+ band: orbit.band,
113
+ bandThickness: orbit.bandThickness,
114
+ hidden: orbit.hidden,
115
+ motion: owner?.motion ??
116
+ createMotionModel(orbit.object, orbit, minimumMotionMetric, frozen),
117
+ };
118
+ }
119
+ function resolveSpatialObjectPosition(entry, scene, sceneCenter, objectMap, orbitMap, cache) {
120
+ const cached = cache.get(entry.objectId);
121
+ if (cached) {
122
+ return cached;
123
+ }
124
+ const placement = entry.object.placement;
125
+ let position;
126
+ if (placement?.mode === "orbit" && entry.parentId) {
127
+ const parent = objectMap.get(entry.parentId);
128
+ const parentPosition = parent
129
+ ? resolveSpatialObjectPosition(parent, scene, sceneCenter, objectMap, orbitMap, cache)
130
+ : { x: 0, y: 0, z: 0 };
131
+ const orbit = orbitMap.get(entry.objectId);
132
+ const motion = createMotionModel(entry.object, orbit, 1, scene.activeEventId !== null);
133
+ const local = motion
134
+ ? computeOrbitPosition(motion, 0)
135
+ : {
136
+ x: (entry.x - sceneCenter.x) * 0.8,
137
+ y: 0,
138
+ z: (entry.y - sceneCenter.y) * 0.8,
139
+ };
140
+ position = addPoint3D(parentPosition, local);
141
+ }
142
+ else if (placement?.mode === "surface" && entry.parentId) {
143
+ const parent = objectMap.get(entry.parentId);
144
+ const parentPosition = parent
145
+ ? resolveSpatialObjectPosition(parent, scene, sceneCenter, objectMap, orbitMap, cache)
146
+ : { x: 0, y: 0, z: 0 };
147
+ const parentRadius = parent?.visualRadius ?? 16;
148
+ const seed = hashUnit(entry.objectId);
149
+ const angle = seed * Math.PI * 2;
150
+ position = {
151
+ x: parentPosition.x + Math.cos(angle) * (parentRadius + entry.visualRadius * 0.9),
152
+ y: parentPosition.y + Math.sin(seed * Math.PI) * Math.max(entry.visualRadius * 0.2, 2),
153
+ z: parentPosition.z + Math.sin(angle) * (parentRadius + entry.visualRadius * 0.9),
154
+ };
155
+ }
156
+ else if (placement?.mode === "at" && entry.parentId) {
157
+ const parent = objectMap.get(entry.parentId);
158
+ const parentPosition = parent
159
+ ? resolveSpatialObjectPosition(parent, scene, sceneCenter, objectMap, orbitMap, cache)
160
+ : { x: 0, y: 0, z: 0 };
161
+ const anchorX = entry.anchorX ?? parent?.x ?? sceneCenter.x;
162
+ const anchorY = entry.anchorY ?? parent?.y ?? sceneCenter.y;
163
+ position = {
164
+ x: parentPosition.x + (entry.x - anchorX),
165
+ y: parentPosition.y,
166
+ z: parentPosition.z + (entry.y - anchorY),
167
+ };
168
+ }
169
+ else {
170
+ position = {
171
+ x: (entry.x - sceneCenter.x) * 0.8,
172
+ y: 0,
173
+ z: (entry.y - sceneCenter.y) * 0.8,
174
+ };
175
+ }
176
+ cache.set(entry.objectId, position);
177
+ return position;
178
+ }
179
+ export function evaluateSpatialSceneAtTime(scene, timeSeconds) {
180
+ const objectMap = new Map(scene.objects.map((object) => [object.objectId, object]));
181
+ const cache = new Map();
182
+ const resolvePosition = (objectId) => {
183
+ const cached = cache.get(objectId);
184
+ if (cached) {
185
+ return cached;
186
+ }
187
+ const object = objectMap.get(objectId);
188
+ if (!object) {
189
+ return { x: 0, y: 0, z: 0 };
190
+ }
191
+ let next = { ...object.position };
192
+ if (object.motion && object.parentId) {
193
+ const parentPosition = resolvePosition(object.parentId);
194
+ const local = computeOrbitPosition(object.motion, scene.timeFrozen ? 0 : timeSeconds);
195
+ next = addPoint3D(parentPosition, local);
196
+ }
197
+ cache.set(objectId, next);
198
+ return next;
199
+ };
200
+ for (const object of scene.objects) {
201
+ resolvePosition(object.objectId);
202
+ }
203
+ return cache;
204
+ }
205
+ function computeOrbitPosition(motion, timeSeconds) {
206
+ const angleDeg = motion.phase0Deg + motion.angularVelocityDegPerSecond * timeSeconds;
207
+ const angle = degreesToRadians(angleDeg);
208
+ const rotation = degreesToRadians(motion.rotationDeg);
209
+ const inclination = degreesToRadians(motion.inclinationDeg);
210
+ const localX = Math.cos(angle) * motion.semiMajor;
211
+ const localZ = Math.sin(angle) * motion.semiMinor;
212
+ const rotatedX = localX * Math.cos(rotation) - localZ * Math.sin(rotation);
213
+ const rotatedZ = localX * Math.sin(rotation) + localZ * Math.cos(rotation);
214
+ return {
215
+ x: rotatedX,
216
+ y: rotatedZ * Math.sin(inclination),
217
+ z: rotatedZ * Math.cos(inclination),
218
+ };
219
+ }
220
+ function createMotionModel(object, orbit, minimumMotionMetric, frozen) {
221
+ const placement = object.placement;
222
+ if (!placement || placement.mode !== "orbit") {
223
+ return null;
224
+ }
225
+ const semiMajor = orbit?.radius ??
226
+ orbit?.rx ??
227
+ clampNumber(resolveRawOrbitMetric(placement) * 48, 24, 1_200);
228
+ const semiMinor = orbit?.radius ?? orbit?.ry ?? semiMajor;
229
+ const periodSeconds = unitValueToDurationSeconds(placement.period);
230
+ const rawMetric = resolveRawOrbitMetric(placement);
231
+ const ratio = clampNumber(rawMetric / Math.max(minimumMotionMetric, 0.0001), 1, 20);
232
+ const visualDurationSeconds = periodSeconds
233
+ ? clampNumber(FASTEST_VISIBLE_ORBIT_SECONDS * ratio, FASTEST_VISIBLE_ORBIT_SECONDS, SLOWEST_VISIBLE_ORBIT_SECONDS)
234
+ : clampNumber(FASTEST_VISIBLE_ORBIT_SECONDS * Math.pow(ratio, 0.75), FASTEST_VISIBLE_ORBIT_SECONDS, SLOWEST_VISIBLE_ORBIT_SECONDS);
235
+ return {
236
+ phase0Deg: unitValueToDegrees(placement.phase) ?? 0,
237
+ rotationDeg: unitValueToDegrees(placement.angle) ??
238
+ orbit?.rotationDeg ??
239
+ 0,
240
+ inclinationDeg: unitValueToDegrees(placement.inclination) ?? 0,
241
+ semiMajor,
242
+ semiMinor,
243
+ eccentricity: placement.eccentricity ?? 0,
244
+ periodSeconds,
245
+ angularVelocityDegPerSecond: 360 / Math.max(visualDurationSeconds, 0.001),
246
+ heuristic: periodSeconds === null,
247
+ frozen,
248
+ };
249
+ }
250
+ function resolveRawOrbitMetric(placement) {
251
+ const distance = unitValueToDistanceMetric(placement.semiMajor) ??
252
+ unitValueToDistanceMetric(placement.distance) ??
253
+ 1;
254
+ return Math.max(distance, 0.01);
255
+ }
256
+ function unitValueToDistanceMetric(value) {
257
+ if (!value) {
258
+ return null;
259
+ }
260
+ switch (value.unit) {
261
+ case "au":
262
+ return value.value;
263
+ case "km":
264
+ return value.value / 149_597_870.7;
265
+ case "m":
266
+ return value.value / 149_597_870_700;
267
+ case "re":
268
+ return (value.value * 6_371) / 149_597_870.7;
269
+ case "rj":
270
+ return (value.value * 71_492) / 149_597_870.7;
271
+ case "sol":
272
+ return (value.value * 695_700) / 149_597_870.7;
273
+ case "ly":
274
+ return value.value * 63_241.077;
275
+ case "pc":
276
+ return value.value * 206_264.806;
277
+ case "kpc":
278
+ return value.value * 206_264_806;
279
+ default:
280
+ return value.value;
281
+ }
282
+ }
283
+ function unitValueToDurationSeconds(value) {
284
+ if (!value) {
285
+ return null;
286
+ }
287
+ switch (value.unit) {
288
+ case "s":
289
+ return value.value;
290
+ case "min":
291
+ return value.value * 60;
292
+ case "h":
293
+ return value.value * 3_600;
294
+ case "d":
295
+ return value.value * DAY_IN_SECONDS;
296
+ case "y":
297
+ return value.value * YEAR_IN_SECONDS;
298
+ case "ky":
299
+ return value.value * YEAR_IN_SECONDS * 1_000;
300
+ case "my":
301
+ return value.value * YEAR_IN_SECONDS * 1_000_000;
302
+ case "gy":
303
+ return value.value * YEAR_IN_SECONDS * 1_000_000_000;
304
+ default:
305
+ return null;
306
+ }
307
+ }
308
+ function unitValueToDegrees(value) {
309
+ if (!value) {
310
+ return null;
311
+ }
312
+ return value.unit === "deg" || value.unit === null ? value.value : null;
313
+ }
314
+ function resolveSpatialScaleModel(layoutPreset, overrides) {
315
+ const defaults = defaultSpatialScaleModel(layoutPreset);
316
+ return {
317
+ ...defaults,
318
+ ...overrides,
319
+ };
320
+ }
321
+ function defaultSpatialScaleModel(layoutPreset) {
322
+ switch (layoutPreset) {
323
+ case "compact":
324
+ return {
325
+ orbitDistanceMultiplier: 0.92,
326
+ bodyRadiusMultiplier: 0.92,
327
+ markerSizeMultiplier: 0.92,
328
+ ringThicknessMultiplier: 0.9,
329
+ focusPadding: 10,
330
+ minBodyRadius: 4,
331
+ maxBodyRadius: 34,
332
+ };
333
+ case "presentation":
334
+ return {
335
+ orbitDistanceMultiplier: 1.15,
336
+ bodyRadiusMultiplier: 1.12,
337
+ markerSizeMultiplier: 1.08,
338
+ ringThicknessMultiplier: 1.14,
339
+ focusPadding: 16,
340
+ minBodyRadius: 5,
341
+ maxBodyRadius: 44,
342
+ };
343
+ default:
344
+ return {
345
+ orbitDistanceMultiplier: 1,
346
+ bodyRadiusMultiplier: 1,
347
+ markerSizeMultiplier: 1,
348
+ ringThicknessMultiplier: 1,
349
+ focusPadding: 12,
350
+ minBodyRadius: 4,
351
+ maxBodyRadius: 40,
352
+ };
353
+ }
354
+ }
355
+ function calculateSpatialBounds(objects) {
356
+ if (objects.length === 0) {
357
+ return {
358
+ minX: 0,
359
+ minY: 0,
360
+ minZ: 0,
361
+ maxX: 0,
362
+ maxY: 0,
363
+ maxZ: 0,
364
+ width: 0,
365
+ height: 0,
366
+ depth: 0,
367
+ center: { x: 0, y: 0, z: 0 },
368
+ };
369
+ }
370
+ let minX = Number.POSITIVE_INFINITY;
371
+ let minY = Number.POSITIVE_INFINITY;
372
+ let minZ = Number.POSITIVE_INFINITY;
373
+ let maxX = Number.NEGATIVE_INFINITY;
374
+ let maxY = Number.NEGATIVE_INFINITY;
375
+ let maxZ = Number.NEGATIVE_INFINITY;
376
+ for (const object of objects) {
377
+ minX = Math.min(minX, object.position.x - object.visualRadius);
378
+ minY = Math.min(minY, object.position.y - object.visualRadius);
379
+ minZ = Math.min(minZ, object.position.z - object.visualRadius);
380
+ maxX = Math.max(maxX, object.position.x + object.visualRadius);
381
+ maxY = Math.max(maxY, object.position.y + object.visualRadius);
382
+ maxZ = Math.max(maxZ, object.position.z + object.visualRadius);
383
+ }
384
+ return {
385
+ minX,
386
+ minY,
387
+ minZ,
388
+ maxX,
389
+ maxY,
390
+ maxZ,
391
+ width: maxX - minX,
392
+ height: maxY - minY,
393
+ depth: maxZ - minZ,
394
+ center: {
395
+ x: (minX + maxX) / 2,
396
+ y: (minY + maxY) / 2,
397
+ z: (minZ + maxZ) / 2,
398
+ },
399
+ };
400
+ }
401
+ function addPoint3D(left, right) {
402
+ return {
403
+ x: left.x + right.x,
404
+ y: left.y + right.y,
405
+ z: left.z + right.z,
406
+ };
407
+ }
408
+ function hashUnit(value) {
409
+ let hash = 0;
410
+ for (let index = 0; index < value.length; index += 1) {
411
+ hash = (hash * 31 + value.charCodeAt(index)) >>> 0;
412
+ }
413
+ return (hash % 10_000) / 10_000;
414
+ }
415
+ function clampNumber(value, min, max) {
416
+ return Math.min(Math.max(value, min), max);
417
+ }
418
+ function degreesToRadians(value) {
419
+ return (value * Math.PI) / 180;
420
+ }
@@ -0,0 +1,4 @@
1
+ import type { LineToken, TokenizeOptions } from "./types.js";
2
+ export declare function tokenizeLine(input: string): string[];
3
+ export declare function tokenizeLineDetailed(input: string, options?: TokenizeOptions): LineToken[];
4
+ export declare function getIndent(rawLine: string): number;
@@ -0,0 +1,68 @@
1
+ import { WorldOrbitError } from "./errors.js";
2
+ export function tokenizeLine(input) {
3
+ return tokenizeLineDetailed(input).map((token) => token.value);
4
+ }
5
+ export function tokenizeLineDetailed(input, options = {}) {
6
+ const tokens = [];
7
+ const columnOffset = options.columnOffset ?? 0;
8
+ let current = "";
9
+ let tokenColumn = null;
10
+ let tokenWasQuoted = false;
11
+ let inQuotes = false;
12
+ let quoteColumn = null;
13
+ const pushToken = () => {
14
+ if (tokenColumn === null) {
15
+ return;
16
+ }
17
+ tokens.push({
18
+ value: current,
19
+ column: tokenColumn,
20
+ quoted: tokenWasQuoted,
21
+ });
22
+ current = "";
23
+ tokenColumn = null;
24
+ tokenWasQuoted = false;
25
+ };
26
+ for (let index = 0; index < input.length; index++) {
27
+ const ch = input[index];
28
+ const absoluteColumn = columnOffset + index + 1;
29
+ if (inQuotes && ch === "\\") {
30
+ const next = input[index + 1];
31
+ if (next === '"' || next === "\\") {
32
+ current += next;
33
+ index++;
34
+ continue;
35
+ }
36
+ }
37
+ if (ch === '"') {
38
+ if (!inQuotes) {
39
+ if (tokenColumn === null) {
40
+ tokenColumn = absoluteColumn;
41
+ }
42
+ tokenWasQuoted = true;
43
+ quoteColumn = absoluteColumn;
44
+ inQuotes = true;
45
+ }
46
+ else {
47
+ inQuotes = false;
48
+ }
49
+ continue;
50
+ }
51
+ if (!inQuotes && /\s/.test(ch)) {
52
+ pushToken();
53
+ continue;
54
+ }
55
+ if (tokenColumn === null) {
56
+ tokenColumn = absoluteColumn;
57
+ }
58
+ current += ch;
59
+ }
60
+ if (inQuotes) {
61
+ throw new WorldOrbitError("Unclosed quote in line", options.line, quoteColumn ?? columnOffset + input.length);
62
+ }
63
+ pushToken();
64
+ return tokens;
65
+ }
66
+ export function getIndent(rawLine) {
67
+ return rawLine.match(/^\s*/)?.[0].length ?? 0;
68
+ }