@johnmorrisdotca/wakusei-planets 0.6.0 → 0.11.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 (58) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/NOTICE.md +16 -1
  3. package/README.md +19 -4
  4. package/dist/bodies/all.d.ts +2 -0
  5. package/dist/bodies/all.js +2 -0
  6. package/dist/bodies/dwarfs.d.ts +1 -0
  7. package/dist/bodies/dwarfs.js +31 -0
  8. package/dist/bodies/moons-dwarf.d.ts +1 -0
  9. package/dist/bodies/moons-dwarf.js +6 -0
  10. package/dist/bodies/moons-neptune.js +1 -0
  11. package/dist/bodies/moons-pluto.js +1 -1
  12. package/dist/bodies/moons-saturn.js +3 -2
  13. package/dist/data/dwarf.d.ts +16 -0
  14. package/dist/data/dwarf.js +24 -0
  15. package/dist/data/orbits.d.ts +2 -2
  16. package/dist/data/orbits.js +4 -0
  17. package/dist/element.d.ts +4 -2
  18. package/dist/element.js +4 -0
  19. package/dist/embed.d.ts +35 -1
  20. package/dist/embed.js +78 -37
  21. package/dist/ephemeris.d.ts +6 -6
  22. package/dist/ephemeris.js +33 -12
  23. package/dist/facts.d.ts +44 -6
  24. package/dist/facts.js +32 -3
  25. package/dist/index.d.ts +3 -2
  26. package/dist/index.js +3 -2
  27. package/dist/line.js +7 -4
  28. package/dist/portrait/element.d.ts +77 -0
  29. package/dist/portrait/element.js +545 -0
  30. package/dist/portrait/model.d.ts +297 -0
  31. package/dist/portrait/model.js +711 -0
  32. package/dist/portrait/overlay.d.ts +50 -0
  33. package/dist/portrait/overlay.js +173 -0
  34. package/dist/portrait/pose.d.ts +13 -0
  35. package/dist/portrait/pose.js +31 -0
  36. package/dist/portrait/scene3d.d.ts +38 -0
  37. package/dist/portrait/scene3d.js +123 -0
  38. package/dist/pose.d.ts +7 -5
  39. package/dist/pose.js +25 -11
  40. package/dist/scene/body.d.ts +1 -1
  41. package/dist/scene/glsl.js +10 -1
  42. package/dist/scene/painter.d.ts +7 -0
  43. package/dist/scene/painter.js +9 -1
  44. package/dist/textures/ceres-1024.webp +0 -0
  45. package/dist/textures/ceres-512.webp +0 -0
  46. package/dist/textures/charon-1024.webp +0 -0
  47. package/dist/textures/charon-512.webp +0 -0
  48. package/dist/textures/dione-1024.webp +0 -0
  49. package/dist/textures/dione-512.webp +0 -0
  50. package/dist/textures/iapetus-1024.webp +0 -0
  51. package/dist/textures/iapetus-512.webp +0 -0
  52. package/dist/textures/tethys-1024.webp +0 -0
  53. package/dist/textures/tethys-512.webp +0 -0
  54. package/dist/textures/triton-1024.webp +0 -0
  55. package/dist/textures/triton-512.webp +0 -0
  56. package/dist/version.d.ts +1 -1
  57. package/dist/version.js +1 -1
  58. package/package.json +18 -1
@@ -1,10 +1,10 @@
1
- import { type BodyId, type MoonId, type PlanetId } from "./facts.ts";
1
+ import { type BodyId, type HostId, type MoonId } from "./facts.ts";
2
2
  import { type Vec3 } from "./vec.ts";
3
3
  /** Solve Kepler's equation for the eccentric anomaly, all in radians. */
4
4
  export declare function kepler(meanAnomaly: number, e: number): number;
5
5
  /**
6
- * A planet's position in the Sun's frame (J2000 ecliptic, astronomical units) at a time, from JPL's approximate elements.
7
- * @param planet - The planet's name.
6
+ * A planet's or dwarf planet's position in the Sun's frame (J2000 ecliptic, astronomical units) at a time: a planet from JPL's approximate elements, a dwarf planet from the osculating elements of one epoch (JPL's Small-Body Database).
7
+ * @param planet - The planet's or dwarf planet's name.
8
8
  * @param ms - The instant, in milliseconds since 1970.
9
9
  * @returns The position as x, y, z in au.
10
10
  *
@@ -16,7 +16,7 @@ export declare function kepler(meanAnomaly: number, e: number): number;
16
16
  * console.log(Math.hypot(x, y, z).toFixed(3));
17
17
  * ```
18
18
  */
