worldorbit 3.2.2 → 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.
- package/README.md +543 -543
- package/dist/browser/core/dist/atlas-edit.js +146 -1
- package/dist/browser/core/dist/atlas-validate.js +105 -10
- package/dist/browser/core/dist/draft-parse.js +461 -17
- package/dist/browser/core/dist/draft.d.ts +2 -1
- package/dist/browser/core/dist/draft.js +26 -4
- package/dist/browser/core/dist/format.js +126 -5
- package/dist/browser/core/dist/index.d.ts +1 -0
- package/dist/browser/core/dist/index.js +1 -0
- package/dist/browser/core/dist/load.js +12 -2
- package/dist/browser/core/dist/normalize.js +1 -0
- package/dist/browser/core/dist/scene.js +226 -5
- package/dist/browser/core/dist/schema.js +11 -1
- package/dist/browser/core/dist/solver.d.ts +33 -0
- package/dist/browser/core/dist/solver.js +99 -0
- package/dist/browser/core/dist/spatial-scene.js +56 -0
- package/dist/browser/core/dist/types.d.ts +130 -4
- package/dist/browser/editor/dist/editor.js +844 -719
- package/dist/browser/editor/dist/types.d.ts +2 -1
- package/dist/browser/viewer/dist/minimap.js +9 -7
- package/dist/browser/viewer/dist/render.js +78 -18
- package/dist/browser/viewer/dist/runtime-3d.js +2 -0
- package/dist/browser/viewer/dist/theme.js +1 -0
- package/dist/browser/viewer/dist/types.d.ts +7 -0
- package/dist/browser/viewer/dist/viewer.js +34 -3
- package/dist/obsidian-plugin/README.md +141 -124
- package/dist/obsidian-plugin/main.js +82 -68
- package/dist/unpkg/core/dist/atlas-edit.js +146 -1
- package/dist/unpkg/core/dist/atlas-validate.js +105 -10
- package/dist/unpkg/core/dist/draft-parse.js +461 -17
- package/dist/unpkg/core/dist/draft.d.ts +2 -1
- package/dist/unpkg/core/dist/draft.js +26 -4
- package/dist/unpkg/core/dist/format.js +126 -5
- package/dist/unpkg/core/dist/index.d.ts +1 -0
- package/dist/unpkg/core/dist/index.js +1 -0
- package/dist/unpkg/core/dist/load.js +12 -2
- package/dist/unpkg/core/dist/normalize.js +1 -0
- package/dist/unpkg/core/dist/scene.js +226 -5
- package/dist/unpkg/core/dist/schema.js +11 -1
- package/dist/unpkg/core/dist/solver.d.ts +33 -0
- package/dist/unpkg/core/dist/solver.js +99 -0
- package/dist/unpkg/core/dist/spatial-scene.js +56 -0
- package/dist/unpkg/core/dist/types.d.ts +130 -4
- package/dist/unpkg/editor/dist/editor.js +844 -719
- package/dist/unpkg/editor/dist/types.d.ts +2 -1
- package/dist/unpkg/viewer/dist/minimap.js +9 -7
- package/dist/unpkg/viewer/dist/render.js +78 -18
- package/dist/unpkg/viewer/dist/runtime-3d.js +2 -0
- package/dist/unpkg/viewer/dist/theme.js +1 -0
- package/dist/unpkg/viewer/dist/types.d.ts +7 -0
- package/dist/unpkg/viewer/dist/viewer.js +34 -3
- package/dist/unpkg/worldorbit-core.min.js +12 -12
- package/dist/unpkg/worldorbit-editor.min.js +381 -340
- package/dist/unpkg/worldorbit-markdown.min.js +47 -33
- package/dist/unpkg/worldorbit-viewer.min.js +238 -224
- package/dist/unpkg/worldorbit.js +1218 -46
- package/dist/unpkg/worldorbit.min.js +242 -228
- package/package.json +5 -1
- package/packages/core/dist/atlas-edit.js +146 -1
- package/packages/core/dist/atlas-validate.js +105 -10
- package/packages/core/dist/draft-parse.js +461 -17
- package/packages/core/dist/draft.d.ts +2 -1
- package/packages/core/dist/draft.js +26 -4
- package/packages/core/dist/format.js +126 -5
- package/packages/core/dist/index.d.ts +1 -0
- package/packages/core/dist/index.js +1 -0
- package/packages/core/dist/load.js +12 -2
- package/packages/core/dist/normalize.js +1 -0
- package/packages/core/dist/scene.js +226 -5
- package/packages/core/dist/schema.js +11 -1
- package/packages/core/dist/solver.d.ts +33 -0
- package/packages/core/dist/solver.js +99 -0
- package/packages/core/dist/spatial-scene.js +56 -0
- package/packages/core/dist/types.d.ts +130 -4
- package/packages/editor/dist/editor.js +844 -719
- package/packages/editor/dist/types.d.ts +2 -1
- package/packages/viewer/dist/minimap.js +9 -7
- package/packages/viewer/dist/render.js +78 -18
- package/packages/viewer/dist/runtime-3d.js +2 -0
- package/packages/viewer/dist/theme.js +1 -0
- package/packages/viewer/dist/types.d.ts +7 -0
- package/packages/viewer/dist/viewer.js +34 -3
package/dist/unpkg/worldorbit.js
CHANGED
|
@@ -30713,6 +30713,7 @@ void main() {
|
|
|
30713
30713
|
createEmptyAtlasDocument: () => createEmptyAtlasDocument,
|
|
30714
30714
|
createInteractiveViewer: () => createInteractiveViewer,
|
|
30715
30715
|
createInteractiveViewer2D: () => createInteractiveViewer2D,
|
|
30716
|
+
createTrajectorySolverSnapshot: () => createTrajectorySolverSnapshot,
|
|
30716
30717
|
createWorldOrbitEmbedMarkup: () => createWorldOrbitEmbedMarkup,
|
|
30717
30718
|
defineWorldOrbitViewerElement: () => defineWorldOrbitViewerElement,
|
|
30718
30719
|
deserializeViewerAtlasState: () => deserializeViewerAtlasState,
|
|
@@ -30810,6 +30811,7 @@ void main() {
|
|
|
30810
30811
|
"asteroid",
|
|
30811
30812
|
"comet",
|
|
30812
30813
|
"ring",
|
|
30814
|
+
"craft",
|
|
30813
30815
|
"structure",
|
|
30814
30816
|
"phenomenon"
|
|
30815
30817
|
];
|
|
@@ -30820,10 +30822,11 @@ void main() {
|
|
|
30820
30822
|
"moon",
|
|
30821
30823
|
"asteroid",
|
|
30822
30824
|
"comet",
|
|
30825
|
+
"craft",
|
|
30823
30826
|
"structure",
|
|
30824
30827
|
"phenomenon"
|
|
30825
30828
|
];
|
|
30826
|
-
var ANCHORED_OBJECTS = ["structure", "phenomenon"];
|
|
30829
|
+
var ANCHORED_OBJECTS = ["craft", "structure", "phenomenon"];
|
|
30827
30830
|
var ORBITAL_OBJECTS = [
|
|
30828
30831
|
"star",
|
|
30829
30832
|
"planet",
|
|
@@ -30832,6 +30835,7 @@ void main() {
|
|
|
30832
30835
|
"asteroid",
|
|
30833
30836
|
"comet",
|
|
30834
30837
|
"ring",
|
|
30838
|
+
"craft",
|
|
30835
30839
|
"structure",
|
|
30836
30840
|
"phenomenon"
|
|
30837
30841
|
];
|
|
@@ -30843,6 +30847,7 @@ void main() {
|
|
|
30843
30847
|
"asteroid",
|
|
30844
30848
|
"comet",
|
|
30845
30849
|
"ring",
|
|
30850
|
+
"craft",
|
|
30846
30851
|
"structure",
|
|
30847
30852
|
"phenomenon"
|
|
30848
30853
|
];
|
|
@@ -31071,6 +31076,12 @@ void main() {
|
|
|
31071
31076
|
arity: "single",
|
|
31072
31077
|
objectTypes: NON_SYSTEM_OBJECTS,
|
|
31073
31078
|
unitFamily: "duration"
|
|
31079
|
+
}),
|
|
31080
|
+
createField("trajectory", {
|
|
31081
|
+
kind: "string",
|
|
31082
|
+
placement: false,
|
|
31083
|
+
arity: "single",
|
|
31084
|
+
objectTypes: ["craft", "structure"]
|
|
31074
31085
|
})
|
|
31075
31086
|
].map((schema) => [schema.key, schema]));
|
|
31076
31087
|
var WORLDORBIT_FIELD_KEYS = new Set(WORLDORBIT_FIELD_SCHEMAS.keys());
|
|
@@ -31384,6 +31395,7 @@ void main() {
|
|
|
31384
31395
|
groups: [],
|
|
31385
31396
|
relations: [],
|
|
31386
31397
|
events: [],
|
|
31398
|
+
trajectories: [],
|
|
31387
31399
|
objects
|
|
31388
31400
|
};
|
|
31389
31401
|
}
|
|
@@ -31989,7 +32001,8 @@ void main() {
|
|
|
31989
32001
|
const labels = createSceneLabels(objects, width, height, scaleModel.labelMultiplier);
|
|
31990
32002
|
const relations = createSceneRelations(document2, objects);
|
|
31991
32003
|
const events = createSceneEvents(document2.events ?? [], objects, activeEventId);
|
|
31992
|
-
const
|
|
32004
|
+
const trajectories = createSceneTrajectories(document2, objects, events, options);
|
|
32005
|
+
const layers = createSceneLayers(orbitVisuals, trajectories, relations, events, leaders, objects, labels);
|
|
31993
32006
|
const groups = createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, scaleModel.labelMultiplier);
|
|
31994
32007
|
const semanticGroups = createSceneSemanticGroups(document2, objects);
|
|
31995
32008
|
const viewpoints = createSceneViewpoints(document2, schemaProjection, frame.preset, relationships, objectMap);
|
|
@@ -32029,6 +32042,7 @@ void main() {
|
|
|
32029
32042
|
viewpoints,
|
|
32030
32043
|
events,
|
|
32031
32044
|
activeEventId,
|
|
32045
|
+
trajectories,
|
|
32032
32046
|
objects,
|
|
32033
32047
|
orbitVisuals,
|
|
32034
32048
|
relations,
|
|
@@ -32304,7 +32318,7 @@ void main() {
|
|
|
32304
32318
|
anchorX,
|
|
32305
32319
|
anchorY,
|
|
32306
32320
|
label: object.id,
|
|
32307
|
-
secondaryLabel: object.type === "structure" ? String(object.properties.kind ?? object.type) : object.type,
|
|
32321
|
+
secondaryLabel: object.type === "structure" || object.type === "craft" ? String(object.properties.kind ?? object.type) : object.type,
|
|
32308
32322
|
fillColor: customColorFor(object.properties.color),
|
|
32309
32323
|
imageHref: typeof object.properties.image === "string" && object.properties.image.trim() ? object.properties.image : void 0,
|
|
32310
32324
|
hidden: object.properties.hidden === true
|
|
@@ -32398,6 +32412,7 @@ void main() {
|
|
|
32398
32412
|
case "asteroid":
|
|
32399
32413
|
case "comet":
|
|
32400
32414
|
return 4;
|
|
32415
|
+
case "craft":
|
|
32401
32416
|
case "structure":
|
|
32402
32417
|
case "phenomenon":
|
|
32403
32418
|
return 5;
|
|
@@ -32422,7 +32437,7 @@ void main() {
|
|
|
32422
32437
|
const oppositeVertical = vertical === "below" ? "above" : "below";
|
|
32423
32438
|
const horizontal = defaultHorizontalDirection(object, parent, sceneWidth);
|
|
32424
32439
|
const oppositeHorizontal = horizontal === "right" ? "left" : "right";
|
|
32425
|
-
const preferHorizontal = object.object.type === "structure" || object.object.type === "phenomenon" || object.object.placement?.mode === "at" || object.object.placement?.mode === "surface" || object.object.placement?.mode === "free";
|
|
32440
|
+
const preferHorizontal = object.object.type === "craft" || object.object.type === "structure" || object.object.type === "phenomenon" || object.object.placement?.mode === "at" || object.object.placement?.mode === "surface" || object.object.placement?.mode === "free";
|
|
32426
32441
|
return preferHorizontal ? [horizontal, vertical, oppositeHorizontal, oppositeVertical] : [vertical, horizontal, oppositeVertical, oppositeHorizontal];
|
|
32427
32442
|
}
|
|
32428
32443
|
function defaultVerticalDirection(object, parent, sceneHeight) {
|
|
@@ -32484,7 +32499,7 @@ void main() {
|
|
|
32484
32499
|
}
|
|
32485
32500
|
}
|
|
32486
32501
|
}
|
|
32487
|
-
function createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels) {
|
|
32502
|
+
function createSceneLayers(orbitVisuals, trajectories, relations, events, leaders, objects, labels) {
|
|
32488
32503
|
const backOrbitIds = orbitVisuals.filter((visual) => !visual.hidden && Boolean(visual.backArcPath)).map((visual) => visual.renderId);
|
|
32489
32504
|
const frontOrbitIds = orbitVisuals.filter((visual) => !visual.hidden).map((visual) => visual.renderId);
|
|
32490
32505
|
return [
|
|
@@ -32495,6 +32510,13 @@ void main() {
|
|
|
32495
32510
|
},
|
|
32496
32511
|
{ id: "orbits-back", renderIds: backOrbitIds },
|
|
32497
32512
|
{ id: "orbits-front", renderIds: frontOrbitIds },
|
|
32513
|
+
{
|
|
32514
|
+
id: "trajectories",
|
|
32515
|
+
renderIds: trajectories.filter((trajectory) => !trajectory.hidden).flatMap((trajectory) => [
|
|
32516
|
+
trajectory.renderId,
|
|
32517
|
+
...trajectory.waypoints.filter((waypoint) => !waypoint.hidden).map((waypoint) => waypoint.renderId)
|
|
32518
|
+
])
|
|
32519
|
+
},
|
|
32498
32520
|
{
|
|
32499
32521
|
id: "relations",
|
|
32500
32522
|
renderIds: relations.filter((relation) => !relation.hidden).map((relation) => relation.renderId)
|
|
@@ -32620,6 +32642,192 @@ void main() {
|
|
|
32620
32642
|
};
|
|
32621
32643
|
}).sort((left, right) => left.event.id.localeCompare(right.event.id));
|
|
32622
32644
|
}
|
|
32645
|
+
function createSceneTrajectories(document2, objects, events, options) {
|
|
32646
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
32647
|
+
return document2.trajectories.map((trajectory) => createSceneTrajectory(trajectory, objectMap, events, options)).sort((left, right) => left.trajectoryId.localeCompare(right.trajectoryId));
|
|
32648
|
+
}
|
|
32649
|
+
function createSceneTrajectory(trajectory, objectMap, events, options) {
|
|
32650
|
+
const craftObject = trajectory.craftObjectId ? objectMap.get(trajectory.craftObjectId) ?? null : null;
|
|
32651
|
+
const mode = resolveTrajectoryMode(trajectory, options);
|
|
32652
|
+
const stroke = trajectory.stroke ?? trajectory.color ?? craftObject?.fillColor ?? null;
|
|
32653
|
+
const strokeWidth = trajectory.strokeWidth ?? 2.4;
|
|
32654
|
+
const showWaypoints = options.showTrajectoryWaypoints ?? trajectory.showWaypoints ?? true;
|
|
32655
|
+
const labelMode = trajectory.labelMode ?? (options.showTrajectoryLabels === false ? "hidden" : "waypoint");
|
|
32656
|
+
const pathParts = [];
|
|
32657
|
+
const waypoints = [];
|
|
32658
|
+
const objectIds = /* @__PURE__ */ new Set();
|
|
32659
|
+
let lastAnchor = craftObject;
|
|
32660
|
+
if (craftObject) {
|
|
32661
|
+
objectIds.add(craftObject.objectId);
|
|
32662
|
+
}
|
|
32663
|
+
trajectory.segments.forEach((segment, index) => {
|
|
32664
|
+
const geometry = buildTrajectorySegmentGeometry(trajectory, segment, index, mode, objectMap, lastAnchor, showWaypoints);
|
|
32665
|
+
if (geometry.path) {
|
|
32666
|
+
pathParts.push(geometry.path);
|
|
32667
|
+
}
|
|
32668
|
+
geometry.objectIds.forEach((objectId) => objectIds.add(objectId));
|
|
32669
|
+
waypoints.push(...geometry.waypoints);
|
|
32670
|
+
lastAnchor = geometry.lastAnchor ?? lastAnchor;
|
|
32671
|
+
});
|
|
32672
|
+
for (const event of events.filter((entry) => entry.event.trajectoryId === trajectory.id)) {
|
|
32673
|
+
const eventObject = event.targetObjectId ? objectMap.get(event.targetObjectId) ?? null : event.objectIds.map((objectId) => objectMap.get(objectId) ?? null).find(Boolean) ?? null;
|
|
32674
|
+
if (!eventObject) {
|
|
32675
|
+
continue;
|
|
32676
|
+
}
|
|
32677
|
+
waypoints.push({
|
|
32678
|
+
renderId: `${createRenderId(`${trajectory.id}-${event.eventId}`)}-waypoint`,
|
|
32679
|
+
trajectoryId: trajectory.id,
|
|
32680
|
+
segmentId: null,
|
|
32681
|
+
maneuverId: null,
|
|
32682
|
+
objectId: eventObject.objectId,
|
|
32683
|
+
x: eventObject.x,
|
|
32684
|
+
y: eventObject.y,
|
|
32685
|
+
label: event.event.label ?? event.event.id,
|
|
32686
|
+
dateLabel: event.event.epoch ?? null,
|
|
32687
|
+
hidden: trajectory.hidden || event.hidden || !showWaypoints
|
|
32688
|
+
});
|
|
32689
|
+
objectIds.add(eventObject.objectId);
|
|
32690
|
+
}
|
|
32691
|
+
return {
|
|
32692
|
+
renderId: `${createRenderId(trajectory.id)}-trajectory`,
|
|
32693
|
+
trajectoryId: trajectory.id,
|
|
32694
|
+
trajectory,
|
|
32695
|
+
craftObjectId: trajectory.craftObjectId,
|
|
32696
|
+
mode,
|
|
32697
|
+
path: pathParts.join(" "),
|
|
32698
|
+
stroke,
|
|
32699
|
+
strokeWidth,
|
|
32700
|
+
marker: trajectory.marker ?? "arrow",
|
|
32701
|
+
labelMode,
|
|
32702
|
+
showWaypoints,
|
|
32703
|
+
objectIds: [...objectIds],
|
|
32704
|
+
waypoints,
|
|
32705
|
+
hidden: trajectory.hidden || pathParts.length === 0
|
|
32706
|
+
};
|
|
32707
|
+
}
|
|
32708
|
+
function buildTrajectorySegmentGeometry(trajectory, segment, segmentIndex, mode, objectMap, fallbackStart, showWaypoints) {
|
|
32709
|
+
const start = resolveTrajectoryObject(segment.fromObjectId, objectMap) ?? fallbackStart;
|
|
32710
|
+
const assist = resolveTrajectoryObject(segment.assist?.objectId ?? segment.aroundObjectId ?? null, objectMap);
|
|
32711
|
+
const end = resolveTrajectoryObject(segment.toObjectId, objectMap) ?? resolveTrajectoryObject(segment.aroundObjectId, objectMap) ?? assist ?? start;
|
|
32712
|
+
if (!start || !end) {
|
|
32713
|
+
return {
|
|
32714
|
+
path: "",
|
|
32715
|
+
objectIds: [],
|
|
32716
|
+
waypoints: [],
|
|
32717
|
+
lastAnchor: fallbackStart
|
|
32718
|
+
};
|
|
32719
|
+
}
|
|
32720
|
+
const objectIds = [start.objectId, end.objectId];
|
|
32721
|
+
if (assist) {
|
|
32722
|
+
objectIds.push(assist.objectId);
|
|
32723
|
+
}
|
|
32724
|
+
const hidden = trajectory.hidden || segment.renderHidden === true || start.hidden || end.hidden;
|
|
32725
|
+
const waypoints = [];
|
|
32726
|
+
const label = segment.waypointLabel ?? segment.label ?? humanizeIdentifier(segment.id);
|
|
32727
|
+
const dateLabel = segment.waypointDate ?? segment.epoch ?? null;
|
|
32728
|
+
if (showWaypoints) {
|
|
32729
|
+
if (segmentIndex === 0) {
|
|
32730
|
+
waypoints.push(createTrajectoryWaypoint(trajectory.id, segment.id, null, start, start.label, null, hidden));
|
|
32731
|
+
}
|
|
32732
|
+
if (assist && assist.objectId !== start.objectId && assist.objectId !== end.objectId) {
|
|
32733
|
+
waypoints.push(createTrajectoryWaypoint(trajectory.id, segment.id, null, assist, label, dateLabel, hidden));
|
|
32734
|
+
}
|
|
32735
|
+
waypoints.push(createTrajectoryWaypoint(trajectory.id, segment.id, null, end, label, dateLabel, hidden));
|
|
32736
|
+
}
|
|
32737
|
+
const samples = mode === "solver" ? sampleQuadraticPoints(start, resolveTrajectoryControlPoint(start, end, assist, segmentIndex), end, Math.max(10, Math.round((segment.sampleDensity ?? 1) * 14))) : null;
|
|
32738
|
+
const control = resolveTrajectoryControlPoint(start, end, assist, segmentIndex);
|
|
32739
|
+
const path = mode === "solver" ? pointsToPath(samples ?? [start, end]) : `M ${formatPathNumber(start.x)} ${formatPathNumber(start.y)} Q ${formatPathNumber(control.x)} ${formatPathNumber(control.y)} ${formatPathNumber(end.x)} ${formatPathNumber(end.y)}`;
|
|
32740
|
+
segment.maneuvers.forEach((maneuver, maneuverIndex) => {
|
|
32741
|
+
if (!showWaypoints) {
|
|
32742
|
+
return;
|
|
32743
|
+
}
|
|
32744
|
+
const point = samplePointOnQuadratic(start, control, end, (maneuverIndex + 1) / (segment.maneuvers.length + 1));
|
|
32745
|
+
waypoints.push({
|
|
32746
|
+
renderId: `${createRenderId(`${trajectory.id}-${segment.id}-${maneuver.id}`)}-waypoint`,
|
|
32747
|
+
trajectoryId: trajectory.id,
|
|
32748
|
+
segmentId: segment.id,
|
|
32749
|
+
maneuverId: maneuver.id,
|
|
32750
|
+
objectId: null,
|
|
32751
|
+
x: point.x,
|
|
32752
|
+
y: point.y,
|
|
32753
|
+
label: maneuver.label ?? maneuver.kind,
|
|
32754
|
+
dateLabel: maneuver.epoch ?? null,
|
|
32755
|
+
hidden
|
|
32756
|
+
});
|
|
32757
|
+
});
|
|
32758
|
+
return {
|
|
32759
|
+
path,
|
|
32760
|
+
objectIds: [...new Set(objectIds)],
|
|
32761
|
+
waypoints,
|
|
32762
|
+
lastAnchor: end
|
|
32763
|
+
};
|
|
32764
|
+
}
|
|
32765
|
+
function createTrajectoryWaypoint(trajectoryId, segmentId, maneuverId, object, label, dateLabel, hidden) {
|
|
32766
|
+
return {
|
|
32767
|
+
renderId: `${createRenderId(`${trajectoryId}-${segmentId ?? object.objectId}-${maneuverId ?? object.objectId}`)}-waypoint`,
|
|
32768
|
+
trajectoryId,
|
|
32769
|
+
segmentId,
|
|
32770
|
+
maneuverId,
|
|
32771
|
+
objectId: object.objectId,
|
|
32772
|
+
x: object.x,
|
|
32773
|
+
y: object.y,
|
|
32774
|
+
label,
|
|
32775
|
+
dateLabel,
|
|
32776
|
+
hidden
|
|
32777
|
+
};
|
|
32778
|
+
}
|
|
32779
|
+
function resolveTrajectoryMode(trajectory, options) {
|
|
32780
|
+
const requested = options.trajectoryMode ?? trajectory.renderMode ?? "auto";
|
|
32781
|
+
if (requested !== "auto") {
|
|
32782
|
+
return requested;
|
|
32783
|
+
}
|
|
32784
|
+
const segmentCount = trajectory.segments.filter((segment) => segment.fromObjectId || segment.toObjectId || segment.assist?.objectId || segment.aroundObjectId).length;
|
|
32785
|
+
return segmentCount > 0 ? "solver" : "illustrative";
|
|
32786
|
+
}
|
|
32787
|
+
function resolveTrajectoryObject(objectId, objectMap) {
|
|
32788
|
+
return objectId ? objectMap.get(objectId) ?? null : null;
|
|
32789
|
+
}
|
|
32790
|
+
function resolveTrajectoryControlPoint(start, end, assist, segmentIndex) {
|
|
32791
|
+
if (assist) {
|
|
32792
|
+
return {
|
|
32793
|
+
x: assist.x,
|
|
32794
|
+
y: assist.y
|
|
32795
|
+
};
|
|
32796
|
+
}
|
|
32797
|
+
const dx = end.x - start.x;
|
|
32798
|
+
const dy = end.y - start.y;
|
|
32799
|
+
const length = Math.max(Math.hypot(dx, dy), 1);
|
|
32800
|
+
const offset = Math.min(Math.max(length * 0.18, 26), 120) * (segmentIndex % 2 === 0 ? 1 : -1);
|
|
32801
|
+
const normalX = -dy / length;
|
|
32802
|
+
const normalY = dx / length;
|
|
32803
|
+
return {
|
|
32804
|
+
x: (start.x + end.x) / 2 + normalX * offset,
|
|
32805
|
+
y: (start.y + end.y) / 2 + normalY * offset
|
|
32806
|
+
};
|
|
32807
|
+
}
|
|
32808
|
+
function sampleQuadraticPoints(start, control, end, count) {
|
|
32809
|
+
const samples = [];
|
|
32810
|
+
for (let index = 0; index <= count; index += 1) {
|
|
32811
|
+
samples.push(samplePointOnQuadratic(start, control, end, index / count));
|
|
32812
|
+
}
|
|
32813
|
+
return samples;
|
|
32814
|
+
}
|
|
32815
|
+
function samplePointOnQuadratic(start, control, end, t) {
|
|
32816
|
+
const inverse = 1 - t;
|
|
32817
|
+
return {
|
|
32818
|
+
x: inverse * inverse * start.x + 2 * inverse * t * control.x + t * t * end.x,
|
|
32819
|
+
y: inverse * inverse * start.y + 2 * inverse * t * control.y + t * t * end.y
|
|
32820
|
+
};
|
|
32821
|
+
}
|
|
32822
|
+
function pointsToPath(points) {
|
|
32823
|
+
if (points.length === 0) {
|
|
32824
|
+
return "";
|
|
32825
|
+
}
|
|
32826
|
+
return points.map((point, index) => `${index === 0 ? "M" : "L"} ${formatPathNumber(point.x)} ${formatPathNumber(point.y)}`).join(" ");
|
|
32827
|
+
}
|
|
32828
|
+
function formatPathNumber(value) {
|
|
32829
|
+
return Number.isFinite(value) ? value.toFixed(2) : "0";
|
|
32830
|
+
}
|
|
32623
32831
|
function createSceneViewpoints(document2, projection, preset, relationships, objectMap) {
|
|
32624
32832
|
const generatedOverview = createGeneratedOverviewViewpoint(document2, projection, preset);
|
|
32625
32833
|
const drafts = /* @__PURE__ */ new Map();
|
|
@@ -32879,14 +33087,14 @@ void main() {
|
|
|
32879
33087
|
next["orbits-front"] = enabled;
|
|
32880
33088
|
continue;
|
|
32881
33089
|
}
|
|
32882
|
-
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "events" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
33090
|
+
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "events" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata" || rawLayer === "trajectories") {
|
|
32883
33091
|
next[rawLayer] = enabled;
|
|
32884
33092
|
}
|
|
32885
33093
|
}
|
|
32886
33094
|
return next;
|
|
32887
33095
|
}
|
|
32888
33096
|
function parseViewpointObjectTypes(value) {
|
|
32889
|
-
return splitListValue(value).filter((entry) => entry === "star" || entry === "planet" || entry === "moon" || entry === "belt" || entry === "asteroid" || entry === "comet" || entry === "ring" || entry === "structure" || entry === "phenomenon");
|
|
33097
|
+
return splitListValue(value).filter((entry) => entry === "star" || entry === "planet" || entry === "moon" || entry === "belt" || entry === "asteroid" || entry === "comet" || entry === "ring" || entry === "craft" || entry === "structure" || entry === "phenomenon");
|
|
32890
33098
|
}
|
|
32891
33099
|
function parseViewpointGroups(value, document2, relationships, objectMap) {
|
|
32892
33100
|
return splitListValue(value).map((entry) => {
|
|
@@ -33507,6 +33715,8 @@ void main() {
|
|
|
33507
33715
|
return clampNumber(6 * multiplier, scaleModel.minBodyRadius, scaleModel.maxBodyRadius);
|
|
33508
33716
|
case "ring":
|
|
33509
33717
|
return clampNumber(5 * multiplier, scaleModel.minBodyRadius, scaleModel.maxBodyRadius);
|
|
33718
|
+
case "craft":
|
|
33719
|
+
return clampNumber(5 * multiplier, scaleModel.minBodyRadius, scaleModel.maxBodyRadius);
|
|
33510
33720
|
case "structure":
|
|
33511
33721
|
return clampNumber(6 * multiplier, scaleModel.minBodyRadius, scaleModel.maxBodyRadius);
|
|
33512
33722
|
case "phenomenon":
|
|
@@ -33520,6 +33730,8 @@ void main() {
|
|
|
33520
33730
|
return radius * 2.4;
|
|
33521
33731
|
case "phenomenon":
|
|
33522
33732
|
return radius * 1.25;
|
|
33733
|
+
case "craft":
|
|
33734
|
+
return radius + 1.5;
|
|
33523
33735
|
case "structure":
|
|
33524
33736
|
return radius + 2;
|
|
33525
33737
|
default:
|
|
@@ -33725,6 +33937,7 @@ void main() {
|
|
|
33725
33937
|
const spatialObjects = scene.objects.map((entry) => createSpatialObject(entry, scene, sceneCenter, objectMap, orbitMap, scaleModel, positionCache, minimumMotionMetric));
|
|
33726
33938
|
const spatialObjectMap = new Map(spatialObjects.map((object) => [object.objectId, object]));
|
|
33727
33939
|
const spatialOrbits = scene.orbitVisuals.map((orbit) => createSpatialOrbit(orbit, spatialObjectMap, minimumMotionMetric, scene.activeEventId !== null));
|
|
33940
|
+
const spatialTrajectories = scene.trajectories.map((trajectory) => createSpatialTrajectory(trajectory, spatialObjectMap));
|
|
33728
33941
|
const focusTargets = spatialObjects.map((object) => ({
|
|
33729
33942
|
objectId: object.objectId,
|
|
33730
33943
|
center: { ...object.position },
|
|
@@ -33754,6 +33967,7 @@ void main() {
|
|
|
33754
33967
|
timeFrozen: scene.activeEventId !== null,
|
|
33755
33968
|
objects: spatialObjects,
|
|
33756
33969
|
orbits: spatialOrbits,
|
|
33970
|
+
trajectories: spatialTrajectories,
|
|
33757
33971
|
focusTargets
|
|
33758
33972
|
};
|
|
33759
33973
|
}
|
|
@@ -33801,6 +34015,39 @@ void main() {
|
|
|
33801
34015
|
motion: owner?.motion ?? createMotionModel(orbit.object, orbit, minimumMotionMetric, frozen)
|
|
33802
34016
|
};
|
|
33803
34017
|
}
|
|
34018
|
+
function createSpatialTrajectory(trajectory, objectMap) {
|
|
34019
|
+
const samples = samplePathPoints(trajectory.path).map((point) => ({
|
|
34020
|
+
x: point.x,
|
|
34021
|
+
y: 0,
|
|
34022
|
+
z: point.y
|
|
34023
|
+
}));
|
|
34024
|
+
return {
|
|
34025
|
+
trajectoryId: trajectory.trajectoryId,
|
|
34026
|
+
trajectory: trajectory.trajectory,
|
|
34027
|
+
craftObjectId: trajectory.craftObjectId,
|
|
34028
|
+
mode: trajectory.mode,
|
|
34029
|
+
stroke: trajectory.stroke,
|
|
34030
|
+
strokeWidth: trajectory.strokeWidth,
|
|
34031
|
+
marker: trajectory.marker,
|
|
34032
|
+
labelMode: trajectory.labelMode,
|
|
34033
|
+
showWaypoints: trajectory.showWaypoints,
|
|
34034
|
+
samples,
|
|
34035
|
+
waypoints: trajectory.waypoints.map((waypoint) => {
|
|
34036
|
+
const object = waypoint.objectId ? objectMap.get(waypoint.objectId) ?? null : null;
|
|
34037
|
+
return {
|
|
34038
|
+
trajectoryId: waypoint.trajectoryId,
|
|
34039
|
+
segmentId: waypoint.segmentId,
|
|
34040
|
+
maneuverId: waypoint.maneuverId,
|
|
34041
|
+
objectId: waypoint.objectId,
|
|
34042
|
+
position: object ? { ...object.position } : { x: waypoint.x, y: 0, z: waypoint.y },
|
|
34043
|
+
label: waypoint.label,
|
|
34044
|
+
dateLabel: waypoint.dateLabel,
|
|
34045
|
+
hidden: waypoint.hidden
|
|
34046
|
+
};
|
|
34047
|
+
}),
|
|
34048
|
+
hidden: trajectory.hidden
|
|
34049
|
+
};
|
|
34050
|
+
}
|
|
33804
34051
|
function resolveSpatialObjectPosition(entry, scene, sceneCenter, objectMap, orbitMap, cache) {
|
|
33805
34052
|
const cached = cache.get(entry.objectId);
|
|
33806
34053
|
if (cached) {
|
|
@@ -34084,6 +34331,54 @@ void main() {
|
|
|
34084
34331
|
function degreesToRadians2(value) {
|
|
34085
34332
|
return value * Math.PI / 180;
|
|
34086
34333
|
}
|
|
34334
|
+
function samplePathPoints(path) {
|
|
34335
|
+
const matches = [...path.matchAll(/[MLQ]\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)(?:\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?))?(?:\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?))?/g)];
|
|
34336
|
+
if (matches.length === 0) {
|
|
34337
|
+
return [];
|
|
34338
|
+
}
|
|
34339
|
+
const points = [];
|
|
34340
|
+
for (const match of matches) {
|
|
34341
|
+
const command = match[0][0];
|
|
34342
|
+
if (command === "M" || command === "L") {
|
|
34343
|
+
points.push({ x: Number(match[1]), y: Number(match[2]) });
|
|
34344
|
+
continue;
|
|
34345
|
+
}
|
|
34346
|
+
if (command === "Q") {
|
|
34347
|
+
points.push({ x: Number(match[1]), y: Number(match[2]) });
|
|
34348
|
+
points.push({ x: Number(match[5]), y: Number(match[6]) });
|
|
34349
|
+
}
|
|
34350
|
+
}
|
|
34351
|
+
return points;
|
|
34352
|
+
}
|
|
34353
|
+
|
|
34354
|
+
// packages/core/dist/solver.js
|
|
34355
|
+
function createTrajectorySolverSnapshot(trajectory) {
|
|
34356
|
+
return {
|
|
34357
|
+
trajectoryId: trajectory.id,
|
|
34358
|
+
craftObjectId: trajectory.craftObjectId,
|
|
34359
|
+
segments: trajectory.segments.map((segment) => ({
|
|
34360
|
+
segmentId: segment.id,
|
|
34361
|
+
kind: segment.kind,
|
|
34362
|
+
fromObjectId: segment.fromObjectId,
|
|
34363
|
+
toObjectId: segment.toObjectId,
|
|
34364
|
+
aroundObjectId: segment.aroundObjectId,
|
|
34365
|
+
assistObjectId: segment.assist?.objectId ?? null,
|
|
34366
|
+
duration: segment.duration ?? null,
|
|
34367
|
+
deltaV: segment.deltaV ?? null
|
|
34368
|
+
})),
|
|
34369
|
+
maneuvers: trajectory.segments.flatMap((segment) => segment.maneuvers.map((maneuver) => mapManeuver(segment.id, maneuver)))
|
|
34370
|
+
};
|
|
34371
|
+
}
|
|
34372
|
+
function mapManeuver(segmentId, maneuver) {
|
|
34373
|
+
return {
|
|
34374
|
+
segmentId,
|
|
34375
|
+
maneuverId: maneuver.id,
|
|
34376
|
+
kind: maneuver.kind,
|
|
34377
|
+
epoch: maneuver.epoch,
|
|
34378
|
+
deltaV: maneuver.deltaV ?? null,
|
|
34379
|
+
duration: maneuver.duration ?? null
|
|
34380
|
+
};
|
|
34381
|
+
}
|
|
34087
34382
|
|
|
34088
34383
|
// packages/core/dist/draft.js
|
|
34089
34384
|
function upgradeDocumentToV2(document2, options = {}) {
|
|
@@ -34103,15 +34398,16 @@ void main() {
|
|
|
34103
34398
|
}
|
|
34104
34399
|
return {
|
|
34105
34400
|
format: "worldorbit",
|
|
34106
|
-
version: "
|
|
34107
|
-
schemaVersion: "
|
|
34401
|
+
version: "3.1",
|
|
34402
|
+
schemaVersion: "3.1",
|
|
34108
34403
|
sourceVersion: document2.version,
|
|
34109
34404
|
theme: document2.theme ?? null,
|
|
34110
34405
|
system,
|
|
34111
34406
|
groups: structuredClone(document2.groups ?? []),
|
|
34112
34407
|
relations: structuredClone(document2.relations ?? []),
|
|
34113
34408
|
events: structuredClone(document2.events ?? []),
|
|
34114
|
-
|
|
34409
|
+
trajectories: structuredClone(document2.trajectories ?? []),
|
|
34410
|
+
objects: document2.objects.map(cloneWorldOrbitObject).map(normalizeLegacyCraftObject),
|
|
34115
34411
|
diagnostics
|
|
34116
34412
|
};
|
|
34117
34413
|
}
|
|
@@ -34140,6 +34436,7 @@ void main() {
|
|
|
34140
34436
|
groups: structuredClone(document2.groups ?? []),
|
|
34141
34437
|
relations: structuredClone(document2.relations ?? []),
|
|
34142
34438
|
events: document2.events.map(cloneWorldOrbitEvent),
|
|
34439
|
+
trajectories: document2.trajectories.map(cloneWorldOrbitTrajectory),
|
|
34143
34440
|
objects
|
|
34144
34441
|
};
|
|
34145
34442
|
}
|
|
@@ -34287,6 +34584,7 @@ void main() {
|
|
|
34287
34584
|
function cloneWorldOrbitObject(object) {
|
|
34288
34585
|
return {
|
|
34289
34586
|
...object,
|
|
34587
|
+
trajectoryId: object.trajectoryId ?? null,
|
|
34290
34588
|
groups: object.groups ? [...object.groups] : void 0,
|
|
34291
34589
|
resonance: object.resonance ? { ...object.resonance } : object.resonance,
|
|
34292
34590
|
renderHints: object.renderHints ? { ...object.renderHints } : object.renderHints,
|
|
@@ -34306,6 +34604,7 @@ void main() {
|
|
|
34306
34604
|
function cloneWorldOrbitEvent(event) {
|
|
34307
34605
|
return {
|
|
34308
34606
|
...event,
|
|
34607
|
+
trajectoryId: event.trajectoryId ?? null,
|
|
34309
34608
|
participantObjectIds: [...event.participantObjectIds],
|
|
34310
34609
|
tags: [...event.tags],
|
|
34311
34610
|
positions: event.positions.map(cloneWorldOrbitEventPose)
|
|
@@ -34315,12 +34614,30 @@ void main() {
|
|
|
34315
34614
|
return {
|
|
34316
34615
|
objectId: pose.objectId,
|
|
34317
34616
|
placement: clonePlacement(pose.placement),
|
|
34617
|
+
trajectorySegmentId: pose.trajectorySegmentId ?? null,
|
|
34618
|
+
trajectoryManeuverId: pose.trajectoryManeuverId ?? null,
|
|
34318
34619
|
inner: pose.inner ? { ...pose.inner } : void 0,
|
|
34319
34620
|
outer: pose.outer ? { ...pose.outer } : void 0,
|
|
34320
34621
|
epoch: pose.epoch ?? null,
|
|
34321
34622
|
referencePlane: pose.referencePlane ?? null
|
|
34322
34623
|
};
|
|
34323
34624
|
}
|
|
34625
|
+
function cloneWorldOrbitTrajectory(trajectory) {
|
|
34626
|
+
return structuredClone(trajectory);
|
|
34627
|
+
}
|
|
34628
|
+
function normalizeLegacyCraftObject(object) {
|
|
34629
|
+
if (object.type !== "structure") {
|
|
34630
|
+
return object;
|
|
34631
|
+
}
|
|
34632
|
+
const kind = typeof object.properties.kind === "string" ? object.properties.kind.toLowerCase() : "";
|
|
34633
|
+
if (!["ship", "probe", "station"].includes(kind)) {
|
|
34634
|
+
return object;
|
|
34635
|
+
}
|
|
34636
|
+
return {
|
|
34637
|
+
...object,
|
|
34638
|
+
type: "craft"
|
|
34639
|
+
};
|
|
34640
|
+
}
|
|
34324
34641
|
function clonePlacement(placement) {
|
|
34325
34642
|
return placement ? structuredClone(placement) : null;
|
|
34326
34643
|
}
|
|
@@ -34508,7 +34825,7 @@ void main() {
|
|
|
34508
34825
|
if (orbitFront !== void 0 || orbitBack !== void 0) {
|
|
34509
34826
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
34510
34827
|
}
|
|
34511
|
-
for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
|
|
34828
|
+
for (const key of ["background", "guides", "relations", "events", "objects", "trajectories", "labels", "metadata"]) {
|
|
34512
34829
|
if (layers[key] !== void 0) {
|
|
34513
34830
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
34514
34831
|
}
|
|
@@ -34561,7 +34878,7 @@ void main() {
|
|
|
34561
34878
|
];
|
|
34562
34879
|
function formatDocument(document2, options = {}) {
|
|
34563
34880
|
const schema = options.schema ?? "auto";
|
|
34564
|
-
const useDraft = schema === "2.0" || schema === "2.1" || schema === "2.5" || schema === "2.6" || schema === "2.0-draft" || document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.5" || document2.version === "2.6" || document2.version === "2.0-draft";
|
|
34881
|
+
const useDraft = schema === "2.0" || schema === "2.1" || schema === "2.5" || schema === "2.6" || schema === "3.0" || schema === "3.1" || schema === "2.0-draft" || document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.5" || document2.version === "3.0" || document2.version === "3.1" || document2.version === "2.6" || document2.version === "2.0-draft";
|
|
34565
34882
|
if (useDraft) {
|
|
34566
34883
|
if (schema === "2.0-draft") {
|
|
34567
34884
|
const legacyDraftDocument = document2.version === "2.0-draft" ? document2 : document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.5" || document2.version === "2.6" ? {
|
|
@@ -34571,12 +34888,12 @@ void main() {
|
|
|
34571
34888
|
} : upgradeDocumentToDraftV2(document2);
|
|
34572
34889
|
return formatDraftDocument(legacyDraftDocument);
|
|
34573
34890
|
}
|
|
34574
|
-
const atlasDocument = document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.5" || document2.version === "2.6" ? document2 : document2.version === "2.0-draft" ? {
|
|
34891
|
+
const atlasDocument = document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.5" || document2.version === "2.6" || document2.version === "3.0" || document2.version === "3.1" ? document2 : document2.version === "2.0-draft" ? {
|
|
34575
34892
|
...document2,
|
|
34576
34893
|
version: "2.0",
|
|
34577
34894
|
schemaVersion: "2.0"
|
|
34578
34895
|
} : upgradeDocumentToV2(document2);
|
|
34579
|
-
if ((schema === "2.0" || schema === "2.1" || schema === "2.5" || schema === "2.6") && atlasDocument.version !== schema) {
|
|
34896
|
+
if ((schema === "2.0" || schema === "2.1" || schema === "2.5" || schema === "2.6" || schema === "3.0" || schema === "3.1") && atlasDocument.version !== schema) {
|
|
34580
34897
|
return formatAtlasDocument({
|
|
34581
34898
|
...atlasDocument,
|
|
34582
34899
|
version: schema,
|
|
@@ -34616,6 +34933,10 @@ void main() {
|
|
|
34616
34933
|
lines.push("");
|
|
34617
34934
|
lines.push(...formatAtlasEvent(event));
|
|
34618
34935
|
}
|
|
34936
|
+
for (const trajectory of [...document2.trajectories].sort(compareIdLike)) {
|
|
34937
|
+
lines.push("");
|
|
34938
|
+
lines.push(...formatAtlasTrajectory(trajectory));
|
|
34939
|
+
}
|
|
34619
34940
|
const sortedObjects = [...document2.objects].sort(compareObjects);
|
|
34620
34941
|
if (sortedObjects.length > 0 && lines.at(-1) !== "") {
|
|
34621
34942
|
lines.push("");
|
|
@@ -34799,6 +35120,9 @@ void main() {
|
|
|
34799
35120
|
if (object.groups?.length) {
|
|
34800
35121
|
lines.push(`groups ${object.groups.join(" ")}`);
|
|
34801
35122
|
}
|
|
35123
|
+
if (object.trajectoryId) {
|
|
35124
|
+
lines.push(`trajectory ${object.trajectoryId}`);
|
|
35125
|
+
}
|
|
34802
35126
|
if (object.epoch) {
|
|
34803
35127
|
lines.push(`epoch ${quoteIfNeeded(object.epoch)}`);
|
|
34804
35128
|
}
|
|
@@ -34959,6 +35283,9 @@ void main() {
|
|
|
34959
35283
|
if (event.summary) {
|
|
34960
35284
|
lines.push(` summary ${quoteIfNeeded(event.summary)}`);
|
|
34961
35285
|
}
|
|
35286
|
+
if (event.trajectoryId) {
|
|
35287
|
+
lines.push(` trajectory ${event.trajectoryId}`);
|
|
35288
|
+
}
|
|
34962
35289
|
if (event.targetObjectId) {
|
|
34963
35290
|
lines.push(` target ${event.targetObjectId}`);
|
|
34964
35291
|
}
|
|
@@ -35001,12 +35328,102 @@ void main() {
|
|
|
35001
35328
|
function formatEventPoseFields(pose) {
|
|
35002
35329
|
return [
|
|
35003
35330
|
...formatPlacement(pose.placement),
|
|
35331
|
+
...pose.trajectorySegmentId ? [`segment ${pose.trajectorySegmentId}`] : [],
|
|
35332
|
+
...pose.trajectoryManeuverId ? [`maneuver ${pose.trajectoryManeuverId}`] : [],
|
|
35004
35333
|
...pose.epoch ? [`epoch ${quoteIfNeeded(pose.epoch)}`] : [],
|
|
35005
35334
|
...pose.referencePlane ? [`referencePlane ${quoteIfNeeded(pose.referencePlane)}`] : [],
|
|
35006
35335
|
...formatOptionalUnit("inner", pose.inner),
|
|
35007
35336
|
...formatOptionalUnit("outer", pose.outer)
|
|
35008
35337
|
];
|
|
35009
35338
|
}
|
|
35339
|
+
function formatAtlasTrajectory(trajectory) {
|
|
35340
|
+
const lines = [`trajectory ${trajectory.id}`];
|
|
35341
|
+
if (trajectory.label) {
|
|
35342
|
+
lines.push(` label ${quoteIfNeeded(trajectory.label)}`);
|
|
35343
|
+
}
|
|
35344
|
+
if (trajectory.summary) {
|
|
35345
|
+
lines.push(` summary ${quoteIfNeeded(trajectory.summary)}`);
|
|
35346
|
+
}
|
|
35347
|
+
if (trajectory.craftObjectId) {
|
|
35348
|
+
lines.push(` craft ${trajectory.craftObjectId}`);
|
|
35349
|
+
}
|
|
35350
|
+
if (trajectory.tags.length > 0) {
|
|
35351
|
+
lines.push(` tags ${trajectory.tags.map(quoteIfNeeded).join(" ")}`);
|
|
35352
|
+
}
|
|
35353
|
+
if (trajectory.color) {
|
|
35354
|
+
lines.push(` color ${quoteIfNeeded(trajectory.color)}`);
|
|
35355
|
+
}
|
|
35356
|
+
if (trajectory.renderMode) {
|
|
35357
|
+
lines.push(` renderMode ${trajectory.renderMode}`);
|
|
35358
|
+
}
|
|
35359
|
+
if (trajectory.stroke) {
|
|
35360
|
+
lines.push(` stroke ${quoteIfNeeded(trajectory.stroke)}`);
|
|
35361
|
+
}
|
|
35362
|
+
if (trajectory.strokeWidth !== null && trajectory.strokeWidth !== void 0) {
|
|
35363
|
+
lines.push(` strokeWidth ${trajectory.strokeWidth}`);
|
|
35364
|
+
}
|
|
35365
|
+
if (trajectory.marker) {
|
|
35366
|
+
lines.push(` marker ${quoteIfNeeded(trajectory.marker)}`);
|
|
35367
|
+
}
|
|
35368
|
+
if (trajectory.labelMode) {
|
|
35369
|
+
lines.push(` labelMode ${quoteIfNeeded(trajectory.labelMode)}`);
|
|
35370
|
+
}
|
|
35371
|
+
if (trajectory.showWaypoints !== null && trajectory.showWaypoints !== void 0) {
|
|
35372
|
+
lines.push(` showWaypoints ${trajectory.showWaypoints ? "true" : "false"}`);
|
|
35373
|
+
}
|
|
35374
|
+
if (trajectory.hidden) {
|
|
35375
|
+
lines.push(" hidden true");
|
|
35376
|
+
}
|
|
35377
|
+
for (const segment of [...trajectory.segments].sort(compareIdLike)) {
|
|
35378
|
+
lines.push("");
|
|
35379
|
+
lines.push(` segment ${segment.id}`);
|
|
35380
|
+
for (const field of formatTrajectorySegmentFields(segment)) {
|
|
35381
|
+
lines.push(` ${field}`);
|
|
35382
|
+
}
|
|
35383
|
+
for (const maneuver of [...segment.maneuvers].sort(compareIdLike)) {
|
|
35384
|
+
lines.push(` maneuver ${maneuver.id}`);
|
|
35385
|
+
for (const field of formatTrajectoryManeuverFields(maneuver)) {
|
|
35386
|
+
lines.push(` ${field}`);
|
|
35387
|
+
}
|
|
35388
|
+
}
|
|
35389
|
+
}
|
|
35390
|
+
return lines;
|
|
35391
|
+
}
|
|
35392
|
+
function formatTrajectorySegmentFields(segment) {
|
|
35393
|
+
return [
|
|
35394
|
+
`kind ${segment.kind}`,
|
|
35395
|
+
...segment.label ? [`label ${quoteIfNeeded(segment.label)}`] : [],
|
|
35396
|
+
...segment.summary ? [`summary ${quoteIfNeeded(segment.summary)}`] : [],
|
|
35397
|
+
...segment.fromObjectId ? [`from ${segment.fromObjectId}`] : [],
|
|
35398
|
+
...segment.toObjectId ? [`to ${segment.toObjectId}`] : [],
|
|
35399
|
+
...segment.aroundObjectId ? [`around ${segment.aroundObjectId}`] : [],
|
|
35400
|
+
...segment.assist?.objectId ? [`assist ${segment.assist.objectId}`] : [],
|
|
35401
|
+
...segment.epoch ? [`epoch ${quoteIfNeeded(segment.epoch)}`] : [],
|
|
35402
|
+
...formatOptionalUnit("periapsis", segment.periapsis),
|
|
35403
|
+
...formatOptionalUnit("apoapsis", segment.apoapsis),
|
|
35404
|
+
...formatOptionalUnit("inclination", segment.inclination),
|
|
35405
|
+
...formatOptionalUnit("duration", segment.duration),
|
|
35406
|
+
...formatOptionalUnit("deltaV", segment.deltaV),
|
|
35407
|
+
...formatOptionalUnit("phaseAngle", segment.phaseAngle),
|
|
35408
|
+
...formatOptionalUnit("turnAngle", segment.turnAngle),
|
|
35409
|
+
...formatOptionalUnit("energy", segment.energy),
|
|
35410
|
+
...segment.waypointLabel ? [`waypointLabel ${quoteIfNeeded(segment.waypointLabel)}`] : [],
|
|
35411
|
+
...segment.waypointDate ? [`waypointDate ${quoteIfNeeded(segment.waypointDate)}`] : [],
|
|
35412
|
+
...segment.renderHidden !== null && segment.renderHidden !== void 0 ? [`renderHidden ${segment.renderHidden ? "true" : "false"}`] : [],
|
|
35413
|
+
...segment.sampleDensity !== null && segment.sampleDensity !== void 0 ? [`sampleDensity ${segment.sampleDensity}`] : [],
|
|
35414
|
+
...segment.notes.length > 0 ? [`notes ${segment.notes.map(quoteIfNeeded).join(" ")}`] : []
|
|
35415
|
+
];
|
|
35416
|
+
}
|
|
35417
|
+
function formatTrajectoryManeuverFields(maneuver) {
|
|
35418
|
+
return [
|
|
35419
|
+
`kind ${quoteIfNeeded(maneuver.kind)}`,
|
|
35420
|
+
...maneuver.label ? [`label ${quoteIfNeeded(maneuver.label)}`] : [],
|
|
35421
|
+
...maneuver.epoch ? [`epoch ${quoteIfNeeded(maneuver.epoch)}`] : [],
|
|
35422
|
+
...formatOptionalUnit("deltaV", maneuver.deltaV),
|
|
35423
|
+
...formatOptionalUnit("duration", maneuver.duration),
|
|
35424
|
+
...maneuver.notes.length > 0 ? [`notes ${maneuver.notes.map(quoteIfNeeded).join(" ")}`] : []
|
|
35425
|
+
];
|
|
35426
|
+
}
|
|
35010
35427
|
function hasCameraValues(camera) {
|
|
35011
35428
|
return camera.azimuth !== null || camera.elevation !== null || camera.roll !== null || camera.distance !== null;
|
|
35012
35429
|
}
|
|
@@ -35051,7 +35468,7 @@ void main() {
|
|
|
35051
35468
|
if (orbitFront !== void 0 || orbitBack !== void 0) {
|
|
35052
35469
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
35053
35470
|
}
|
|
35054
|
-
for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
|
|
35471
|
+
for (const key of ["background", "guides", "relations", "events", "objects", "trajectories", "labels", "metadata"]) {
|
|
35055
35472
|
if (layers[key] !== void 0) {
|
|
35056
35473
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
35057
35474
|
}
|
|
@@ -35098,10 +35515,12 @@ void main() {
|
|
|
35098
35515
|
return 5;
|
|
35099
35516
|
case "ring":
|
|
35100
35517
|
return 6;
|
|
35101
|
-
case "
|
|
35518
|
+
case "craft":
|
|
35102
35519
|
return 7;
|
|
35103
|
-
case "
|
|
35520
|
+
case "structure":
|
|
35104
35521
|
return 8;
|
|
35522
|
+
case "phenomenon":
|
|
35523
|
+
return 9;
|
|
35105
35524
|
}
|
|
35106
35525
|
}
|
|
35107
35526
|
function quoteIfNeeded(value) {
|
|
@@ -35278,6 +35697,7 @@ void main() {
|
|
|
35278
35697
|
const objectMap = new Map(document2.objects.map((object) => [object.id, object]));
|
|
35279
35698
|
const groupIds = new Set(document2.groups.map((group) => group.id));
|
|
35280
35699
|
const eventIds = new Set(document2.events.map((event) => event.id));
|
|
35700
|
+
const trajectoryMap = new Map(document2.trajectories.map((trajectory) => [trajectory.id, trajectory]));
|
|
35281
35701
|
if (!document2.system) {
|
|
35282
35702
|
diagnostics.push(error("validate.system.required", "Atlas documents must declare exactly one system."));
|
|
35283
35703
|
}
|
|
@@ -35288,6 +35708,7 @@ void main() {
|
|
|
35288
35708
|
["annotation", document2.system?.annotations.map((annotation) => annotation.id) ?? []],
|
|
35289
35709
|
["relation", document2.relations.map((relation) => relation.id)],
|
|
35290
35710
|
["event", document2.events.map((event) => event.id)],
|
|
35711
|
+
["trajectory", document2.trajectories.map((trajectory) => trajectory.id)],
|
|
35291
35712
|
["object", document2.objects.map((object) => object.id)]
|
|
35292
35713
|
]) {
|
|
35293
35714
|
for (const id of ids) {
|
|
@@ -35306,10 +35727,13 @@ void main() {
|
|
|
35306
35727
|
validateViewpoint(viewpoint, groupIds, eventIds, sourceSchemaVersion, diagnostics, objectMap);
|
|
35307
35728
|
}
|
|
35308
35729
|
for (const object of document2.objects) {
|
|
35309
|
-
validateObject(object, document2.system, objectMap, groupIds, diagnostics);
|
|
35730
|
+
validateObject(object, document2.system, objectMap, groupIds, trajectoryMap, diagnostics);
|
|
35310
35731
|
}
|
|
35311
35732
|
for (const event of document2.events) {
|
|
35312
|
-
validateEvent(event, document2.system, objectMap, diagnostics);
|
|
35733
|
+
validateEvent(event, document2.system, objectMap, trajectoryMap, diagnostics);
|
|
35734
|
+
}
|
|
35735
|
+
for (const trajectory of document2.trajectories) {
|
|
35736
|
+
validateTrajectory(trajectory, objectMap, diagnostics);
|
|
35313
35737
|
}
|
|
35314
35738
|
return diagnostics;
|
|
35315
35739
|
}
|
|
@@ -35347,7 +35771,7 @@ void main() {
|
|
|
35347
35771
|
validateProjection(viewpoint.projection, diagnostics, `viewpoint.${viewpoint.id}.projection`, viewpoint.id);
|
|
35348
35772
|
validateCamera(viewpoint.camera, viewpoint.projection, viewpoint.rotationDeg, diagnostics, viewpoint.id, viewpoint.focusObjectId, viewpoint.selectedObjectId, filter, objectMap);
|
|
35349
35773
|
}
|
|
35350
|
-
function validateObject(object, system, objectMap, groupIds, diagnostics) {
|
|
35774
|
+
function validateObject(object, system, objectMap, groupIds, trajectoryMap, diagnostics) {
|
|
35351
35775
|
const placement = object.placement;
|
|
35352
35776
|
const orbitPlacement = placement?.mode === "orbit" ? placement : null;
|
|
35353
35777
|
const parentObject = placement?.mode === "orbit" ? objectMap.get(placement.target) ?? null : null;
|
|
@@ -35364,6 +35788,13 @@ void main() {
|
|
|
35364
35788
|
if (typeof object.referencePlane === "string" && !object.referencePlane.trim()) {
|
|
35365
35789
|
diagnostics.push(warn("validate.referencePlane.empty", `Object "${object.id}" defines an empty reference plane string.`, object.id, "referencePlane"));
|
|
35366
35790
|
}
|
|
35791
|
+
if (object.trajectoryId) {
|
|
35792
|
+
if (!trajectoryMap.has(object.trajectoryId)) {
|
|
35793
|
+
diagnostics.push(error("validate.trajectory.object.unknown", `Unknown trajectory "${object.trajectoryId}" on "${object.id}".`, object.id, "trajectory"));
|
|
35794
|
+
} else if (!isTrajectoryCapableObject(object)) {
|
|
35795
|
+
diagnostics.push(error("validate.trajectory.object.invalidType", `Only craft or legacy ship-like structures may reference trajectories; found "${object.type}" on "${object.id}".`, object.id, "trajectory"));
|
|
35796
|
+
}
|
|
35797
|
+
}
|
|
35367
35798
|
if (orbitPlacement) {
|
|
35368
35799
|
if (!objectMap.has(orbitPlacement.target)) {
|
|
35369
35800
|
diagnostics.push(error("validate.orbit.target.unknown", `Unknown placement target "${orbitPlacement.target}" on "${object.id}".`, object.id, "orbit"));
|
|
@@ -35390,8 +35821,8 @@ void main() {
|
|
|
35390
35821
|
}
|
|
35391
35822
|
}
|
|
35392
35823
|
if (placement?.mode === "at") {
|
|
35393
|
-
if (object.type !== "structure" && object.type !== "phenomenon") {
|
|
35394
|
-
diagnostics.push(error("validate.at.objectType", `Only structures and phenomena may use "at" placement; found "${object.type}" on "${object.id}".`, object.id, "at"));
|
|
35824
|
+
if (object.type !== "craft" && object.type !== "structure" && object.type !== "phenomenon") {
|
|
35825
|
+
diagnostics.push(error("validate.at.objectType", `Only craft, structures, and phenomena may use "at" placement; found "${object.type}" on "${object.id}".`, object.id, "at"));
|
|
35395
35826
|
}
|
|
35396
35827
|
if (!validateAtTarget(object, objectMap, diagnostics)) {
|
|
35397
35828
|
diagnostics.push(error("validate.at.target.unknown", `Unknown at-reference target "${placement.target}" on "${object.id}".`, object.id, "at"));
|
|
@@ -35435,7 +35866,7 @@ void main() {
|
|
|
35435
35866
|
}
|
|
35436
35867
|
}
|
|
35437
35868
|
}
|
|
35438
|
-
function validateEvent(event, system, objectMap, diagnostics) {
|
|
35869
|
+
function validateEvent(event, system, objectMap, trajectoryMap, diagnostics) {
|
|
35439
35870
|
const fieldPrefix = `event.${event.id}`;
|
|
35440
35871
|
const referencedIds = /* @__PURE__ */ new Set();
|
|
35441
35872
|
if (!event.kind.trim()) {
|
|
@@ -35447,6 +35878,9 @@ void main() {
|
|
|
35447
35878
|
if (typeof event.referencePlane === "string" && !event.referencePlane.trim()) {
|
|
35448
35879
|
diagnostics.push(warn("validate.event.referencePlane.empty", `Event "${event.id}" defines an empty reference plane string.`, void 0, `${fieldPrefix}.referencePlane`));
|
|
35449
35880
|
}
|
|
35881
|
+
if (event.trajectoryId && !trajectoryMap.has(event.trajectoryId)) {
|
|
35882
|
+
diagnostics.push(error("validate.event.trajectory.unknown", `Unknown trajectory "${event.trajectoryId}" on event "${event.id}".`, void 0, `${fieldPrefix}.trajectory`));
|
|
35883
|
+
}
|
|
35450
35884
|
if (!event.targetObjectId && event.participantObjectIds.length === 0) {
|
|
35451
35885
|
diagnostics.push(error("validate.event.references.required", `Event "${event.id}" must define a "target" or at least one participant.`, void 0, `${fieldPrefix}.participants`));
|
|
35452
35886
|
}
|
|
@@ -35493,19 +35927,25 @@ void main() {
|
|
|
35493
35927
|
if (!referencedIds.has(pose.objectId)) {
|
|
35494
35928
|
diagnostics.push(warn("validate.event.pose.unreferenced", `Event pose "${pose.objectId}" on "${event.id}" is not listed in target/participants.`, void 0, poseFieldPrefix));
|
|
35495
35929
|
}
|
|
35496
|
-
validateEventPose(pose, object, event, system, objectMap, diagnostics, poseFieldPrefix, event.id);
|
|
35930
|
+
validateEventPose(pose, object, event, system, objectMap, trajectoryMap, diagnostics, poseFieldPrefix, event.id);
|
|
35497
35931
|
}
|
|
35498
35932
|
const missingPoseIds = [...referencedIds].filter((objectId) => !poseIds.has(objectId));
|
|
35499
35933
|
if (event.positions.length > 0 && missingPoseIds.length > 0) {
|
|
35500
35934
|
diagnostics.push(warn("validate.event.positions.partial", `Event "${event.id}" leaves ${missingPoseIds.length} referenced object(s) on their base placement.`, void 0, `${fieldPrefix}.positions`));
|
|
35501
35935
|
}
|
|
35502
35936
|
}
|
|
35503
|
-
function validateEventPose(pose, object, event, system, objectMap, diagnostics, fieldPrefix, eventId) {
|
|
35937
|
+
function validateEventPose(pose, object, event, system, objectMap, trajectoryMap, diagnostics, fieldPrefix, eventId) {
|
|
35504
35938
|
const placement = pose.placement;
|
|
35505
35939
|
if (!placement) {
|
|
35506
35940
|
diagnostics.push(error("validate.event.pose.placement.required", `Event "${eventId}" pose "${pose.objectId}" is missing a placement mode.`, void 0, fieldPrefix));
|
|
35507
35941
|
return;
|
|
35508
35942
|
}
|
|
35943
|
+
if (pose.trajectorySegmentId && !findTrajectorySegment(trajectoryMap, pose.trajectorySegmentId)) {
|
|
35944
|
+
diagnostics.push(error("validate.event.pose.segment.unknown", `Unknown trajectory segment "${pose.trajectorySegmentId}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.segment`));
|
|
35945
|
+
}
|
|
35946
|
+
if (pose.trajectoryManeuverId && !findTrajectoryManeuver(trajectoryMap, pose.trajectoryManeuverId)) {
|
|
35947
|
+
diagnostics.push(error("validate.event.pose.maneuver.unknown", `Unknown trajectory maneuver "${pose.trajectoryManeuverId}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.maneuver`));
|
|
35948
|
+
}
|
|
35509
35949
|
if (placement.mode === "orbit") {
|
|
35510
35950
|
if (!objectMap.has(placement.target)) {
|
|
35511
35951
|
diagnostics.push(error("validate.event.pose.orbit.target.unknown", `Unknown event orbit target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.orbit`));
|
|
@@ -35534,8 +35974,8 @@ void main() {
|
|
|
35534
35974
|
return;
|
|
35535
35975
|
}
|
|
35536
35976
|
if (placement.mode === "at") {
|
|
35537
|
-
if (object.type !== "structure" && object.type !== "phenomenon") {
|
|
35538
|
-
diagnostics.push(error("validate.event.pose.at.objectType", `Only structures and phenomena may use "at" placement in events; found "${object.type}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
35977
|
+
if (object.type !== "craft" && object.type !== "structure" && object.type !== "phenomenon") {
|
|
35978
|
+
diagnostics.push(error("validate.event.pose.at.objectType", `Only craft, structures, and phenomena may use "at" placement in events; found "${object.type}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
35539
35979
|
}
|
|
35540
35980
|
const reference = placement.reference;
|
|
35541
35981
|
if (reference.kind === "named" && !objectMap.has(reference.name)) {
|
|
@@ -35551,6 +35991,78 @@ void main() {
|
|
|
35551
35991
|
}
|
|
35552
35992
|
}
|
|
35553
35993
|
}
|
|
35994
|
+
function validateTrajectory(trajectory, objectMap, diagnostics) {
|
|
35995
|
+
if (trajectory.craftObjectId) {
|
|
35996
|
+
const craft = objectMap.get(trajectory.craftObjectId);
|
|
35997
|
+
if (!craft) {
|
|
35998
|
+
diagnostics.push(error("validate.trajectory.craft.unknown", `Unknown craft "${trajectory.craftObjectId}" on trajectory "${trajectory.id}".`, void 0, `trajectory.${trajectory.id}.craft`));
|
|
35999
|
+
} else if (!isTrajectoryCapableObject(craft)) {
|
|
36000
|
+
diagnostics.push(error("validate.trajectory.craft.invalidType", `Trajectory "${trajectory.id}" targets "${trajectory.craftObjectId}", which is not craft-like.`, void 0, `trajectory.${trajectory.id}.craft`));
|
|
36001
|
+
}
|
|
36002
|
+
}
|
|
36003
|
+
for (const segment of trajectory.segments) {
|
|
36004
|
+
validateTrajectorySegment(trajectory.id, segment, objectMap, diagnostics);
|
|
36005
|
+
}
|
|
36006
|
+
}
|
|
36007
|
+
function validateTrajectorySegment(trajectoryId, segment, objectMap, diagnostics) {
|
|
36008
|
+
const fieldPrefix = `trajectory.${trajectoryId}.segment.${segment.id}`;
|
|
36009
|
+
for (const [field, objectId] of [
|
|
36010
|
+
["from", segment.fromObjectId],
|
|
36011
|
+
["to", segment.toObjectId],
|
|
36012
|
+
["around", segment.aroundObjectId]
|
|
36013
|
+
]) {
|
|
36014
|
+
if (objectId && !objectMap.has(objectId)) {
|
|
36015
|
+
diagnostics.push(error(`validate.trajectory.segment.${field}.unknown`, `Unknown ${field} object "${objectId}" on trajectory "${trajectoryId}" segment "${segment.id}".`, void 0, `${fieldPrefix}.${field}`));
|
|
36016
|
+
}
|
|
36017
|
+
}
|
|
36018
|
+
if (segment.assist?.objectId && !objectMap.has(segment.assist.objectId)) {
|
|
36019
|
+
diagnostics.push(error("validate.trajectory.segment.assist.unknown", `Unknown assist object "${segment.assist.objectId}" on trajectory "${trajectoryId}" segment "${segment.id}".`, void 0, `${fieldPrefix}.assist`));
|
|
36020
|
+
}
|
|
36021
|
+
if (segment.kind === "flyby" && !segment.assist?.objectId) {
|
|
36022
|
+
diagnostics.push(error("validate.trajectory.segment.assist.required", `Trajectory "${trajectoryId}" segment "${segment.id}" is a flyby and requires an "assist" object.`, void 0, `${fieldPrefix}.assist`));
|
|
36023
|
+
}
|
|
36024
|
+
if ((segment.kind === "capture" || segment.kind === "departure") && !segment.toObjectId && !segment.aroundObjectId) {
|
|
36025
|
+
diagnostics.push(error("validate.trajectory.segment.target.required", `Trajectory "${trajectoryId}" segment "${segment.id}" requires a target reference.`, void 0, `${fieldPrefix}.to`));
|
|
36026
|
+
}
|
|
36027
|
+
for (const maneuver of segment.maneuvers) {
|
|
36028
|
+
validateTrajectoryManeuver(trajectoryId, segment.id, maneuver, diagnostics);
|
|
36029
|
+
}
|
|
36030
|
+
}
|
|
36031
|
+
function validateTrajectoryManeuver(trajectoryId, segmentId, maneuver, diagnostics) {
|
|
36032
|
+
if (!maneuver.kind.trim()) {
|
|
36033
|
+
diagnostics.push(error("validate.trajectory.maneuver.kind.required", `Trajectory "${trajectoryId}" segment "${segmentId}" maneuver "${maneuver.id}" is missing a kind.`, void 0, `trajectory.${trajectoryId}.segment.${segmentId}.maneuver.${maneuver.id}.kind`));
|
|
36034
|
+
}
|
|
36035
|
+
}
|
|
36036
|
+
function isTrajectoryCapableObject(object) {
|
|
36037
|
+
if (object.type === "craft") {
|
|
36038
|
+
return true;
|
|
36039
|
+
}
|
|
36040
|
+
if (object.type !== "structure") {
|
|
36041
|
+
return false;
|
|
36042
|
+
}
|
|
36043
|
+
const kind = typeof object.properties.kind === "string" ? object.properties.kind.toLowerCase() : "";
|
|
36044
|
+
return kind === "ship" || kind === "probe" || kind === "station";
|
|
36045
|
+
}
|
|
36046
|
+
function findTrajectorySegment(trajectories, segmentId) {
|
|
36047
|
+
for (const trajectory of trajectories.values()) {
|
|
36048
|
+
const match = trajectory.segments.find((segment) => segment.id === segmentId);
|
|
36049
|
+
if (match) {
|
|
36050
|
+
return match;
|
|
36051
|
+
}
|
|
36052
|
+
}
|
|
36053
|
+
return null;
|
|
36054
|
+
}
|
|
36055
|
+
function findTrajectoryManeuver(trajectories, maneuverId) {
|
|
36056
|
+
for (const trajectory of trajectories.values()) {
|
|
36057
|
+
for (const segment of trajectory.segments) {
|
|
36058
|
+
const match = segment.maneuvers.find((maneuver) => maneuver.id === maneuverId);
|
|
36059
|
+
if (match) {
|
|
36060
|
+
return match;
|
|
36061
|
+
}
|
|
36062
|
+
}
|
|
36063
|
+
}
|
|
36064
|
+
return null;
|
|
36065
|
+
}
|
|
35554
36066
|
function validateAtTarget(object, objectMap, diagnostics) {
|
|
35555
36067
|
const reference = object.placement?.mode === "at" ? object.placement.reference : null;
|
|
35556
36068
|
if (!reference) {
|
|
@@ -35731,6 +36243,14 @@ void main() {
|
|
|
35731
36243
|
"habitability",
|
|
35732
36244
|
"settlement"
|
|
35733
36245
|
]);
|
|
36246
|
+
var TRAJECTORY_SEGMENT_KINDS = /* @__PURE__ */ new Set([
|
|
36247
|
+
"departure",
|
|
36248
|
+
"transfer",
|
|
36249
|
+
"flyby",
|
|
36250
|
+
"capture",
|
|
36251
|
+
"stationkeeping",
|
|
36252
|
+
"escape"
|
|
36253
|
+
]);
|
|
35734
36254
|
var DRAFT_OBJECT_FIELD_SPECS = /* @__PURE__ */ new Map();
|
|
35735
36255
|
for (const key of [
|
|
35736
36256
|
"orbit",
|
|
@@ -35762,7 +36282,8 @@ void main() {
|
|
|
35762
36282
|
"outer",
|
|
35763
36283
|
"on",
|
|
35764
36284
|
"source",
|
|
35765
|
-
"cycle"
|
|
36285
|
+
"cycle",
|
|
36286
|
+
"trajectory"
|
|
35766
36287
|
]) {
|
|
35767
36288
|
const schema = getFieldSchema(key);
|
|
35768
36289
|
if (schema) {
|
|
@@ -35787,11 +36308,12 @@ void main() {
|
|
|
35787
36308
|
{ key: "derive", inlineMode: "pair", allowRepeat: true },
|
|
35788
36309
|
{ key: "validate", inlineMode: "single", allowRepeat: true },
|
|
35789
36310
|
{ key: "locked", inlineMode: "multiple", allowRepeat: false },
|
|
35790
|
-
{ key: "tolerance", inlineMode: "pair", allowRepeat: true }
|
|
36311
|
+
{ key: "tolerance", inlineMode: "pair", allowRepeat: true },
|
|
36312
|
+
{ key: "trajectory", inlineMode: "single", allowRepeat: false }
|
|
35791
36313
|
]) {
|
|
35792
36314
|
DRAFT_OBJECT_FIELD_SPECS.set(spec.key, {
|
|
35793
36315
|
key: spec.key,
|
|
35794
|
-
version: "2.1",
|
|
36316
|
+
version: spec.key === "trajectory" ? "3.0" : "2.1",
|
|
35795
36317
|
inlineMode: spec.inlineMode,
|
|
35796
36318
|
allowRepeat: spec.allowRepeat
|
|
35797
36319
|
});
|
|
@@ -35812,7 +36334,9 @@ void main() {
|
|
|
35812
36334
|
"inner",
|
|
35813
36335
|
"outer",
|
|
35814
36336
|
"epoch",
|
|
35815
|
-
"referencePlane"
|
|
36337
|
+
"referencePlane",
|
|
36338
|
+
"segment",
|
|
36339
|
+
"maneuver"
|
|
35816
36340
|
]);
|
|
35817
36341
|
function parseWorldOrbitAtlas(source) {
|
|
35818
36342
|
return parseAtlasSource(source);
|
|
@@ -35832,6 +36356,7 @@ void main() {
|
|
|
35832
36356
|
const groups = [];
|
|
35833
36357
|
const relations = [];
|
|
35834
36358
|
const events = [];
|
|
36359
|
+
const trajectories = [];
|
|
35835
36360
|
const eventPoseNodes = /* @__PURE__ */ new Map();
|
|
35836
36361
|
let sawDefaults = false;
|
|
35837
36362
|
let sawAtlas = false;
|
|
@@ -35840,6 +36365,7 @@ void main() {
|
|
|
35840
36365
|
const groupIds = /* @__PURE__ */ new Set();
|
|
35841
36366
|
const relationIds = /* @__PURE__ */ new Set();
|
|
35842
36367
|
const eventIds = /* @__PURE__ */ new Set();
|
|
36368
|
+
const trajectoryIds = /* @__PURE__ */ new Set();
|
|
35843
36369
|
for (let index = 0; index < lines.length; index++) {
|
|
35844
36370
|
const rawLine = lines[index];
|
|
35845
36371
|
const lineNumber = index + 1;
|
|
@@ -35870,7 +36396,7 @@ void main() {
|
|
|
35870
36396
|
continue;
|
|
35871
36397
|
}
|
|
35872
36398
|
if (indent === 0) {
|
|
35873
|
-
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, { sawDefaults, sawAtlas });
|
|
36399
|
+
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, trajectories, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, trajectoryIds, { sawDefaults, sawAtlas });
|
|
35874
36400
|
if (section.kind === "system") {
|
|
35875
36401
|
system = section.system;
|
|
35876
36402
|
} else if (section.kind === "defaults") {
|
|
@@ -35886,7 +36412,7 @@ void main() {
|
|
|
35886
36412
|
handleSectionLine(section, indent, tokens, lineNumber);
|
|
35887
36413
|
}
|
|
35888
36414
|
if (!sawSchemaHeader) {
|
|
35889
|
-
throw new WorldOrbitError('Missing required atlas schema header "schema 2.0"');
|
|
36415
|
+
throw new WorldOrbitError('Missing required atlas schema header "schema 2.0", "schema 3.0", or "schema 3.1"');
|
|
35890
36416
|
}
|
|
35891
36417
|
const objects = objectNodes.map((node) => normalizeDraftObject(node, sourceSchemaVersion, diagnostics));
|
|
35892
36418
|
const normalizedEvents = events.map((event) => normalizeDraftEvent(event, eventPoseNodes.get(event.id) ?? []));
|
|
@@ -35899,6 +36425,7 @@ void main() {
|
|
|
35899
36425
|
groups,
|
|
35900
36426
|
relations,
|
|
35901
36427
|
events: normalizedEvents,
|
|
36428
|
+
trajectories,
|
|
35902
36429
|
objects,
|
|
35903
36430
|
diagnostics
|
|
35904
36431
|
};
|
|
@@ -35928,13 +36455,13 @@ void main() {
|
|
|
35928
36455
|
return document2;
|
|
35929
36456
|
}
|
|
35930
36457
|
function assertDraftSchemaHeader(tokens, line) {
|
|
35931
|
-
if (tokens.length !== 2 || tokens[0].value.toLowerCase() !== "schema" || !["2.0-draft", "2.0", "2.1", "2.5", "2.6"].includes(tokens[1].value.toLowerCase())) {
|
|
35932
|
-
throw new WorldOrbitError('Expected atlas header "schema 2.0", "schema 2.1", "schema 2.5", "schema 2.6", or legacy "schema 2.0-draft"', line, tokens[0]?.column ?? 1);
|
|
36458
|
+
if (tokens.length !== 2 || tokens[0].value.toLowerCase() !== "schema" || !["2.0-draft", "2.0", "2.1", "2.5", "2.6", "3.0", "3.1"].includes(tokens[1].value.toLowerCase())) {
|
|
36459
|
+
throw new WorldOrbitError('Expected atlas header "schema 2.0", "schema 2.1", "schema 2.5", "schema 2.6", "schema 3.0", "schema 3.1", or legacy "schema 2.0-draft"', line, tokens[0]?.column ?? 1);
|
|
35933
36460
|
}
|
|
35934
36461
|
const version = tokens[1].value.toLowerCase();
|
|
35935
|
-
return version === "2.6" ? "2.6" : version === "2.5" ? "2.5" : version === "2.1" ? "2.1" : version === "2.0-draft" ? "2.0-draft" : "2.0";
|
|
36462
|
+
return version === "2.6" ? "2.6" : version === "3.0" ? "3.0" : version === "3.1" ? "3.1" : version === "2.5" ? "2.5" : version === "2.1" ? "2.1" : version === "2.0-draft" ? "2.0-draft" : "2.0";
|
|
35936
36463
|
}
|
|
35937
|
-
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, flags) {
|
|
36464
|
+
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, trajectories, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, trajectoryIds, flags) {
|
|
35938
36465
|
const keyword = tokens[0]?.value.toLowerCase();
|
|
35939
36466
|
switch (keyword) {
|
|
35940
36467
|
case "system":
|
|
@@ -35988,6 +36515,9 @@ void main() {
|
|
|
35988
36515
|
case "event":
|
|
35989
36516
|
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "event", { line, column: tokens[0].column });
|
|
35990
36517
|
return startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics);
|
|
36518
|
+
case "trajectory":
|
|
36519
|
+
warnIfSchema30Feature(sourceSchemaVersion, diagnostics, "trajectory", { line, column: tokens[0].column });
|
|
36520
|
+
return startTrajectorySection(tokens, line, trajectories, trajectoryIds, sourceSchemaVersion, diagnostics);
|
|
35991
36521
|
case "object":
|
|
35992
36522
|
return startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes);
|
|
35993
36523
|
default:
|
|
@@ -36195,6 +36725,51 @@ void main() {
|
|
|
36195
36725
|
activePoseSeenFields: /* @__PURE__ */ new Set()
|
|
36196
36726
|
};
|
|
36197
36727
|
}
|
|
36728
|
+
function startTrajectorySection(tokens, line, trajectories, trajectoryIds, sourceSchemaVersion, diagnostics) {
|
|
36729
|
+
if (tokens.length !== 2) {
|
|
36730
|
+
throw new WorldOrbitError("Invalid trajectory declaration", line, tokens[0]?.column ?? 1);
|
|
36731
|
+
}
|
|
36732
|
+
const id = normalizeIdentifier2(tokens[1].value);
|
|
36733
|
+
if (!id) {
|
|
36734
|
+
throw new WorldOrbitError("Trajectory id must not be empty", line, tokens[1].column);
|
|
36735
|
+
}
|
|
36736
|
+
if (trajectoryIds.has(id)) {
|
|
36737
|
+
throw new WorldOrbitError(`Duplicate trajectory id "${id}"`, line, tokens[1].column);
|
|
36738
|
+
}
|
|
36739
|
+
const trajectory = {
|
|
36740
|
+
id,
|
|
36741
|
+
label: humanizeIdentifier3(id),
|
|
36742
|
+
summary: null,
|
|
36743
|
+
craftObjectId: null,
|
|
36744
|
+
tags: [],
|
|
36745
|
+
color: null,
|
|
36746
|
+
renderMode: null,
|
|
36747
|
+
stroke: null,
|
|
36748
|
+
strokeWidth: null,
|
|
36749
|
+
marker: null,
|
|
36750
|
+
labelMode: null,
|
|
36751
|
+
showWaypoints: null,
|
|
36752
|
+
hidden: false,
|
|
36753
|
+
segments: []
|
|
36754
|
+
};
|
|
36755
|
+
trajectories.push(trajectory);
|
|
36756
|
+
trajectoryIds.add(id);
|
|
36757
|
+
return {
|
|
36758
|
+
kind: "trajectory",
|
|
36759
|
+
trajectory,
|
|
36760
|
+
sourceSchemaVersion,
|
|
36761
|
+
diagnostics,
|
|
36762
|
+
seenFields: /* @__PURE__ */ new Set(),
|
|
36763
|
+
inSegment: false,
|
|
36764
|
+
segmentIndent: null,
|
|
36765
|
+
activeSegment: null,
|
|
36766
|
+
activeSegmentSeenFields: /* @__PURE__ */ new Set(),
|
|
36767
|
+
inManeuver: false,
|
|
36768
|
+
maneuverIndent: null,
|
|
36769
|
+
activeManeuver: null,
|
|
36770
|
+
activeManeuverSeenFields: /* @__PURE__ */ new Set()
|
|
36771
|
+
};
|
|
36772
|
+
}
|
|
36198
36773
|
function startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes) {
|
|
36199
36774
|
if (tokens.length < 3) {
|
|
36200
36775
|
throw new WorldOrbitError("Invalid atlas object declaration", line, tokens[0]?.column ?? 1);
|
|
@@ -36254,6 +36829,9 @@ void main() {
|
|
|
36254
36829
|
case "event":
|
|
36255
36830
|
applyEventField(section, indent, tokens, line);
|
|
36256
36831
|
return;
|
|
36832
|
+
case "trajectory":
|
|
36833
|
+
applyTrajectoryField(section, indent, tokens, line);
|
|
36834
|
+
return;
|
|
36257
36835
|
case "object":
|
|
36258
36836
|
applyObjectField(section, indent, tokens, line);
|
|
36259
36837
|
return;
|
|
@@ -36572,6 +37150,12 @@ void main() {
|
|
|
36572
37150
|
column: tokens[0]?.column ?? 1
|
|
36573
37151
|
});
|
|
36574
37152
|
}
|
|
37153
|
+
if (tokens[0]?.value === "segment" || tokens[0]?.value === "maneuver") {
|
|
37154
|
+
warnIfSchema30Feature(section.sourceSchemaVersion, section.diagnostics, `pose.${tokens[0].value}`, {
|
|
37155
|
+
line,
|
|
37156
|
+
column: tokens[0]?.column ?? 1
|
|
37157
|
+
});
|
|
37158
|
+
}
|
|
36575
37159
|
section.activePose.fields.push(parseEventPoseField(tokens, line, section.activePoseSeenFields));
|
|
36576
37160
|
return;
|
|
36577
37161
|
}
|
|
@@ -36614,6 +37198,13 @@ void main() {
|
|
|
36614
37198
|
case "summary":
|
|
36615
37199
|
section.event.summary = joinFieldValue(tokens, line);
|
|
36616
37200
|
return;
|
|
37201
|
+
case "trajectory":
|
|
37202
|
+
warnIfSchema30Feature(section.sourceSchemaVersion, section.diagnostics, "event.trajectory", {
|
|
37203
|
+
line,
|
|
37204
|
+
column: tokens[0].column
|
|
37205
|
+
});
|
|
37206
|
+
section.event.trajectoryId = joinFieldValue(tokens, line);
|
|
37207
|
+
return;
|
|
36617
37208
|
case "target":
|
|
36618
37209
|
section.event.targetObjectId = joinFieldValue(tokens, line);
|
|
36619
37210
|
return;
|
|
@@ -36656,6 +37247,302 @@ void main() {
|
|
|
36656
37247
|
throw new WorldOrbitError(`Unknown event field "${tokens[0].value}"`, line, tokens[0].column);
|
|
36657
37248
|
}
|
|
36658
37249
|
}
|
|
37250
|
+
function applyTrajectoryField(section, indent, tokens, line) {
|
|
37251
|
+
if (section.activeManeuver && indent <= (section.maneuverIndent ?? 0)) {
|
|
37252
|
+
section.activeManeuver = null;
|
|
37253
|
+
section.maneuverIndent = null;
|
|
37254
|
+
section.activeManeuverSeenFields.clear();
|
|
37255
|
+
section.inManeuver = false;
|
|
37256
|
+
}
|
|
37257
|
+
if (section.activeSegment && indent <= (section.segmentIndent ?? 0)) {
|
|
37258
|
+
section.activeSegment = null;
|
|
37259
|
+
section.segmentIndent = null;
|
|
37260
|
+
section.activeSegmentSeenFields.clear();
|
|
37261
|
+
section.inSegment = false;
|
|
37262
|
+
}
|
|
37263
|
+
if (section.activeManeuver) {
|
|
37264
|
+
applyTrajectoryManeuverField(section, tokens, line);
|
|
37265
|
+
return;
|
|
37266
|
+
}
|
|
37267
|
+
if (section.activeSegment) {
|
|
37268
|
+
if (tokens[0]?.value.toLowerCase() === "maneuver") {
|
|
37269
|
+
if (tokens.length !== 2) {
|
|
37270
|
+
throw new WorldOrbitError("Invalid trajectory maneuver declaration", line, tokens[0]?.column ?? 1);
|
|
37271
|
+
}
|
|
37272
|
+
const id = normalizeIdentifier2(tokens[1].value);
|
|
37273
|
+
if (!id) {
|
|
37274
|
+
throw new WorldOrbitError("Trajectory maneuver id must not be empty", line, tokens[1].column);
|
|
37275
|
+
}
|
|
37276
|
+
if (section.activeSegment.maneuvers.some((maneuver2) => maneuver2.id === id)) {
|
|
37277
|
+
throw new WorldOrbitError(`Duplicate trajectory maneuver id "${id}"`, line, tokens[1].column);
|
|
37278
|
+
}
|
|
37279
|
+
const maneuver = {
|
|
37280
|
+
id,
|
|
37281
|
+
kind: "burn",
|
|
37282
|
+
label: null,
|
|
37283
|
+
epoch: null,
|
|
37284
|
+
notes: []
|
|
37285
|
+
};
|
|
37286
|
+
section.activeSegment.maneuvers.push(maneuver);
|
|
37287
|
+
section.activeManeuver = maneuver;
|
|
37288
|
+
section.inManeuver = true;
|
|
37289
|
+
section.maneuverIndent = indent;
|
|
37290
|
+
section.activeManeuverSeenFields = /* @__PURE__ */ new Set();
|
|
37291
|
+
return;
|
|
37292
|
+
}
|
|
37293
|
+
applyTrajectorySegmentField(section, tokens, line);
|
|
37294
|
+
return;
|
|
37295
|
+
}
|
|
37296
|
+
if (tokens[0]?.value.toLowerCase() === "segment") {
|
|
37297
|
+
if (tokens.length !== 2) {
|
|
37298
|
+
throw new WorldOrbitError("Invalid trajectory segment declaration", line, tokens[0]?.column ?? 1);
|
|
37299
|
+
}
|
|
37300
|
+
const id = normalizeIdentifier2(tokens[1].value);
|
|
37301
|
+
if (!id) {
|
|
37302
|
+
throw new WorldOrbitError("Trajectory segment id must not be empty", line, tokens[1].column);
|
|
37303
|
+
}
|
|
37304
|
+
if (section.trajectory.segments.some((segment2) => segment2.id === id)) {
|
|
37305
|
+
throw new WorldOrbitError(`Duplicate trajectory segment id "${id}"`, line, tokens[1].column);
|
|
37306
|
+
}
|
|
37307
|
+
const segment = {
|
|
37308
|
+
id,
|
|
37309
|
+
kind: "transfer",
|
|
37310
|
+
label: null,
|
|
37311
|
+
summary: null,
|
|
37312
|
+
fromObjectId: null,
|
|
37313
|
+
toObjectId: null,
|
|
37314
|
+
aroundObjectId: null,
|
|
37315
|
+
assist: null,
|
|
37316
|
+
epoch: null,
|
|
37317
|
+
waypointLabel: null,
|
|
37318
|
+
waypointDate: null,
|
|
37319
|
+
renderHidden: null,
|
|
37320
|
+
sampleDensity: null,
|
|
37321
|
+
notes: [],
|
|
37322
|
+
maneuvers: []
|
|
37323
|
+
};
|
|
37324
|
+
section.trajectory.segments.push(segment);
|
|
37325
|
+
section.activeSegment = {
|
|
37326
|
+
id,
|
|
37327
|
+
fields: [],
|
|
37328
|
+
maneuvers: segment.maneuvers,
|
|
37329
|
+
assist: null,
|
|
37330
|
+
location: { line, column: tokens[0].column }
|
|
37331
|
+
};
|
|
37332
|
+
section.inSegment = true;
|
|
37333
|
+
section.segmentIndent = indent;
|
|
37334
|
+
section.activeSegmentSeenFields = /* @__PURE__ */ new Set();
|
|
37335
|
+
return;
|
|
37336
|
+
}
|
|
37337
|
+
const key = requireUniqueField(tokens, section.seenFields, line);
|
|
37338
|
+
const value = joinFieldValue(tokens, line);
|
|
37339
|
+
switch (key) {
|
|
37340
|
+
case "label":
|
|
37341
|
+
section.trajectory.label = value;
|
|
37342
|
+
return;
|
|
37343
|
+
case "summary":
|
|
37344
|
+
section.trajectory.summary = value;
|
|
37345
|
+
return;
|
|
37346
|
+
case "craft":
|
|
37347
|
+
section.trajectory.craftObjectId = value;
|
|
37348
|
+
return;
|
|
37349
|
+
case "tags":
|
|
37350
|
+
section.trajectory.tags = parseTokenList(tokens.slice(1), line, "tags");
|
|
37351
|
+
return;
|
|
37352
|
+
case "color":
|
|
37353
|
+
section.trajectory.color = value;
|
|
37354
|
+
return;
|
|
37355
|
+
case "rendermode":
|
|
37356
|
+
warnIfSchema31Feature(section.sourceSchemaVersion, section.diagnostics, "trajectory.renderMode", {
|
|
37357
|
+
line,
|
|
37358
|
+
column: tokens[0].column
|
|
37359
|
+
});
|
|
37360
|
+
if (value !== "illustrative" && value !== "solver" && value !== "auto") {
|
|
37361
|
+
throw new WorldOrbitError(`Unknown trajectory render mode "${value}"`, line, tokens[0].column);
|
|
37362
|
+
}
|
|
37363
|
+
section.trajectory.renderMode = value;
|
|
37364
|
+
return;
|
|
37365
|
+
case "stroke":
|
|
37366
|
+
warnIfSchema31Feature(section.sourceSchemaVersion, section.diagnostics, "trajectory.stroke", {
|
|
37367
|
+
line,
|
|
37368
|
+
column: tokens[0].column
|
|
37369
|
+
});
|
|
37370
|
+
section.trajectory.stroke = value;
|
|
37371
|
+
return;
|
|
37372
|
+
case "strokewidth":
|
|
37373
|
+
warnIfSchema31Feature(section.sourceSchemaVersion, section.diagnostics, "trajectory.strokeWidth", {
|
|
37374
|
+
line,
|
|
37375
|
+
column: tokens[0].column
|
|
37376
|
+
});
|
|
37377
|
+
section.trajectory.strokeWidth = parsePositiveNumber2(value, line, tokens[0].column, "strokeWidth");
|
|
37378
|
+
return;
|
|
37379
|
+
case "marker":
|
|
37380
|
+
warnIfSchema31Feature(section.sourceSchemaVersion, section.diagnostics, "trajectory.marker", {
|
|
37381
|
+
line,
|
|
37382
|
+
column: tokens[0].column
|
|
37383
|
+
});
|
|
37384
|
+
section.trajectory.marker = value;
|
|
37385
|
+
return;
|
|
37386
|
+
case "labelmode":
|
|
37387
|
+
warnIfSchema31Feature(section.sourceSchemaVersion, section.diagnostics, "trajectory.labelMode", {
|
|
37388
|
+
line,
|
|
37389
|
+
column: tokens[0].column
|
|
37390
|
+
});
|
|
37391
|
+
section.trajectory.labelMode = value;
|
|
37392
|
+
return;
|
|
37393
|
+
case "showwaypoints":
|
|
37394
|
+
warnIfSchema31Feature(section.sourceSchemaVersion, section.diagnostics, "trajectory.showWaypoints", {
|
|
37395
|
+
line,
|
|
37396
|
+
column: tokens[0].column
|
|
37397
|
+
});
|
|
37398
|
+
section.trajectory.showWaypoints = parseAtlasBoolean(value, "showWaypoints", {
|
|
37399
|
+
line,
|
|
37400
|
+
column: tokens[0].column
|
|
37401
|
+
});
|
|
37402
|
+
return;
|
|
37403
|
+
case "hidden":
|
|
37404
|
+
section.trajectory.hidden = parseAtlasBoolean(value, "hidden", {
|
|
37405
|
+
line,
|
|
37406
|
+
column: tokens[0].column
|
|
37407
|
+
});
|
|
37408
|
+
return;
|
|
37409
|
+
default:
|
|
37410
|
+
throw new WorldOrbitError(`Unknown trajectory field "${tokens[0].value}"`, line, tokens[0].column);
|
|
37411
|
+
}
|
|
37412
|
+
}
|
|
37413
|
+
function applyTrajectorySegmentField(section, tokens, line) {
|
|
37414
|
+
const segment = section.activeSegment;
|
|
37415
|
+
if (!segment) {
|
|
37416
|
+
return;
|
|
37417
|
+
}
|
|
37418
|
+
const key = requireUniqueField(tokens, section.activeSegmentSeenFields, line);
|
|
37419
|
+
const value = joinFieldValue(tokens, line);
|
|
37420
|
+
const target = section.trajectory.segments.find((entry) => entry.id === segment.id);
|
|
37421
|
+
switch (key) {
|
|
37422
|
+
case "kind": {
|
|
37423
|
+
const normalized = value.toLowerCase();
|
|
37424
|
+
if (!TRAJECTORY_SEGMENT_KINDS.has(normalized)) {
|
|
37425
|
+
throw new WorldOrbitError(`Unknown trajectory segment kind "${value}"`, line, tokens[0].column);
|
|
37426
|
+
}
|
|
37427
|
+
target.kind = normalized;
|
|
37428
|
+
return;
|
|
37429
|
+
}
|
|
37430
|
+
case "label":
|
|
37431
|
+
target.label = value;
|
|
37432
|
+
return;
|
|
37433
|
+
case "summary":
|
|
37434
|
+
target.summary = value;
|
|
37435
|
+
return;
|
|
37436
|
+
case "from":
|
|
37437
|
+
target.fromObjectId = value;
|
|
37438
|
+
return;
|
|
37439
|
+
case "to":
|
|
37440
|
+
target.toObjectId = value;
|
|
37441
|
+
return;
|
|
37442
|
+
case "around":
|
|
37443
|
+
target.aroundObjectId = value;
|
|
37444
|
+
return;
|
|
37445
|
+
case "assist":
|
|
37446
|
+
target.assist = {
|
|
37447
|
+
objectId: value,
|
|
37448
|
+
notes: []
|
|
37449
|
+
};
|
|
37450
|
+
return;
|
|
37451
|
+
case "epoch":
|
|
37452
|
+
target.epoch = value;
|
|
37453
|
+
return;
|
|
37454
|
+
case "periapsis":
|
|
37455
|
+
target.periapsis = parseAtlasUnitValue(value, { line, column: tokens[0].column }, "periapsis");
|
|
37456
|
+
return;
|
|
37457
|
+
case "apoapsis":
|
|
37458
|
+
target.apoapsis = parseAtlasUnitValue(value, { line, column: tokens[0].column }, "apoapsis");
|
|
37459
|
+
return;
|
|
37460
|
+
case "inclination":
|
|
37461
|
+
target.inclination = parseAtlasUnitValue(value, { line, column: tokens[0].column }, "inclination");
|
|
37462
|
+
return;
|
|
37463
|
+
case "duration":
|
|
37464
|
+
target.duration = parseAtlasUnitValue(value, { line, column: tokens[0].column }, "duration");
|
|
37465
|
+
return;
|
|
37466
|
+
case "deltav":
|
|
37467
|
+
target.deltaV = parseAtlasUnitValue(value, { line, column: tokens[0].column });
|
|
37468
|
+
return;
|
|
37469
|
+
case "phaseangle":
|
|
37470
|
+
target.phaseAngle = parseAtlasUnitValue(value, { line, column: tokens[0].column }, "phaseAngle");
|
|
37471
|
+
return;
|
|
37472
|
+
case "turnangle":
|
|
37473
|
+
target.turnAngle = parseAtlasUnitValue(value, { line, column: tokens[0].column }, "turnAngle");
|
|
37474
|
+
return;
|
|
37475
|
+
case "energy":
|
|
37476
|
+
target.energy = parseAtlasUnitValue(value, { line, column: tokens[0].column });
|
|
37477
|
+
return;
|
|
37478
|
+
case "waypointlabel":
|
|
37479
|
+
warnIfSchema31Feature(section.sourceSchemaVersion, section.diagnostics, "segment.waypointLabel", {
|
|
37480
|
+
line,
|
|
37481
|
+
column: tokens[0].column
|
|
37482
|
+
});
|
|
37483
|
+
target.waypointLabel = value;
|
|
37484
|
+
return;
|
|
37485
|
+
case "waypointdate":
|
|
37486
|
+
warnIfSchema31Feature(section.sourceSchemaVersion, section.diagnostics, "segment.waypointDate", {
|
|
37487
|
+
line,
|
|
37488
|
+
column: tokens[0].column
|
|
37489
|
+
});
|
|
37490
|
+
target.waypointDate = value;
|
|
37491
|
+
return;
|
|
37492
|
+
case "renderhidden":
|
|
37493
|
+
warnIfSchema31Feature(section.sourceSchemaVersion, section.diagnostics, "segment.renderHidden", {
|
|
37494
|
+
line,
|
|
37495
|
+
column: tokens[0].column
|
|
37496
|
+
});
|
|
37497
|
+
target.renderHidden = parseAtlasBoolean(value, "renderHidden", {
|
|
37498
|
+
line,
|
|
37499
|
+
column: tokens[0].column
|
|
37500
|
+
});
|
|
37501
|
+
return;
|
|
37502
|
+
case "sampledensity":
|
|
37503
|
+
warnIfSchema31Feature(section.sourceSchemaVersion, section.diagnostics, "segment.sampleDensity", {
|
|
37504
|
+
line,
|
|
37505
|
+
column: tokens[0].column
|
|
37506
|
+
});
|
|
37507
|
+
target.sampleDensity = parsePositiveNumber2(value, line, tokens[0].column, "sampleDensity");
|
|
37508
|
+
return;
|
|
37509
|
+
case "notes":
|
|
37510
|
+
target.notes = parseTokenList(tokens.slice(1), line, "notes");
|
|
37511
|
+
return;
|
|
37512
|
+
default:
|
|
37513
|
+
throw new WorldOrbitError(`Unknown trajectory segment field "${tokens[0].value}"`, line, tokens[0].column);
|
|
37514
|
+
}
|
|
37515
|
+
}
|
|
37516
|
+
function applyTrajectoryManeuverField(section, tokens, line) {
|
|
37517
|
+
const maneuver = section.activeManeuver;
|
|
37518
|
+
if (!maneuver) {
|
|
37519
|
+
return;
|
|
37520
|
+
}
|
|
37521
|
+
const key = requireUniqueField(tokens, section.activeManeuverSeenFields, line);
|
|
37522
|
+
const value = joinFieldValue(tokens, line);
|
|
37523
|
+
switch (key) {
|
|
37524
|
+
case "kind":
|
|
37525
|
+
maneuver.kind = value;
|
|
37526
|
+
return;
|
|
37527
|
+
case "label":
|
|
37528
|
+
maneuver.label = value;
|
|
37529
|
+
return;
|
|
37530
|
+
case "epoch":
|
|
37531
|
+
maneuver.epoch = value;
|
|
37532
|
+
return;
|
|
37533
|
+
case "deltav":
|
|
37534
|
+
maneuver.deltaV = parseAtlasUnitValue(value, { line, column: tokens[0].column });
|
|
37535
|
+
return;
|
|
37536
|
+
case "duration":
|
|
37537
|
+
maneuver.duration = parseAtlasUnitValue(value, { line, column: tokens[0].column }, "duration");
|
|
37538
|
+
return;
|
|
37539
|
+
case "notes":
|
|
37540
|
+
maneuver.notes = parseTokenList(tokens.slice(1), line, "notes");
|
|
37541
|
+
return;
|
|
37542
|
+
default:
|
|
37543
|
+
throw new WorldOrbitError(`Unknown trajectory maneuver field "${tokens[0].value}"`, line, tokens[0].column);
|
|
37544
|
+
}
|
|
37545
|
+
}
|
|
36659
37546
|
function parseEventPoseField(tokens, line, seenFields) {
|
|
36660
37547
|
if (tokens.length < 2) {
|
|
36661
37548
|
throw new WorldOrbitError("Invalid event pose field line", line, tokens[0]?.column ?? 1);
|
|
@@ -36743,7 +37630,7 @@ void main() {
|
|
|
36743
37630
|
layers["orbits-front"] = enabled;
|
|
36744
37631
|
continue;
|
|
36745
37632
|
}
|
|
36746
|
-
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "events" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
37633
|
+
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "events" || raw === "objects" || raw === "labels" || raw === "metadata" || raw === "trajectories") {
|
|
36747
37634
|
if (raw === "events" && sourceSchemaVersion && diagnostics) {
|
|
36748
37635
|
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "layers.events", {
|
|
36749
37636
|
line,
|
|
@@ -36861,6 +37748,16 @@ void main() {
|
|
|
36861
37748
|
line,
|
|
36862
37749
|
column: keyToken.column
|
|
36863
37750
|
});
|
|
37751
|
+
} else if (spec.version === "3.0") {
|
|
37752
|
+
warnIfSchema30Feature(sourceSchemaVersion, diagnostics, keyToken.value, {
|
|
37753
|
+
line,
|
|
37754
|
+
column: keyToken.column
|
|
37755
|
+
});
|
|
37756
|
+
} else if (spec.version === "3.1") {
|
|
37757
|
+
warnIfSchema31Feature(sourceSchemaVersion, diagnostics, keyToken.value, {
|
|
37758
|
+
line,
|
|
37759
|
+
column: keyToken.column
|
|
37760
|
+
});
|
|
36864
37761
|
}
|
|
36865
37762
|
index++;
|
|
36866
37763
|
const valueTokens = [];
|
|
@@ -36911,6 +37808,16 @@ void main() {
|
|
|
36911
37808
|
line,
|
|
36912
37809
|
column: tokens[0].column
|
|
36913
37810
|
});
|
|
37811
|
+
} else if (spec.version === "3.0") {
|
|
37812
|
+
warnIfSchema30Feature(sourceSchemaVersion, diagnostics, tokens[0].value, {
|
|
37813
|
+
line,
|
|
37814
|
+
column: tokens[0].column
|
|
37815
|
+
});
|
|
37816
|
+
} else if (spec.version === "3.1") {
|
|
37817
|
+
warnIfSchema31Feature(sourceSchemaVersion, diagnostics, tokens[0].value, {
|
|
37818
|
+
line,
|
|
37819
|
+
column: tokens[0].column
|
|
37820
|
+
});
|
|
36914
37821
|
}
|
|
36915
37822
|
const field = {
|
|
36916
37823
|
type: "field",
|
|
@@ -36950,6 +37857,7 @@ void main() {
|
|
|
36950
37857
|
const tolerances = fieldMap.get("tolerance")?.map((field) => parseToleranceField(field));
|
|
36951
37858
|
const typedBlocks = normalizeTypedBlocks(node.typedBlockEntries);
|
|
36952
37859
|
const info2 = normalizeInfoEntries(node.infoEntries, "info");
|
|
37860
|
+
const trajectoryId = parseOptionalJoinedValue(fieldMap.get("trajectory")?.[0]);
|
|
36953
37861
|
const object = {
|
|
36954
37862
|
type: node.objectType,
|
|
36955
37863
|
id: node.id,
|
|
@@ -36979,11 +37887,16 @@ void main() {
|
|
|
36979
37887
|
object.tolerances = tolerances;
|
|
36980
37888
|
if (typedBlocks && Object.keys(typedBlocks).length > 0)
|
|
36981
37889
|
object.typedBlocks = typedBlocks;
|
|
37890
|
+
if (trajectoryId)
|
|
37891
|
+
object.trajectoryId = trajectoryId;
|
|
36982
37892
|
if (isSchemaOlderThan(sourceSchemaVersion, "2.1")) {
|
|
36983
|
-
if (object.groups || object.epoch || object.referencePlane || object.tidalLock !== void 0 || object.resonance || object.renderHints || object.deriveRules?.length || object.validationRules?.length || object.lockedFields?.length || object.tolerances?.length || object.typedBlocks) {
|
|
37893
|
+
if (object.groups || object.epoch || object.referencePlane || object.tidalLock !== void 0 || object.resonance || object.renderHints || object.deriveRules?.length || object.validationRules?.length || object.lockedFields?.length || object.tolerances?.length || object.typedBlocks || object.trajectoryId) {
|
|
36984
37894
|
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, node.id, node.location);
|
|
36985
37895
|
}
|
|
36986
37896
|
}
|
|
37897
|
+
if (object.trajectoryId) {
|
|
37898
|
+
warnIfSchema30Feature(sourceSchemaVersion, diagnostics, `${node.id}.trajectory`, node.location);
|
|
37899
|
+
}
|
|
36987
37900
|
return object;
|
|
36988
37901
|
}
|
|
36989
37902
|
function normalizeDraftEvent(event, rawPoses) {
|
|
@@ -37000,6 +37913,8 @@ void main() {
|
|
|
37000
37913
|
return {
|
|
37001
37914
|
objectId: rawPose.objectId,
|
|
37002
37915
|
placement,
|
|
37916
|
+
trajectorySegmentId: parseOptionalJoinedValue(fieldMap.get("segment")?.[0]),
|
|
37917
|
+
trajectoryManeuverId: parseOptionalJoinedValue(fieldMap.get("maneuver")?.[0]),
|
|
37003
37918
|
inner: parseOptionalUnitField(fieldMap.get("inner")?.[0], "inner"),
|
|
37004
37919
|
outer: parseOptionalUnitField(fieldMap.get("outer")?.[0], "outer"),
|
|
37005
37920
|
epoch: parseOptionalJoinedValue(fieldMap.get("epoch")?.[0]),
|
|
@@ -37215,6 +38130,32 @@ void main() {
|
|
|
37215
38130
|
column: location.column
|
|
37216
38131
|
});
|
|
37217
38132
|
}
|
|
38133
|
+
function warnIfSchema30Feature(sourceSchemaVersion, diagnostics, featureName, location) {
|
|
38134
|
+
if (!isSchemaOlderThan(sourceSchemaVersion, "3.0")) {
|
|
38135
|
+
return;
|
|
38136
|
+
}
|
|
38137
|
+
diagnostics.push({
|
|
38138
|
+
code: "parse.schema30.featureCompatibility",
|
|
38139
|
+
severity: "warning",
|
|
38140
|
+
source: "parse",
|
|
38141
|
+
message: `Feature "${featureName}" requires schema 3.0; parsed in compatibility mode because the document header is "schema ${sourceSchemaVersion}".`,
|
|
38142
|
+
line: location.line,
|
|
38143
|
+
column: location.column
|
|
38144
|
+
});
|
|
38145
|
+
}
|
|
38146
|
+
function warnIfSchema31Feature(sourceSchemaVersion, diagnostics, featureName, location) {
|
|
38147
|
+
if (!isSchemaOlderThan(sourceSchemaVersion, "3.1")) {
|
|
38148
|
+
return;
|
|
38149
|
+
}
|
|
38150
|
+
diagnostics.push({
|
|
38151
|
+
code: "parse.schema31.featureCompatibility",
|
|
38152
|
+
severity: "warning",
|
|
38153
|
+
source: "parse",
|
|
38154
|
+
message: `Feature "${featureName}" requires schema 3.1; parsed in compatibility mode because the document header is "schema ${sourceSchemaVersion}".`,
|
|
38155
|
+
line: location.line,
|
|
38156
|
+
column: location.column
|
|
38157
|
+
});
|
|
38158
|
+
}
|
|
37218
38159
|
function isSchemaOlderThan(sourceSchemaVersion, requiredVersion) {
|
|
37219
38160
|
return schemaVersionRank(sourceSchemaVersion) < schemaVersionRank(requiredVersion);
|
|
37220
38161
|
}
|
|
@@ -37230,8 +38171,12 @@ void main() {
|
|
|
37230
38171
|
return 3;
|
|
37231
38172
|
case "2.6":
|
|
37232
38173
|
return 4;
|
|
37233
|
-
|
|
38174
|
+
case "3.0":
|
|
37234
38175
|
return 5;
|
|
38176
|
+
case "3.1":
|
|
38177
|
+
return 6;
|
|
38178
|
+
default:
|
|
38179
|
+
return 7;
|
|
37235
38180
|
}
|
|
37236
38181
|
}
|
|
37237
38182
|
function preprocessAtlasSource(source) {
|
|
@@ -37321,7 +38266,7 @@ void main() {
|
|
|
37321
38266
|
}
|
|
37322
38267
|
|
|
37323
38268
|
// packages/core/dist/atlas-edit.js
|
|
37324
|
-
function createEmptyAtlasDocument(systemId = "WorldOrbit", version = "
|
|
38269
|
+
function createEmptyAtlasDocument(systemId = "WorldOrbit", version = "3.0") {
|
|
37325
38270
|
return {
|
|
37326
38271
|
format: "worldorbit",
|
|
37327
38272
|
version,
|
|
@@ -37352,6 +38297,7 @@ void main() {
|
|
|
37352
38297
|
groups: [],
|
|
37353
38298
|
relations: [],
|
|
37354
38299
|
events: [],
|
|
38300
|
+
trajectories: [],
|
|
37355
38301
|
objects: [],
|
|
37356
38302
|
diagnostics: []
|
|
37357
38303
|
};
|
|
@@ -37384,6 +38330,19 @@ void main() {
|
|
|
37384
38330
|
paths.push({ kind: "event-pose", id: event.id, key: pose.objectId });
|
|
37385
38331
|
}
|
|
37386
38332
|
}
|
|
38333
|
+
for (const trajectory of [...document2.trajectories].sort(compareIdLike2)) {
|
|
38334
|
+
paths.push({ kind: "trajectory", id: trajectory.id });
|
|
38335
|
+
for (const segment of [...trajectory.segments].sort(compareIdLike2)) {
|
|
38336
|
+
paths.push({ kind: "trajectory-segment", id: trajectory.id, key: segment.id });
|
|
38337
|
+
for (const maneuver of [...segment.maneuvers].sort(compareIdLike2)) {
|
|
38338
|
+
paths.push({
|
|
38339
|
+
kind: "trajectory-maneuver",
|
|
38340
|
+
id: trajectory.id,
|
|
38341
|
+
key: `${segment.id}:${maneuver.id}`
|
|
38342
|
+
});
|
|
38343
|
+
}
|
|
38344
|
+
}
|
|
38345
|
+
}
|
|
37387
38346
|
for (const object of [...document2.objects].sort(compareIdLike2)) {
|
|
37388
38347
|
paths.push({ kind: "object", id: object.id });
|
|
37389
38348
|
}
|
|
@@ -37403,6 +38362,12 @@ void main() {
|
|
|
37403
38362
|
return path.id ? findEvent(document2, path.id) : null;
|
|
37404
38363
|
case "event-pose":
|
|
37405
38364
|
return path.id && path.key ? findEventPose(document2, path.id, path.key) : null;
|
|
38365
|
+
case "trajectory":
|
|
38366
|
+
return path.id ? findTrajectory(document2, path.id) : null;
|
|
38367
|
+
case "trajectory-segment":
|
|
38368
|
+
return path.id && path.key ? findTrajectorySegment2(document2, path.id, path.key) : null;
|
|
38369
|
+
case "trajectory-maneuver":
|
|
38370
|
+
return path.id && path.key ? findTrajectoryManeuver2(document2, path.id, path.key) : null;
|
|
37406
38371
|
case "object":
|
|
37407
38372
|
return path.id ? findObject(document2, path.id) : null;
|
|
37408
38373
|
case "viewpoint":
|
|
@@ -37454,6 +38419,24 @@ void main() {
|
|
|
37454
38419
|
}
|
|
37455
38420
|
upsertEventPose(next.events, path.id, value);
|
|
37456
38421
|
return next;
|
|
38422
|
+
case "trajectory":
|
|
38423
|
+
if (!path.id) {
|
|
38424
|
+
throw new Error('Trajectory updates require an "id" value.');
|
|
38425
|
+
}
|
|
38426
|
+
upsertById(next.trajectories, value);
|
|
38427
|
+
return next;
|
|
38428
|
+
case "trajectory-segment":
|
|
38429
|
+
if (!path.id || !path.key) {
|
|
38430
|
+
throw new Error('Trajectory segment updates require a trajectory "id" and segment "key" value.');
|
|
38431
|
+
}
|
|
38432
|
+
upsertTrajectorySegment(next.trajectories, path.id, value);
|
|
38433
|
+
return next;
|
|
38434
|
+
case "trajectory-maneuver":
|
|
38435
|
+
if (!path.id || !path.key) {
|
|
38436
|
+
throw new Error('Trajectory maneuver updates require a trajectory "id" and maneuver "key" value.');
|
|
38437
|
+
}
|
|
38438
|
+
upsertTrajectoryManeuver(next.trajectories, path.id, path.key, value);
|
|
38439
|
+
return next;
|
|
37457
38440
|
case "object":
|
|
37458
38441
|
if (!path.id) {
|
|
37459
38442
|
throw new Error('Object updates require an "id" value.');
|
|
@@ -37515,6 +38498,30 @@ void main() {
|
|
|
37515
38498
|
}
|
|
37516
38499
|
}
|
|
37517
38500
|
return next;
|
|
38501
|
+
case "trajectory":
|
|
38502
|
+
if (path.id) {
|
|
38503
|
+
next.trajectories = next.trajectories.filter((trajectory) => trajectory.id !== path.id);
|
|
38504
|
+
}
|
|
38505
|
+
return next;
|
|
38506
|
+
case "trajectory-segment":
|
|
38507
|
+
if (path.id && path.key) {
|
|
38508
|
+
const trajectory = findTrajectory(next, path.id);
|
|
38509
|
+
if (trajectory) {
|
|
38510
|
+
trajectory.segments = trajectory.segments.filter((segment) => segment.id !== path.key);
|
|
38511
|
+
}
|
|
38512
|
+
}
|
|
38513
|
+
return next;
|
|
38514
|
+
case "trajectory-maneuver":
|
|
38515
|
+
if (path.id && path.key) {
|
|
38516
|
+
const maneuver = splitTrajectoryManeuverKey(path.key);
|
|
38517
|
+
if (maneuver) {
|
|
38518
|
+
const segment = findTrajectorySegment2(next, path.id, maneuver.segmentId);
|
|
38519
|
+
if (segment) {
|
|
38520
|
+
segment.maneuvers = segment.maneuvers.filter((entry) => entry.id !== maneuver.maneuverId);
|
|
38521
|
+
}
|
|
38522
|
+
}
|
|
38523
|
+
}
|
|
38524
|
+
return next;
|
|
37518
38525
|
case "viewpoint":
|
|
37519
38526
|
if (path.id) {
|
|
37520
38527
|
system.viewpoints = system.viewpoints.filter((viewpoint) => viewpoint.id !== path.id);
|
|
@@ -37599,6 +38606,29 @@ void main() {
|
|
|
37599
38606
|
};
|
|
37600
38607
|
}
|
|
37601
38608
|
}
|
|
38609
|
+
if (diagnostic.field?.startsWith("trajectory.")) {
|
|
38610
|
+
const parts = diagnostic.field.split(".");
|
|
38611
|
+
if (parts[1] && findTrajectory(document2, parts[1])) {
|
|
38612
|
+
if (parts[2] === "segment" && parts[3] && findTrajectorySegment2(document2, parts[1], parts[3])) {
|
|
38613
|
+
if (parts[4] === "maneuver" && parts[5] && findTrajectoryManeuver2(document2, parts[1], `${parts[3]}:${parts[5]}`)) {
|
|
38614
|
+
return {
|
|
38615
|
+
kind: "trajectory-maneuver",
|
|
38616
|
+
id: parts[1],
|
|
38617
|
+
key: `${parts[3]}:${parts[5]}`
|
|
38618
|
+
};
|
|
38619
|
+
}
|
|
38620
|
+
return {
|
|
38621
|
+
kind: "trajectory-segment",
|
|
38622
|
+
id: parts[1],
|
|
38623
|
+
key: parts[3]
|
|
38624
|
+
};
|
|
38625
|
+
}
|
|
38626
|
+
return {
|
|
38627
|
+
kind: "trajectory",
|
|
38628
|
+
id: parts[1]
|
|
38629
|
+
};
|
|
38630
|
+
}
|
|
38631
|
+
}
|
|
37602
38632
|
if (diagnostic.field && diagnostic.field in ensureSystem(document2).atlasMetadata) {
|
|
37603
38633
|
return {
|
|
37604
38634
|
kind: "metadata",
|
|
@@ -37636,6 +38666,19 @@ void main() {
|
|
|
37636
38666
|
function findEventPose(document2, eventId, objectId) {
|
|
37637
38667
|
return findEvent(document2, eventId)?.positions.find((pose) => pose.objectId === objectId) ?? null;
|
|
37638
38668
|
}
|
|
38669
|
+
function findTrajectory(document2, trajectoryId) {
|
|
38670
|
+
return document2.trajectories.find((trajectory) => trajectory.id === trajectoryId) ?? null;
|
|
38671
|
+
}
|
|
38672
|
+
function findTrajectorySegment2(document2, trajectoryId, segmentId) {
|
|
38673
|
+
return findTrajectory(document2, trajectoryId)?.segments.find((segment) => segment.id === segmentId) ?? null;
|
|
38674
|
+
}
|
|
38675
|
+
function findTrajectoryManeuver2(document2, trajectoryId, combinedKey) {
|
|
38676
|
+
const parsed = splitTrajectoryManeuverKey(combinedKey);
|
|
38677
|
+
if (!parsed) {
|
|
38678
|
+
return null;
|
|
38679
|
+
}
|
|
38680
|
+
return findTrajectorySegment2(document2, trajectoryId, parsed.segmentId)?.maneuvers.find((maneuver) => maneuver.id === parsed.maneuverId) ?? null;
|
|
38681
|
+
}
|
|
37639
38682
|
function findViewpoint(system, viewpointId) {
|
|
37640
38683
|
return system?.viewpoints.find((viewpoint) => viewpoint.id === viewpointId) ?? null;
|
|
37641
38684
|
}
|
|
@@ -37664,6 +38707,50 @@ void main() {
|
|
|
37664
38707
|
}
|
|
37665
38708
|
event.positions[index] = value;
|
|
37666
38709
|
}
|
|
38710
|
+
function upsertTrajectorySegment(trajectories, trajectoryId, value) {
|
|
38711
|
+
const trajectory = trajectories.find((entry) => entry.id === trajectoryId);
|
|
38712
|
+
if (!trajectory) {
|
|
38713
|
+
throw new Error(`Unknown trajectory "${trajectoryId}" for segment update.`);
|
|
38714
|
+
}
|
|
38715
|
+
const index = trajectory.segments.findIndex((entry) => entry.id === value.id);
|
|
38716
|
+
if (index === -1) {
|
|
38717
|
+
trajectory.segments.push(value);
|
|
38718
|
+
trajectory.segments.sort(compareIdLike2);
|
|
38719
|
+
return;
|
|
38720
|
+
}
|
|
38721
|
+
trajectory.segments[index] = value;
|
|
38722
|
+
}
|
|
38723
|
+
function upsertTrajectoryManeuver(trajectories, trajectoryId, combinedKey, value) {
|
|
38724
|
+
const parsed = splitTrajectoryManeuverKey(combinedKey);
|
|
38725
|
+
if (!parsed) {
|
|
38726
|
+
throw new Error(`Invalid trajectory maneuver key "${combinedKey}".`);
|
|
38727
|
+
}
|
|
38728
|
+
const trajectory = trajectories.find((entry) => entry.id === trajectoryId);
|
|
38729
|
+
if (!trajectory) {
|
|
38730
|
+
throw new Error(`Unknown trajectory "${trajectoryId}" for maneuver update.`);
|
|
38731
|
+
}
|
|
38732
|
+
const segment = trajectory.segments.find((entry) => entry.id === parsed.segmentId);
|
|
38733
|
+
if (!segment) {
|
|
38734
|
+
throw new Error(`Unknown trajectory segment "${parsed.segmentId}" on "${trajectoryId}".`);
|
|
38735
|
+
}
|
|
38736
|
+
const index = segment.maneuvers.findIndex((entry) => entry.id === value.id);
|
|
38737
|
+
if (index === -1) {
|
|
38738
|
+
segment.maneuvers.push(value);
|
|
38739
|
+
segment.maneuvers.sort(compareIdLike2);
|
|
38740
|
+
return;
|
|
38741
|
+
}
|
|
38742
|
+
segment.maneuvers[index] = value;
|
|
38743
|
+
}
|
|
38744
|
+
function splitTrajectoryManeuverKey(key) {
|
|
38745
|
+
const separator = key.indexOf(":");
|
|
38746
|
+
if (separator <= 0 || separator >= key.length - 1) {
|
|
38747
|
+
return null;
|
|
38748
|
+
}
|
|
38749
|
+
return {
|
|
38750
|
+
segmentId: key.slice(0, separator),
|
|
38751
|
+
maneuverId: key.slice(separator + 1)
|
|
38752
|
+
};
|
|
38753
|
+
}
|
|
37667
38754
|
function compareIdLike2(left, right) {
|
|
37668
38755
|
return left.id.localeCompare(right.id);
|
|
37669
38756
|
}
|
|
@@ -37672,10 +38759,12 @@ void main() {
|
|
|
37672
38759
|
}
|
|
37673
38760
|
|
|
37674
38761
|
// packages/core/dist/load.js
|
|
37675
|
-
var ATLAS_SCHEMA_PATTERN = /^schema\s+2(?:\.0|\.1|\.5|\.6)
|
|
38762
|
+
var ATLAS_SCHEMA_PATTERN = /^schema\s+(?:2(?:\.0|\.1|\.5|\.6)?|3(?:\.0|\.1)?)$/i;
|
|
37676
38763
|
var ATLAS_SCHEMA_21_PATTERN = /^schema\s+2\.1$/i;
|
|
37677
38764
|
var ATLAS_SCHEMA_25_PATTERN = /^schema\s+2\.5$/i;
|
|
37678
38765
|
var ATLAS_SCHEMA_26_PATTERN = /^schema\s+2\.6$/i;
|
|
38766
|
+
var ATLAS_SCHEMA_30_PATTERN = /^schema\s+3(?:\.0)?$/i;
|
|
38767
|
+
var ATLAS_SCHEMA_31_PATTERN = /^schema\s+3\.1$/i;
|
|
37679
38768
|
var LEGACY_DRAFT_SCHEMA_PATTERN = /^schema\s+2\.0-draft$/i;
|
|
37680
38769
|
function detectWorldOrbitSchemaVersion(source) {
|
|
37681
38770
|
for (const line of stripCommentsForSchemaDetection(source).split(/\r?\n/)) {
|
|
@@ -37695,6 +38784,12 @@ void main() {
|
|
|
37695
38784
|
if (ATLAS_SCHEMA_26_PATTERN.test(trimmed)) {
|
|
37696
38785
|
return "2.6";
|
|
37697
38786
|
}
|
|
38787
|
+
if (ATLAS_SCHEMA_30_PATTERN.test(trimmed)) {
|
|
38788
|
+
return "3.0";
|
|
38789
|
+
}
|
|
38790
|
+
if (ATLAS_SCHEMA_31_PATTERN.test(trimmed)) {
|
|
38791
|
+
return "3.1";
|
|
38792
|
+
}
|
|
37698
38793
|
if (ATLAS_SCHEMA_PATTERN.test(trimmed)) {
|
|
37699
38794
|
return "2.0";
|
|
37700
38795
|
}
|
|
@@ -37755,7 +38850,7 @@ void main() {
|
|
|
37755
38850
|
}
|
|
37756
38851
|
function loadWorldOrbitSourceWithDiagnostics(source) {
|
|
37757
38852
|
const schemaVersion = detectWorldOrbitSchemaVersion(source);
|
|
37758
|
-
if (schemaVersion === "2.0" || schemaVersion === "2.0-draft" || schemaVersion === "2.1" || schemaVersion === "2.5" || schemaVersion === "2.6") {
|
|
38853
|
+
if (schemaVersion === "2.0" || schemaVersion === "2.0-draft" || schemaVersion === "2.1" || schemaVersion === "2.5" || schemaVersion === "2.6" || schemaVersion === "3.0" || schemaVersion === "3.1") {
|
|
37759
38854
|
return loadAtlasSourceWithDiagnostics(source, schemaVersion);
|
|
37760
38855
|
}
|
|
37761
38856
|
let ast;
|
|
@@ -37928,6 +39023,7 @@ void main() {
|
|
|
37928
39023
|
relations: true,
|
|
37929
39024
|
events: true,
|
|
37930
39025
|
orbits: true,
|
|
39026
|
+
trajectories: true,
|
|
37931
39027
|
objects: true,
|
|
37932
39028
|
labels: true,
|
|
37933
39029
|
structures: true,
|
|
@@ -38469,6 +39565,11 @@ void main() {
|
|
|
38469
39565
|
const orbitMarkup = layers.orbits ? renderOrbitLayer(scene, visibleObjectIds, layers.structures) : { back: "", front: "" };
|
|
38470
39566
|
const leaderMarkup = layers.guides ? scene.leaders.filter((leader) => !leader.hidden).filter((leader) => visibleObjectIds.has(leader.objectId)).filter((leader) => layers.structures || !isStructureLike(leader.object)).map((leader) => `<line class="wo-leader wo-leader-${leader.mode}" x1="${leader.x1}" y1="${leader.y1}" x2="${leader.x2}" y2="${leader.y2}" data-render-id="${escapeXml(leader.renderId)}" data-group-id="${escapeAttribute(leader.groupId ?? "")}" />`).join("") : "";
|
|
38471
39567
|
const relationMarkup = layers.relations ? scene.relations.filter((relation) => !relation.hidden).filter((relation) => visibleObjectIds.has(relation.fromObjectId) && visibleObjectIds.has(relation.toObjectId)).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)}" />`).join("") : "";
|
|
39568
|
+
const trajectoryMarkup = layers.trajectories ? renderTrajectoryLayer(scene, visibleObjectIds, {
|
|
39569
|
+
showLabels: options.showTrajectoryLabels ?? true,
|
|
39570
|
+
showWaypoints: options.showTrajectoryWaypoints ?? true,
|
|
39571
|
+
includeStructures: layers.structures
|
|
39572
|
+
}) : "";
|
|
38472
39573
|
const eventMarkup = layers.events ? scene.events.filter((event) => !event.hidden).map((event) => renderSceneEventOverlay(scene, event, visibleObjectIds, theme)).join("") : "";
|
|
38473
39574
|
const objectMarkup = layers.objects ? visibleObjects.map((object) => renderSceneObject(object, options.selectedObjectId ?? null, theme)).join("") : "";
|
|
38474
39575
|
const labelMarkup = layers.labels ? visibleLabels.map((label) => renderSceneLabel(scene, label, options.selectedObjectId ?? null)).join("") : "";
|
|
@@ -38494,6 +39595,9 @@ void main() {
|
|
|
38494
39595
|
<stop offset="0%" stop-color="${theme.backgroundGlow}" />
|
|
38495
39596
|
<stop offset="100%" stop-color="transparent" />
|
|
38496
39597
|
</radialGradient>
|
|
39598
|
+
<marker id="wo-trajectory-arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto" markerUnits="strokeWidth">
|
|
39599
|
+
<path d="M 0 0 L 12 6 L 0 12 z" fill="${theme.accent}" />
|
|
39600
|
+
</marker>
|
|
38497
39601
|
${imageDefinitions}
|
|
38498
39602
|
</defs>
|
|
38499
39603
|
<style>
|
|
@@ -38505,6 +39609,10 @@ void main() {
|
|
|
38505
39609
|
.wo-orbit-front { opacity: 0.9; }
|
|
38506
39610
|
.wo-orbit-band { stroke: ${theme.orbitBand}; stroke-linecap: round; }
|
|
38507
39611
|
.wo-relation { stroke: ${theme.relation}; stroke-width: 2; stroke-dasharray: 10 6; }
|
|
39612
|
+
.wo-trajectory { fill: none; stroke: ${theme.accent}; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; opacity: 0.92; }
|
|
39613
|
+
.wo-trajectory-waypoint { fill: ${theme.spaceFog}; stroke: ${theme.selected}; stroke-width: 1.4; }
|
|
39614
|
+
.wo-trajectory-label { fill: ${theme.accent}; font-family: ${theme.fontFamily}; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
|
|
39615
|
+
.wo-trajectory-date { fill: ${theme.muted}; font-family: ${theme.fontFamily}; font-weight: 500; }
|
|
38508
39616
|
.wo-event-line { stroke: ${theme.accent}; stroke-width: 1.6; stroke-dasharray: 5 5; opacity: 0.72; }
|
|
38509
39617
|
.wo-event-node { fill: ${theme.accent}; stroke: ${theme.selected}; stroke-width: 1.4; opacity: 0.92; }
|
|
38510
39618
|
.wo-event-label { fill: ${theme.accent}; font-family: ${theme.fontFamily}; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
|
|
@@ -38545,6 +39653,7 @@ void main() {
|
|
|
38545
39653
|
${layers.events ? `<g data-layer-id="events">${eventMarkup}</g>` : ""}
|
|
38546
39654
|
${layers.objects ? `<g data-layer-id="objects">${objectMarkup}</g>` : ""}
|
|
38547
39655
|
${layers.orbits ? `<g data-layer-id="orbits-front">${orbitMarkup.front}</g>` : ""}
|
|
39656
|
+
${layers.trajectories ? `<g data-layer-id="trajectories">${trajectoryMarkup}</g>` : ""}
|
|
38548
39657
|
${layers.labels ? `<g data-layer-id="labels">${labelMarkup}</g>` : ""}
|
|
38549
39658
|
</g>
|
|
38550
39659
|
</g>
|
|
@@ -38565,6 +39674,30 @@ void main() {
|
|
|
38565
39674
|
<text class="wo-event-label" x="${event.x}" y="${event.y - 10}" text-anchor="middle" font-size="10">${escapeXml(label)}</text>
|
|
38566
39675
|
</g>`;
|
|
38567
39676
|
}
|
|
39677
|
+
function renderTrajectoryLayer(scene, visibleObjectIds, options) {
|
|
39678
|
+
return scene.trajectories.filter((trajectory) => !trajectory.hidden).filter((trajectory) => trajectory.objectIds.length === 0 || trajectory.objectIds.some((objectId) => visibleObjectIds.has(objectId))).filter((trajectory) => options.includeStructures || !trajectory.objectIds.some((objectId) => {
|
|
39679
|
+
const object = scene.objects.find((entry) => entry.objectId === objectId)?.object;
|
|
39680
|
+
return object ? isStructureLike(object) : false;
|
|
39681
|
+
})).map((trajectory) => {
|
|
39682
|
+
const stroke = trajectory.stroke ?? "#f0b464";
|
|
39683
|
+
const markerEnd = trajectory.marker === "none" ? "" : ` marker-end="url(#wo-trajectory-arrow)"`;
|
|
39684
|
+
const waypointMarkup = trajectory.showWaypoints && options.showWaypoints ? trajectory.waypoints.filter((waypoint) => !waypoint.hidden).map((waypoint) => renderTrajectoryWaypoint(trajectory, waypoint, options.showLabels)).join("") : "";
|
|
39685
|
+
return `<g class="wo-trajectory-group" data-render-id="${escapeXml(trajectory.renderId)}" data-trajectory-id="${escapeAttribute(trajectory.trajectoryId)}">
|
|
39686
|
+
<path class="wo-trajectory wo-trajectory-${trajectory.mode}" d="${trajectory.path}" stroke="${escapeAttribute(stroke)}" stroke-width="${trajectory.strokeWidth}"${markerEnd} />
|
|
39687
|
+
${waypointMarkup}
|
|
39688
|
+
</g>`;
|
|
39689
|
+
}).join("");
|
|
39690
|
+
}
|
|
39691
|
+
function renderTrajectoryWaypoint(trajectory, waypoint, showLabels) {
|
|
39692
|
+
const labelMarkup = showLabels && trajectory.labelMode !== "hidden" ? [
|
|
39693
|
+
waypoint.label ? `<text class="wo-trajectory-label" x="${waypoint.x + 10}" y="${waypoint.y - 10}" font-size="10">${escapeXml(waypoint.label)}</text>` : "",
|
|
39694
|
+
waypoint.dateLabel ? `<text class="wo-trajectory-date" x="${waypoint.x + 10}" y="${waypoint.y + 4}" font-size="9">${escapeXml(waypoint.dateLabel)}</text>` : ""
|
|
39695
|
+
].join("") : "";
|
|
39696
|
+
return `<g class="wo-trajectory-waypoint-group" data-render-id="${escapeXml(waypoint.renderId)}" data-trajectory-id="${escapeAttribute(waypoint.trajectoryId)}">
|
|
39697
|
+
<circle class="wo-trajectory-waypoint" cx="${waypoint.x}" cy="${waypoint.y}" r="4.5" />
|
|
39698
|
+
${labelMarkup}
|
|
39699
|
+
</g>`;
|
|
39700
|
+
}
|
|
38568
39701
|
function renderDocumentToSvg(document2, options = {}) {
|
|
38569
39702
|
return renderSceneToSvg(renderDocumentToScene(document2, options), options);
|
|
38570
39703
|
}
|
|
@@ -38653,6 +39786,8 @@ void main() {
|
|
|
38653
39786
|
case "comet":
|
|
38654
39787
|
return options.outlineOnly ? `<circle cx="${x}" cy="${y}" r="${radius}" fill="transparent" stroke="${palette.stroke}" stroke-width="1.4" />` : `<path d="M ${x - radius * 2} ${y + radius * 1.3} Q ${x - radius * 0.7} ${y + radius * 0.3} ${x - radius * 0.45} ${y}" fill="none" stroke="${tail}" stroke-width="${Math.max(2, radius * 0.8)}" stroke-linecap="round" opacity="0.85" />
|
|
38655
39788
|
<circle cx="${x}" cy="${y}" r="${radius}" fill="${fill}" stroke="${palette.stroke}" stroke-width="1.4" />`;
|
|
39789
|
+
case "craft":
|
|
39790
|
+
return `<polygon points="${diamondPoints(x, y, radius * 0.85)}" fill="${fill}" stroke="${palette.stroke}" stroke-width="1.4" />`;
|
|
38656
39791
|
case "structure":
|
|
38657
39792
|
return `<polygon points="${diamondPoints(x, y, radius)}" fill="${fill}" stroke="${palette.stroke}" stroke-width="1.4" />`;
|
|
38658
39793
|
case "phenomenon": {
|
|
@@ -38786,6 +39921,8 @@ void main() {
|
|
|
38786
39921
|
return { fill: "#9ce7ff", stroke: "#e7fbff" };
|
|
38787
39922
|
case "ring":
|
|
38788
39923
|
return { fill: "#e59f7d", stroke: "#fff0d3" };
|
|
39924
|
+
case "craft":
|
|
39925
|
+
return { fill: "#ffb47f", stroke: "#fff0d3" };
|
|
38789
39926
|
case "structure":
|
|
38790
39927
|
return { fill: theme.accentStrong, stroke: "#fff2ea" };
|
|
38791
39928
|
case "phenomenon":
|
|
@@ -39051,6 +40188,8 @@ void main() {
|
|
|
39051
40188
|
return "#a7a5b8";
|
|
39052
40189
|
case "comet":
|
|
39053
40190
|
return "#9ce7ff";
|
|
40191
|
+
case "craft":
|
|
40192
|
+
return "#ffb47f";
|
|
39054
40193
|
case "structure":
|
|
39055
40194
|
return "#ff7f5f";
|
|
39056
40195
|
case "phenomenon":
|
|
@@ -39709,6 +40848,8 @@ void main() {
|
|
|
39709
40848
|
return "#b8926a";
|
|
39710
40849
|
case "ring":
|
|
39711
40850
|
return "#cdbf9a";
|
|
40851
|
+
case "craft":
|
|
40852
|
+
return "#ffce8a";
|
|
39712
40853
|
case "structure":
|
|
39713
40854
|
return "#ffce8a";
|
|
39714
40855
|
case "phenomenon":
|
|
@@ -40965,7 +42106,7 @@ void main() {
|
|
|
40965
42106
|
tooltipRoot.hidden = false;
|
|
40966
42107
|
tooltipRoot.dataset.mode = resolved.mode;
|
|
40967
42108
|
tooltipRoot.classList.toggle("is-pinned", resolved.mode === "pinned");
|
|
40968
|
-
tooltipRoot.style.pointerEvents = "auto";
|
|
42109
|
+
tooltipRoot.style.pointerEvents = resolved.mode === "pinned" ? "auto" : "none";
|
|
40969
42110
|
tooltipRoot.style.visibility = "hidden";
|
|
40970
42111
|
renderTooltipContent(tooltipRoot, tooltipDetails, resolved.mode);
|
|
40971
42112
|
positionTooltip(tooltipRoot, details.renderObject);
|
|
@@ -41517,6 +42658,33 @@ void main() {
|
|
|
41517
42658
|
hidden: orbit.hidden,
|
|
41518
42659
|
motion: null
|
|
41519
42660
|
})),
|
|
42661
|
+
trajectories: scene.trajectories.map((trajectory) => ({
|
|
42662
|
+
trajectoryId: trajectory.trajectoryId,
|
|
42663
|
+
trajectory: trajectory.trajectory,
|
|
42664
|
+
craftObjectId: trajectory.craftObjectId,
|
|
42665
|
+
mode: trajectory.mode,
|
|
42666
|
+
stroke: trajectory.stroke,
|
|
42667
|
+
strokeWidth: trajectory.strokeWidth,
|
|
42668
|
+
marker: trajectory.marker,
|
|
42669
|
+
labelMode: trajectory.labelMode,
|
|
42670
|
+
showWaypoints: trajectory.showWaypoints,
|
|
42671
|
+
samples: [],
|
|
42672
|
+
waypoints: trajectory.waypoints.map((waypoint) => ({
|
|
42673
|
+
trajectoryId: waypoint.trajectoryId,
|
|
42674
|
+
segmentId: waypoint.segmentId,
|
|
42675
|
+
maneuverId: waypoint.maneuverId,
|
|
42676
|
+
objectId: waypoint.objectId,
|
|
42677
|
+
position: {
|
|
42678
|
+
x: waypoint.x - scene.contentBounds.centerX,
|
|
42679
|
+
y: 0,
|
|
42680
|
+
z: waypoint.y - scene.contentBounds.centerY
|
|
42681
|
+
},
|
|
42682
|
+
label: waypoint.label,
|
|
42683
|
+
dateLabel: waypoint.dateLabel,
|
|
42684
|
+
hidden: waypoint.hidden
|
|
42685
|
+
})),
|
|
42686
|
+
hidden: trajectory.hidden
|
|
42687
|
+
})),
|
|
41520
42688
|
focusTargets: scene.objects.map((object) => ({
|
|
41521
42689
|
objectId: object.objectId,
|
|
41522
42690
|
center: {
|
|
@@ -41558,7 +42726,11 @@ void main() {
|
|
|
41558
42726
|
if (!(target instanceof Element)) {
|
|
41559
42727
|
return null;
|
|
41560
42728
|
}
|
|
41561
|
-
|
|
42729
|
+
const selectionTarget = target.closest("[data-object-id], [data-orbit-object-id]");
|
|
42730
|
+
if (!selectionTarget) {
|
|
42731
|
+
return null;
|
|
42732
|
+
}
|
|
42733
|
+
return selectionTarget.dataset.objectId ?? selectionTarget.dataset.orbitObjectId ?? null;
|
|
41562
42734
|
}
|
|
41563
42735
|
function ensureBrowserEnvironment(container) {
|
|
41564
42736
|
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
@@ -41690,7 +42862,7 @@ void main() {
|
|
|
41690
42862
|
backdrop-filter: blur(12px);
|
|
41691
42863
|
font: 500 13px/1.5 "Segoe UI Variable", "Segoe UI", sans-serif;
|
|
41692
42864
|
}
|
|
41693
|
-
.wo-viewer-tooltip-root[data-mode="hover"] { pointer-events:
|
|
42865
|
+
.wo-viewer-tooltip-root[data-mode="hover"] { pointer-events: none; }
|
|
41694
42866
|
.wo-viewer-tooltip-root[data-mode="pinned"] { pointer-events: auto; }
|
|
41695
42867
|
.wo-tooltip-card { display: grid; gap: 10px; }
|
|
41696
42868
|
.wo-tooltip-head { display: grid; grid-template-columns: 52px minmax(0, 1fr); gap: 12px; align-items: center; }
|