worldorbit 3.2.2 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +546 -545
  2. package/dist/browser/core/dist/atlas-edit.js +146 -1
  3. package/dist/browser/core/dist/atlas-validate.js +105 -10
  4. package/dist/browser/core/dist/draft-parse.js +341 -16
  5. package/dist/browser/core/dist/draft.d.ts +2 -1
  6. package/dist/browser/core/dist/draft.js +25 -3
  7. package/dist/browser/core/dist/format.js +86 -4
  8. package/dist/browser/core/dist/index.d.ts +1 -0
  9. package/dist/browser/core/dist/index.js +1 -0
  10. package/dist/browser/core/dist/load.js +7 -2
  11. package/dist/browser/core/dist/normalize.js +1 -0
  12. package/dist/browser/core/dist/scene.js +11 -2
  13. package/dist/browser/core/dist/schema.js +11 -1
  14. package/dist/browser/core/dist/solver.d.ts +26 -0
  15. package/dist/browser/core/dist/solver.js +27 -0
  16. package/dist/browser/core/dist/types.d.ts +57 -3
  17. package/dist/browser/editor/dist/editor.js +844 -719
  18. package/dist/browser/editor/dist/types.d.ts +2 -1
  19. package/dist/browser/viewer/dist/minimap.js +9 -7
  20. package/dist/browser/viewer/dist/render.js +23 -19
  21. package/dist/browser/viewer/dist/runtime-3d.js +2 -0
  22. package/dist/browser/viewer/dist/viewer.js +7 -3
  23. package/dist/obsidian-plugin/README.md +141 -124
  24. package/dist/obsidian-plugin/main.js +31 -31
  25. package/dist/unpkg/core/dist/atlas-edit.js +146 -1
  26. package/dist/unpkg/core/dist/atlas-validate.js +105 -10
  27. package/dist/unpkg/core/dist/draft-parse.js +341 -16
  28. package/dist/unpkg/core/dist/draft.d.ts +2 -1
  29. package/dist/unpkg/core/dist/draft.js +25 -3
  30. package/dist/unpkg/core/dist/format.js +86 -4
  31. package/dist/unpkg/core/dist/index.d.ts +1 -0
  32. package/dist/unpkg/core/dist/index.js +1 -0
  33. package/dist/unpkg/core/dist/load.js +7 -2
  34. package/dist/unpkg/core/dist/normalize.js +1 -0
  35. package/dist/unpkg/core/dist/scene.js +11 -2
  36. package/dist/unpkg/core/dist/schema.js +11 -1
  37. package/dist/unpkg/core/dist/solver.d.ts +26 -0
  38. package/dist/unpkg/core/dist/solver.js +27 -0
  39. package/dist/unpkg/core/dist/types.d.ts +57 -3
  40. package/dist/unpkg/editor/dist/editor.js +844 -719
  41. package/dist/unpkg/editor/dist/types.d.ts +2 -1
  42. package/dist/unpkg/viewer/dist/minimap.js +9 -7
  43. package/dist/unpkg/viewer/dist/render.js +23 -19
  44. package/dist/unpkg/viewer/dist/runtime-3d.js +2 -0
  45. package/dist/unpkg/viewer/dist/viewer.js +7 -3
  46. package/dist/unpkg/worldorbit-core.min.js +10 -10
  47. package/dist/unpkg/worldorbit-editor.min.js +359 -332
  48. package/dist/unpkg/worldorbit-markdown.min.js +28 -28
  49. package/dist/unpkg/worldorbit-viewer.min.js +214 -214
  50. package/dist/unpkg/worldorbit.js +758 -40
  51. package/dist/unpkg/worldorbit.min.js +223 -223
  52. package/package.json +5 -1
  53. package/packages/core/dist/atlas-edit.js +146 -1
  54. package/packages/core/dist/atlas-validate.js +105 -10
  55. package/packages/core/dist/draft-parse.js +341 -16
  56. package/packages/core/dist/draft.d.ts +2 -1
  57. package/packages/core/dist/draft.js +25 -3
  58. package/packages/core/dist/format.js +86 -4
  59. package/packages/core/dist/index.d.ts +1 -0
  60. package/packages/core/dist/index.js +1 -0
  61. package/packages/core/dist/load.js +7 -2
  62. package/packages/core/dist/normalize.js +1 -0
  63. package/packages/core/dist/scene.js +11 -2
  64. package/packages/core/dist/schema.js +11 -1
  65. package/packages/core/dist/solver.d.ts +26 -0
  66. package/packages/core/dist/solver.js +27 -0
  67. package/packages/core/dist/types.d.ts +57 -3
  68. package/packages/editor/dist/editor.js +844 -719
  69. package/packages/editor/dist/types.d.ts +2 -1
  70. package/packages/viewer/dist/minimap.js +9 -7
  71. package/packages/viewer/dist/render.js +23 -19
  72. package/packages/viewer/dist/runtime-3d.js +2 -0
  73. package/packages/viewer/dist/viewer.js +7 -3
