spacemap 0.1.4 → 0.1.5
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 +21 -1
- package/dist/spacemap.iife.js +26 -6
- package/dist/spacemap.js +26 -6
- package/index.d.ts +17 -0
- package/index.js +267 -30
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -1587,6 +1587,9 @@ export declare interface PolylineOptions {
|
|
|
1587
1587
|
widthPx?: number;
|
|
1588
1588
|
/** 0 to 1. */
|
|
1589
1589
|
opacity?: number;
|
|
1590
|
+
/** A dash and a gap in screen pixels, written as the flat map takes them:
|
|
1591
|
+
* `"4 3"`. Solid when left out. */
|
|
1592
|
+
dash?: string;
|
|
1590
1593
|
/** Fade the line toward its last point, the way an orbit trail fades
|
|
1591
1594
|
* behind a body. */
|
|
1592
1595
|
fade?: boolean;
|
|
@@ -2035,6 +2038,17 @@ export declare class SpaceMap {
|
|
|
2035
2038
|
* is nothing to choose once a host has said what it looks like.
|
|
2036
2039
|
*/
|
|
2037
2040
|
setBodyAppearance(id: string, appearance: BodyAppearance): this;
|
|
2041
|
+
/**
|
|
2042
|
+
* Keep these bodies in sight from however far: named, with their orbits,
|
|
2043
|
+
* where the map would let a small or distant one drop out and would give
|
|
2044
|
+
* its name up to a bigger neighbour's. A hidden layer does not take them
|
|
2045
|
+
* either. An id the map has not loaded yet is pinned once it has. Each call
|
|
2046
|
+
* replaces the last; an empty list gives the map its own judgement back.
|
|
2047
|
+
*
|
|
2048
|
+
* A moon is only drawn inside the system the camera is in, pinned or not:
|
|
2049
|
+
* pin its planet to mark it from outside.
|
|
2050
|
+
*/
|
|
2051
|
+
setPinnedBodies(ids: readonly string[]): this;
|
|
2038
2052
|
/** A cap's radius as an angle, from whichever of the two ways the host gave
|
|
2039
2053
|
* it. A radius in kilometres needs the body's own radius, which an
|
|
2040
2054
|
* unloaded body has not published yet. */
|
|
@@ -2114,6 +2128,9 @@ export declare interface SurfacePolygonOptions extends SurfaceShapeOptions {
|
|
|
2114
2128
|
export declare interface SurfacePolylineOptions extends SurfaceShapeOptions {
|
|
2115
2129
|
/** Join the last place back to the first. */
|
|
2116
2130
|
closed?: boolean;
|
|
2131
|
+
/** A dash and a gap in screen pixels, written as the flat map takes them:
|
|
2132
|
+
* `"4 3"`. Solid when left out. */
|
|
2133
|
+
dash?: string;
|
|
2117
2134
|
}
|
|
2118
2135
|
|
|
2119
2136
|
/** A shape on a body's surface, for as long as the host keeps it. */
|
package/index.js
CHANGED
|
@@ -6789,6 +6789,7 @@ var VisibilityController = class {
|
|
|
6789
6789
|
scaledSystem = SYSTEM_DISTANCE_RATIO_THRESHOLDS;
|
|
6790
6790
|
fullMoonIds = /* @__PURE__ */ new Set();
|
|
6791
6791
|
moonVisibilityCache = /* @__PURE__ */ new Map();
|
|
6792
|
+
pinned = /* @__PURE__ */ new Set();
|
|
6792
6793
|
constructor(bodies, getProbeStore = () => null, getEarthSatGroupFilter = () => null, getSmallBodyFilter = () => null, getLayers = () => ALL_LAYERS) {
|
|
6793
6794
|
this.bodies = bodies;
|
|
6794
6795
|
this.getProbeStore = getProbeStore;
|
|
@@ -6885,8 +6886,19 @@ var VisibilityController = class {
|
|
|
6885
6886
|
this.moonVisibilityCache.set(moon.data.id, vis);
|
|
6886
6887
|
return vis;
|
|
6887
6888
|
}
|
|
6889
|
+
setPinned(ids) {
|
|
6890
|
+
this.pinned = new Set(ids);
|
|
6891
|
+
}
|
|
6892
|
+
isPinned(id) {
|
|
6893
|
+
return this.pinned.has(id);
|
|
6894
|
+
}
|
|
6888
6895
|
getPlanetVisibility(body, camDistThreeJS) {
|
|
6889
|
-
|
|
6896
|
+
const pinned = this.pinned.has(body.data.id);
|
|
6897
|
+
const vis = this.ratioVisibility(body, camDistThreeJS, pinned);
|
|
6898
|
+
return pinned && vis !== VISIBILITY.CLOSE ? VISIBILITY.FULL : vis;
|
|
6899
|
+
}
|
|
6900
|
+
ratioVisibility(body, camDistThreeJS, pinned) {
|
|
6901
|
+
if (!pinned && this.getLayers().hidesBody(body.data.objectType, body.data.parentId)) return VISIBILITY.HIDE;
|
|
6890
6902
|
if (body.data.orbitalSource === OrbitalSource.SPICE_PROBE) return this.getProbeVisibility(body);
|
|
6891
6903
|
const earthFilter = this.getEarthSatGroupFilter();
|
|
6892
6904
|
if (earthFilter && body.data.parentId === "naif-399" && !earthFilter.has(body.data.id)) return VISIBILITY.HIDE;
|
|
@@ -6939,7 +6951,7 @@ var VisibilityController = class {
|
|
|
6939
6951
|
return sysNaif !== null && this.isInFocusedSystem(`naif-${sysNaif}`);
|
|
6940
6952
|
}
|
|
6941
6953
|
hasFullRendering(body) {
|
|
6942
|
-
if (!this.activeSystemId) return true;
|
|
6954
|
+
if (!this.activeSystemId || this.pinned.has(body.data.id)) return true;
|
|
6943
6955
|
if (this.isInActiveSystem(isTopLevelParent(body.data.parentId) ? body.data.id : body.data.parentId)) return true;
|
|
6944
6956
|
if (body.data.orbitalSource !== OrbitalSource.SPICE_PROBE) return false;
|
|
6945
6957
|
const ps = this.getProbeStore();
|
|
@@ -12286,8 +12298,9 @@ function makeTrailMaterial(color, brightness = TRAIL_DIM) {
|
|
|
12286
12298
|
`
|
|
12287
12299
|
});
|
|
12288
12300
|
}
|
|
12289
|
-
function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM) {
|
|
12301
|
+
function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM, dash) {
|
|
12290
12302
|
return new ShaderMaterial({
|
|
12303
|
+
defines: dash ? { DASHED: "" } : {},
|
|
12291
12304
|
transparent: true,
|
|
12292
12305
|
depthWrite: false,
|
|
12293
12306
|
side: DoubleSide,
|
|
@@ -12298,7 +12311,8 @@ function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM) {
|
|
|
12298
12311
|
uAlphaMin: { value: 0 },
|
|
12299
12312
|
uShowFull: { value: 0 },
|
|
12300
12313
|
uLineWidth: { value: lineWidth },
|
|
12301
|
-
uResolution: { value: TRAIL_RESOLUTION }
|
|
12314
|
+
uResolution: { value: TRAIL_RESOLUTION },
|
|
12315
|
+
uDash: { value: new Vector2(dash?.[0] ?? 0, dash?.[1] ?? 0) }
|
|
12302
12316
|
},
|
|
12303
12317
|
vertexShader: `
|
|
12304
12318
|
#include <common>
|
|
@@ -12312,6 +12326,11 @@ function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM) {
|
|
|
12312
12326
|
attribute float trailAlpha;
|
|
12313
12327
|
attribute float fullAlpha;
|
|
12314
12328
|
varying float vAlpha;
|
|
12329
|
+
#ifdef DASHED
|
|
12330
|
+
attribute float lineDistance;
|
|
12331
|
+
varying float vDistW;
|
|
12332
|
+
varying float vW;
|
|
12333
|
+
#endif
|
|
12315
12334
|
void main() {
|
|
12316
12335
|
vAlpha = mix(trailAlpha, fullAlpha, uShowFull);
|
|
12317
12336
|
vec3 currRel = position + uCenterOffset;
|
|
@@ -12328,6 +12347,13 @@ function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM) {
|
|
|
12328
12347
|
vec2 perp = vec2(-dirN.y, dirN.x) * side * uLineWidth * 0.5;
|
|
12329
12348
|
vec2 offsetNDC = perp / (uResolution * 0.5);
|
|
12330
12349
|
gl_Position = vec4((currNDC + offsetNDC) * currClip.w, currClip.zw);
|
|
12350
|
+
#ifdef DASHED
|
|
12351
|
+
// Carried times w and divided back out per fragment, which undoes
|
|
12352
|
+
// the perspective a varying is interpolated with: the dashes are
|
|
12353
|
+
// even on screen however much nearer one end is.
|
|
12354
|
+
vDistW = lineDistance * currClip.w;
|
|
12355
|
+
vW = currClip.w;
|
|
12356
|
+
#endif
|
|
12331
12357
|
#include <logdepthbuf_vertex>
|
|
12332
12358
|
}
|
|
12333
12359
|
`,
|
|
@@ -12337,7 +12363,15 @@ function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM) {
|
|
|
12337
12363
|
uniform float uAlphaMultiplier;
|
|
12338
12364
|
uniform float uAlphaMin;
|
|
12339
12365
|
varying float vAlpha;
|
|
12366
|
+
#ifdef DASHED
|
|
12367
|
+
uniform vec2 uDash;
|
|
12368
|
+
varying float vDistW;
|
|
12369
|
+
varying float vW;
|
|
12370
|
+
#endif
|
|
12340
12371
|
void main() {
|
|
12372
|
+
#ifdef DASHED
|
|
12373
|
+
if (mod(vDistW / vW, uDash.x + uDash.y) > uDash.x) discard;
|
|
12374
|
+
#endif
|
|
12341
12375
|
gl_FragColor = vec4(uColor, clamp(max(vAlpha * uAlphaMultiplier, uAlphaMin), 0.0, 1.0));
|
|
12342
12376
|
#include <logdepthbuf_fragment>
|
|
12343
12377
|
}
|
|
@@ -14142,7 +14176,7 @@ function cullOverlappingLabels(bodyObjects, screenWidth, screenHeight, camera, f
|
|
|
14142
14176
|
c.isCapped = body.data.objectType === ObjectType.MOON ? ctx.visibility.getMoonVisibility(body) === VISIBILITY.CAPPED : false;
|
|
14143
14177
|
c.isMinor = bo.isMinor;
|
|
14144
14178
|
c.isFocused = isFocused;
|
|
14145
|
-
c.isSelected = isFocused || isHovered;
|
|
14179
|
+
c.isSelected = isFocused || isHovered || ctx.visibility.isPinned(body.data.id);
|
|
14146
14180
|
c.dist = bo.cachedDist;
|
|
14147
14181
|
}
|
|
14148
14182
|
_candidates.length = _candidatesActive;
|
|
@@ -17768,10 +17802,18 @@ function buildThinLineFromArrays(posArr, trailAlphas, fullAlphas, total, color)
|
|
|
17768
17802
|
line.renderOrder = TRAIL_RENDER_ORDER;
|
|
17769
17803
|
return line;
|
|
17770
17804
|
}
|
|
17771
|
-
function
|
|
17805
|
+
function writeLineDistances(geometry, src, n) {
|
|
17806
|
+
const attr = geometry.getAttribute("lineDistance");
|
|
17807
|
+
const arr = attr.array;
|
|
17808
|
+
const m = Math.min(n, arr.length / 2);
|
|
17809
|
+
for (let i = 0; i < m; i++) arr[2 * i] = arr[2 * i + 1] = src[i];
|
|
17810
|
+
attr.needsUpdate = true;
|
|
17811
|
+
}
|
|
17812
|
+
function buildFatLineFromThin(capacity, posArr, trailAlphas, fullAlphas, total, color, lineWidth, brightness, dash) {
|
|
17772
17813
|
const geometry = makeFatTrailGeometry(capacity);
|
|
17814
|
+
if (dash) geometry.setAttribute("lineDistance", new Float32BufferAttribute(new Float32Array(2 * capacity), 1));
|
|
17773
17815
|
writeFatTrailVertices(geometry, posArr, trailAlphas, fullAlphas, total);
|
|
17774
|
-
const mesh = new Mesh(geometry, makeFatTrailMaterial(color, lineWidth, brightness));
|
|
17816
|
+
const mesh = new Mesh(geometry, makeFatTrailMaterial(color, lineWidth, brightness, dash));
|
|
17775
17817
|
mesh.matrixAutoUpdate = false;
|
|
17776
17818
|
mesh.renderOrder = TRAIL_RENDER_ORDER;
|
|
17777
17819
|
return mesh;
|
|
@@ -20183,7 +20225,7 @@ function updateBodyVisibility(bodyObjects, camera, ctx, focusTruePos, focusedBod
|
|
|
20183
20225
|
isClose = !subPixel;
|
|
20184
20226
|
showLabel = !isClose;
|
|
20185
20227
|
}
|
|
20186
|
-
if (bo.isMinor && !isFocused && trail) trail.visible = false;
|
|
20228
|
+
if (bo.isMinor && !isFocused && trail && !ctx.visibility.isPinned(body.data.id)) trail.visible = false;
|
|
20187
20229
|
if (suppressHeliocentricTrails && trail?.visible) {
|
|
20188
20230
|
const oc = trail.userData.orbitCenter;
|
|
20189
20231
|
if (oc && oc.distanceToSquared(_focusV3.set(fp[0], fp[1], fp[2])) > HELIO_CENTER_DIST_SQ) trail.visible = false;
|
|
@@ -22732,6 +22774,8 @@ var PromotionRegistry = class {
|
|
|
22732
22774
|
defaults = /* @__PURE__ */ new Set();
|
|
22733
22775
|
userPromoted = /* @__PURE__ */ new Set();
|
|
22734
22776
|
autoPromoted = /* @__PURE__ */ new Set();
|
|
22777
|
+
pinned = /* @__PURE__ */ new Set();
|
|
22778
|
+
pinPromoted = /* @__PURE__ */ new Set();
|
|
22735
22779
|
groupTargets = null;
|
|
22736
22780
|
groupMode = "none";
|
|
22737
22781
|
smallBodyZone = null;
|
|
@@ -22741,6 +22785,7 @@ var PromotionRegistry = class {
|
|
|
22741
22785
|
this.deps = deps;
|
|
22742
22786
|
deps.ctx.bodies.onBodiesAdded(() => {
|
|
22743
22787
|
this.onBodiesAdded();
|
|
22788
|
+
this.buildPinned();
|
|
22744
22789
|
this.autoPromoteAsteroidMoons();
|
|
22745
22790
|
this.reevaluateEarthSatMode();
|
|
22746
22791
|
if (this.smallBodyZone !== null) this.refreshSmallBodyEmphasis();
|
|
@@ -22930,6 +22975,31 @@ var PromotionRegistry = class {
|
|
|
22930
22975
|
if (toRemove.length === 0) return;
|
|
22931
22976
|
this.tearDownBodies(toRemove, this.autoPromoted);
|
|
22932
22977
|
}
|
|
22978
|
+
setPinned(ids) {
|
|
22979
|
+
this.pinned = new Set(ids);
|
|
22980
|
+
const focusedId = this.deps.getFocusedId();
|
|
22981
|
+
const dropped = [...this.pinPromoted].filter((id) => !this.pinned.has(id));
|
|
22982
|
+
if (focusedId && dropped.includes(focusedId)) {
|
|
22983
|
+
this.pinPromoted.delete(focusedId);
|
|
22984
|
+
this.userPromoted.add(focusedId);
|
|
22985
|
+
this.emitUserPromotedCount();
|
|
22986
|
+
}
|
|
22987
|
+
this.tearDownBodies(dropped.filter((id) => id !== focusedId), this.pinPromoted);
|
|
22988
|
+
this.buildPinned();
|
|
22989
|
+
}
|
|
22990
|
+
buildPinned() {
|
|
22991
|
+
let built = false;
|
|
22992
|
+
for (const id of this.pinned) {
|
|
22993
|
+
const body = this.deps.ctx.getBody(id);
|
|
22994
|
+
if (!body || isSurfaceFeature(body) || body.data.objectType === ObjectType.MOON) continue;
|
|
22995
|
+
if (!this.buildBodyInstance(body)) continue;
|
|
22996
|
+
built = true;
|
|
22997
|
+
if (this.userPromoted.delete(id)) this.pinPromoted.add(id);
|
|
22998
|
+
}
|
|
22999
|
+
if (!built) return;
|
|
23000
|
+
this.emitUserPromotedCount();
|
|
23001
|
+
this.finalizeBuilds();
|
|
23002
|
+
}
|
|
22933
23003
|
clearUserPromoted() {
|
|
22934
23004
|
const focusedId = this.deps.getFocusedId();
|
|
22935
23005
|
const toRemove = [...this.userPromoted].filter((id) => id !== focusedId);
|
|
@@ -24866,6 +24936,10 @@ var SceneRenderer = class SceneRenderer {
|
|
|
24866
24936
|
setBodyAppearance(id, appearance) {
|
|
24867
24937
|
this.appearances.set(id, appearance);
|
|
24868
24938
|
}
|
|
24939
|
+
setPinnedBodies(ids) {
|
|
24940
|
+
this.ctx.visibility.setPinned(ids);
|
|
24941
|
+
this.focusController.promotion.setPinned(ids);
|
|
24942
|
+
}
|
|
24869
24943
|
setNorthReference(id) {
|
|
24870
24944
|
this.cameraUp.setNorthReference(id);
|
|
24871
24945
|
}
|
|
@@ -25484,6 +25558,153 @@ var MarkerExtension = class {
|
|
|
25484
25558
|
}
|
|
25485
25559
|
};
|
|
25486
25560
|
|
|
25561
|
+
//#endregion
|
|
25562
|
+
//#region src/lib/scene/extensions/screen.ts
|
|
25563
|
+
var REACH = 3;
|
|
25564
|
+
var right = new Vector3();
|
|
25565
|
+
var up = new Vector3();
|
|
25566
|
+
var forward = new Vector3();
|
|
25567
|
+
function parseDash(pattern) {
|
|
25568
|
+
const [dash, gap = dash] = (pattern ?? "").split(/[\s,]+/).filter(Boolean).map(Number);
|
|
25569
|
+
return dash > 0 && gap > 0 ? [dash, gap] : null;
|
|
25570
|
+
}
|
|
25571
|
+
function aim(camera, viewportPx) {
|
|
25572
|
+
right.set(1, 0, 0).applyQuaternion(camera.quaternion);
|
|
25573
|
+
up.set(0, 1, 0).applyQuaternion(camera.quaternion);
|
|
25574
|
+
forward.set(0, 0, -1).applyQuaternion(camera.quaternion);
|
|
25575
|
+
return viewportPx / (2 * Math.tan(camera.getEffectiveFOV() * Math.PI / 360));
|
|
25576
|
+
}
|
|
25577
|
+
function view(points, i, camera, out) {
|
|
25578
|
+
const x = points[i * 3] - camera.position.x;
|
|
25579
|
+
const y = points[i * 3 + 1] - camera.position.y;
|
|
25580
|
+
const z = points[i * 3 + 2] - camera.position.z;
|
|
25581
|
+
out[0] = x * right.x + y * right.y + z * right.z;
|
|
25582
|
+
out[1] = x * up.x + y * up.y + z * up.z;
|
|
25583
|
+
out[2] = x * forward.x + y * forward.y + z * forward.z;
|
|
25584
|
+
}
|
|
25585
|
+
function reachesBehind(points, count, camera) {
|
|
25586
|
+
forward.set(0, 0, -1).applyQuaternion(camera.quaternion);
|
|
25587
|
+
const { x, y, z } = camera.position;
|
|
25588
|
+
for (let i = 0; i < count; i++) if ((points[i * 3] - x) * forward.x + (points[i * 3 + 1] - y) * forward.y + (points[i * 3 + 2] - z) * forward.z < camera.near * 2) return true;
|
|
25589
|
+
return false;
|
|
25590
|
+
}
|
|
25591
|
+
function screenLengths(points, count, camera, viewportPx, out) {
|
|
25592
|
+
const focal = aim(camera, viewportPx);
|
|
25593
|
+
const at = [
|
|
25594
|
+
0,
|
|
25595
|
+
0,
|
|
25596
|
+
0
|
|
25597
|
+
];
|
|
25598
|
+
let length = 0;
|
|
25599
|
+
let lastX = 0;
|
|
25600
|
+
let lastY = 0;
|
|
25601
|
+
let seen = false;
|
|
25602
|
+
for (let i = 0; i < count; i++) {
|
|
25603
|
+
view(points, i, camera, at);
|
|
25604
|
+
if (at[2] > camera.near) {
|
|
25605
|
+
const px = at[0] / at[2] * focal;
|
|
25606
|
+
const py = at[1] / at[2] * focal;
|
|
25607
|
+
if (seen) length += Math.hypot(px - lastX, py - lastY);
|
|
25608
|
+
lastX = px;
|
|
25609
|
+
lastY = py;
|
|
25610
|
+
seen = true;
|
|
25611
|
+
}
|
|
25612
|
+
out[i] = length;
|
|
25613
|
+
}
|
|
25614
|
+
}
|
|
25615
|
+
var SeenLine = class {
|
|
25616
|
+
points = new Float32Array(0);
|
|
25617
|
+
alphas = new Float32Array(0);
|
|
25618
|
+
lengths = new Float32Array(0);
|
|
25619
|
+
count = 0;
|
|
25620
|
+
a = [
|
|
25621
|
+
0,
|
|
25622
|
+
0,
|
|
25623
|
+
0
|
|
25624
|
+
];
|
|
25625
|
+
b = [
|
|
25626
|
+
0,
|
|
25627
|
+
0,
|
|
25628
|
+
0
|
|
25629
|
+
];
|
|
25630
|
+
see(points, alphas, count, camera, viewportPx) {
|
|
25631
|
+
if (this.alphas.length < count * 4) {
|
|
25632
|
+
this.points = new Float32Array(count * 12);
|
|
25633
|
+
this.alphas = new Float32Array(count * 4);
|
|
25634
|
+
this.lengths = new Float32Array(count * 4);
|
|
25635
|
+
}
|
|
25636
|
+
this.count = 0;
|
|
25637
|
+
const focal = aim(camera, viewportPx);
|
|
25638
|
+
const halfW = viewportPx * camera.aspect * REACH / 2;
|
|
25639
|
+
const halfH = viewportPx * REACH / 2;
|
|
25640
|
+
const near = camera.near * 2;
|
|
25641
|
+
let { a, b } = this;
|
|
25642
|
+
let joined = false;
|
|
25643
|
+
let length = 0;
|
|
25644
|
+
let lastX = 0;
|
|
25645
|
+
let lastY = 0;
|
|
25646
|
+
if (count > 0) view(points, 0, camera, a);
|
|
25647
|
+
for (let i = 0; i + 1 < count; i++, [a, b] = [b, a]) {
|
|
25648
|
+
view(points, i + 1, camera, b);
|
|
25649
|
+
let from = 0;
|
|
25650
|
+
let to = 1;
|
|
25651
|
+
for (let plane = 0; plane < 5 && from <= to; plane++) {
|
|
25652
|
+
const ga = edge(plane, a, focal, halfW, halfH, near);
|
|
25653
|
+
const gb = edge(plane, b, focal, halfW, halfH, near);
|
|
25654
|
+
if (ga < 0 && gb < 0) to = -1;
|
|
25655
|
+
else if (ga < 0) from = Math.max(from, ga / (ga - gb));
|
|
25656
|
+
else if (gb < 0) to = Math.min(to, ga / (ga - gb));
|
|
25657
|
+
}
|
|
25658
|
+
if (from > to) {
|
|
25659
|
+
joined = false;
|
|
25660
|
+
continue;
|
|
25661
|
+
}
|
|
25662
|
+
const depth = a[2] + (b[2] - a[2]) * from;
|
|
25663
|
+
const x = (a[0] + (b[0] - a[0]) * from) / depth * focal;
|
|
25664
|
+
const y = (a[1] + (b[1] - a[1]) * from) / depth * focal;
|
|
25665
|
+
if (!joined || from > 0) {
|
|
25666
|
+
if (this.count > 0) {
|
|
25667
|
+
this.copy(this.count - 1, 0);
|
|
25668
|
+
this.put(points, alphas, i, from, length, 0);
|
|
25669
|
+
}
|
|
25670
|
+
this.put(points, alphas, i, from, length, 1);
|
|
25671
|
+
lastX = x;
|
|
25672
|
+
lastY = y;
|
|
25673
|
+
}
|
|
25674
|
+
const endDepth = a[2] + (b[2] - a[2]) * to;
|
|
25675
|
+
const endX = (a[0] + (b[0] - a[0]) * to) / endDepth * focal;
|
|
25676
|
+
const endY = (a[1] + (b[1] - a[1]) * to) / endDepth * focal;
|
|
25677
|
+
length += Math.hypot(endX - lastX, endY - lastY);
|
|
25678
|
+
lastX = endX;
|
|
25679
|
+
lastY = endY;
|
|
25680
|
+
this.put(points, alphas, i, to, length, 1);
|
|
25681
|
+
joined = to === 1;
|
|
25682
|
+
}
|
|
25683
|
+
}
|
|
25684
|
+
put(points, alphas, i, t, length, shown) {
|
|
25685
|
+
const at = this.count++;
|
|
25686
|
+
for (let k = 0; k < 3; k++) {
|
|
25687
|
+
const from = points[i * 3 + k];
|
|
25688
|
+
this.points[at * 3 + k] = from + (points[i * 3 + 3 + k] - from) * t;
|
|
25689
|
+
}
|
|
25690
|
+
this.alphas[at] = (alphas[i] + (alphas[i + 1] - alphas[i]) * t) * shown;
|
|
25691
|
+
this.lengths[at] = length;
|
|
25692
|
+
}
|
|
25693
|
+
copy(from, shown) {
|
|
25694
|
+
const at = this.count++;
|
|
25695
|
+
this.points.copyWithin(at * 3, from * 3, from * 3 + 3);
|
|
25696
|
+
this.alphas[at] = this.alphas[from] * shown;
|
|
25697
|
+
this.lengths[at] = this.lengths[from];
|
|
25698
|
+
}
|
|
25699
|
+
};
|
|
25700
|
+
function edge(plane, at, focal, halfW, halfH, near) {
|
|
25701
|
+
if (plane === 0) return at[2] - near;
|
|
25702
|
+
if (plane === 1) return halfW * at[2] - focal * at[0];
|
|
25703
|
+
if (plane === 2) return halfW * at[2] + focal * at[0];
|
|
25704
|
+
if (plane === 3) return halfH * at[2] - focal * at[1];
|
|
25705
|
+
return halfH * at[2] + focal * at[1];
|
|
25706
|
+
}
|
|
25707
|
+
|
|
25487
25708
|
//#endregion
|
|
25488
25709
|
//#region src/lib/scene/extensions/polyline.ts
|
|
25489
25710
|
var REDRAW_EPSILON$1 = 1e-9;
|
|
@@ -25493,6 +25714,7 @@ var PolylineExtension = class {
|
|
|
25493
25714
|
color;
|
|
25494
25715
|
widthPx;
|
|
25495
25716
|
opacity;
|
|
25717
|
+
dash;
|
|
25496
25718
|
fade;
|
|
25497
25719
|
closed;
|
|
25498
25720
|
local;
|
|
@@ -25500,6 +25722,7 @@ var PolylineExtension = class {
|
|
|
25500
25722
|
mesh = null;
|
|
25501
25723
|
scratch = new Float32Array(0);
|
|
25502
25724
|
alphas = new Float32Array(0);
|
|
25725
|
+
seen = new SeenLine();
|
|
25503
25726
|
capacity = 0;
|
|
25504
25727
|
lastOrigin = [
|
|
25505
25728
|
0,
|
|
@@ -25514,6 +25737,7 @@ var PolylineExtension = class {
|
|
|
25514
25737
|
this.color = options.color ?? "#ffffff";
|
|
25515
25738
|
this.widthPx = options.widthPx ?? 2;
|
|
25516
25739
|
this.opacity = options.opacity ?? 1;
|
|
25740
|
+
this.dash = parseDash(options.dash);
|
|
25517
25741
|
this.fade = options.fade ?? false;
|
|
25518
25742
|
this.closed = options.closed ?? false;
|
|
25519
25743
|
this.local = new Float64Array(0);
|
|
@@ -25534,6 +25758,10 @@ var PolylineExtension = class {
|
|
|
25534
25758
|
}
|
|
25535
25759
|
if (count > points.length) this.local.copyWithin(points.length * 3, 0, 3);
|
|
25536
25760
|
this.count = count;
|
|
25761
|
+
if (this.alphas.length < count) {
|
|
25762
|
+
this.scratch = new Float32Array(count * 3);
|
|
25763
|
+
this.alphas = new Float32Array(count);
|
|
25764
|
+
}
|
|
25537
25765
|
if (count > this.capacity) this.rebuild(count);
|
|
25538
25766
|
this.fillAlphas();
|
|
25539
25767
|
this.dirty = true;
|
|
@@ -25552,38 +25780,35 @@ var PolylineExtension = class {
|
|
|
25552
25780
|
this.removeSelf?.();
|
|
25553
25781
|
this.removeSelf = null;
|
|
25554
25782
|
}
|
|
25555
|
-
update({ jd, basis, camera, ctx }) {
|
|
25556
|
-
const mesh = this.mesh;
|
|
25557
|
-
if (!mesh) return;
|
|
25783
|
+
update({ jd, basis, camera, viewportPx, ctx }) {
|
|
25558
25784
|
const world = this.wanted && this.count >= 2 ? resolveAnchor(this.anchor, ctx, jd) : null;
|
|
25559
|
-
mesh.visible = world !== null;
|
|
25560
|
-
if (!world) return;
|
|
25785
|
+
if (this.mesh) this.mesh.visible = world !== null;
|
|
25786
|
+
if (!this.mesh || !world) return;
|
|
25561
25787
|
const origin = [
|
|
25562
25788
|
world[0] - basis[0],
|
|
25563
25789
|
world[1] - basis[1],
|
|
25564
25790
|
world[2] - basis[2]
|
|
25565
25791
|
];
|
|
25566
|
-
|
|
25567
|
-
|
|
25792
|
+
const moved = this.dirty || Math.abs(origin[0] - this.lastOrigin[0]) > REDRAW_EPSILON$1 || Math.abs(origin[1] - this.lastOrigin[1]) > REDRAW_EPSILON$1 || Math.abs(origin[2] - this.lastOrigin[2]) > REDRAW_EPSILON$1;
|
|
25793
|
+
if (moved) {
|
|
25794
|
+
for (let i = 0; i < this.count * 3; i++) this.scratch[i] = this.local[i] + origin[i % 3];
|
|
25568
25795
|
this.lastOrigin = origin;
|
|
25569
|
-
this.dirty = false;
|
|
25570
25796
|
}
|
|
25571
|
-
|
|
25572
|
-
|
|
25573
|
-
|
|
25574
|
-
|
|
25575
|
-
|
|
25576
|
-
this.
|
|
25577
|
-
this.
|
|
25578
|
-
}
|
|
25579
|
-
|
|
25797
|
+
const cut = this.dash !== null || reachesBehind(this.scratch, this.count, camera);
|
|
25798
|
+
if (cut) {
|
|
25799
|
+
const { seen } = this;
|
|
25800
|
+
seen.see(this.scratch, this.alphas, this.count, camera, viewportPx);
|
|
25801
|
+
if (seen.count > this.capacity) this.rebuild(seen.count);
|
|
25802
|
+
writeFatTrailVertices(this.mesh.geometry, seen.points, seen.alphas, seen.alphas, seen.count);
|
|
25803
|
+
if (this.dash) writeLineDistances(this.mesh.geometry, seen.lengths, seen.count);
|
|
25804
|
+
} else if (moved) writeFatTrailVertices(this.mesh.geometry, this.scratch, this.alphas, this.alphas, this.count);
|
|
25805
|
+
this.dirty = cut;
|
|
25806
|
+
this.mesh.material.uniforms.uCenterOffset.value.copy(camera.position).negate();
|
|
25580
25807
|
}
|
|
25581
25808
|
rebuild(capacity) {
|
|
25582
25809
|
this.disposeMesh();
|
|
25583
25810
|
this.dirty = true;
|
|
25584
|
-
this.scratch
|
|
25585
|
-
this.alphas = new Float32Array(capacity);
|
|
25586
|
-
const mesh = buildFatLineFromThin(capacity, this.scratch, this.alphas, this.alphas, capacity, this.color, this.widthPx, 1);
|
|
25811
|
+
const mesh = buildFatLineFromThin(capacity, this.scratch, this.alphas, this.alphas, 0, this.color, this.widthPx, 1, this.dash ?? void 0);
|
|
25587
25812
|
mesh.frustumCulled = false;
|
|
25588
25813
|
this.object.add(mesh);
|
|
25589
25814
|
this.mesh = mesh;
|
|
@@ -26772,6 +26997,7 @@ var SurfaceShapeExtension = class {
|
|
|
26772
26997
|
color;
|
|
26773
26998
|
widthPx;
|
|
26774
26999
|
opacity;
|
|
27000
|
+
dash;
|
|
26775
27001
|
fillColor;
|
|
26776
27002
|
fillOpacity;
|
|
26777
27003
|
dirs = new Float64Array(0);
|
|
@@ -26779,6 +27005,7 @@ var SurfaceShapeExtension = class {
|
|
|
26779
27005
|
line = null;
|
|
26780
27006
|
scratch = new Float32Array(0);
|
|
26781
27007
|
alphas = new Float32Array(0);
|
|
27008
|
+
lengths = new Float32Array(0);
|
|
26782
27009
|
fanDirs = new Float64Array(0);
|
|
26783
27010
|
fill = null;
|
|
26784
27011
|
fillScratch = new Float32Array(0);
|
|
@@ -26798,6 +27025,7 @@ var SurfaceShapeExtension = class {
|
|
|
26798
27025
|
this.color = options.color ?? "#ffffff";
|
|
26799
27026
|
this.widthPx = options.widthPx ?? 2;
|
|
26800
27027
|
this.opacity = options.opacity ?? 1;
|
|
27028
|
+
this.dash = parseDash(options.dash);
|
|
26801
27029
|
this.fillColor = options.fill ?? null;
|
|
26802
27030
|
this.fillOpacity = options.fillOpacity ?? .25;
|
|
26803
27031
|
this.object.matrixAutoUpdate = false;
|
|
@@ -26830,7 +27058,7 @@ var SurfaceShapeExtension = class {
|
|
|
26830
27058
|
this.removeSelf?.();
|
|
26831
27059
|
this.removeSelf = null;
|
|
26832
27060
|
}
|
|
26833
|
-
update({ jd, basis, camera, ctx }) {
|
|
27061
|
+
update({ jd, basis, camera, viewportPx, ctx }) {
|
|
26834
27062
|
const body = this.wanted && this.count >= 2 ? ctx.getBody(this.body) : void 0;
|
|
26835
27063
|
const centre = body && bodyCentre(body, ctx, jd);
|
|
26836
27064
|
if (this.line) this.line.visible = !!centre;
|
|
@@ -26847,6 +27075,10 @@ var SurfaceShapeExtension = class {
|
|
|
26847
27075
|
if (this.line) {
|
|
26848
27076
|
this.place(this.dirs, this.count, q, scale, origin, this.scratch);
|
|
26849
27077
|
writeFatTrailVertices(this.line.geometry, this.scratch, this.alphas, this.alphas, this.count);
|
|
27078
|
+
if (this.dash) {
|
|
27079
|
+
screenLengths(this.scratch, this.count, camera, viewportPx, this.lengths);
|
|
27080
|
+
writeLineDistances(this.line.geometry, this.lengths, this.count);
|
|
27081
|
+
}
|
|
26850
27082
|
this.line.material.uniforms.uCenterOffset.value.copy(camera.position).negate();
|
|
26851
27083
|
}
|
|
26852
27084
|
if (this.fill) {
|
|
@@ -26875,7 +27107,8 @@ var SurfaceShapeExtension = class {
|
|
|
26875
27107
|
if (this.count < 2 || this.widthPx <= 0) return;
|
|
26876
27108
|
this.scratch = new Float32Array(this.count * 3);
|
|
26877
27109
|
this.alphas = new Float32Array(this.count).fill(this.opacity);
|
|
26878
|
-
|
|
27110
|
+
this.lengths = new Float32Array(this.count);
|
|
27111
|
+
const line = buildFatLineFromThin(this.count, this.scratch, this.alphas, this.alphas, this.count, this.color, this.widthPx, 1, this.dash ?? void 0);
|
|
26879
27112
|
line.frustumCulled = false;
|
|
26880
27113
|
line.renderOrder = SURFACE_RENDER_ORDER;
|
|
26881
27114
|
this.object.add(line);
|
|
@@ -27914,6 +28147,10 @@ var SpaceMap = class {
|
|
|
27914
28147
|
this.requireRenderer().setBodyAppearance(id, appearance);
|
|
27915
28148
|
return this;
|
|
27916
28149
|
}
|
|
28150
|
+
setPinnedBodies(ids) {
|
|
28151
|
+
this.requireRenderer().setPinnedBodies(ids);
|
|
28152
|
+
return this;
|
|
28153
|
+
}
|
|
27917
28154
|
capRadiusDeg(options) {
|
|
27918
28155
|
if (options.radiusDeg !== void 0) return options.radiusDeg;
|
|
27919
28156
|
const bodyRadiusKm = this.getBody(options.body)?.radiusKm;
|
package/package.json
CHANGED