@johnmorrisdotca/uchusen-rockets 0.3.0 → 0.5.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/CHANGELOG.md +31 -5
- package/NOTICE.md +2 -0
- package/README.md +316 -4
- package/dist/assets/droneship-asog-landed.glb +0 -0
- package/dist/assets/droneship-asog.glb +0 -0
- package/dist/assets/droneship-jrti-landed.glb +0 -0
- package/dist/assets/droneship-jrti.glb +0 -0
- package/dist/assets/droneship-ocisly-landed.glb +0 -0
- package/dist/assets/droneship-ocisly.glb +0 -0
- package/dist/assets/falcon-9-block-5-dragon-2-first-stage.glb +0 -0
- package/dist/assets/falcon-9-block-5-dragon-2.glb +0 -0
- package/dist/assets/falcon-9-block-5-first-stage.glb +0 -0
- package/dist/assets/falcon-9-block-5.glb +0 -0
- package/dist/assets/falcon-9-ft-first-stage.glb +0 -0
- package/dist/assets/falcon-9-ft.glb +0 -0
- package/dist/assets/falcon-9-v1.1-first-stage.glb +0 -0
- package/dist/assets/falcon-9-v1.1.glb +0 -0
- package/dist/assets/falcon-heavy-falcon-heavy-centre.glb +0 -0
- package/dist/assets/falcon-heavy-falcon-heavy-side-left.glb +0 -0
- package/dist/assets/falcon-heavy-falcon-heavy-side-right.glb +0 -0
- package/dist/assets/falcon-heavy-falcon-heavy.glb +0 -0
- package/dist/assets/landing-zone-lz-1-landed.glb +0 -0
- package/dist/assets/landing-zone-lz-1.glb +0 -0
- package/dist/assets/landing-zone-lz-4-landed.glb +0 -0
- package/dist/assets/landing-zone-lz-4.glb +0 -0
- package/dist/assets/launch-tower-catch-booster.glb +0 -0
- package/dist/assets/launch-tower-catch.glb +0 -0
- package/dist/assets/launch-tower-stack-booster.glb +0 -0
- package/dist/assets/launch-tower-stack-ship.glb +0 -0
- package/dist/assets/launch-tower-stack.glb +0 -0
- package/dist/assets/starship-2019.glb +0 -0
- package/dist/assets/starship-v1-booster.glb +0 -0
- package/dist/assets/starship-v1-flight1-booster.glb +0 -0
- package/dist/assets/starship-v1-flight1-ship.glb +0 -0
- package/dist/assets/starship-v1-flight1.glb +0 -0
- package/dist/assets/starship-v1-ship.glb +0 -0
- package/dist/assets/starship-v1.glb +0 -0
- package/dist/assets/starship-v2-booster.glb +0 -0
- package/dist/assets/starship-v2-ship.glb +0 -0
- package/dist/assets/starship-v2.glb +0 -0
- package/dist/assets/starship-v3-booster.glb +0 -0
- package/dist/assets/starship-v3-ship.glb +0 -0
- package/dist/assets/starship-v3.glb +0 -0
- package/dist/assets/starship-v4-booster.glb +0 -0
- package/dist/assets/starship-v4-ship.glb +0 -0
- package/dist/assets/starship-v4.glb +0 -0
- package/dist/attrs.d.ts +70 -4
- package/dist/attrs.js +59 -4
- package/dist/build/glb.d.ts +25 -0
- package/dist/build/glb.js +29 -7
- package/dist/build/index.d.ts +94 -4
- package/dist/build/index.js +71 -7
- package/dist/build/lineup.d.ts +56 -2
- package/dist/build/lineup.js +23 -2
- package/dist/builder.d.ts +47 -1
- package/dist/builder.js +14 -1
- package/dist/crossfade.d.ts +44 -2
- package/dist/crossfade.js +44 -2
- package/dist/data/credits.d.ts +44 -1
- package/dist/data/credits.js +22 -1
- package/dist/data/flight-log.d.ts +33 -1
- package/dist/data/flight-log.js +22 -1
- package/dist/data/flights.d.ts +61 -2
- package/dist/data/flights.js +160 -3
- package/dist/data/makers.d.ts +21 -0
- package/dist/data/makers.js +10 -0
- package/dist/data/propellants.d.ts +59 -0
- package/dist/data/propellants.js +43 -0
- package/dist/data/sources.d.ts +102 -0
- package/dist/data/sources.js +19 -0
- package/dist/data/types.d.ts +81 -1
- package/dist/data/types.js +26 -1
- package/dist/draw/plume.d.ts +10 -1
- package/dist/draw/plume.js +15 -5
- package/dist/element/plumes.d.ts +7 -8
- package/dist/element/plumes.js +36 -21
- package/dist/element/scene.js +30 -5
- package/dist/element.d.ts +61 -3
- package/dist/element.js +53 -5
- package/dist/embed.d.ts +110 -5
- package/dist/embed.js +88 -5
- package/dist/engines.d.ts +86 -4
- package/dist/engines.js +75 -4
- package/dist/fit.d.ts +68 -0
- package/dist/fit.js +13 -0
- package/dist/flight.d.ts +136 -9
- package/dist/flight.js +130 -10
- package/dist/flightbar.d.ts +12 -0
- package/dist/flightbar.js +13 -1
- package/dist/framing.d.ts +182 -8
- package/dist/framing.js +127 -6
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/layout.d.ts +65 -1
- package/dist/layout.js +43 -1
- package/dist/looks.d.ts +64 -1
- package/dist/looks.js +42 -1
- package/dist/model/falcon.js +2 -2
- package/dist/model/materials.d.ts +32 -0
- package/dist/model/materials.js +10 -0
- package/dist/model/moves.d.ts +36 -0
- package/dist/model/moves.js +70 -0
- package/dist/model/pieces.d.ts +31 -0
- package/dist/model/pieces.js +51 -9
- package/dist/model/registry.d.ts +22 -0
- package/dist/model/registry.js +22 -0
- package/dist/model/starship.d.ts +6 -3
- package/dist/model/starship.js +12 -7
- package/dist/parts.d.ts +33 -1
- package/dist/pixels.d.ts +44 -4
- package/dist/pixels.js +44 -4
- package/dist/react.d.ts +26 -2
- package/dist/react.js +13 -0
- package/dist/rockets.d.ts +91 -3
- package/dist/rockets.js +58 -2
- package/dist/spin.d.ts +57 -2
- package/dist/spin.js +35 -2
- package/dist/tilt.d.ts +48 -4
- package/dist/tilt.js +26 -4
- package/package.json +27 -7
package/dist/framing.js
CHANGED
|
@@ -1,11 +1,69 @@
|
|
|
1
1
|
// Where the camera stands. One rule for the drawing and the 3D view, so the drawing turns into the 3D view without a jump. Pure, in metres.
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* The camera's field of view, in degrees, top to bottom. Narrow, because a rocket is long.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { FOV_DEG } from "@johnmorrisdotca/uchusen-rockets";
|
|
8
|
+
*
|
|
9
|
+
* console.log(FOV_DEG);
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
3
12
|
export const FOV_DEG = 24;
|
|
4
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* The width of the picture a drawing is made in, in drawing units.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { PICTURE_W, PICTURE_H } from "@johnmorrisdotca/uchusen-rockets";
|
|
19
|
+
*
|
|
20
|
+
* console.log(PICTURE_W, PICTURE_H);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
5
23
|
export const PICTURE_W = 480;
|
|
24
|
+
/**
|
|
25
|
+
* The height of the picture a drawing is made in, in drawing units.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { PICTURE_H } from "@johnmorrisdotca/uchusen-rockets";
|
|
30
|
+
*
|
|
31
|
+
* console.log(PICTURE_H);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
6
34
|
export const PICTURE_H = 640;
|
|
35
|
+
/**
|
|
36
|
+
* The names of the views, in the order the demo lists them: `three-quarter`, `front`, `back`, `side` and `below`.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { VIEW_NAMES } from "@johnmorrisdotca/uchusen-rockets";
|
|
41
|
+
*
|
|
42
|
+
* console.log(VIEW_NAMES.join(", "));
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
7
45
|
export const VIEW_NAMES = ["three-quarter", "front", "back", "side", "below"];
|
|
46
|
+
/**
|
|
47
|
+
* The view used when none is named or the name is not a view: `three-quarter`.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* import { DEFAULT_VIEW } from "@johnmorrisdotca/uchusen-rockets";
|
|
52
|
+
*
|
|
53
|
+
* console.log(DEFAULT_VIEW);
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
8
56
|
export const DEFAULT_VIEW = "three-quarter";
|
|
57
|
+
/**
|
|
58
|
+
* The angle of each named view.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* import { VIEWS } from "@johnmorrisdotca/uchusen-rockets";
|
|
63
|
+
*
|
|
64
|
+
* console.log(VIEWS.front, VIEWS.below);
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
9
67
|
export const VIEWS = {
|
|
10
68
|
"three-quarter": { az: 32, el: 9 },
|
|
11
69
|
front: { az: 0, el: 3 },
|
|
@@ -13,13 +71,49 @@ export const VIEWS = {
|
|
|
13
71
|
side: { az: 90, el: 3 },
|
|
14
72
|
below: { az: 24, el: -70 },
|
|
15
73
|
};
|
|
74
|
+
/**
|
|
75
|
+
* A value from outside as a view's name.
|
|
76
|
+
*
|
|
77
|
+
* @param value Anything.
|
|
78
|
+
* @returns The name if it is one of the views, and `three-quarter` for anything else.
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* import { cleanView } from "@johnmorrisdotca/uchusen-rockets";
|
|
82
|
+
*
|
|
83
|
+
* console.log(cleanView("side"), cleanView("sideways"), cleanView(42));
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
16
86
|
export const cleanView = (value) => (VIEW_NAMES.includes(value) ? value : DEFAULT_VIEW);
|
|
17
87
|
export const deg = (d) => (d * Math.PI) / 180;
|
|
18
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* What the family's view controls choose: the turn and tip, in degrees, from a base angle. Dragging right makes `yaw` larger, which carries the camera the other way round; `tilt` larger tips the top away, which lowers the camera.
|
|
90
|
+
*
|
|
91
|
+
* @param base The angle to turn from.
|
|
92
|
+
* @param yaw Degrees turned round.
|
|
93
|
+
* @param tilt Degrees tipped up or down.
|
|
94
|
+
* @returns The new angle.
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* import { turnedBy, VIEWS } from "@johnmorrisdotca/uchusen-rockets";
|
|
98
|
+
*
|
|
99
|
+
* console.log(turnedBy(VIEWS.front, 30, 10));
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
19
102
|
export function turnedBy(base, yaw, tilt) {
|
|
20
103
|
return { az: base.az - yaw, el: Math.min(87, Math.max(-87, base.el - tilt)) };
|
|
21
104
|
}
|
|
22
|
-
/**
|
|
105
|
+
/**
|
|
106
|
+
* The unit vector from what is looked at towards the camera.
|
|
107
|
+
*
|
|
108
|
+
* @param angle The angle to look from.
|
|
109
|
+
* @returns A unit vector.
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* import { directionOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
113
|
+
*
|
|
114
|
+
* console.log(directionOf({ az: 0, el: 0 }));
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
23
117
|
export function directionOf({ az, el }) {
|
|
24
118
|
const c = Math.cos(deg(el));
|
|
25
119
|
return [c * Math.sin(deg(az)), Math.sin(deg(el)), c * Math.cos(deg(az))];
|
|
@@ -30,14 +124,41 @@ const unit = (a) => {
|
|
|
30
124
|
const l = Math.hypot(...a) || 1;
|
|
31
125
|
return [a[0] / l, a[1] / l, a[2] / l];
|
|
32
126
|
};
|
|
33
|
-
/**
|
|
127
|
+
/**
|
|
128
|
+
* The camera's own axes for looking along `direction`, with up as near to +Y as it can be.
|
|
129
|
+
*
|
|
130
|
+
* @param direction The direction from the target to the camera.
|
|
131
|
+
* @returns The camera's right, up and forward axes.
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* import { axesOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
135
|
+
*
|
|
136
|
+
* console.log(axesOf([0, 0, 1]));
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
34
139
|
export function axesOf(direction) {
|
|
35
140
|
const forward = [-direction[0], -direction[1], -direction[2]];
|
|
36
141
|
const near = Math.abs(forward[1]) > 0.999;
|
|
37
142
|
const right = unit(cross(forward, near ? [0, 0, -1] : [0, 1, 0]));
|
|
38
143
|
return { right, up: cross(right, forward), forward };
|
|
39
144
|
}
|
|
40
|
-
/**
|
|
145
|
+
/**
|
|
146
|
+
* The nearest camera that holds the whole of `min` to `max` in a picture `aspect` wide for 1 tall, from `angle`.
|
|
147
|
+
*
|
|
148
|
+
* @param min The lowest corner of the box to hold.
|
|
149
|
+
* @param max The highest corner.
|
|
150
|
+
* @param angle The angle to look from.
|
|
151
|
+
* @param aspect The picture's width over its height.
|
|
152
|
+
* @param margin Room left round the box, as a multiple. Defaults to 1.08.
|
|
153
|
+
* @returns The camera that holds the whole box.
|
|
154
|
+
* @example
|
|
155
|
+
* ```ts
|
|
156
|
+
* import { frameFor, VIEWS } from "@johnmorrisdotca/uchusen-rockets";
|
|
157
|
+
*
|
|
158
|
+
* const framing = frameFor([-4.5, 0, -4.5], [4.5, 124, 4.5], VIEWS.front, 480 / 640);
|
|
159
|
+
* console.log(framing.target, framing.distance.toFixed(0));
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
41
162
|
export function frameFor(min, max, angle, aspect, margin = 1.08) {
|
|
42
163
|
const target = [(min[0] + max[0]) / 2, (min[1] + max[1]) / 2, (min[2] + max[2]) / 2];
|
|
43
164
|
const direction = directionOf(angle);
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,9 @@ export { MAKERS } from "./data/makers.ts";
|
|
|
6
6
|
export type { MakerId } from "./data/makers.ts";
|
|
7
7
|
export { FLIGHT_LOG, flightLogOf } from "./data/flight-log.ts";
|
|
8
8
|
export type { LoggedFlight } from "./data/flight-log.ts";
|
|
9
|
+
export { moved, movingGroupsOf } from "./model/moves.ts";
|
|
10
|
+
export { PROPELLANTS, propellantOf } from "./data/propellants.ts";
|
|
11
|
+
export type { EnginePropellant, FlameKind } from "./data/propellants.ts";
|
|
9
12
|
export { SOURCES } from "./data/sources.ts";
|
|
10
13
|
export type { Source, SourceId } from "./data/sources.ts";
|
|
11
14
|
export { creditLine, MODEL_CREDITS } from "./data/credits.ts";
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,8 @@ export { PLANNED_ROCKETS, ROCKETS, partIdOf, SLOT_NAMES, variantOf } from "./roc
|
|
|
3
3
|
export { blank, figureWords } from "./data/types.js";
|
|
4
4
|
export { MAKERS } from "./data/makers.js";
|
|
5
5
|
export { FLIGHT_LOG, flightLogOf } from "./data/flight-log.js";
|
|
6
|
+
export { moved, movingGroupsOf } from "./model/moves.js";
|
|
7
|
+
export { PROPELLANTS, propellantOf } from "./data/propellants.js";
|
|
6
8
|
export { SOURCES } from "./data/sources.js";
|
|
7
9
|
export { creditLine, MODEL_CREDITS } from "./data/credits.js";
|
|
8
10
|
export { PART_ENTRIES, partEntry } from "./model/registry.js";
|
package/dist/layout.d.ts
CHANGED
|
@@ -1,16 +1,80 @@
|
|
|
1
1
|
import type { Vec3 } from "./framing.ts";
|
|
2
2
|
import type { PartRecord } from "./parts.ts";
|
|
3
|
+
/**
|
|
4
|
+
* What to show of a rocket: `together`, `apart`, or the slot of one part, such as `booster`.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import type { ShowName } from "@johnmorrisdotca/uchusen-rockets";
|
|
9
|
+
*
|
|
10
|
+
* const shows: ShowName[] = ["together", "apart", "booster"];
|
|
11
|
+
* console.log(shows);
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
3
14
|
export type ShowName = "together" | "apart" | (string & {});
|
|
4
15
|
/** A part's own width from the axis, for keeping apart parts clear of each other. */
|
|
5
16
|
export type WidthOf = (part: PartRecord) => number;
|
|
17
|
+
/**
|
|
18
|
+
* Where one part stands for a choice of what to show: its slot, its position in metres and whether it is shown at all.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { placesFor, type Place } from "@johnmorrisdotca/uchusen-rockets";
|
|
23
|
+
*
|
|
24
|
+
* const places: Place[] = placesFor([], "together", () => 1);
|
|
25
|
+
* console.log(places.length);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
6
28
|
export interface Place {
|
|
7
29
|
slot: string;
|
|
8
30
|
at: Vec3;
|
|
9
31
|
shown: boolean;
|
|
10
32
|
}
|
|
11
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* The first choices of `show`, then one per slot.
|
|
35
|
+
*
|
|
36
|
+
* @param slots A variant's slots, from the bottom.
|
|
37
|
+
* @returns What can be shown: together and apart first when there is more than one slot, then one for each slot.
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { showsOf, variantOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
41
|
+
*
|
|
42
|
+
* console.log(showsOf(variantOf("falcon-9", "block-5")?.slots ?? []));
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
12
45
|
export declare const showsOf: (slots: readonly string[]) => string[];
|
|
46
|
+
/**
|
|
47
|
+
* A value from outside as something that can be shown.
|
|
48
|
+
*
|
|
49
|
+
* @param value Anything.
|
|
50
|
+
* @param slots The variant's slots.
|
|
51
|
+
* @returns The value if it can be shown, and the first choice (together) for anything else.
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { cleanShow, variantOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
55
|
+
*
|
|
56
|
+
* const slots = variantOf("falcon-9", "block-5")?.slots ?? [];
|
|
57
|
+
* console.log(cleanShow("first-stage", slots), cleanShow("nonsense", slots));
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
13
60
|
export declare function cleanShow(value: unknown, slots: readonly string[]): string;
|
|
61
|
+
/**
|
|
62
|
+
* Where each part stands: up the stack joint to joint, or spread apart on a diagonal of the ground, or one part alone.
|
|
63
|
+
*
|
|
64
|
+
* @param parts The parts with their slots, from the bottom.
|
|
65
|
+
* @param show What to show.
|
|
66
|
+
* @param widthOf The width of a part, for spacing when they are apart.
|
|
67
|
+
* @returns A place for each part.
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* import { build } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
71
|
+
* import { placesFor } from "@johnmorrisdotca/uchusen-rockets";
|
|
72
|
+
*
|
|
73
|
+
* const rocket = build({ rocket: "falcon-9", variant: "block-5" });
|
|
74
|
+
* const parts = rocket.parts.map((part) => ({ slot: part.slot, part: part.record }));
|
|
75
|
+
* console.log(placesFor(parts, "apart", (part) => part.diameter / 2).map((place) => place.slot));
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
14
78
|
export declare function placesFor(parts: readonly {
|
|
15
79
|
slot: string;
|
|
16
80
|
part: PartRecord;
|
package/dist/layout.js
CHANGED
|
@@ -1,11 +1,53 @@
|
|
|
1
1
|
/** Seen square-on to the diagonal the parts take the whole distance; from the front or the side, seven tenths of it. */
|
|
2
2
|
const APART_SPREAD = 1.45;
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* The first choices of `show`, then one per slot.
|
|
5
|
+
*
|
|
6
|
+
* @param slots A variant's slots, from the bottom.
|
|
7
|
+
* @returns What can be shown: together and apart first when there is more than one slot, then one for each slot.
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { showsOf, variantOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
11
|
+
*
|
|
12
|
+
* console.log(showsOf(variantOf("falcon-9", "block-5")?.slots ?? []));
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
4
15
|
export const showsOf = (slots) => (slots.length > 1 ? ["together", "apart", ...slots] : [...slots]);
|
|
16
|
+
/**
|
|
17
|
+
* A value from outside as something that can be shown.
|
|
18
|
+
*
|
|
19
|
+
* @param value Anything.
|
|
20
|
+
* @param slots The variant's slots.
|
|
21
|
+
* @returns The value if it can be shown, and the first choice (together) for anything else.
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { cleanShow, variantOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
25
|
+
*
|
|
26
|
+
* const slots = variantOf("falcon-9", "block-5")?.slots ?? [];
|
|
27
|
+
* console.log(cleanShow("first-stage", slots), cleanShow("nonsense", slots));
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
5
30
|
export function cleanShow(value, slots) {
|
|
6
31
|
const shows = showsOf(slots);
|
|
7
32
|
return typeof value === "string" && shows.includes(value) ? value : shows[0];
|
|
8
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Where each part stands: up the stack joint to joint, or spread apart on a diagonal of the ground, or one part alone.
|
|
36
|
+
*
|
|
37
|
+
* @param parts The parts with their slots, from the bottom.
|
|
38
|
+
* @param show What to show.
|
|
39
|
+
* @param widthOf The width of a part, for spacing when they are apart.
|
|
40
|
+
* @returns A place for each part.
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { build } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
44
|
+
* import { placesFor } from "@johnmorrisdotca/uchusen-rockets";
|
|
45
|
+
*
|
|
46
|
+
* const rocket = build({ rocket: "falcon-9", variant: "block-5" });
|
|
47
|
+
* const parts = rocket.parts.map((part) => ({ slot: part.slot, part: part.record }));
|
|
48
|
+
* console.log(placesFor(parts, "apart", (part) => part.diameter / 2).map((place) => place.slot));
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
9
51
|
export function placesFor(parts, show, widthOf) {
|
|
10
52
|
if (show === "apart") {
|
|
11
53
|
const widths = parts.map(({ part }) => widthOf(part));
|
package/dist/looks.d.ts
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The names of the looks: `line`, `thick` and `painted`.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { LOOK_NAMES } from "@johnmorrisdotca/uchusen-rockets";
|
|
7
|
+
*
|
|
8
|
+
* console.log(LOOK_NAMES.join(", "));
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
1
11
|
export declare const LOOK_NAMES: readonly ["line", "thick", "painted"];
|
|
12
|
+
/**
|
|
13
|
+
* The name of one look in `LOOK_NAMES`.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import type { LookName } from "@johnmorrisdotca/uchusen-rockets";
|
|
18
|
+
*
|
|
19
|
+
* const look: LookName = "thick";
|
|
20
|
+
* console.log(look);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
2
23
|
export type LookName = (typeof LOOK_NAMES)[number];
|
|
24
|
+
/**
|
|
25
|
+
* The look used when none is named or the name is not a look: `line`.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { DEFAULT_LOOK } from "@johnmorrisdotca/uchusen-rockets";
|
|
30
|
+
*
|
|
31
|
+
* console.log(DEFAULT_LOOK);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
3
34
|
export declare const DEFAULT_LOOK: LookName;
|
|
35
|
+
/**
|
|
36
|
+
* What a look changes: the colour and width of its lines in a 3D view and in a drawing, how much of the weld lines shows, the fills by material group and whether there is a halo. A look never changes a shape.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { LOOKS, type Look } from "@johnmorrisdotca/uchusen-rockets";
|
|
41
|
+
*
|
|
42
|
+
* const thick: Look = LOOKS.thick;
|
|
43
|
+
* console.log(thick.line, thick.outline);
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
4
46
|
export interface Look {
|
|
5
47
|
/** The colour of its lines. */
|
|
6
48
|
line: string;
|
|
@@ -20,6 +62,27 @@ export interface Look {
|
|
|
20
62
|
halo: boolean;
|
|
21
63
|
}
|
|
22
64
|
export type FillName = "hull" | "white" | "tile" | "metal" | "dark" | "bell" | "foam";
|
|
65
|
+
/**
|
|
66
|
+
* Every look, by name. A look is one entry of this table.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* import { LOOKS } from "@johnmorrisdotca/uchusen-rockets";
|
|
71
|
+
*
|
|
72
|
+
* console.log(Object.keys(LOOKS));
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
23
75
|
export declare const LOOKS: Readonly<Record<LookName, Look>>;
|
|
24
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* A value from outside as a look's name: the default for anything else.
|
|
78
|
+
*
|
|
79
|
+
* @param value Anything.
|
|
80
|
+
* @returns The look's name if it is one, and the default (`line`) for anything else.
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* import { cleanLook } from "@johnmorrisdotca/uchusen-rockets";
|
|
84
|
+
*
|
|
85
|
+
* console.log(cleanLook("painted"), cleanLook("shiny"));
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
25
88
|
export declare const cleanLook: (value: unknown) => LookName;
|
package/dist/looks.js
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
// The three looks, each one table entry: the line drawing, the thick lines, and the painted rocket. A look changes lines, colours and fills, never a shape. Pure.
|
|
2
|
+
/**
|
|
3
|
+
* The names of the looks: `line`, `thick` and `painted`.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { LOOK_NAMES } from "@johnmorrisdotca/uchusen-rockets";
|
|
8
|
+
*
|
|
9
|
+
* console.log(LOOK_NAMES.join(", "));
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
2
12
|
export const LOOK_NAMES = ["line", "thick", "painted"];
|
|
13
|
+
/**
|
|
14
|
+
* The look used when none is named or the name is not a look: `line`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { DEFAULT_LOOK } from "@johnmorrisdotca/uchusen-rockets";
|
|
19
|
+
*
|
|
20
|
+
* console.log(DEFAULT_LOOK);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
3
23
|
export const DEFAULT_LOOK = "line";
|
|
4
24
|
const NIGHT = {
|
|
5
25
|
hull: ["#0c1422", "#2a3850", "#0c1422"],
|
|
@@ -10,6 +30,16 @@ const NIGHT = {
|
|
|
10
30
|
bell: ["#0a0f18", "#242f42", "#0a0f18"],
|
|
11
31
|
foam: ["#16202f", "#3a475c", "#16202f"],
|
|
12
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Every look, by name. A look is one entry of this table.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { LOOKS } from "@johnmorrisdotca/uchusen-rockets";
|
|
39
|
+
*
|
|
40
|
+
* console.log(Object.keys(LOOKS));
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
13
43
|
export const LOOKS = {
|
|
14
44
|
line: { line: "#8fa1b8", outlinePx: 1.4, featurePx: 1, weldPx: 0.6, weldOpacity: 0.45, outline: 1.2, feature: 0.8, weld: 0.45, fills: NIGHT, halo: true },
|
|
15
45
|
thick: { line: "#b4c2d4", outlinePx: 3.4, featurePx: 2, weldPx: 0.9, weldOpacity: 0.5, outline: 3.4, feature: 1.7, weld: 0.6, fills: NIGHT, halo: true },
|
|
@@ -34,5 +64,16 @@ export const LOOKS = {
|
|
|
34
64
|
halo: false,
|
|
35
65
|
},
|
|
36
66
|
};
|
|
37
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* A value from outside as a look's name: the default for anything else.
|
|
69
|
+
*
|
|
70
|
+
* @param value Anything.
|
|
71
|
+
* @returns The look's name if it is one, and the default (`line`) for anything else.
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* import { cleanLook } from "@johnmorrisdotca/uchusen-rockets";
|
|
75
|
+
*
|
|
76
|
+
* console.log(cleanLook("painted"), cleanLook("shiny"));
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
38
79
|
export const cleanLook = (value) => (LOOK_NAMES.includes(value) ? value : DEFAULT_LOOK);
|
package/dist/model/falcon.js
CHANGED
|
@@ -56,11 +56,11 @@ function firstStage(d, withTop) {
|
|
|
56
56
|
if (d.legs)
|
|
57
57
|
for (const az of [45, 135, 225, 315]) {
|
|
58
58
|
const frame = radial(deg(az));
|
|
59
|
-
pieces.push({ kind: "plate", material: "black", frame, outline: [[r - 0.05, 0.8], [r + 0.5, 0.8], [r + 0.55, 3], [r + 0.15, 10.5], [r - 0.05, 11]], thickness: 1.2 });
|
|
59
|
+
pieces.push({ kind: "plate", material: "black", frame, outline: [[r - 0.05, 0.8], [r + 0.5, 0.8], [r + 0.55, 3], [r + 0.15, 10.5], [r - 0.05, 11]], thickness: 1.2, move: { name: "legs", pivot: pointOf(frame, r + 0.2, 0.8), axis: frame.w } });
|
|
60
60
|
}
|
|
61
61
|
if (d.fins)
|
|
62
62
|
for (const az of [45, 135, 225, 315])
|
|
63
|
-
pieces.push(...gridFin(az, tank + 0.1, r, r + 1.4, 1.5, 0.3, false));
|
|
63
|
+
pieces.push(...gridFin(az, tank + 0.1, r, r + 1.4, 1.5, 0.3, false, { name: "grid-fins", about: "tangent" }));
|
|
64
64
|
return pieces;
|
|
65
65
|
}
|
|
66
66
|
function secondStage(d) {
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import type { FillName } from "../looks.ts";
|
|
2
|
+
/**
|
|
3
|
+
* One material: its colour, how metal and how rough it is in a 3D view, and the fill group it takes in a drawing.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { MATERIALS, type MaterialSpec } from "@johnmorrisdotca/uchusen-rockets";
|
|
8
|
+
*
|
|
9
|
+
* const steel: MaterialSpec = MATERIALS.steel;
|
|
10
|
+
* console.log(steel.color, steel.fill);
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
2
13
|
export interface MaterialSpec {
|
|
3
14
|
color: string;
|
|
4
15
|
metal: number;
|
|
@@ -6,6 +17,16 @@ export interface MaterialSpec {
|
|
|
6
17
|
/** The fill it takes in a drawing. */
|
|
7
18
|
fill: FillName;
|
|
8
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Every material the meshes use, by name. One naming scheme serves every source.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { MATERIALS } from "@johnmorrisdotca/uchusen-rockets";
|
|
26
|
+
*
|
|
27
|
+
* console.log(Object.keys(MATERIALS).length > 5);
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
9
30
|
export declare const MATERIALS: {
|
|
10
31
|
readonly steel: {
|
|
11
32
|
readonly color: "#c3c7cb";
|
|
@@ -152,4 +173,15 @@ export declare const MATERIALS: {
|
|
|
152
173
|
readonly fill: "metal";
|
|
153
174
|
};
|
|
154
175
|
};
|
|
176
|
+
/**
|
|
177
|
+
* The name of one material in `MATERIALS`.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* import type { MaterialName } from "@johnmorrisdotca/uchusen-rockets";
|
|
182
|
+
*
|
|
183
|
+
* const name: MaterialName = "steel";
|
|
184
|
+
* console.log(name);
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
155
187
|
export type MaterialName = keyof typeof MATERIALS;
|
package/dist/model/materials.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every material the meshes use, by name. One naming scheme serves every source.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { MATERIALS } from "@johnmorrisdotca/uchusen-rockets";
|
|
7
|
+
*
|
|
8
|
+
* console.log(Object.keys(MATERIALS).length > 5);
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
1
11
|
export const MATERIALS = {
|
|
2
12
|
steel: { color: "#c3c7cb", metal: 1, rough: 0.3, fill: "hull" },
|
|
3
13
|
tile: { color: "#101114", metal: 0, rough: 0.62, fill: "tile" },
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Piece, Vec3 } from "./pieces.ts";
|
|
2
|
+
/** A direction turned by `degrees` right-handed about `axis` (Rodrigues' rotation). */
|
|
3
|
+
export declare function turnedVector(v: Vec3, axis: Vec3, degrees: number): Vec3;
|
|
4
|
+
/** A point turned about a pivot. */
|
|
5
|
+
export declare function turnedPoint(p: Vec3, pivot: Vec3, axis: Vec3, degrees: number): Vec3;
|
|
6
|
+
/**
|
|
7
|
+
* The pieces with each moving group turned by the angle its name has in `angles` (degrees, 0 where it has none). A turned piece no longer carries its `move`: it is drawn where it stands. A body of revolution cannot turn, and is left as it is.
|
|
8
|
+
*
|
|
9
|
+
* @param pieces The pieces of a part.
|
|
10
|
+
* @param angles Degrees by the name of a moving group, such as `grid-fins`.
|
|
11
|
+
* @returns The pieces, with the moving groups turned.
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { build } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
15
|
+
* import { movingGroupsOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
16
|
+
*
|
|
17
|
+
* const booster = build({ rocket: "starship", variant: "v3" }).parts[0];
|
|
18
|
+
* console.log(booster ? movingGroupsOf(booster.pieces) : []);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function moved(pieces: readonly Piece[], angles: Readonly<Record<string, number>>): readonly Piece[];
|
|
22
|
+
/**
|
|
23
|
+
* The names of the groups a part has that a flight can turn.
|
|
24
|
+
*
|
|
25
|
+
* @param pieces The pieces of a part.
|
|
26
|
+
* @returns The distinct names, in the order they come.
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { build } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
30
|
+
* import { movingGroupsOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
31
|
+
*
|
|
32
|
+
* const stage = build({ rocket: "falcon-9", variant: "block-5" }).parts[0];
|
|
33
|
+
* console.log(stage ? movingGroupsOf(stage.pieces) : []);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function movingGroupsOf(pieces: readonly Piece[]): string[];
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const unit = (v) => {
|
|
2
|
+
const length = Math.hypot(...v) || 1;
|
|
3
|
+
return [v[0] / length, v[1] / length, v[2] / length];
|
|
4
|
+
};
|
|
5
|
+
/** A direction turned by `degrees` right-handed about `axis` (Rodrigues' rotation). */
|
|
6
|
+
export function turnedVector(v, axis, degrees) {
|
|
7
|
+
const k = unit(axis);
|
|
8
|
+
const a = (degrees * Math.PI) / 180;
|
|
9
|
+
const cos = Math.cos(a);
|
|
10
|
+
const sin = Math.sin(a);
|
|
11
|
+
const dot = k[0] * v[0] + k[1] * v[1] + k[2] * v[2];
|
|
12
|
+
const cross = [k[1] * v[2] - k[2] * v[1], k[2] * v[0] - k[0] * v[2], k[0] * v[1] - k[1] * v[0]];
|
|
13
|
+
return [v[0] * cos + cross[0] * sin + k[0] * dot * (1 - cos), v[1] * cos + cross[1] * sin + k[1] * dot * (1 - cos), v[2] * cos + cross[2] * sin + k[2] * dot * (1 - cos)];
|
|
14
|
+
}
|
|
15
|
+
/** A point turned about a pivot. */
|
|
16
|
+
export function turnedPoint(p, pivot, axis, degrees) {
|
|
17
|
+
const d = turnedVector([p[0] - pivot[0], p[1] - pivot[1], p[2] - pivot[2]], axis, degrees);
|
|
18
|
+
return [pivot[0] + d[0], pivot[1] + d[1], pivot[2] + d[2]];
|
|
19
|
+
}
|
|
20
|
+
const turnedFrame = (f, move, degrees) => ({
|
|
21
|
+
o: turnedPoint(f.o, move.pivot, move.axis, degrees),
|
|
22
|
+
u: turnedVector(f.u, move.axis, degrees),
|
|
23
|
+
v: turnedVector(f.v, move.axis, degrees),
|
|
24
|
+
w: turnedVector(f.w, move.axis, degrees),
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* The pieces with each moving group turned by the angle its name has in `angles` (degrees, 0 where it has none). A turned piece no longer carries its `move`: it is drawn where it stands. A body of revolution cannot turn, and is left as it is.
|
|
28
|
+
*
|
|
29
|
+
* @param pieces The pieces of a part.
|
|
30
|
+
* @param angles Degrees by the name of a moving group, such as `grid-fins`.
|
|
31
|
+
* @returns The pieces, with the moving groups turned.
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* import { build } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
35
|
+
* import { movingGroupsOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
36
|
+
*
|
|
37
|
+
* const booster = build({ rocket: "starship", variant: "v3" }).parts[0];
|
|
38
|
+
* console.log(booster ? movingGroupsOf(booster.pieces) : []);
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export function moved(pieces, angles) {
|
|
42
|
+
if (!pieces.some((piece) => piece.move && angles[piece.move.name]))
|
|
43
|
+
return pieces;
|
|
44
|
+
return pieces.map((piece) => {
|
|
45
|
+
const move = piece.move;
|
|
46
|
+
const degrees = move ? (angles[move.name] ?? 0) : 0;
|
|
47
|
+
if (!move || degrees === 0 || piece.kind === "lathe")
|
|
48
|
+
return piece;
|
|
49
|
+
if (piece.kind === "plate")
|
|
50
|
+
return { ...piece, move: undefined, frame: turnedFrame(piece.frame, move, degrees) };
|
|
51
|
+
return { ...piece, move: undefined, paths: piece.paths.map((path) => path.map((p) => turnedPoint(p, move.pivot, move.axis, degrees))) };
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The names of the groups a part has that a flight can turn.
|
|
56
|
+
*
|
|
57
|
+
* @param pieces The pieces of a part.
|
|
58
|
+
* @returns The distinct names, in the order they come.
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* import { build } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
62
|
+
* import { movingGroupsOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
63
|
+
*
|
|
64
|
+
* const stage = build({ rocket: "falcon-9", variant: "block-5" }).parts[0];
|
|
65
|
+
* console.log(stage ? movingGroupsOf(stage.pieces) : []);
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export function movingGroupsOf(pieces) {
|
|
69
|
+
return [...new Set(pieces.flatMap((piece) => (piece.move ? [piece.move.name] : [])))];
|
|
70
|
+
}
|