19
- export declare function heliocentric(planet: PlanetId, ms: number): Vec3;
19
+ export declare function heliocentric(planet: HostId, ms: number): Vec3;
20
20
  /**
21
21
  * The Moon's position from the Earth's centre (J2000 ecliptic, kilometres), from the largest terms of Meeus's lunar series.
22
22
  * @param ms - The instant, in milliseconds since 1970.
@@ -164,7 +164,7 @@ export interface System {
164
164
  * console.log(moons.map((moon) => `${moon.id} ${moon.x.toFixed(1)}`).join(", "));
165
165
  * ```
166
166
  */
167
- export declare function system(planet: PlanetId, time: number): System;
167
+ export declare function system(planet: HostId, time: number): System;
168
168
  /**
169
169
  * The path one moon follows round its planet over one trip, as the Earth sees it at `time`: x, y, z in planet radii, in the viewer's frame at that moment.
170
170
  *
@@ -183,7 +183,7 @@ export declare function system(planet: PlanetId, time: number): System;
183
183
  */
184
184
  export declare function orbitPath(id: MoonId, time: number, points?: number): Float32Array;
185
185
  /** The planets' moons that are near enough to draw in a system view, nearest first, with how far each goes in planet radii. */
186
- export declare function nearMoons(planet: PlanetId, within?: number): {
186
+ export declare function nearMoons(planet: HostId, within?: number): {
187
187
  id: MoonId;
188
188
  reach: number;
189
189
  }[];
package/dist/ephemeris.js CHANGED
@@ -3,6 +3,7 @@
3
3
  // good to about an arc minute. The Moon: the largest terms of Meeus, "Astronomical Algorithms", chapter 47. Other moons: JPL's mean elements (data/orbits.ts).
4
4
  // Light travel time is allowed for, so a turning planet shows the face it really showed when the light left. Pure: no DOM, no three.js.
5
5
  import { ORBITS } from "./data/orbits.js";
6
+ import { DWARF_ELEMENTS } from "./data/dwarf.js";
6
7
  import { BODIES, MOONS_OF } from "./facts.js";
7
8
  import { add, cross, DEG, dot, fromRaDec, length, OBLIQUITY, RAD, scale, sub, toEcliptic, unit, wrap360 } from "./vec.js";
8
9
  /** Milliseconds since 1970 at J2000.0 (2000-01-01 12:00 TT, taken as UTC). */
@@ -42,8 +43,8 @@ export function kepler(meanAnomaly, e) {
42
43
  return E;
43
44
  }
44
45
  /**
45
- * A planet's position in the Sun's frame (J2000 ecliptic, astronomical units) at a time, from JPL's approximate elements.
46
- * @param planet - The planet's name.
46
+ * A planet's or dwarf planet's position in the Sun's frame (J2000 ecliptic, astronomical units) at a time: a planet from JPL's approximate elements, a dwarf planet from the osculating elements of one epoch (JPL's Small-Body Database).
47
+ * @param planet - The planet's or dwarf planet's name.
47
48
  * @param ms - The instant, in milliseconds since 1970.
48
49
  * @returns The position as x, y, z in au.
49
50
  *
@@ -56,16 +57,34 @@ export function kepler(meanAnomaly, e) {
56
57
  * ```
57
58
  */
58
59
  export function heliocentric(planet, ms) {
59
- const el = ELEMENTS[planet];
60
- const T = centuries(ms);
61
- const a = el[0] + el[6] * T;
62
- const e = el[1] + el[7] * T;
63
- const I = (el[2] + el[8] * T) * RAD;
64
- const L = el[3] + el[9] * T;
65
- const peri = el[4] + el[10] * T;
66
- const node = (el[5] + el[11] * T) * RAD;
67
- const w = peri * RAD - node;
68
- const E = kepler((L - peri) * RAD, e);
60
+ let a;
61
+ let e;
62
+ let I;
63
+ let node;
64
+ let w;
65
+ let E;
66
+ const dwarf = DWARF_ELEMENTS[planet];
67
+ if (dwarf !== undefined) {
68
+ // a dwarf planet: the osculating elements of one epoch, run as a plain ellipse (good for years either side of it)
69
+ a = dwarf.a;
70
+ e = dwarf.e;
71
+ I = dwarf.i * RAD;
72
+ node = dwarf.node * RAD;
73
+ w = dwarf.w * RAD;
74
+ E = kepler((dwarf.m + (dwarf.n * (ms - dwarf.epoch)) / DAY) * RAD, e);
75
+ }
76
+ else {
77
+ const el = ELEMENTS[planet];
78
+ const T = centuries(ms);
79
+ a = el[0] + el[6] * T;
80
+ e = el[1] + el[7] * T;
81
+ I = (el[2] + el[8] * T) * RAD;
82
+ const L = el[3] + el[9] * T;
83
+ const peri = el[4] + el[10] * T;
84
+ node = (el[5] + el[11] * T) * RAD;
85
+ w = peri * RAD - node;
86
+ E = kepler((L - peri) * RAD, e);
87
+ }
69
88
  const x = a * (Math.cos(E) - e);
70
89
  const y = a * Math.sqrt(1 - e * e) * Math.sin(E);
71
90
  const cw = Math.cos(w);
@@ -231,6 +250,8 @@ export function moonVector(id, ms) {
231
250
  function referenceBasis(orbit) {
232
251
  if (orbit.frame === "ecliptic")
233
252
  return { x: [1, 0, 0], y: [0, 1, 0], z: [0, 0, 1] };
253
+ if (orbit.frame === "j2000")
254
+ return { x: toEcliptic([1, 0, 0]), y: toEcliptic([0, 1, 0]), z: toEcliptic([0, 0, 1]) };
234
255
  const pole = orbit.frame === "laplace" && orbit.pole !== undefined ? orbit.pole : [BODIES[orbit.parent].pole.ra, BODIES[orbit.parent].pole.dec];
235
256
  const z = fromRaDec(pole[0], pole[1]);
236
257
  const x = fromRaDec(pole[0] + 90, 0);
package/dist/facts.d.ts CHANGED
@@ -10,7 +10,18 @@
10
10
  */
11
11
  export declare const PLANET_IDS: readonly ["mercury", "venus", "earth", "mars", "jupiter", "saturn", "uranus", "neptune", "pluto"];
12
12
  /**
13
- * The moons the package draws, by planet.
13
+ * The dwarf planets besides Pluto, nearest the Sun first (by the size of their orbits).
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { DWARF_IDS } from "@johnmorrisdotca/wakusei-planets";
18
+ *
19
+ * console.log(DWARF_IDS.join(", "));
20
+ * ```
21
+ */
22
+ export declare const DWARF_IDS: readonly ["ceres", "orcus", "haumea", "quaoar", "makemake", "gonggong", "eris", "sedna"];
23
+ /**
24
+ * The moons the package draws, by planet or dwarf planet.
14
25
  *
15
26
  * @example
16
27
  * ```ts
@@ -27,6 +38,9 @@ export declare const MOONS_OF: {
27
38
  readonly uranus: readonly ["miranda", "ariel", "umbriel", "titania", "oberon"];
28
39
  readonly neptune: readonly ["proteus", "triton", "nereid"];
29
40
  readonly pluto: readonly ["charon", "nix", "hydra"];
41
+ readonly orcus: readonly ["vanth"];
42
+ readonly haumea: readonly ["hiiaka", "namaka"];
43
+ readonly eris: readonly ["dysnomia"];
30
44
  };
31
45
  /**
32
46
  * The name of a planet or of Pluto: `mercury` to `pluto`.
@@ -40,6 +54,30 @@ export declare const MOONS_OF: {
40
54
  * ```
41
55
  */
42
56
  export type PlanetId = (typeof PLANET_IDS)[number];
57
+ /**
58
+ * The name of a dwarf planet besides Pluto: `ceres`, `eris`, `haumea`...
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * import { DWARF_IDS, type DwarfId } from "@johnmorrisdotca/wakusei-planets";
63
+ *
64
+ * const id: DwarfId = DWARF_IDS[0];
65
+ * console.log(id);
66
+ * ```
67
+ */
68
+ export type DwarfId = (typeof DWARF_IDS)[number];
69
+ /**
70
+ * A body a moon can go round: a planet, Pluto or another dwarf planet.
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * import { MOONS_OF, type HostId } from "@johnmorrisdotca/wakusei-planets";
75
+ *
76
+ * const host: HostId = "eris";
77
+ * console.log(MOONS_OF[host]);
78
+ * ```
79
+ */
80
+ export type HostId = PlanetId | DwarfId;
43
81
  /**
44
82
  * The name of a moon the package draws, such as `moon`, `io` or `titan`.
45
83
  *
@@ -53,7 +91,7 @@ export type PlanetId = (typeof PLANET_IDS)[number];
53
91
  */
54
92
  export type MoonId = (typeof MOONS_OF)[keyof typeof MOONS_OF][number];
55
93
  /**
56
- * The name of a body: `sun`, a planet or a moon.
94
+ * The name of a body: `sun`, a planet, a dwarf planet or a moon.
57
95
  *
58
96
  * @example
59
97
  * ```ts
@@ -63,7 +101,7 @@ export type MoonId = (typeof MOONS_OF)[keyof typeof MOONS_OF][number];
63
101
  * console.log(lineSvg(id, { size: 64 }).length > 100);
64
102
  * ```
65
103
  */
66
- export type BodyId = "sun" | PlanetId | MoonId;
104
+ export type BodyId = "sun" | PlanetId | DwarfId | MoonId;
67
105
  /**
68
106
  * How a body is drawn: `line` (an outline drawing), `realistic` (shaded, from the numbers) or `painted` (a real surface map).
69
107
  *
@@ -139,8 +177,8 @@ export type Feature = {
139
177
  export interface BodyFacts {
140
178
  id: BodyId;
141
179
  kind: "star" | "planet" | "dwarf-planet" | "moon";
142
- /** The planet a moon goes round. */
143
- parent?: PlanetId;
180
+ /** The planet or dwarf planet a moon goes round. */
181
+ parent?: HostId;
144
182
  name: {
145
183
  en: string;
146
184
  ja: string;
@@ -186,7 +224,7 @@ export interface BodyFacts {
186
224
  */
187
225
  export declare const BODIES: Readonly<Record<BodyId, BodyFacts>>;
188
226
  /**
189
- * Every body's name: the Sun, the planets outward, then the moons of each planet.
227
+ * Every body's name: the Sun, the planets outward, the dwarf planets, then the moons of each.
190
228
  *
191
229
  * @example
192
230
  * ```ts
package/dist/facts.js CHANGED
@@ -12,7 +12,18 @@
12
12
  */
13
13
  export const PLANET_IDS = ["mercury", "venus", "earth", "mars", "jupiter", "saturn", "uranus", "neptune", "pluto"];
14
14
  /**
15
- * The moons the package draws, by planet.
15
+ * The dwarf planets besides Pluto, nearest the Sun first (by the size of their orbits).
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { DWARF_IDS } from "@johnmorrisdotca/wakusei-planets";
20
+ *
21
+ * console.log(DWARF_IDS.join(", "));
22
+ * ```
23
+ */
24
+ export const DWARF_IDS = ["ceres", "orcus", "haumea", "quaoar", "makemake", "gonggong", "eris", "sedna"];
25
+ /**
26
+ * The moons the package draws, by planet or dwarf planet.
16
27
  *
17
28
  * @example
18
29
  * ```ts
@@ -29,6 +40,9 @@ export const MOONS_OF = {
29
40
  uranus: ["miranda", "ariel", "umbriel", "titania", "oberon"],
30
41
  neptune: ["proteus", "triton", "nereid"],
31
42
  pluto: ["charon", "nix", "hydra"],
43
+ orcus: ["vanth"],
44
+ haumea: ["hiiaka", "namaka"],
45
+ eris: ["dysnomia"],
32
46
  };
33
47
  const f = (id, kind, en, ja, radiusKm, flattening, tiltDeg, ra, dec, w0, rate, rotationHours, colour, more = {}) => ({
34
48
  id,
@@ -131,6 +145,17 @@ export const BODIES = {
131
145
  ...dots([[-60, 20, 6], [-100, -20, 7], [60, 40, 5]]),
132
146
  ],
133
147
  }),
148
+ ceres: f("ceres", "dwarf-planet", "Ceres", "ケレス", 481.05, 0.0731, 4.04, 291.42744, 66.76033, 170.65, 952.1532, 9.07417, "#7b7873", {
149
+ showLon: 239,
150
+ features: [{ kind: "circle", lon: 239, lat: 20, radius: 6 }, { kind: "circle", lon: 239, lat: 20, radius: 1.5, fill: true }, { kind: "circle", lon: 10, lat: -42, radius: 10 }, ...dots([[-60, 30, 8], [100, 15, 9], [160, -20, 7], [-120, -35, 8], [40, 45, 6], [-20, 0, 5]])],
151
+ }),
152
+ orcus: f("orcus", "dwarf-planet", "Orcus", "オルクス", 455, 0, 73.83, 142.474, 15.004, 0, 655.15, 13.188, "#9a9a9c", { features: dots([[-60, 20, 9], [40, -15, 7], [130, 30, 8], [-130, -30, 6]]) }),
153
+ haumea: f("haumea", "dwarf-planet", "Haumea", "ハウメア", 798, 0, 90.15, 282.6, -13, 0, 2206.6, 3.915341, "#dfe0e3", { showLon: 90, axesKm: [1161, 852, 513], features: [{ kind: "oval", lon: 40, lat: 5, rx: 22, ry: 12, fill: true }, { kind: "band", lat: 0 }, ...dots([[-80, 25, 7]])] }),
154
+ quaoar: f("quaoar", "dwarf-planet", "Quaoar", "クワオアー", 557.8, 0, 0, 265.4, 74.409, 0, 488.72, 17.6788, "#a3735a", { showLon: 90, axesKm: [620.7, 546.5, 511.5], features: dots([[-40, 20, 8], [70, -15, 9], [150, 35, 7], [-110, -30, 6]]) }),
155
+ makemake: f("makemake", "dwarf-planet", "Makemake", "マケマケ", 715, 0.01, 0, 317.92, 50.03, 0, 378.5, 22.8266, "#b87f5d", { features: [{ kind: "oval", lon: 30, lat: 10, rx: 30, ry: 18, fill: true }, ...dots([[-70, -20, 8], [120, 25, 7]])] }),
156
+ gonggong: f("gonggong", "dwarf-planet", "Gonggong", "ゴンゴン", 615, 0, 0, 255.383, 36.831, 0, 385.7, 22.4, "#9c4f3b", { features: dots([[-50, 10, 9], [60, -25, 8], [140, 30, 7]]) }),
157
+ eris: f("eris", "dwarf-planet", "Eris", "エリス", 1163, 0, 78.22, 36.17, 44.51, 0, 22.805163, 378.8616, "#e8e4dc", { features: [{ kind: "band", lat: 0 }, ...dots([[-30, 30, 8], [80, -20, 9]])] }),
158
+ sedna: f("sedna", "dwarf-planet", "Sedna", "セドナ", 453, 0, 0, 297.062, 74.71, 0, 840.95, 10.273, "#9a3f2b", { features: dots([[-40, 20, 9], [70, -30, 8], [150, 10, 7]]) }),
134
159
  moon: f("moon", "moon", "Moon", "月", 1737.4, 0.0012, 6.68, 269.9949, 66.5392, 38.3213, 13.17635815, 655.728, "#b8b5ae", {
135
160
  parent: "earth",
136
161
  synchronous: true,
@@ -169,9 +194,13 @@ export const BODIES = {
169
194
  charon: f("charon", "moon", "Charon", "カロン", 606, 0, 0, 132.993, -6.163, 122.695, 56.3625225, 153.2935, "#9c9189", { parent: "pluto", synchronous: true, features: [{ kind: "oval", lon: 0, lat: 76, rx: 90, ry: 14, fill: true }, { kind: "circle", lon: 40, lat: -15, radius: 12 }, ...dots([[-60, 10, 8], [120, 30, 7]])] }),
170
195
  nix: f("nix", "moon", "Nix", "ニクス", 19.3, 0.3, 0, 132.993, -6.163, 0, 14.48, 0, "#b3ada7", { parent: "pluto", axesKm: [24.9, 16.6, 15.6], features: [{ kind: "circle", lon: 0, lat: 0, radius: 18 }] }),
171
196
  hydra: f("hydra", "moon", "Hydra", "ヒドラ", 19.5, 0.4, 0, 132.993, -6.163, 0, 9.42, 0, "#c4beb6", { parent: "pluto", axesKm: [32.5, 22.5, 12.5], features: [{ kind: "circle", lon: 30, lat: 10, radius: 20 }] }),
197
+ vanth: f("vanth", "moon", "Vanth", "ヴァント", 221, 0, 0, 142.474, 15.004, 0, 37.738618, 228.9488, "#6e6a66", { parent: "orcus", synchronous: true, features: dots([[-50, 15, 10], [80, -20, 9], [150, 30, 8]]) }),
198
+ hiiaka: f("hiiaka", "moon", "Hiʻiaka", "ヒイアカ", 185, 0, 0, 282.6, -13, 0, 0, 0, "#e0e0e0", { parent: "haumea", features: dots([[-30, 20, 12], [70, -25, 10]]) }),
199
+ namaka: f("namaka", "moon", "Namaka", "ナマカ", 75, 0, 0, 282.6, -13, 0, 0, 0, "#d0d0d0", { parent: "haumea", features: dots([[0, 0, 14]]) }),
200
+ dysnomia: f("dysnomia", "moon", "Dysnomia", "ディスノミア", 308, 0, 0, 36.17, 44.51, 0, 22.805163, 378.8616, "#5a5856", { parent: "eris", synchronous: true, features: dots([[-60, 20, 10], [50, -25, 9], [140, 30, 8]]) }),
172
201
  };
173
202
  /**
174
- * Every body's name: the Sun, the planets outward, then the moons of each planet.
203
+ * Every body's name: the Sun, the planets outward, the dwarf planets, then the moons of each.
175
204
  *
176
205
  * @example
177
206
  * ```ts
@@ -180,7 +209,7 @@ export const BODIES = {
180
209
  * console.log(BODY_IDS.length, BODY_IDS[0]);
181
210
  * ```
182
211
  */
183
- export const BODY_IDS = ["sun", ...PLANET_IDS, ...Object.values(MOONS_OF).flat()];
212
+ export const BODY_IDS = ["sun", ...PLANET_IDS, ...DWARF_IDS, ...Object.values(MOONS_OF).flat()];
184
213
  /** A body's polar radius as a fraction of its equatorial radius. */
185
214
  export const polarRatio = (facts) => 1 - facts.flattening;
186
215
  /**
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export { BODIES, BODY_IDS, MOONS_OF, PLANET_IDS, ringReach, type BodyFacts, type BodyId, type Feature, type Look, type MoonId, type PlanetId, type RingBand } from "./facts.ts";
1
+ export { BODIES, BODY_IDS, DWARF_IDS, MOONS_OF, PLANET_IDS, ringReach, type BodyFacts, type BodyId, type DwarfId, type Feature, type HostId, type Look, type MoonId, type PlanetId, type RingBand } from "./facts.ts";
2
2
  export { apparent, moonGeocentric, heliocentric, orbitPath, system, type Apparent, type MoonPlace, type Pose, type System } from "./ephemeris.ts";
3
3
  export { drawnTilt, portrait, type PortraitOptions } from "./pose.ts";
4
4
  export { lineSvg, mix, type LineOptions } from "./line.ts";
5
5
  export { ringStrip, type RingStrip } from "./scene/rings.ts";
6
- export { embedCode, embedCredit, EMBED_KINDS, type EmbedKind, type EmbedOptions, type EmbedSettings } from "./embed.ts";
6
+ export { embedCode, embedCredit, EMBED_KINDS, portraitCode, type EmbedKind, type EmbedOptions, type EmbedSettings, type PortraitEmbed } from "./embed.ts";
7
+ export { addBody, decodeScene, defaultPortrait, encodeScene, PRESETS as PORTRAIT_PRESETS, resolve as layoutPortrait, type Item as PortraitItem, type Placed as PlacedItem, type Portrait, type Preset as PortraitPreset, type Resolved as PortraitLayout } from "./portrait/model.ts";
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
- export { BODIES, BODY_IDS, MOONS_OF, PLANET_IDS, ringReach } from "./facts.js";
1
+ export { BODIES, BODY_IDS, DWARF_IDS, MOONS_OF, PLANET_IDS, ringReach } from "./facts.js";
2
2
  export { apparent, moonGeocentric, heliocentric, orbitPath, system } from "./ephemeris.js";
3
3
  export { drawnTilt, portrait } from "./pose.js";
4
4
  export { lineSvg, mix } from "./line.js";
5
5
  export { ringStrip } from "./scene/rings.js";
6
- export { embedCode, embedCredit, EMBED_KINDS } from "./embed.js";
6
+ export { embedCode, embedCredit, EMBED_KINDS, portraitCode } from "./embed.js";
7
+ export { addBody, decodeScene, defaultPortrait, encodeScene, PRESETS as PORTRAIT_PRESETS, resolve as layoutPortrait } from "./portrait/model.js";
package/dist/line.js CHANGED
@@ -54,12 +54,15 @@ function around(lon, lat, rx, ry, steps = 28) {
54
54
  }
55
55
  return out;
56
56
  }
57
+ /** The semi-axes of a body that is far from round, as fractions of its radius. */
58
+ const axesOf = (facts) => (facts.axesKm === undefined ? undefined : [facts.axesKm[0] / facts.radiusKm, facts.axesKm[1] / facts.radiusKm, facts.axesKm[2] / facts.radiusKm]);
57
59
  function featurePaths(facts, pose, frame, stroke, hair) {
58
60
  const f = facts.flattening;
59
- const visible = (lon, lat) => facing(pose, lon, lat, f) > 0.02;
61
+ const axes = axesOf(facts);
62
+ const visible = (lon, lat) => facing(pose, lon, lat, f, axes) > 0.02;
60
63
  const out = [];
61
64
  const draw = (pts, close, fill) => {
62
- const parts = runs(pts.map((p) => surfacePoint(pose, p.lon, p.lat, f)), (_, i) => visible(pts[i].lon, pts[i].lat));
65
+ const parts = runs(pts.map((p) => surfacePoint(pose, p.lon, p.lat, f, axes)), (_, i) => visible(pts[i].lon, pts[i].lat));
63
66
  for (const part of parts) {
64
67
  const whole = close && part.length === pts.length;
65
68
  if (part.length < 2)
@@ -176,7 +179,7 @@ function cachedOrbit(id, time) {
176
179
  }
177
180
  function bodyGroup(id, pose, frame, o, hair, ringScale) {
178
181
  const facts = BODIES[id];
179
- const sil = silhouette(pose, facts.flattening);
182
+ const sil = silhouette(pose, facts.flattening, axesOf(facts));
180
183
  const disc = `<ellipse cx="${n(frame.cx)}" cy="${n(frame.cy)}" rx="${n(frame.r * sil.a)}" ry="${n(frame.r * sil.b)}" transform="rotate(${n(sil.angle)} ${n(frame.cx)} ${n(frame.cy)})"`;
181
184
  const rings = ringPaths(facts, pose, frame, o.stroke, hair, ringScale);
182
185
  const dark = id === "sun" || facts.kind === "star" ? "" : nightPath(pose, frame);
@@ -227,7 +230,7 @@ export function lineSvg(id, options = {}) {
227
230
  if (options.moons === true && facts.parent === undefined && id !== "sun")
228
231
  return systemSvg(id, options, size, stroke, paper, hair, head);
229
232
  const pose = poseFor(id, options);
230
- const reach = Math.max(ringReach(facts), id === "sun" ? 1.08 : 1);
233
+ const reach = Math.max(ringReach(facts), id === "sun" ? 1.08 : 1, ...(axesOf(facts) ?? []));
231
234
  const fit = options.fill === undefined ? 0.94 / reach : options.fill;
232
235
  const zoom = options.zoom ?? 1;
233
236
  const frame = { cx: (size / 2) * (1 - (options.panX ?? 0)), cy: (size / 2) * (1 + (options.panY ?? 0)), r: (size / 2) * fit * zoom };
@@ -0,0 +1,77 @@
1
+ import type { SharedRenderer } from "@johnmorrisdotca/kazoku-ui/renderer";
2
+ import type { ThreeParts } from "../scene/body.ts";
3
+ import { setThreeLoader } from "../scene/shared.ts";
4
+ import { type Guide, type Placed, type Portrait, type Resolved } from "./model.ts";
5
+ export { setThreeLoader };
6
+ /**
7
+ * What the element is doing: `line` (an SVG), `loading`, `still`, `live`, `lost` or `unavailable` (no WebGL: the line drawing is shown).
8
+ *
9
+ * @example
10
+ * ```ts no-run
11
+ * import type { PortraitState } from "@johnmorrisdotca/wakusei-planets/portrait";
12
+ *
13
+ * const done = (state: PortraitState): boolean => state === "live" || state === "line";
14
+ * console.log(done("still"));
15
+ * ```
16
+ */
17
+ export type PortraitState = "line" | "loading" | "still" | "live" | "lost" | "unavailable";
18
+ /**
19
+ * The `<wakusei-portrait>` custom element: a scene of bodies arranged on one picture.
20
+ *
21
+ * Attributes: `scene` (the scene as the portrait builder writes it in its address), `look` (`line`, `realistic` or `painted`: replaces the scene's), `size` (pixels across), `lang` (`en` or `ja`: the names),
22
+ * `live` (`always`, `hover` or `off`: when it takes the page's one WebGL context), `texture-base` and `texture-far-base` (where the surface pictures are).
23
+ *
24
+ * @example
25
+ * ```ts no-run
26
+ * import { WakuseiPortrait } from "@johnmorrisdotca/wakusei-planets/portrait";
27
+ *
28
+ * const view = document.createElement("wakusei-portrait") as WakuseiPortrait;
29
+ * view.setAttribute("scene", "arrange:arc~look:painted~sun_0_0_0.3_0~earth_0_0_0.3_0~moon_0_0_0.3_0");
30
+ * document.body.append(view);
31
+ * ```
32
+ */
33
+ export declare class WakuseiPortrait extends HTMLElement {
34
+ #private;
35
+ static observedAttributes: string[];
36
+ /** The scene now. Setting it hands the element a scene of your own, as the builder does; it is drawn at once and at most thirty times a second after. */
37
+ get portrait(): Portrait;
38
+ set portrait(value: Portrait);
39
+ /** The chosen body's index and the guides to draw over the picture (the builder's editing). */
40
+ set editing(value: {
41
+ selected?: number;
42
+ guides?: readonly Guide[];
43
+ });
44
+ get state(): PortraitState;
45
+ /** Numbers for a test or a status line. */
46
+ get stats(): {
47
+ state: PortraitState;
48
+ bodies: number;
49
+ renderer: SharedRenderer<ThreeParts>["stats"] | undefined;
50
+ };
51
+ /** Where everything is on the page now: the picture's size in pixels, pixels to a scene unit, and the bodies (back to front). */
52
+ get metrics(): {
53
+ width: number;
54
+ height: number;
55
+ scale: number;
56
+ camera: Resolved["camera"];
57
+ placed: readonly Placed[];
58
+ };
59
+ /** The body under a point of the page (client coordinates): its index in the list, or -1. `slop` is the smallest radius, in pixels, a body is hit within. */
60
+ pick(clientX: number, clientY: number, slop?: number): number;
61
+ /** A point of the page (client coordinates) in the scene's units. */
62
+ worldAt(clientX: number, clientY: number): {
63
+ x: number;
64
+ y: number;
65
+ };
66
+ connectedCallback(): void;
67
+ disconnectedCallback(): void;
68
+ attributeChangedCallback(name: string): void;
69
+ /** Take the page's one WebGL context and draw the scene on it. Resolves true when it is live; a line scene has nothing to take and resolves false. */
70
+ goLive(): Promise<boolean>;
71
+ /** Give the WebGL context back: the picture stays as a still. */
72
+ rest(): void;
73
+ /** The picture as a PNG: the background, the bodies and the names, at the size it is on the page times `scale` (the canvas of the bodies is at most the page's pixel ratio, 2). */
74
+ toPng(scale?: number): Promise<Blob>;
75
+ /** The picture as SVG. The line look is all vector. The shaded looks hold the bodies as a picture inside the SVG, with the background, the orbits and the names as vector. */
76
+ toSvg(): Promise<string>;
77
+ }