worldorbit 4.0.0 → 5.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 (48) hide show
  1. package/README.md +17 -18
  2. package/dist/browser/core/dist/draft-parse.js +131 -12
  3. package/dist/browser/core/dist/draft.js +4 -4
  4. package/dist/browser/core/dist/format.js +42 -3
  5. package/dist/browser/core/dist/load.js +7 -2
  6. package/dist/browser/core/dist/scene.js +215 -3
  7. package/dist/browser/core/dist/solver.d.ts +8 -1
  8. package/dist/browser/core/dist/solver.js +72 -0
  9. package/dist/browser/core/dist/spatial-scene.js +56 -0
  10. package/dist/browser/core/dist/types.d.ts +74 -2
  11. package/dist/browser/viewer/dist/render.js +71 -15
  12. package/dist/browser/viewer/dist/theme.js +1 -0
  13. package/dist/browser/viewer/dist/types.d.ts +7 -0
  14. package/dist/browser/viewer/dist/viewer.js +27 -0
  15. package/dist/obsidian-plugin/main.js +81 -67
  16. package/dist/unpkg/core/dist/draft-parse.js +131 -12
  17. package/dist/unpkg/core/dist/draft.js +4 -4
  18. package/dist/unpkg/core/dist/format.js +42 -3
  19. package/dist/unpkg/core/dist/load.js +7 -2
  20. package/dist/unpkg/core/dist/scene.js +215 -3
  21. package/dist/unpkg/core/dist/solver.d.ts +8 -1
  22. package/dist/unpkg/core/dist/solver.js +72 -0
  23. package/dist/unpkg/core/dist/spatial-scene.js +56 -0
  24. package/dist/unpkg/core/dist/types.d.ts +74 -2
  25. package/dist/unpkg/viewer/dist/render.js +71 -15
  26. package/dist/unpkg/viewer/dist/theme.js +1 -0
  27. package/dist/unpkg/viewer/dist/types.d.ts +7 -0
  28. package/dist/unpkg/viewer/dist/viewer.js +27 -0
  29. package/dist/unpkg/worldorbit-core.min.js +12 -12
  30. package/dist/unpkg/worldorbit-editor.min.js +336 -322
  31. package/dist/unpkg/worldorbit-markdown.min.js +50 -36
  32. package/dist/unpkg/worldorbit-viewer.min.js +225 -211
  33. package/dist/unpkg/worldorbit.js +473 -19
  34. package/dist/unpkg/worldorbit.min.js +229 -215
  35. package/package.json +1 -1
  36. package/packages/core/dist/draft-parse.js +131 -12
  37. package/packages/core/dist/draft.js +4 -4
  38. package/packages/core/dist/format.js +42 -3
  39. package/packages/core/dist/load.js +7 -2
  40. package/packages/core/dist/scene.js +215 -3
  41. package/packages/core/dist/solver.d.ts +8 -1
  42. package/packages/core/dist/solver.js +72 -0
  43. package/packages/core/dist/spatial-scene.js +56 -0
  44. package/packages/core/dist/types.d.ts +74 -2
  45. package/packages/viewer/dist/render.js +71 -15
  46. package/packages/viewer/dist/theme.js +1 -0
  47. package/packages/viewer/dist/types.d.ts +7 -0
  48. package/packages/viewer/dist/viewer.js +27 -0