@@ -40,10 +40,12 @@ export function formatDocument(document, options = {}) {
40
40
  schema === "2.1" ||
41
41
  schema === "2.5" ||
42
42
  schema === "2.6" ||
43
+ schema === "3.0" ||
43
44
  schema === "2.0-draft" ||
44
45
  document.version === "2.0" ||
45
46
  document.version === "2.1" ||
46
47
  document.version === "2.5" ||
48
+ document.version === "3.0" ||
47
49
  document.version === "2.6" ||
48
50
  document.version === "2.0-draft";
49
51
  if (useDraft) {
@@ -59,7 +61,7 @@ export function formatDocument(document, options = {}) {
59
61
  : upgradeDocumentToDraftV2(document);
60
62
  return formatDraftDocument(legacyDraftDocument);
61
63
  }
62
- const atlasDocument = document.version === "2.0" || document.version === "2.1" || document.version === "2.5" || document.version === "2.6"
64
+ const atlasDocument = document.version === "2.0" || document.version === "2.1" || document.version === "2.5" || document.version === "2.6" || document.version === "3.0"
63
65
  ? document
64
66
  : document.version === "2.0-draft"
65
67
  ? {
@@ -68,7 +70,7 @@ export function formatDocument(document, options = {}) {
68
70
  schemaVersion: "2.0",
69
71
  }
70
72
  : upgradeDocumentToV2(document);
71
- if ((schema === "2.0" || schema === "2.1" || schema === "2.5" || schema === "2.6") && atlasDocument.version !== schema) {
73
+ if ((schema === "2.0" || schema === "2.1" || schema === "2.5" || schema === "2.6" || schema === "3.0") && atlasDocument.version !== schema) {
72
74
  return formatAtlasDocument({
73
75
  ...atlasDocument,
74
76
  version: schema,
@@ -108,6 +110,10 @@ export function formatAtlasDocument(document) {
108
110
  lines.push("");
109
111
  lines.push(...formatAtlasEvent(event));
110
112
  }
113
+ for (const trajectory of [...document.trajectories].sort(compareIdLike)) {
114
+ lines.push("");
115
+ lines.push(...formatAtlasTrajectory(trajectory));
116
+ }
111
117
  const sortedObjects = [...document.objects].sort(compareObjects);
112
118
  if (sortedObjects.length > 0 && lines.at(-1) !== "") {
113
119
  lines.push("");
@@ -295,6 +301,9 @@ function formatObjectMetadata(object) {
295
301
  if (object.groups?.length) {
296
302
  lines.push(`groups ${object.groups.join(" ")}`);
297
303
  }
304
+ if (object.trajectoryId) {
305
+ lines.push(`trajectory ${object.trajectoryId}`);
306
+ }
298
307
  if (object.epoch) {
299
308
  lines.push(`epoch ${quoteIfNeeded(object.epoch)}`);
300
309
  }
@@ -455,6 +464,9 @@ function formatAtlasEvent(event) {
455
464
  if (event.summary) {
456
465
  lines.push(` summary ${quoteIfNeeded(event.summary)}`);
457
466
  }
467
+ if (event.trajectoryId) {
468
+ lines.push(` trajectory ${event.trajectoryId}`);
469
+ }
458
470
  if (event.targetObjectId) {
459
471
  lines.push(` target ${event.targetObjectId}`);
460
472
  }
@@ -497,12 +509,80 @@ function formatAtlasEvent(event) {
497
509
  function formatEventPoseFields(pose) {
498
510
  return [
499
511
  ...formatPlacement(pose.placement),
512
+ ...(pose.trajectorySegmentId ? [`segment ${pose.trajectorySegmentId}`] : []),
513
+ ...(pose.trajectoryManeuverId ? [`maneuver ${pose.trajectoryManeuverId}`] : []),
500
514
  ...(pose.epoch ? [`epoch ${quoteIfNeeded(pose.epoch)}`] : []),
501
515
  ...(pose.referencePlane ? [`referencePlane ${quoteIfNeeded(pose.referencePlane)}`] : []),
502
516
  ...formatOptionalUnit("inner", pose.inner),
503
517
  ...formatOptionalUnit("outer", pose.outer),
504
518
  ];
505
519
  }
520
+ function formatAtlasTrajectory(trajectory) {
521
+ const lines = [`trajectory ${trajectory.id}`];
522
+ if (trajectory.label) {
523
+ lines.push(` label ${quoteIfNeeded(trajectory.label)}`);
524
+ }
525
+ if (trajectory.summary) {
526
+ lines.push(` summary ${quoteIfNeeded(trajectory.summary)}`);
527
+ }
528
+ if (trajectory.craftObjectId) {
529
+ lines.push(` craft ${trajectory.craftObjectId}`);
530
+ }
531
+ if (trajectory.tags.length > 0) {
532
+ lines.push(` tags ${trajectory.tags.map(quoteIfNeeded).join(" ")}`);
533
+ }
534
+ if (trajectory.color) {
535
+ lines.push(` color ${quoteIfNeeded(trajectory.color)}`);
536
+ }
537
+ if (trajectory.hidden) {
538
+ lines.push(" hidden true");
539
+ }
540
+ for (const segment of [...trajectory.segments].sort(compareIdLike)) {
541
+ lines.push("");
542
+ lines.push(` segment ${segment.id}`);
543
+ for (const field of formatTrajectorySegmentFields(segment)) {
544
+ lines.push(` ${field}`);
545
+ }
546
+ for (const maneuver of [...segment.maneuvers].sort(compareIdLike)) {
547
+ lines.push(` maneuver ${maneuver.id}`);
548
+ for (const field of formatTrajectoryManeuverFields(maneuver)) {
549
+ lines.push(` ${field}`);
550
+ }
551
+ }
552
+ }
553
+ return lines;
554
+ }
555
+ function formatTrajectorySegmentFields(segment) {
556
+ return [
557
+ `kind ${segment.kind}`,
558
+ ...(segment.label ? [`label ${quoteIfNeeded(segment.label)}`] : []),
559
+ ...(segment.summary ? [`summary ${quoteIfNeeded(segment.summary)}`] : []),
560
+ ...(segment.fromObjectId ? [`from ${segment.fromObjectId}`] : []),
561
+ ...(segment.toObjectId ? [`to ${segment.toObjectId}`] : []),
562
+ ...(segment.aroundObjectId ? [`around ${segment.aroundObjectId}`] : []),
563
+ ...(segment.assist?.objectId ? [`assist ${segment.assist.objectId}`] : []),
564
+ ...(segment.epoch ? [`epoch ${quoteIfNeeded(segment.epoch)}`] : []),
565
+ ...formatOptionalUnit("periapsis", segment.periapsis),
566
+ ...formatOptionalUnit("apoapsis", segment.apoapsis),
567
+ ...formatOptionalUnit("inclination", segment.inclination),
568
+ ...formatOptionalUnit("duration", segment.duration),
569
+ ...formatOptionalUnit("deltaV", segment.deltaV),
570
+ ...formatOptionalUnit("phaseAngle", segment.phaseAngle),
571
+ ...formatOptionalUnit("turnAngle", segment.turnAngle),
572
+ ...formatOptionalUnit("energy", segment.energy),
573
+ ...(segment.notes.length > 0 ? [`notes ${segment.notes.map(quoteIfNeeded).join(" ")}`] : []),
574
+ ];
575
+ }
576
+ function formatTrajectoryManeuverFields(maneuver) {
577
+ return [
578
+ `kind ${quoteIfNeeded(maneuver.kind)}`,
579
+ ...(maneuver.label ? [`label ${quoteIfNeeded(maneuver.label)}`] : []),
580
+ ...(maneuver.epoch ? [`epoch ${quoteIfNeeded(maneuver.epoch)}`] : []),
581
+ ...formatOptionalUnit("deltaV", maneuver.deltaV),
582
+ ...formatOptionalUnit("duration", maneuver.duration),
583
+ ...(maneuver.notes.length > 0 ? [`notes ${maneuver.notes.map(quoteIfNeeded).join(" ")}`] : []),
584
+ ];
585
+ }
506
586
  function hasCameraValues(camera) {
507
587
  return (camera.azimuth !== null ||
508
588
  camera.elevation !== null ||
@@ -601,10 +681,12 @@ function objectTypeIndex(objectType) {
601
681
  return 5;
602
682
  case "ring":
603
683
  return 6;
604
- case "structure":
684
+ case "craft":
605
685
  return 7;
606
- case "phenomenon":
686
+ case "structure":
607
687
  return 8;
688
+ case "phenomenon":
689
+ return 9;
608
690
  }
609
691
  }
610
692
  function quoteIfNeeded(value) {
@@ -8,6 +8,7 @@ export { validateDocument } from "./validate.js";
8
8
  export { createDiagnostic, diagnosticFromError, normalizeWithDiagnostics, parseWithDiagnostics, validateDocumentWithDiagnostics, } from "./diagnostics.js";
9
9
  export { renderDocumentToScene, rotatePoint } from "./scene.js";
10
10
  export { evaluateSpatialSceneAtTime, renderDocumentToSpatialScene, } from "./spatial-scene.js";
11
+ export { createTrajectorySolverSnapshot } from "./solver.js";
11
12
  export { formatAtlasDocument, formatDocument, formatDraftDocument } from "./format.js";
12
13
  export { materializeAtlasDocument, materializeDraftDocument, upgradeDocumentToDraftV2, upgradeDocumentToV2, } from "./draft.js";
13
14
  export { parseWorldOrbitAtlas, parseWorldOrbitDraft } from "./draft-parse.js";
@@ -8,6 +8,7 @@ export { validateDocument } from "./validate.js";
8
8
  export { createDiagnostic, diagnosticFromError, normalizeWithDiagnostics, parseWithDiagnostics, validateDocumentWithDiagnostics, } from "./diagnostics.js";
9
9
  export { renderDocumentToScene, rotatePoint } from "./scene.js";
10
10
  export { evaluateSpatialSceneAtTime, renderDocumentToSpatialScene, } from "./spatial-scene.js";
11
+ export { createTrajectorySolverSnapshot } from "./solver.js";
11
12
  export { formatAtlasDocument, formatDocument, formatDraftDocument } from "./format.js";
12
13
  export { materializeAtlasDocument, materializeDraftDocument, upgradeDocumentToDraftV2, upgradeDocumentToV2, } from "./draft.js";
13
14
  export { parseWorldOrbitAtlas, parseWorldOrbitDraft } from "./draft-parse.js";
@@ -5,10 +5,11 @@ import { WorldOrbitError } from "./errors.js";
5
5
  import { normalizeDocument } from "./normalize.js";
6
6
  import { parseWorldOrbit } from "./parse.js";
7
7
  import { validateDocument } from "./validate.js";
8
- const ATLAS_SCHEMA_PATTERN = /^schema\s+2(?:\.0|\.1|\.5|\.6)?$/i;
8
+ const ATLAS_SCHEMA_PATTERN = /^schema\s+(?:2(?:\.0|\.1|\.5|\.6)?|3(?:\.0)?)$/i;
9
9
  const ATLAS_SCHEMA_21_PATTERN = /^schema\s+2\.1$/i;
10
10
  const ATLAS_SCHEMA_25_PATTERN = /^schema\s+2\.5$/i;
11
11
  const ATLAS_SCHEMA_26_PATTERN = /^schema\s+2\.6$/i;
12
+ const ATLAS_SCHEMA_30_PATTERN = /^schema\s+3(?:\.0)?$/i;
12
13
  const LEGACY_DRAFT_SCHEMA_PATTERN = /^schema\s+2\.0-draft$/i;
13
14
  export function detectWorldOrbitSchemaVersion(source) {
14
15
  for (const line of stripCommentsForSchemaDetection(source).split(/\r?\n/)) {
@@ -28,6 +29,9 @@ export function detectWorldOrbitSchemaVersion(source) {
28
29
  if (ATLAS_SCHEMA_26_PATTERN.test(trimmed)) {
29
30
  return "2.6";
30
31
  }
32
+ if (ATLAS_SCHEMA_30_PATTERN.test(trimmed)) {
33
+ return "3.0";
34
+ }
31
35
  if (ATLAS_SCHEMA_PATTERN.test(trimmed)) {
32
36
  return "2.0";
33
37
  }
@@ -92,7 +96,8 @@ export function loadWorldOrbitSourceWithDiagnostics(source) {
92
96
  schemaVersion === "2.0-draft" ||
93
97
  schemaVersion === "2.1" ||
94
98
  schemaVersion === "2.5" ||
95
- schemaVersion === "2.6") {
99
+ schemaVersion === "2.6" ||
100
+ schemaVersion === "3.0") {
96
101
  return loadAtlasSourceWithDiagnostics(source, schemaVersion);
97
102
  }
98
103
  let ast;
@@ -33,6 +33,7 @@ export function normalizeDocument(ast) {
33
33
  groups: [],
34
34
  relations: [],
35
35
  events: [],
36
+ trajectories: [],
36
37
  objects,
37
38
  };
38
39
  }
@@ -467,7 +467,9 @@ function createSceneObject(position, scaleModel, relationships) {
467
467
  anchorX,
468
468
  anchorY,
469
469
  label: object.id,
470
- secondaryLabel: object.type === "structure" ? String(object.properties.kind ?? object.type) : object.type,
470
+ secondaryLabel: object.type === "structure" || object.type === "craft"
471
+ ? String(object.properties.kind ?? object.type)
472
+ : object.type,
471
473
  fillColor: customColorFor(object.properties.color),
472
474
  imageHref: typeof object.properties.image === "string" && object.properties.image.trim()
473
475
  ? object.properties.image
@@ -566,6 +568,7 @@ function labelPlacementPriority(object) {
566
568
  case "asteroid":
567
569
  case "comet":
568
570
  return 4;
571
+ case "craft":
569
572
  case "structure":
570
573
  case "phenomenon":
571
574
  return 5;
@@ -590,7 +593,8 @@ function preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight) {
590
593
  const oppositeVertical = vertical === "below" ? "above" : "below";
591
594
  const horizontal = defaultHorizontalDirection(object, parent, sceneWidth);
592
595
  const oppositeHorizontal = horizontal === "right" ? "left" : "right";
593
- const preferHorizontal = object.object.type === "structure" ||
596
+ const preferHorizontal = object.object.type === "craft" ||
597
+ object.object.type === "structure" ||
594
598
  object.object.type === "phenomenon" ||
595
599
  object.object.placement?.mode === "at" ||
596
600
  object.object.placement?.mode === "surface" ||
@@ -1109,6 +1113,7 @@ function parseViewpointObjectTypes(value) {
1109
1113
  entry === "asteroid" ||
1110
1114
  entry === "comet" ||
1111
1115
  entry === "ring" ||
1116
+ entry === "craft" ||
1112
1117
  entry === "structure" ||
1113
1118
  entry === "phenomenon");
1114
1119
  }
@@ -1785,6 +1790,8 @@ function visualRadiusFor(object, depth, scaleModel, sceneMetricScale) {
1785
1790
  return clampNumber(6 * multiplier, scaleModel.minBodyRadius, scaleModel.maxBodyRadius);
1786
1791
  case "ring":
1787
1792
  return clampNumber(5 * multiplier, scaleModel.minBodyRadius, scaleModel.maxBodyRadius);
1793
+ case "craft":
1794
+ return clampNumber(5 * multiplier, scaleModel.minBodyRadius, scaleModel.maxBodyRadius);
1788
1795
  case "structure":
1789
1796
  return clampNumber(6 * multiplier, scaleModel.minBodyRadius, scaleModel.maxBodyRadius);
1790
1797
  case "phenomenon":
@@ -1798,6 +1805,8 @@ function visualExtentForObject(object, radius, scaleModel) {
1798
1805
  return radius * 2.4;
1799
1806
  case "phenomenon":
1800
1807
  return radius * 1.25;
1808
+ case "craft":
1809
+ return radius + 1.5;
1801
1810
  case "structure":
1802
1811
  return radius + 2;
1803
1812
  default:
@@ -7,6 +7,7 @@ const ALL_OBJECTS = [
7
7
  "asteroid",
8
8
  "comet",
9
9
  "ring",
10
+ "craft",
10
11
  "structure",
11
12
  "phenomenon",
12
13
  ];
@@ -17,10 +18,11 @@ const IMAGE_OBJECTS = [
17
18
  "moon",
18
19
  "asteroid",
19
20
  "comet",
21
+ "craft",
20
22
  "structure",
21
23
  "phenomenon",
22
24
  ];
23
- const ANCHORED_OBJECTS = ["structure", "phenomenon"];
25
+ const ANCHORED_OBJECTS = ["craft", "structure", "phenomenon"];
24
26
  const ORBITAL_OBJECTS = [
25
27
  "star",
26
28
  "planet",
@@ -29,6 +31,7 @@ const ORBITAL_OBJECTS = [
29
31
  "asteroid",
30
32
  "comet",
31
33
  "ring",
34
+ "craft",
32
35
  "structure",
33
36
  "phenomenon",
34
37
  ];
@@ -40,6 +43,7 @@ const FREE_OBJECTS = [
40
43
  "asteroid",
41
44
  "comet",
42
45
  "ring",
46
+ "craft",
43
47
  "structure",
44
48
  "phenomenon",
45
49
  ];
@@ -269,6 +273,12 @@ export const WORLDORBIT_FIELD_SCHEMAS = new Map([
269
273
  objectTypes: NON_SYSTEM_OBJECTS,
270
274
  unitFamily: "duration",
271
275
  }),
276
+ createField("trajectory", {
277
+ kind: "string",
278
+ placement: false,
279
+ arity: "single",
280
+ objectTypes: ["craft", "structure"],
281
+ }),
272
282
  ].map((schema) => [schema.key, schema]));
273
283
  export const WORLDORBIT_FIELD_KEYS = new Set(WORLDORBIT_FIELD_SCHEMAS.keys());
274
284
  export function getFieldSchema(key) {
@@ -0,0 +1,26 @@
1
+ import type { UnitValue, WorldOrbitTrajectory, WorldOrbitTrajectorySegment } from "./types.js";
2
+ export interface SolverSegmentSample {
3
+ segmentId: string;
4
+ kind: WorldOrbitTrajectorySegment["kind"];
5
+ fromObjectId: string | null;
6
+ toObjectId: string | null;
7
+ aroundObjectId: string | null;
8
+ assistObjectId: string | null;
9
+ duration: UnitValue | null;
10
+ deltaV: UnitValue | null;
11
+ }
12
+ export interface SolverManeuverSample {
13
+ segmentId: string;
14
+ maneuverId: string;
15
+ kind: string;
16
+ epoch: string | null;
17
+ deltaV: UnitValue | null;
18
+ duration: UnitValue | null;
19
+ }
20
+ export interface SolverTrajectorySnapshot {
21
+ trajectoryId: string;
22
+ craftObjectId: string | null;
23
+ segments: SolverSegmentSample[];
24
+ maneuvers: SolverManeuverSample[];
25
+ }
26
+ export declare function createTrajectorySolverSnapshot(trajectory: WorldOrbitTrajectory): SolverTrajectorySnapshot;
@@ -0,0 +1,27 @@
1
+ export function createTrajectorySolverSnapshot(trajectory) {
2
+ return {
3
+ trajectoryId: trajectory.id,
4
+ craftObjectId: trajectory.craftObjectId,
5
+ segments: trajectory.segments.map((segment) => ({
6
+ segmentId: segment.id,
7
+ kind: segment.kind,
8
+ fromObjectId: segment.fromObjectId,
9
+ toObjectId: segment.toObjectId,
10
+ aroundObjectId: segment.aroundObjectId,
11
+ assistObjectId: segment.assist?.objectId ?? null,
12
+ duration: segment.duration ?? null,
13
+ deltaV: segment.deltaV ?? null,
14
+ })),
15
+ maneuvers: trajectory.segments.flatMap((segment) => segment.maneuvers.map((maneuver) => mapManeuver(segment.id, maneuver))),
16
+ };
17
+ }
18
+ function mapManeuver(segmentId, maneuver) {
19
+ return {
20
+ segmentId,
21
+ maneuverId: maneuver.id,
22
+ kind: maneuver.kind,
23
+ epoch: maneuver.epoch,
24
+ deltaV: maneuver.deltaV ?? null,
25
+ duration: maneuver.duration ?? null,
26
+ };
27
+ }
@@ -1,8 +1,8 @@
1
- export type WorldOrbitObjectType = "system" | "star" | "planet" | "moon" | "belt" | "asteroid" | "comet" | "ring" | "structure" | "phenomenon";
1
+ export type WorldOrbitObjectType = "system" | "star" | "planet" | "moon" | "belt" | "asteroid" | "comet" | "ring" | "craft" | "structure" | "phenomenon";
2
2
  export type PlacementMode = "orbit" | "at" | "surface" | "free";
3
3
  export type Unit = "au" | "km" | "m" | "ly" | "pc" | "kpc" | "re" | "rj" | "sol" | "me" | "mj" | "s" | "min" | "h" | "d" | "y" | "ky" | "my" | "gy" | "K" | "deg";
4
4
  export type WorldOrbitDocumentVersion = "1.0";
5
- export type WorldOrbitAtlasDocumentVersion = "2.0" | "2.1" | "2.5" | "2.6";
5
+ export type WorldOrbitAtlasDocumentVersion = "2.0" | "2.1" | "2.5" | "2.6" | "3.0";
6
6
  export type WorldOrbitDraftDocumentVersion = "2.0-draft";
7
7
  export type WorldOrbitAnyDocumentVersion = WorldOrbitDocumentVersion | WorldOrbitAtlasDocumentVersion | WorldOrbitDraftDocumentVersion;
8
8
  export type ViewProjection = "topdown" | "isometric" | "orthographic" | "perspective";
@@ -86,6 +86,7 @@ export interface WorldOrbitDocument {
86
86
  groups: WorldOrbitGroup[];
87
87
  relations: WorldOrbitRelation[];
88
88
  events: WorldOrbitEvent[];
89
+ trajectories: WorldOrbitTrajectory[];
89
90
  objects: WorldOrbitObject[];
90
91
  }
91
92
  export interface WorldOrbitAtlasDocument {
@@ -98,6 +99,7 @@ export interface WorldOrbitAtlasDocument {
98
99
  groups: WorldOrbitGroup[];
99
100
  relations: WorldOrbitRelation[];
100
101
  events: WorldOrbitEvent[];
102
+ trajectories: WorldOrbitTrajectory[];
101
103
  objects: WorldOrbitObject[];
102
104
  diagnostics: WorldOrbitDiagnostic[];
103
105
  }
@@ -111,6 +113,7 @@ export interface WorldOrbitDraftDocument {
111
113
  groups: WorldOrbitGroup[];
112
114
  relations: WorldOrbitRelation[];
113
115
  events: WorldOrbitEvent[];
116
+ trajectories: WorldOrbitTrajectory[];
114
117
  objects: WorldOrbitObject[];
115
118
  diagnostics: WorldOrbitDiagnostic[];
116
119
  }
@@ -127,6 +130,7 @@ export interface WorldOrbitSystem {
127
130
  export interface WorldOrbitObject {
128
131
  type: Exclude<WorldOrbitObjectType, "system">;
129
132
  id: string;
133
+ trajectoryId?: string | null;
130
134
  groups?: string[];
131
135
  epoch?: string | null;
132
136
  referencePlane?: string | null;
@@ -167,6 +171,7 @@ export interface WorldOrbitEvent {
167
171
  kind: string;
168
172
  label: string;
169
173
  summary: string | null;
174
+ trajectoryId?: string | null;
170
175
  targetObjectId: string | null;
171
176
  participantObjectIds: string[];
172
177
  timing: string | null;
@@ -181,11 +186,60 @@ export interface WorldOrbitEvent {
181
186
  export interface WorldOrbitEventPose {
182
187
  objectId: string;
183
188
  placement: Placement | null;
189
+ trajectorySegmentId?: string | null;
190
+ trajectoryManeuverId?: string | null;
184
191
  inner?: UnitValue;
185
192
  outer?: UnitValue;
186
193
  epoch?: string | null;
187
194
  referencePlane?: string | null;
188
195
  }
196
+ export interface WorldOrbitTrajectory {
197
+ id: string;
198
+ label: string;
199
+ summary: string | null;
200
+ craftObjectId: string | null;
201
+ tags: string[];
202
+ color: string | null;
203
+ hidden: boolean;
204
+ segments: WorldOrbitTrajectorySegment[];
205
+ }
206
+ export interface WorldOrbitTrajectorySegment {
207
+ id: string;
208
+ kind: WorldOrbitTrajectorySegmentKind;
209
+ label: string | null;
210
+ summary: string | null;
211
+ fromObjectId: string | null;
212
+ toObjectId: string | null;
213
+ aroundObjectId: string | null;
214
+ assist: WorldOrbitGravityAssist | null;
215
+ epoch: string | null;
216
+ periapsis?: UnitValue;
217
+ apoapsis?: UnitValue;
218
+ inclination?: UnitValue;
219
+ duration?: UnitValue;
220
+ deltaV?: UnitValue;
221
+ phaseAngle?: UnitValue;
222
+ turnAngle?: UnitValue;
223
+ energy?: UnitValue;
224
+ notes: string[];
225
+ maneuvers: WorldOrbitManeuver[];
226
+ }
227
+ export type WorldOrbitTrajectorySegmentKind = "departure" | "transfer" | "flyby" | "capture" | "stationkeeping" | "escape";
228
+ export interface WorldOrbitManeuver {
229
+ id: string;
230
+ kind: string;
231
+ label: string | null;
232
+ epoch: string | null;
233
+ deltaV?: UnitValue;
234
+ duration?: UnitValue;
235
+ notes: string[];
236
+ }
237
+ export interface WorldOrbitGravityAssist {
238
+ objectId: string;
239
+ periapsis?: UnitValue;
240
+ turnAngle?: UnitValue;
241
+ notes: string[];
242
+ }
189
243
  export interface WorldOrbitResonance {
190
244
  targetObjectId: string;
191
245
  ratio: string;
@@ -632,7 +686,7 @@ export interface WorldOrbitAtlasSystem {
632
686
  viewpoints: WorldOrbitAtlasViewpoint[];
633
687
  annotations: WorldOrbitAtlasAnnotation[];
634
688
  }
635
- export type AtlasDocumentPathKind = "system" | "defaults" | "metadata" | "group" | "event" | "event-pose" | "object" | "viewpoint" | "annotation" | "relation";
689
+ export type AtlasDocumentPathKind = "system" | "defaults" | "metadata" | "group" | "event" | "event-pose" | "trajectory" | "trajectory-segment" | "trajectory-maneuver" | "object" | "viewpoint" | "annotation" | "relation";
636
690
  export interface AtlasDocumentPath {
637
691
  kind: AtlasDocumentPathKind;
638
692
  id?: string;