@@ -40,6 +40,13 @@ export function renderSceneToSvg(scene, options = {}) {
40
40
  .map((relation) => `<line class="wo-relation" x1="${relation.x1}" y1="${relation.y1}" x2="${relation.x2}" y2="${relation.y2}" data-render-id="${escapeXml(relation.renderId)}" data-relation-id="${escapeAttribute(relation.relationId)}" />`)
41
41
  .join("")
42
42
  : "";
43
+ const trajectoryMarkup = layers.trajectories
44
+ ? renderTrajectoryLayer(scene, visibleObjectIds, {
45
+ showLabels: options.showTrajectoryLabels ?? true,
46
+ showWaypoints: options.showTrajectoryWaypoints ?? true,
47
+ includeStructures: layers.structures,
48
+ })
49
+ : "";
43
50
  const eventMarkup = layers.events
44
51
  ? scene.events
45
52
  .filter((event) => !event.hidden)
@@ -78,12 +85,15 @@ export function renderSceneToSvg(scene, options = {}) {
78
85
  <stop offset="0%" stop-color="${theme.starGlow}" stop-opacity="0.95" />
79
86
  <stop offset="100%" stop-color="${theme.starCore}" stop-opacity="0" />
80
87
  </radialGradient>
81
- <radialGradient id="wo-bg-glow" cx="20%" cy="10%" r="90%">
82
- <stop offset="0%" stop-color="${theme.backgroundGlow}" />
83
- <stop offset="100%" stop-color="transparent" />
84
- </radialGradient>
85
- ${imageDefinitions}
86
- </defs>
88
+ <radialGradient id="wo-bg-glow" cx="20%" cy="10%" r="90%">
89
+ <stop offset="0%" stop-color="${theme.backgroundGlow}" />
90
+ <stop offset="100%" stop-color="transparent" />
91
+ </radialGradient>
92
+ <marker id="wo-trajectory-arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto" markerUnits="strokeWidth">
93
+ <path d="M 0 0 L 12 6 L 0 12 z" fill="${theme.accent}" />
94
+ </marker>
95
+ ${imageDefinitions}
96
+ </defs>
87
97
  <style>
88
98
  .wo-bg { fill: url(#wo-bg); }
89
99
  .wo-bg-glow { fill: url(#wo-bg-glow); }
@@ -91,9 +101,13 @@ export function renderSceneToSvg(scene, options = {}) {
91
101
  .wo-orbit { fill: none; stroke: ${theme.orbit}; stroke-width: 1.5; }
92
102
  .wo-orbit-back { opacity: 0.38; stroke-dasharray: 8 6; }
93
103
  .wo-orbit-front { opacity: 0.9; }
94
- .wo-orbit-band { stroke: ${theme.orbitBand}; stroke-linecap: round; }
95
- .wo-relation { stroke: ${theme.relation}; stroke-width: 2; stroke-dasharray: 10 6; }
96
- .wo-event-line { stroke: ${theme.accent}; stroke-width: 1.6; stroke-dasharray: 5 5; opacity: 0.72; }
104
+ .wo-orbit-band { stroke: ${theme.orbitBand}; stroke-linecap: round; }
105
+ .wo-relation { stroke: ${theme.relation}; stroke-width: 2; stroke-dasharray: 10 6; }
106
+ .wo-trajectory { fill: none; stroke: ${theme.accent}; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; opacity: 0.92; }
107
+ .wo-trajectory-waypoint { fill: ${theme.spaceFog}; stroke: ${theme.selected}; stroke-width: 1.4; }
108
+ .wo-trajectory-label { fill: ${theme.accent}; font-family: ${theme.fontFamily}; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
109
+ .wo-trajectory-date { fill: ${theme.muted}; font-family: ${theme.fontFamily}; font-weight: 500; }
110
+ .wo-event-line { stroke: ${theme.accent}; stroke-width: 1.6; stroke-dasharray: 5 5; opacity: 0.72; }
97
111
  .wo-event-node { fill: ${theme.accent}; stroke: ${theme.selected}; stroke-width: 1.4; opacity: 0.92; }
98
112
  .wo-event-label { fill: ${theme.accent}; font-family: ${theme.fontFamily}; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
99
113
  .wo-leader { stroke: ${theme.leader}; stroke-width: 1.5; stroke-dasharray: 6 5; }
@@ -129,12 +143,13 @@ export function renderSceneToSvg(scene, options = {}) {
129
143
  <g data-worldorbit-world-content="true">
130
144
  ${layers.orbits ? `<g data-layer-id="orbits-back">${orbitMarkup.back}</g>` : ""}
131
145
  ${layers.guides ? `<g data-layer-id="guides">${leaderMarkup}</g>` : ""}
132
- ${layers.relations ? `<g data-layer-id="relations">${relationMarkup}</g>` : ""}
133
- ${layers.events ? `<g data-layer-id="events">${eventMarkup}</g>` : ""}
134
- ${layers.objects ? `<g data-layer-id="objects">${objectMarkup}</g>` : ""}
135
- ${layers.orbits ? `<g data-layer-id="orbits-front">${orbitMarkup.front}</g>` : ""}
136
- ${layers.labels ? `<g data-layer-id="labels">${labelMarkup}</g>` : ""}
137
- </g>
146
+ ${layers.relations ? `<g data-layer-id="relations">${relationMarkup}</g>` : ""}
147
+ ${layers.events ? `<g data-layer-id="events">${eventMarkup}</g>` : ""}
148
+ ${layers.objects ? `<g data-layer-id="objects">${objectMarkup}</g>` : ""}
149
+ ${layers.orbits ? `<g data-layer-id="orbits-front">${orbitMarkup.front}</g>` : ""}
150
+ ${layers.trajectories ? `<g data-layer-id="trajectories">${trajectoryMarkup}</g>` : ""}
151
+ ${layers.labels ? `<g data-layer-id="labels">${labelMarkup}</g>` : ""}
152
+ </g>
138
153
  </g>
139
154
  </g>
140
155
  </svg>`;
@@ -158,6 +173,47 @@ function renderSceneEventOverlay(scene, event, visibleObjectIds, theme) {
158
173
  <text class="wo-event-label" x="${event.x}" y="${event.y - 10}" text-anchor="middle" font-size="10">${escapeXml(label)}</text>
159
174
  </g>`;
160
175
  }
176
+ function renderTrajectoryLayer(scene, visibleObjectIds, options) {
177
+ return scene.trajectories
178
+ .filter((trajectory) => !trajectory.hidden)
179
+ .filter((trajectory) => trajectory.objectIds.length === 0 || trajectory.objectIds.some((objectId) => visibleObjectIds.has(objectId)))
180
+ .filter((trajectory) => options.includeStructures ||
181
+ !trajectory.objectIds.some((objectId) => {
182
+ const object = scene.objects.find((entry) => entry.objectId === objectId)?.object;
183
+ return object ? isStructureLike(object) : false;
184
+ }))
185
+ .map((trajectory) => {
186
+ const stroke = trajectory.stroke ?? "#f0b464";
187
+ const markerEnd = trajectory.marker === "none" ? "" : ` marker-end="url(#wo-trajectory-arrow)"`;
188
+ const waypointMarkup = trajectory.showWaypoints && options.showWaypoints
189
+ ? trajectory.waypoints
190
+ .filter((waypoint) => !waypoint.hidden)
191
+ .map((waypoint) => renderTrajectoryWaypoint(trajectory, waypoint, options.showLabels))
192
+ .join("")
193
+ : "";
194
+ return `<g class="wo-trajectory-group" data-render-id="${escapeXml(trajectory.renderId)}" data-trajectory-id="${escapeAttribute(trajectory.trajectoryId)}">
195
+ <path class="wo-trajectory wo-trajectory-${trajectory.mode}" d="${trajectory.path}" stroke="${escapeAttribute(stroke)}" stroke-width="${trajectory.strokeWidth}"${markerEnd} />
196
+ ${waypointMarkup}
197
+ </g>`;
198
+ })
199
+ .join("");
200
+ }
201
+ function renderTrajectoryWaypoint(trajectory, waypoint, showLabels) {
202
+ const labelMarkup = showLabels && trajectory.labelMode !== "hidden"
203
+ ? [
204
+ waypoint.label
205
+ ? `<text class="wo-trajectory-label" x="${waypoint.x + 10}" y="${waypoint.y - 10}" font-size="10">${escapeXml(waypoint.label)}</text>`
206
+ : "",
207
+ waypoint.dateLabel
208
+ ? `<text class="wo-trajectory-date" x="${waypoint.x + 10}" y="${waypoint.y + 4}" font-size="9">${escapeXml(waypoint.dateLabel)}</text>`
209
+ : "",
210
+ ].join("")
211
+ : "";
212
+ return `<g class="wo-trajectory-waypoint-group" data-render-id="${escapeXml(waypoint.renderId)}" data-trajectory-id="${escapeAttribute(waypoint.trajectoryId)}">
213
+ <circle class="wo-trajectory-waypoint" cx="${waypoint.x}" cy="${waypoint.y}" r="4.5" />
214
+ ${labelMarkup}
215
+ </g>`;
216
+ }
161
217
  export function renderDocumentToSvg(document, options = {}) {
162
218
  return renderSceneToSvg(renderDocumentToScene(document, options), options);
163
219
  }
@@ -4,6 +4,7 @@ const DEFAULT_LAYERS = {
4
4
  relations: true,
5
5
  events: true,
6
6
  orbits: true,
7
+ trajectories: true,
7
8
  objects: true,
8
9
  labels: true,
9
10
  structures: true,
@@ -43,6 +43,7 @@ export interface ViewerLayerOptions {
43
43
  relations?: boolean;
44
44
  events?: boolean;
45
45
  orbits?: boolean;
46
+ trajectories?: boolean;
46
47
  objects?: boolean;
47
48
  labels?: boolean;
48
49
  structures?: boolean;
@@ -77,6 +78,9 @@ export interface ViewerRenderOptions extends Omit<SvgRenderOptions, "selectedObj
77
78
  viewMode?: WorldOrbitViewMode;
78
79
  quality?: WorldOrbit3DQuality;
79
80
  style3d?: WorldOrbit3DStyle;
81
+ trajectoryMode?: "illustrative" | "solver" | "auto";
82
+ showTrajectoryWaypoints?: boolean;
83
+ showTrajectoryLabels?: boolean;
80
84
  }
81
85
  export interface ViewerState {
82
86
  scale: number;
@@ -130,6 +134,9 @@ export interface ViewerAtlasState {
130
134
  layers?: ViewerLayerOptions;
131
135
  scaleModel?: Partial<RenderScaleModel>;
132
136
  bodyScaleMode?: SceneRenderOptions["bodyScaleMode"];
137
+ trajectoryMode?: SceneRenderOptions["trajectoryMode"];
138
+ showTrajectoryWaypoints?: boolean;
139
+ showTrajectoryLabels?: boolean;
133
140
  activeEventId?: string | null;
134
141
  viewMode?: WorldOrbitViewMode;
135
142
  quality?: WorldOrbit3DQuality;
@@ -1691,6 +1691,33 @@ function fallbackSpatialSceneFromRenderScene(scene) {
1691
1691
  hidden: orbit.hidden,
1692
1692
  motion: null,
1693
1693
  })),
1694
+ trajectories: scene.trajectories.map((trajectory) => ({
1695
+ trajectoryId: trajectory.trajectoryId,
1696
+ trajectory: trajectory.trajectory,
1697
+ craftObjectId: trajectory.craftObjectId,
1698
+ mode: trajectory.mode,
1699
+ stroke: trajectory.stroke,
1700
+ strokeWidth: trajectory.strokeWidth,
1701
+ marker: trajectory.marker,
1702
+ labelMode: trajectory.labelMode,
1703
+ showWaypoints: trajectory.showWaypoints,
1704
+ samples: [],
1705
+ waypoints: trajectory.waypoints.map((waypoint) => ({
1706
+ trajectoryId: waypoint.trajectoryId,
1707
+ segmentId: waypoint.segmentId,
1708
+ maneuverId: waypoint.maneuverId,
1709
+ objectId: waypoint.objectId,
1710
+ position: {
1711
+ x: waypoint.x - scene.contentBounds.centerX,
1712
+ y: 0,
1713
+ z: waypoint.y - scene.contentBounds.centerY,
1714
+ },
1715
+ label: waypoint.label,
1716
+ dateLabel: waypoint.dateLabel,
1717
+ hidden: waypoint.hidden,
1718
+ })),
1719
+ hidden: trajectory.hidden,
1720
+ })),
1694
1721
  focusTargets: scene.objects.map((object) => ({
1695
1722
  objectId: object.objectId,
1696
1723
  center: {