spacemap 0.1.4 → 0.1.6
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 +39 -1
- package/dist/spacemap.iife.js +68 -37
- package/dist/spacemap.js +74 -43
- package/index.d.ts +35 -0
- package/index.js +481 -49
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*! spacemap SDK — https://spacemap.co — Mozilla Public License 2.0. Bundles MIT and ISC libraries: THIRD_PARTY_NOTICES.txt in the spacemap npm package. */
|
|
2
|
-
import { ACESFilmicToneMapping, AdditiveBlending, AmbientLight, ArrowHelper, BackSide, Box3, BufferAttribute, BufferGeometry, CanvasTexture, Color, CubeTexture, CustomBlending, DataTexture, DepthTexture, DirectionalLight, DoubleSide, Euler, Float32BufferAttribute, FloatType, FrontSide, Group, HalfFloatType, InstancedBufferAttribute, InstancedMesh, Line, LineBasicMaterial, LineLoop, LinearFilter, LinearMipmapLinearFilter, LinearSRGBColorSpace, MathUtils, Matrix4, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshStandardMaterial, NoBlending, NoColorSpace, NormalBlending, OneFactor, OneMinusSrcAlphaFactor, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, PerspectiveCamera, PlaneGeometry, PointLight, Points, PointsMaterial, Quaternion, RGBAFormat, RawShaderMaterial, Raycaster, RedFormat, RingGeometry, SRGBColorSpace, Scene, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry, ShapeUtils, SphereGeometry, Sprite, SpriteMaterial, TOUCH, Texture, TextureLoader, Uint16BufferAttribute, UnsignedByteType, Vector2, Vector3, Vector4, WebGLRenderTarget, WebGLRenderer } from "three";
|
|
2
|
+
import { ACESFilmicToneMapping, AdditiveBlending, AmbientLight, ArrowHelper, BackSide, Box3, BufferAttribute, BufferGeometry, CanvasTexture, Color, CubeTexture, CustomBlending, DataTexture, DepthTexture, DirectionalLight, DoubleSide, Euler, Float32BufferAttribute, FloatType, FrontSide, Group, HalfFloatType, InstancedBufferAttribute, InstancedMesh, Line, LineBasicMaterial, LineLoop, LinearFilter, LinearMipmapLinearFilter, LinearSRGBColorSpace, MathUtils, Matrix4, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshStandardMaterial, NoBlending, NoColorSpace, NormalBlending, OneFactor, OneMinusSrcAlphaFactor, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, PerspectiveCamera, PlaneGeometry, PointLight, Points, PointsMaterial, Quaternion, RGBAFormat, RawShaderMaterial, Raycaster, RedFormat, RingGeometry, SRGBColorSpace, Scene, ShaderChunk, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry, ShapeUtils, SphereGeometry, Sprite, SpriteMaterial, TOUCH, Texture, TextureLoader, Uint16BufferAttribute, UnsignedByteType, Vector2, Vector3, Vector4, WebGLRenderTarget, WebGLRenderer } from "three";
|
|
3
3
|
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
|
|
4
4
|
import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";
|
|
5
5
|
import { RenderPass } from "three/addons/postprocessing/RenderPass.js";
|
|
@@ -6287,6 +6287,12 @@ var BodyIndex = class {
|
|
|
6287
6287
|
findAsteroidZone(id) {
|
|
6288
6288
|
for (const [zone, byId] of this.asteroidBodiesByZone) if (byId.has(id)) return zone;
|
|
6289
6289
|
}
|
|
6290
|
+
elementRow(body) {
|
|
6291
|
+
const d = body.data;
|
|
6292
|
+
if (d.orbitalSource !== OrbitalSource.SPICE) return d;
|
|
6293
|
+
const zone = this.findAsteroidZone(d.id);
|
|
6294
|
+
return zone === void 0 ? void 0 : this.asteroidBodiesByZone.get(zone)?.get(d.id)?.data;
|
|
6295
|
+
}
|
|
6290
6296
|
maxMoonA(parentId) {
|
|
6291
6297
|
return this.moonMaxAByParent.get(parentId);
|
|
6292
6298
|
}
|
|
@@ -6789,6 +6795,7 @@ var VisibilityController = class {
|
|
|
6789
6795
|
scaledSystem = SYSTEM_DISTANCE_RATIO_THRESHOLDS;
|
|
6790
6796
|
fullMoonIds = /* @__PURE__ */ new Set();
|
|
6791
6797
|
moonVisibilityCache = /* @__PURE__ */ new Map();
|
|
6798
|
+
pinned = /* @__PURE__ */ new Set();
|
|
6792
6799
|
constructor(bodies, getProbeStore = () => null, getEarthSatGroupFilter = () => null, getSmallBodyFilter = () => null, getLayers = () => ALL_LAYERS) {
|
|
6793
6800
|
this.bodies = bodies;
|
|
6794
6801
|
this.getProbeStore = getProbeStore;
|
|
@@ -6885,8 +6892,19 @@ var VisibilityController = class {
|
|
|
6885
6892
|
this.moonVisibilityCache.set(moon.data.id, vis);
|
|
6886
6893
|
return vis;
|
|
6887
6894
|
}
|
|
6895
|
+
setPinned(ids) {
|
|
6896
|
+
this.pinned = new Set(ids);
|
|
6897
|
+
}
|
|
6898
|
+
isPinned(id) {
|
|
6899
|
+
return this.pinned.has(id);
|
|
6900
|
+
}
|
|
6888
6901
|
getPlanetVisibility(body, camDistThreeJS) {
|
|
6889
|
-
|
|
6902
|
+
const pinned = this.pinned.has(body.data.id);
|
|
6903
|
+
const vis = this.ratioVisibility(body, camDistThreeJS, pinned);
|
|
6904
|
+
return pinned && vis !== VISIBILITY.CLOSE ? VISIBILITY.FULL : vis;
|
|
6905
|
+
}
|
|
6906
|
+
ratioVisibility(body, camDistThreeJS, pinned) {
|
|
6907
|
+
if (!pinned && this.getLayers().hidesBody(body.data.objectType, body.data.parentId)) return VISIBILITY.HIDE;
|
|
6890
6908
|
if (body.data.orbitalSource === OrbitalSource.SPICE_PROBE) return this.getProbeVisibility(body);
|
|
6891
6909
|
const earthFilter = this.getEarthSatGroupFilter();
|
|
6892
6910
|
if (earthFilter && body.data.parentId === "naif-399" && !earthFilter.has(body.data.id)) return VISIBILITY.HIDE;
|
|
@@ -6939,7 +6957,7 @@ var VisibilityController = class {
|
|
|
6939
6957
|
return sysNaif !== null && this.isInFocusedSystem(`naif-${sysNaif}`);
|
|
6940
6958
|
}
|
|
6941
6959
|
hasFullRendering(body) {
|
|
6942
|
-
if (!this.activeSystemId) return true;
|
|
6960
|
+
if (!this.activeSystemId || this.pinned.has(body.data.id)) return true;
|
|
6943
6961
|
if (this.isInActiveSystem(isTopLevelParent(body.data.parentId) ? body.data.id : body.data.parentId)) return true;
|
|
6944
6962
|
if (body.data.orbitalSource !== OrbitalSource.SPICE_PROBE) return false;
|
|
6945
6963
|
const ps = this.getProbeStore();
|
|
@@ -12089,6 +12107,26 @@ function isReversedDepth() {
|
|
|
12089
12107
|
function ndcZVisible(z) {
|
|
12090
12108
|
return reversed ? z >= 0 && z <= 1 : z >= -1 && z <= 1;
|
|
12091
12109
|
}
|
|
12110
|
+
var LOG_DEPTH_FLOOR = -44;
|
|
12111
|
+
function installLogDepthChunks() {
|
|
12112
|
+
ShaderChunk.logdepthbuf_vertex = `
|
|
12113
|
+
#ifdef USE_LOGARITHMIC_DEPTH_BUFFER
|
|
12114
|
+
vFragDepth = gl_Position.w;
|
|
12115
|
+
vIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );
|
|
12116
|
+
#endif
|
|
12117
|
+
`;
|
|
12118
|
+
ShaderChunk.logdepthbuf_fragment = `
|
|
12119
|
+
#if defined( USE_LOGARITHMIC_DEPTH_BUFFER )
|
|
12120
|
+
gl_FragDepth = vIsPerspective == 0.0
|
|
12121
|
+
? gl_FragCoord.z
|
|
12122
|
+
: max( log2( vFragDepth ) - ${LOG_DEPTH_FLOOR.toFixed(1)}, 0.0 ) / ( 2.0 / logDepthBufFC - ${LOG_DEPTH_FLOOR.toFixed(1)} );
|
|
12123
|
+
#endif
|
|
12124
|
+
`;
|
|
12125
|
+
}
|
|
12126
|
+
function logDepthToEyeGlsl(depth, far) {
|
|
12127
|
+
const floor = LOG_DEPTH_FLOOR.toFixed(1);
|
|
12128
|
+
return `exp2(${depth} * (log2(${far} + 1.0) - ${floor}) + ${floor})`;
|
|
12129
|
+
}
|
|
12092
12130
|
|
|
12093
12131
|
//#endregion
|
|
12094
12132
|
//#region src/lib/scene/label/throttled-renderer.ts
|
|
@@ -12286,8 +12324,9 @@ function makeTrailMaterial(color, brightness = TRAIL_DIM) {
|
|
|
12286
12324
|
`
|
|
12287
12325
|
});
|
|
12288
12326
|
}
|
|
12289
|
-
function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM) {
|
|
12327
|
+
function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM, dash) {
|
|
12290
12328
|
return new ShaderMaterial({
|
|
12329
|
+
defines: dash ? { DASHED: "" } : {},
|
|
12291
12330
|
transparent: true,
|
|
12292
12331
|
depthWrite: false,
|
|
12293
12332
|
side: DoubleSide,
|
|
@@ -12298,7 +12337,8 @@ function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM) {
|
|
|
12298
12337
|
uAlphaMin: { value: 0 },
|
|
12299
12338
|
uShowFull: { value: 0 },
|
|
12300
12339
|
uLineWidth: { value: lineWidth },
|
|
12301
|
-
uResolution: { value: TRAIL_RESOLUTION }
|
|
12340
|
+
uResolution: { value: TRAIL_RESOLUTION },
|
|
12341
|
+
uDash: { value: new Vector2(dash?.[0] ?? 0, dash?.[1] ?? 0) }
|
|
12302
12342
|
},
|
|
12303
12343
|
vertexShader: `
|
|
12304
12344
|
#include <common>
|
|
@@ -12312,6 +12352,11 @@ function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM) {
|
|
|
12312
12352
|
attribute float trailAlpha;
|
|
12313
12353
|
attribute float fullAlpha;
|
|
12314
12354
|
varying float vAlpha;
|
|
12355
|
+
#ifdef DASHED
|
|
12356
|
+
attribute float lineDistance;
|
|
12357
|
+
varying float vDistW;
|
|
12358
|
+
varying float vW;
|
|
12359
|
+
#endif
|
|
12315
12360
|
void main() {
|
|
12316
12361
|
vAlpha = mix(trailAlpha, fullAlpha, uShowFull);
|
|
12317
12362
|
vec3 currRel = position + uCenterOffset;
|
|
@@ -12328,6 +12373,13 @@ function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM) {
|
|
|
12328
12373
|
vec2 perp = vec2(-dirN.y, dirN.x) * side * uLineWidth * 0.5;
|
|
12329
12374
|
vec2 offsetNDC = perp / (uResolution * 0.5);
|
|
12330
12375
|
gl_Position = vec4((currNDC + offsetNDC) * currClip.w, currClip.zw);
|
|
12376
|
+
#ifdef DASHED
|
|
12377
|
+
// Carried times w and divided back out per fragment, which undoes
|
|
12378
|
+
// the perspective a varying is interpolated with: the dashes are
|
|
12379
|
+
// even on screen however much nearer one end is.
|
|
12380
|
+
vDistW = lineDistance * currClip.w;
|
|
12381
|
+
vW = currClip.w;
|
|
12382
|
+
#endif
|
|
12331
12383
|
#include <logdepthbuf_vertex>
|
|
12332
12384
|
}
|
|
12333
12385
|
`,
|
|
@@ -12337,7 +12389,15 @@ function makeFatTrailMaterial(color, lineWidth, brightness = TRAIL_DIM) {
|
|
|
12337
12389
|
uniform float uAlphaMultiplier;
|
|
12338
12390
|
uniform float uAlphaMin;
|
|
12339
12391
|
varying float vAlpha;
|
|
12392
|
+
#ifdef DASHED
|
|
12393
|
+
uniform vec2 uDash;
|
|
12394
|
+
varying float vDistW;
|
|
12395
|
+
varying float vW;
|
|
12396
|
+
#endif
|
|
12340
12397
|
void main() {
|
|
12398
|
+
#ifdef DASHED
|
|
12399
|
+
if (mod(vDistW / vW, uDash.x + uDash.y) > uDash.x) discard;
|
|
12400
|
+
#endif
|
|
12341
12401
|
gl_FragColor = vec4(uColor, clamp(max(vAlpha * uAlphaMultiplier, uAlphaMin), 0.0, 1.0));
|
|
12342
12402
|
#include <logdepthbuf_fragment>
|
|
12343
12403
|
}
|
|
@@ -12385,6 +12445,7 @@ var WebGLUnavailableError = class extends Error {
|
|
|
12385
12445
|
function bootThree(canvas, labelContainer, ctx) {
|
|
12386
12446
|
let renderer;
|
|
12387
12447
|
const reversedDepth = probeClipControl();
|
|
12448
|
+
if (!reversedDepth) installLogDepthChunks();
|
|
12388
12449
|
try {
|
|
12389
12450
|
renderer = new WebGLRenderer(reversedDepth ? {
|
|
12390
12451
|
canvas,
|
|
@@ -14142,7 +14203,7 @@ function cullOverlappingLabels(bodyObjects, screenWidth, screenHeight, camera, f
|
|
|
14142
14203
|
c.isCapped = body.data.objectType === ObjectType.MOON ? ctx.visibility.getMoonVisibility(body) === VISIBILITY.CAPPED : false;
|
|
14143
14204
|
c.isMinor = bo.isMinor;
|
|
14144
14205
|
c.isFocused = isFocused;
|
|
14145
|
-
c.isSelected = isFocused || isHovered;
|
|
14206
|
+
c.isSelected = isFocused || isHovered || ctx.visibility.isPinned(body.data.id);
|
|
14146
14207
|
c.dist = bo.cachedDist;
|
|
14147
14208
|
}
|
|
14148
14209
|
_candidates.length = _candidatesActive;
|
|
@@ -15260,7 +15321,7 @@ var FRAGMENT_SHADER = `
|
|
|
15260
15321
|
if (hitGeom && fwd > 1e-4) {
|
|
15261
15322
|
float terrainW = uReversedDepth > 0.5
|
|
15262
15323
|
? uCameraNear * uCameraFar / (d * (uCameraFar - uCameraNear) + uCameraNear)
|
|
15263
|
-
:
|
|
15324
|
+
: ${logDepthToEyeGlsl("d", "uCameraFar")};
|
|
15264
15325
|
float tTerrain = terrainW * dLen / (uPlanetRadiusScene * fwd);
|
|
15265
15326
|
if (tTerrain < tEnd) {
|
|
15266
15327
|
tEnd = tTerrain;
|
|
@@ -17768,10 +17829,18 @@ function buildThinLineFromArrays(posArr, trailAlphas, fullAlphas, total, color)
|
|
|
17768
17829
|
line.renderOrder = TRAIL_RENDER_ORDER;
|
|
17769
17830
|
return line;
|
|
17770
17831
|
}
|
|
17771
|
-
function
|
|
17832
|
+
function writeLineDistances(geometry, src, n) {
|
|
17833
|
+
const attr = geometry.getAttribute("lineDistance");
|
|
17834
|
+
const arr = attr.array;
|
|
17835
|
+
const m = Math.min(n, arr.length / 2);
|
|
17836
|
+
for (let i = 0; i < m; i++) arr[2 * i] = arr[2 * i + 1] = src[i];
|
|
17837
|
+
attr.needsUpdate = true;
|
|
17838
|
+
}
|
|
17839
|
+
function buildFatLineFromThin(capacity, posArr, trailAlphas, fullAlphas, total, color, lineWidth, brightness, dash) {
|
|
17772
17840
|
const geometry = makeFatTrailGeometry(capacity);
|
|
17841
|
+
if (dash) geometry.setAttribute("lineDistance", new Float32BufferAttribute(new Float32Array(2 * capacity), 1));
|
|
17773
17842
|
writeFatTrailVertices(geometry, posArr, trailAlphas, fullAlphas, total);
|
|
17774
|
-
const mesh = new Mesh(geometry, makeFatTrailMaterial(color, lineWidth, brightness));
|
|
17843
|
+
const mesh = new Mesh(geometry, makeFatTrailMaterial(color, lineWidth, brightness, dash));
|
|
17775
17844
|
mesh.matrixAutoUpdate = false;
|
|
17776
17845
|
mesh.renderOrder = TRAIL_RENDER_ORDER;
|
|
17777
17846
|
return mesh;
|
|
@@ -20183,7 +20252,7 @@ function updateBodyVisibility(bodyObjects, camera, ctx, focusTruePos, focusedBod
|
|
|
20183
20252
|
isClose = !subPixel;
|
|
20184
20253
|
showLabel = !isClose;
|
|
20185
20254
|
}
|
|
20186
|
-
if (bo.isMinor && !isFocused && trail) trail.visible = false;
|
|
20255
|
+
if (bo.isMinor && !isFocused && trail && !ctx.visibility.isPinned(body.data.id)) trail.visible = false;
|
|
20187
20256
|
if (suppressHeliocentricTrails && trail?.visible) {
|
|
20188
20257
|
const oc = trail.userData.orbitCenter;
|
|
20189
20258
|
if (oc && oc.distanceToSquared(_focusV3.set(fp[0], fp[1], fp[2])) > HELIO_CENTER_DIST_SQ) trail.visible = false;
|
|
@@ -21387,6 +21456,18 @@ function updatePositions(params) {
|
|
|
21387
21456
|
ctx.bodies.hostRead.delete(id);
|
|
21388
21457
|
return false;
|
|
21389
21458
|
};
|
|
21459
|
+
const elementRowOffset = (body, parentPos) => {
|
|
21460
|
+
const row = ctx.bodies.elementRow(body);
|
|
21461
|
+
const rowParentPos = row && positionMap.get(row.parentId);
|
|
21462
|
+
if (!rowParentPos) return null;
|
|
21463
|
+
const offset = row.q != null ? parabolicToPositionJD(row, jd) : orbitalElementsToPositionJD(row, jd);
|
|
21464
|
+
if (!offset) return null;
|
|
21465
|
+
return [
|
|
21466
|
+
rowParentPos[0] - parentPos[0] + offset[0],
|
|
21467
|
+
rowParentPos[1] - parentPos[1] + offset[1],
|
|
21468
|
+
rowParentPos[2] - parentPos[2] + offset[2]
|
|
21469
|
+
];
|
|
21470
|
+
};
|
|
21390
21471
|
const computePosition = (body) => {
|
|
21391
21472
|
if (computed.has(body.data.id)) return;
|
|
21392
21473
|
computed.add(body.data.id);
|
|
@@ -21447,7 +21528,7 @@ function updatePositions(params) {
|
|
|
21447
21528
|
let y;
|
|
21448
21529
|
let z;
|
|
21449
21530
|
if (isChebTracked) {
|
|
21450
|
-
const chebOffset = ctx.chebStore.positionScene(d.id, jd);
|
|
21531
|
+
const chebOffset = ctx.chebStore.positionScene(d.id, jd) ?? elementRowOffset(body, parentPos);
|
|
21451
21532
|
if (!chebOffset) {
|
|
21452
21533
|
hide(true);
|
|
21453
21534
|
const coverage = ctx.chebStore.zoneCoverage(d.id);
|
|
@@ -22732,6 +22813,8 @@ var PromotionRegistry = class {
|
|
|
22732
22813
|
defaults = /* @__PURE__ */ new Set();
|
|
22733
22814
|
userPromoted = /* @__PURE__ */ new Set();
|
|
22734
22815
|
autoPromoted = /* @__PURE__ */ new Set();
|
|
22816
|
+
pinned = /* @__PURE__ */ new Set();
|
|
22817
|
+
pinPromoted = /* @__PURE__ */ new Set();
|
|
22735
22818
|
groupTargets = null;
|
|
22736
22819
|
groupMode = "none";
|
|
22737
22820
|
smallBodyZone = null;
|
|
@@ -22741,6 +22824,7 @@ var PromotionRegistry = class {
|
|
|
22741
22824
|
this.deps = deps;
|
|
22742
22825
|
deps.ctx.bodies.onBodiesAdded(() => {
|
|
22743
22826
|
this.onBodiesAdded();
|
|
22827
|
+
this.buildPinned();
|
|
22744
22828
|
this.autoPromoteAsteroidMoons();
|
|
22745
22829
|
this.reevaluateEarthSatMode();
|
|
22746
22830
|
if (this.smallBodyZone !== null) this.refreshSmallBodyEmphasis();
|
|
@@ -22930,6 +23014,31 @@ var PromotionRegistry = class {
|
|
|
22930
23014
|
if (toRemove.length === 0) return;
|
|
22931
23015
|
this.tearDownBodies(toRemove, this.autoPromoted);
|
|
22932
23016
|
}
|
|
23017
|
+
setPinned(ids) {
|
|
23018
|
+
this.pinned = new Set(ids);
|
|
23019
|
+
const focusedId = this.deps.getFocusedId();
|
|
23020
|
+
const dropped = [...this.pinPromoted].filter((id) => !this.pinned.has(id));
|
|
23021
|
+
if (focusedId && dropped.includes(focusedId)) {
|
|
23022
|
+
this.pinPromoted.delete(focusedId);
|
|
23023
|
+
this.userPromoted.add(focusedId);
|
|
23024
|
+
this.emitUserPromotedCount();
|
|
23025
|
+
}
|
|
23026
|
+
this.tearDownBodies(dropped.filter((id) => id !== focusedId), this.pinPromoted);
|
|
23027
|
+
this.buildPinned();
|
|
23028
|
+
}
|
|
23029
|
+
buildPinned() {
|
|
23030
|
+
let built = false;
|
|
23031
|
+
for (const id of this.pinned) {
|
|
23032
|
+
const body = this.deps.ctx.getBody(id);
|
|
23033
|
+
if (!body || isSurfaceFeature(body) || body.data.objectType === ObjectType.MOON) continue;
|
|
23034
|
+
if (!this.buildBodyInstance(body)) continue;
|
|
23035
|
+
built = true;
|
|
23036
|
+
if (this.userPromoted.delete(id)) this.pinPromoted.add(id);
|
|
23037
|
+
}
|
|
23038
|
+
if (!built) return;
|
|
23039
|
+
this.emitUserPromotedCount();
|
|
23040
|
+
this.finalizeBuilds();
|
|
23041
|
+
}
|
|
22933
23042
|
clearUserPromoted() {
|
|
22934
23043
|
const focusedId = this.deps.getFocusedId();
|
|
22935
23044
|
const toRemove = [...this.userPromoted].filter((id) => id !== focusedId);
|
|
@@ -23419,10 +23528,7 @@ function rotateByQuaternion(q, x, y, z, out, at) {
|
|
|
23419
23528
|
function bodyCentre(body, ctx, jd) {
|
|
23420
23529
|
return placeForRead(body, jd, ctx) ? body.position : null;
|
|
23421
23530
|
}
|
|
23422
|
-
function
|
|
23423
|
-
const body = ctx.getBody(anchor.body);
|
|
23424
|
-
const centre = body && bodyCentre(body, ctx, jd);
|
|
23425
|
-
if (!centre) return null;
|
|
23531
|
+
function placeAnchor(anchor, body, centre, jd) {
|
|
23426
23532
|
const [cx, cy, cz] = centre;
|
|
23427
23533
|
if (isSurface(anchor)) {
|
|
23428
23534
|
const distance = kmToScene(effectiveRadiusKm(body.data) + (anchor.altitudeKm ?? 0));
|
|
@@ -23459,6 +23565,11 @@ function resolveAnchor(anchor, ctx, jd) {
|
|
|
23459
23565
|
cz + oz
|
|
23460
23566
|
];
|
|
23461
23567
|
}
|
|
23568
|
+
function resolveAnchor(anchor, ctx, jd) {
|
|
23569
|
+
const body = ctx.getBody(anchor.body);
|
|
23570
|
+
const centre = body && bodyCentre(body, ctx, jd);
|
|
23571
|
+
return centre ? placeAnchor(anchor, body, centre, jd) : null;
|
|
23572
|
+
}
|
|
23462
23573
|
function anchorNormal(anchor, world, ctx, jd) {
|
|
23463
23574
|
const body = ctx.getBody(anchor.body);
|
|
23464
23575
|
const centre = body && bodyCentre(body, ctx, jd);
|
|
@@ -24866,6 +24977,10 @@ var SceneRenderer = class SceneRenderer {
|
|
|
24866
24977
|
setBodyAppearance(id, appearance) {
|
|
24867
24978
|
this.appearances.set(id, appearance);
|
|
24868
24979
|
}
|
|
24980
|
+
setPinnedBodies(ids) {
|
|
24981
|
+
this.ctx.visibility.setPinned(ids);
|
|
24982
|
+
this.focusController.promotion.setPinned(ids);
|
|
24983
|
+
}
|
|
24869
24984
|
setNorthReference(id) {
|
|
24870
24985
|
this.cameraUp.setNorthReference(id);
|
|
24871
24986
|
}
|
|
@@ -25484,6 +25599,153 @@ var MarkerExtension = class {
|
|
|
25484
25599
|
}
|
|
25485
25600
|
};
|
|
25486
25601
|
|
|
25602
|
+
//#endregion
|
|
25603
|
+
//#region src/lib/scene/extensions/screen.ts
|
|
25604
|
+
var REACH = 3;
|
|
25605
|
+
var right = new Vector3();
|
|
25606
|
+
var up = new Vector3();
|
|
25607
|
+
var forward = new Vector3();
|
|
25608
|
+
function parseDash(pattern) {
|
|
25609
|
+
const [dash, gap = dash] = (pattern ?? "").split(/[\s,]+/).filter(Boolean).map(Number);
|
|
25610
|
+
return dash > 0 && gap > 0 ? [dash, gap] : null;
|
|
25611
|
+
}
|
|
25612
|
+
function aim(camera, viewportPx) {
|
|
25613
|
+
right.set(1, 0, 0).applyQuaternion(camera.quaternion);
|
|
25614
|
+
up.set(0, 1, 0).applyQuaternion(camera.quaternion);
|
|
25615
|
+
forward.set(0, 0, -1).applyQuaternion(camera.quaternion);
|
|
25616
|
+
return viewportPx / (2 * Math.tan(camera.getEffectiveFOV() * Math.PI / 360));
|
|
25617
|
+
}
|
|
25618
|
+
function view(points, i, camera, out) {
|
|
25619
|
+
const x = points[i * 3] - camera.position.x;
|
|
25620
|
+
const y = points[i * 3 + 1] - camera.position.y;
|
|
25621
|
+
const z = points[i * 3 + 2] - camera.position.z;
|
|
25622
|
+
out[0] = x * right.x + y * right.y + z * right.z;
|
|
25623
|
+
out[1] = x * up.x + y * up.y + z * up.z;
|
|
25624
|
+
out[2] = x * forward.x + y * forward.y + z * forward.z;
|
|
25625
|
+
}
|
|
25626
|
+
function reachesBehind(points, count, camera) {
|
|
25627
|
+
forward.set(0, 0, -1).applyQuaternion(camera.quaternion);
|
|
25628
|
+
const { x, y, z } = camera.position;
|
|
25629
|
+
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;
|
|
25630
|
+
return false;
|
|
25631
|
+
}
|
|
25632
|
+
function screenLengths(points, count, camera, viewportPx, out) {
|
|
25633
|
+
const focal = aim(camera, viewportPx);
|
|
25634
|
+
const at = [
|
|
25635
|
+
0,
|
|
25636
|
+
0,
|
|
25637
|
+
0
|
|
25638
|
+
];
|
|
25639
|
+
let length = 0;
|
|
25640
|
+
let lastX = 0;
|
|
25641
|
+
let lastY = 0;
|
|
25642
|
+
let seen = false;
|
|
25643
|
+
for (let i = 0; i < count; i++) {
|
|
25644
|
+
view(points, i, camera, at);
|
|
25645
|
+
if (at[2] > camera.near) {
|
|
25646
|
+
const px = at[0] / at[2] * focal;
|
|
25647
|
+
const py = at[1] / at[2] * focal;
|
|
25648
|
+
if (seen) length += Math.hypot(px - lastX, py - lastY);
|
|
25649
|
+
lastX = px;
|
|
25650
|
+
lastY = py;
|
|
25651
|
+
seen = true;
|
|
25652
|
+
}
|
|
25653
|
+
out[i] = length;
|
|
25654
|
+
}
|
|
25655
|
+
}
|
|
25656
|
+
var SeenLine = class {
|
|
25657
|
+
points = new Float32Array(0);
|
|
25658
|
+
alphas = new Float32Array(0);
|
|
25659
|
+
lengths = new Float32Array(0);
|
|
25660
|
+
count = 0;
|
|
25661
|
+
a = [
|
|
25662
|
+
0,
|
|
25663
|
+
0,
|
|
25664
|
+
0
|
|
25665
|
+
];
|
|
25666
|
+
b = [
|
|
25667
|
+
0,
|
|
25668
|
+
0,
|
|
25669
|
+
0
|
|
25670
|
+
];
|
|
25671
|
+
see(points, alphas, count, camera, viewportPx) {
|
|
25672
|
+
if (this.alphas.length < count * 4) {
|
|
25673
|
+
this.points = new Float32Array(count * 12);
|
|
25674
|
+
this.alphas = new Float32Array(count * 4);
|
|
25675
|
+
this.lengths = new Float32Array(count * 4);
|
|
25676
|
+
}
|
|
25677
|
+
this.count = 0;
|
|
25678
|
+
const focal = aim(camera, viewportPx);
|
|
25679
|
+
const halfW = viewportPx * camera.aspect * REACH / 2;
|
|
25680
|
+
const halfH = viewportPx * REACH / 2;
|
|
25681
|
+
const near = camera.near * 2;
|
|
25682
|
+
let { a, b } = this;
|
|
25683
|
+
let joined = false;
|
|
25684
|
+
let length = 0;
|
|
25685
|
+
let lastX = 0;
|
|
25686
|
+
let lastY = 0;
|
|
25687
|
+
if (count > 0) view(points, 0, camera, a);
|
|
25688
|
+
for (let i = 0; i + 1 < count; i++, [a, b] = [b, a]) {
|
|
25689
|
+
view(points, i + 1, camera, b);
|
|
25690
|
+
let from = 0;
|
|
25691
|
+
let to = 1;
|
|
25692
|
+
for (let plane = 0; plane < 5 && from <= to; plane++) {
|
|
25693
|
+
const ga = edge(plane, a, focal, halfW, halfH, near);
|
|
25694
|
+
const gb = edge(plane, b, focal, halfW, halfH, near);
|
|
25695
|
+
if (ga < 0 && gb < 0) to = -1;
|
|
25696
|
+
else if (ga < 0) from = Math.max(from, ga / (ga - gb));
|
|
25697
|
+
else if (gb < 0) to = Math.min(to, ga / (ga - gb));
|
|
25698
|
+
}
|
|
25699
|
+
if (from > to) {
|
|
25700
|
+
joined = false;
|
|
25701
|
+
continue;
|
|
25702
|
+
}
|
|
25703
|
+
const depth = a[2] + (b[2] - a[2]) * from;
|
|
25704
|
+
const x = (a[0] + (b[0] - a[0]) * from) / depth * focal;
|
|
25705
|
+
const y = (a[1] + (b[1] - a[1]) * from) / depth * focal;
|
|
25706
|
+
if (!joined || from > 0) {
|
|
25707
|
+
if (this.count > 0) {
|
|
25708
|
+
this.copy(this.count - 1, 0);
|
|
25709
|
+
this.put(points, alphas, i, from, length, 0);
|
|
25710
|
+
}
|
|
25711
|
+
this.put(points, alphas, i, from, length, 1);
|
|
25712
|
+
lastX = x;
|
|
25713
|
+
lastY = y;
|
|
25714
|
+
}
|
|
25715
|
+
const endDepth = a[2] + (b[2] - a[2]) * to;
|
|
25716
|
+
const endX = (a[0] + (b[0] - a[0]) * to) / endDepth * focal;
|
|
25717
|
+
const endY = (a[1] + (b[1] - a[1]) * to) / endDepth * focal;
|
|
25718
|
+
length += Math.hypot(endX - lastX, endY - lastY);
|
|
25719
|
+
lastX = endX;
|
|
25720
|
+
lastY = endY;
|
|
25721
|
+
this.put(points, alphas, i, to, length, 1);
|
|
25722
|
+
joined = to === 1;
|
|
25723
|
+
}
|
|
25724
|
+
}
|
|
25725
|
+
put(points, alphas, i, t, length, shown) {
|
|
25726
|
+
const at = this.count++;
|
|
25727
|
+
for (let k = 0; k < 3; k++) {
|
|
25728
|
+
const from = points[i * 3 + k];
|
|
25729
|
+
this.points[at * 3 + k] = from + (points[i * 3 + 3 + k] - from) * t;
|
|
25730
|
+
}
|
|
25731
|
+
this.alphas[at] = (alphas[i] + (alphas[i + 1] - alphas[i]) * t) * shown;
|
|
25732
|
+
this.lengths[at] = length;
|
|
25733
|
+
}
|
|
25734
|
+
copy(from, shown) {
|
|
25735
|
+
const at = this.count++;
|
|
25736
|
+
this.points.copyWithin(at * 3, from * 3, from * 3 + 3);
|
|
25737
|
+
this.alphas[at] = this.alphas[from] * shown;
|
|
25738
|
+
this.lengths[at] = this.lengths[from];
|
|
25739
|
+
}
|
|
25740
|
+
};
|
|
25741
|
+
function edge(plane, at, focal, halfW, halfH, near) {
|
|
25742
|
+
if (plane === 0) return at[2] - near;
|
|
25743
|
+
if (plane === 1) return halfW * at[2] - focal * at[0];
|
|
25744
|
+
if (plane === 2) return halfW * at[2] + focal * at[0];
|
|
25745
|
+
if (plane === 3) return halfH * at[2] - focal * at[1];
|
|
25746
|
+
return halfH * at[2] + focal * at[1];
|
|
25747
|
+
}
|
|
25748
|
+
|
|
25487
25749
|
//#endregion
|
|
25488
25750
|
//#region src/lib/scene/extensions/polyline.ts
|
|
25489
25751
|
var REDRAW_EPSILON$1 = 1e-9;
|
|
@@ -25493,6 +25755,7 @@ var PolylineExtension = class {
|
|
|
25493
25755
|
color;
|
|
25494
25756
|
widthPx;
|
|
25495
25757
|
opacity;
|
|
25758
|
+
dash;
|
|
25496
25759
|
fade;
|
|
25497
25760
|
closed;
|
|
25498
25761
|
local;
|
|
@@ -25500,6 +25763,7 @@ var PolylineExtension = class {
|
|
|
25500
25763
|
mesh = null;
|
|
25501
25764
|
scratch = new Float32Array(0);
|
|
25502
25765
|
alphas = new Float32Array(0);
|
|
25766
|
+
seen = new SeenLine();
|
|
25503
25767
|
capacity = 0;
|
|
25504
25768
|
lastOrigin = [
|
|
25505
25769
|
0,
|
|
@@ -25514,6 +25778,7 @@ var PolylineExtension = class {
|
|
|
25514
25778
|
this.color = options.color ?? "#ffffff";
|
|
25515
25779
|
this.widthPx = options.widthPx ?? 2;
|
|
25516
25780
|
this.opacity = options.opacity ?? 1;
|
|
25781
|
+
this.dash = parseDash(options.dash);
|
|
25517
25782
|
this.fade = options.fade ?? false;
|
|
25518
25783
|
this.closed = options.closed ?? false;
|
|
25519
25784
|
this.local = new Float64Array(0);
|
|
@@ -25534,6 +25799,10 @@ var PolylineExtension = class {
|
|
|
25534
25799
|
}
|
|
25535
25800
|
if (count > points.length) this.local.copyWithin(points.length * 3, 0, 3);
|
|
25536
25801
|
this.count = count;
|
|
25802
|
+
if (this.alphas.length < count) {
|
|
25803
|
+
this.scratch = new Float32Array(count * 3);
|
|
25804
|
+
this.alphas = new Float32Array(count);
|
|
25805
|
+
}
|
|
25537
25806
|
if (count > this.capacity) this.rebuild(count);
|
|
25538
25807
|
this.fillAlphas();
|
|
25539
25808
|
this.dirty = true;
|
|
@@ -25552,38 +25821,35 @@ var PolylineExtension = class {
|
|
|
25552
25821
|
this.removeSelf?.();
|
|
25553
25822
|
this.removeSelf = null;
|
|
25554
25823
|
}
|
|
25555
|
-
update({ jd, basis, camera, ctx }) {
|
|
25556
|
-
const mesh = this.mesh;
|
|
25557
|
-
if (!mesh) return;
|
|
25824
|
+
update({ jd, basis, camera, viewportPx, ctx }) {
|
|
25558
25825
|
const world = this.wanted && this.count >= 2 ? resolveAnchor(this.anchor, ctx, jd) : null;
|
|
25559
|
-
mesh.visible = world !== null;
|
|
25560
|
-
if (!world) return;
|
|
25826
|
+
if (this.mesh) this.mesh.visible = world !== null;
|
|
25827
|
+
if (!this.mesh || !world) return;
|
|
25561
25828
|
const origin = [
|
|
25562
25829
|
world[0] - basis[0],
|
|
25563
25830
|
world[1] - basis[1],
|
|
25564
25831
|
world[2] - basis[2]
|
|
25565
25832
|
];
|
|
25566
|
-
|
|
25567
|
-
|
|
25833
|
+
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;
|
|
25834
|
+
if (moved) {
|
|
25835
|
+
for (let i = 0; i < this.count * 3; i++) this.scratch[i] = this.local[i] + origin[i % 3];
|
|
25568
25836
|
this.lastOrigin = origin;
|
|
25569
|
-
this.dirty = false;
|
|
25570
25837
|
}
|
|
25571
|
-
|
|
25572
|
-
|
|
25573
|
-
|
|
25574
|
-
|
|
25575
|
-
|
|
25576
|
-
this.
|
|
25577
|
-
this.
|
|
25578
|
-
}
|
|
25579
|
-
|
|
25838
|
+
const cut = this.dash !== null || reachesBehind(this.scratch, this.count, camera);
|
|
25839
|
+
if (cut) {
|
|
25840
|
+
const { seen } = this;
|
|
25841
|
+
seen.see(this.scratch, this.alphas, this.count, camera, viewportPx);
|
|
25842
|
+
if (seen.count > this.capacity) this.rebuild(seen.count);
|
|
25843
|
+
writeFatTrailVertices(this.mesh.geometry, seen.points, seen.alphas, seen.alphas, seen.count);
|
|
25844
|
+
if (this.dash) writeLineDistances(this.mesh.geometry, seen.lengths, seen.count);
|
|
25845
|
+
} else if (moved) writeFatTrailVertices(this.mesh.geometry, this.scratch, this.alphas, this.alphas, this.count);
|
|
25846
|
+
this.dirty = cut;
|
|
25847
|
+
this.mesh.material.uniforms.uCenterOffset.value.copy(camera.position).negate();
|
|
25580
25848
|
}
|
|
25581
25849
|
rebuild(capacity) {
|
|
25582
25850
|
this.disposeMesh();
|
|
25583
25851
|
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);
|
|
25852
|
+
const mesh = buildFatLineFromThin(capacity, this.scratch, this.alphas, this.alphas, 0, this.color, this.widthPx, 1, this.dash ?? void 0);
|
|
25587
25853
|
mesh.frustumCulled = false;
|
|
25588
25854
|
this.object.add(mesh);
|
|
25589
25855
|
this.mesh = mesh;
|
|
@@ -26772,6 +27038,7 @@ var SurfaceShapeExtension = class {
|
|
|
26772
27038
|
color;
|
|
26773
27039
|
widthPx;
|
|
26774
27040
|
opacity;
|
|
27041
|
+
dash;
|
|
26775
27042
|
fillColor;
|
|
26776
27043
|
fillOpacity;
|
|
26777
27044
|
dirs = new Float64Array(0);
|
|
@@ -26779,6 +27046,7 @@ var SurfaceShapeExtension = class {
|
|
|
26779
27046
|
line = null;
|
|
26780
27047
|
scratch = new Float32Array(0);
|
|
26781
27048
|
alphas = new Float32Array(0);
|
|
27049
|
+
lengths = new Float32Array(0);
|
|
26782
27050
|
fanDirs = new Float64Array(0);
|
|
26783
27051
|
fill = null;
|
|
26784
27052
|
fillScratch = new Float32Array(0);
|
|
@@ -26798,6 +27066,7 @@ var SurfaceShapeExtension = class {
|
|
|
26798
27066
|
this.color = options.color ?? "#ffffff";
|
|
26799
27067
|
this.widthPx = options.widthPx ?? 2;
|
|
26800
27068
|
this.opacity = options.opacity ?? 1;
|
|
27069
|
+
this.dash = parseDash(options.dash);
|
|
26801
27070
|
this.fillColor = options.fill ?? null;
|
|
26802
27071
|
this.fillOpacity = options.fillOpacity ?? .25;
|
|
26803
27072
|
this.object.matrixAutoUpdate = false;
|
|
@@ -26830,7 +27099,7 @@ var SurfaceShapeExtension = class {
|
|
|
26830
27099
|
this.removeSelf?.();
|
|
26831
27100
|
this.removeSelf = null;
|
|
26832
27101
|
}
|
|
26833
|
-
update({ jd, basis, camera, ctx }) {
|
|
27102
|
+
update({ jd, basis, camera, viewportPx, ctx }) {
|
|
26834
27103
|
const body = this.wanted && this.count >= 2 ? ctx.getBody(this.body) : void 0;
|
|
26835
27104
|
const centre = body && bodyCentre(body, ctx, jd);
|
|
26836
27105
|
if (this.line) this.line.visible = !!centre;
|
|
@@ -26847,6 +27116,10 @@ var SurfaceShapeExtension = class {
|
|
|
26847
27116
|
if (this.line) {
|
|
26848
27117
|
this.place(this.dirs, this.count, q, scale, origin, this.scratch);
|
|
26849
27118
|
writeFatTrailVertices(this.line.geometry, this.scratch, this.alphas, this.alphas, this.count);
|
|
27119
|
+
if (this.dash) {
|
|
27120
|
+
screenLengths(this.scratch, this.count, camera, viewportPx, this.lengths);
|
|
27121
|
+
writeLineDistances(this.line.geometry, this.lengths, this.count);
|
|
27122
|
+
}
|
|
26850
27123
|
this.line.material.uniforms.uCenterOffset.value.copy(camera.position).negate();
|
|
26851
27124
|
}
|
|
26852
27125
|
if (this.fill) {
|
|
@@ -26875,7 +27148,8 @@ var SurfaceShapeExtension = class {
|
|
|
26875
27148
|
if (this.count < 2 || this.widthPx <= 0) return;
|
|
26876
27149
|
this.scratch = new Float32Array(this.count * 3);
|
|
26877
27150
|
this.alphas = new Float32Array(this.count).fill(this.opacity);
|
|
26878
|
-
|
|
27151
|
+
this.lengths = new Float32Array(this.count);
|
|
27152
|
+
const line = buildFatLineFromThin(this.count, this.scratch, this.alphas, this.alphas, this.count, this.color, this.widthPx, 1, this.dash ?? void 0);
|
|
26879
27153
|
line.frustumCulled = false;
|
|
26880
27154
|
line.renderOrder = SURFACE_RENDER_ORDER;
|
|
26881
27155
|
this.object.add(line);
|
|
@@ -27088,13 +27362,7 @@ function anchorDistanceKm(a, b, ctx, jd) {
|
|
|
27088
27362
|
const offset = anchorOffsetKm(a, b, ctx, jd);
|
|
27089
27363
|
return offset && Math.hypot(...offset);
|
|
27090
27364
|
}
|
|
27091
|
-
function
|
|
27092
|
-
const body = ctx.getBody(id);
|
|
27093
|
-
const sun = ctx.getBody(SUN_ID);
|
|
27094
|
-
if (!body || !sun || body === sun) return null;
|
|
27095
|
-
if (!body.orientation && !ctx.bodies.orientationRead.has(id)) return null;
|
|
27096
|
-
const centre = bodyCentre(body, ctx, jd);
|
|
27097
|
-
if (!centre) return null;
|
|
27365
|
+
function subsolarAt(body, centre, sun, jd) {
|
|
27098
27366
|
const turn = body.orientation ? bodyQuaternion(body.orientation, jd, body.nutPrec).toArray() : [
|
|
27099
27367
|
0,
|
|
27100
27368
|
0,
|
|
@@ -27102,9 +27370,9 @@ function subsolarPoint(id, ctx, jd) {
|
|
|
27102
27370
|
1
|
|
27103
27371
|
];
|
|
27104
27372
|
const { latitude, longitude, distance } = cartesianToSpherical([
|
|
27105
|
-
sun
|
|
27106
|
-
sun
|
|
27107
|
-
sun
|
|
27373
|
+
sun[0],
|
|
27374
|
+
sun[1],
|
|
27375
|
+
sun[2]
|
|
27108
27376
|
], [
|
|
27109
27377
|
centre[0],
|
|
27110
27378
|
centre[1],
|
|
@@ -27115,6 +27383,14 @@ function subsolarPoint(id, ctx, jd) {
|
|
|
27115
27383
|
lat: latitude
|
|
27116
27384
|
} : null;
|
|
27117
27385
|
}
|
|
27386
|
+
function subsolarPoint$1(id, ctx, jd) {
|
|
27387
|
+
const body = ctx.getBody(id);
|
|
27388
|
+
const sun = ctx.getBody(SUN_ID);
|
|
27389
|
+
if (!body || !sun || body === sun) return null;
|
|
27390
|
+
if (!body.orientation && !ctx.bodies.orientationRead.has(id)) return null;
|
|
27391
|
+
const centre = bodyCentre(body, ctx, jd);
|
|
27392
|
+
return centre && subsolarAt(body, centre, sun.position, jd);
|
|
27393
|
+
}
|
|
27118
27394
|
|
|
27119
27395
|
//#endregion
|
|
27120
27396
|
//#region src/lib/interaction/gesture.ts
|
|
@@ -27434,7 +27710,7 @@ var SpaceMap = class {
|
|
|
27434
27710
|
return anchorOffsetKm(from, to, this.ctx, this.placedJd);
|
|
27435
27711
|
}
|
|
27436
27712
|
getSubsolarPoint(id) {
|
|
27437
|
-
return subsolarPoint(id, this.ctx, this.placedJd);
|
|
27713
|
+
return subsolarPoint$1(id, this.ctx, this.placedJd);
|
|
27438
27714
|
}
|
|
27439
27715
|
load(targetId = this.initialView.id) {
|
|
27440
27716
|
return this.ctx.load(jdToDate(this.clock.jd), targetId);
|
|
@@ -27914,6 +28190,10 @@ var SpaceMap = class {
|
|
|
27914
28190
|
this.requireRenderer().setBodyAppearance(id, appearance);
|
|
27915
28191
|
return this;
|
|
27916
28192
|
}
|
|
28193
|
+
setPinnedBodies(ids) {
|
|
28194
|
+
this.requireRenderer().setPinnedBodies(ids);
|
|
28195
|
+
return this;
|
|
28196
|
+
}
|
|
27917
28197
|
capRadiusDeg(options) {
|
|
27918
28198
|
if (options.radiusDeg !== void 0) return options.radiusDeg;
|
|
27919
28199
|
const bodyRadiusKm = this.getBody(options.body)?.radiusKm;
|
|
@@ -31979,6 +32259,158 @@ function kmToAu(km) {
|
|
|
31979
32259
|
return km / AU_KM;
|
|
31980
32260
|
}
|
|
31981
32261
|
|
|
32262
|
+
//#endregion
|
|
32263
|
+
//#region src/lib/scene/extensions/ephemeris.ts
|
|
32264
|
+
var chebyshev = null;
|
|
32265
|
+
var queue = Promise.resolve();
|
|
32266
|
+
function inTurn(read) {
|
|
32267
|
+
const turn = queue.then(read, read);
|
|
32268
|
+
queue = turn.catch(() => {});
|
|
32269
|
+
return turn;
|
|
32270
|
+
}
|
|
32271
|
+
async function open(date) {
|
|
32272
|
+
const jd = dateToJD(date);
|
|
32273
|
+
const metadata = await fetchMetadata();
|
|
32274
|
+
if (!chebyshev) {
|
|
32275
|
+
const params = chebyshevZoneParams(metadata);
|
|
32276
|
+
if (params.size > 0) chebyshev = new ChebyshevStore(params);
|
|
32277
|
+
}
|
|
32278
|
+
try {
|
|
32279
|
+
await chebyshev?.ensure(jd).done;
|
|
32280
|
+
} catch (error) {
|
|
32281
|
+
chebyshev = null;
|
|
32282
|
+
throw error;
|
|
32283
|
+
}
|
|
32284
|
+
return {
|
|
32285
|
+
jd,
|
|
32286
|
+
metadata,
|
|
32287
|
+
chebyshev
|
|
32288
|
+
};
|
|
32289
|
+
}
|
|
32290
|
+
function discovered(visibleFromDays, jd) {
|
|
32291
|
+
return !(visibleFromDays !== void 0 && jd - 2451545 < visibleFromDays);
|
|
32292
|
+
}
|
|
32293
|
+
async function moonRow(id, { jd, metadata }) {
|
|
32294
|
+
const zone = metadata.position.zones.moons;
|
|
32295
|
+
const zoom = zone && flatZoom(zone);
|
|
32296
|
+
if (!zoom) return null;
|
|
32297
|
+
const cols = await fetchElements("moons", null, 0, isChunkIndexed(zoom) ? String(chunkIndexForJd(zoom, jd)) : null);
|
|
32298
|
+
for (let i = 0; i < cols.rowCount; i++) if (rowId(cols, i) === id) return materializeBodyData(cols, i, /* @__PURE__ */ new Map(), "naif");
|
|
32299
|
+
return null;
|
|
32300
|
+
}
|
|
32301
|
+
function elementsOffset(data, jd) {
|
|
32302
|
+
if (!discovered(data.visibleFromDays, jd)) return null;
|
|
32303
|
+
if (jd < data.validityStart || jd > data.validityEnd) return null;
|
|
32304
|
+
if (data.satrec) return sgp4PositionScene(data.satrec, jd);
|
|
32305
|
+
if (data.q != null) return parabolicToPositionJD(data, jd);
|
|
32306
|
+
if (data.a === 0) return [
|
|
32307
|
+
0,
|
|
32308
|
+
0,
|
|
32309
|
+
0
|
|
32310
|
+
];
|
|
32311
|
+
return orbitalElementsToPositionJD(data, jd);
|
|
32312
|
+
}
|
|
32313
|
+
async function locate(id, at) {
|
|
32314
|
+
const { jd } = at;
|
|
32315
|
+
if (at.chebyshev?.has(id)) {
|
|
32316
|
+
const body = at.chebyshev.body(id, jd);
|
|
32317
|
+
if (body && !discovered(body.visibleFromDays, jd)) return null;
|
|
32318
|
+
const offset = body && chebyshevPositionScene(body, jd);
|
|
32319
|
+
if (offset) {
|
|
32320
|
+
const { radiusKm, objectType } = body;
|
|
32321
|
+
return {
|
|
32322
|
+
data: {
|
|
32323
|
+
radiusKm,
|
|
32324
|
+
objectType,
|
|
32325
|
+
orbitalSource: OrbitalSource.SPICE
|
|
32326
|
+
},
|
|
32327
|
+
parentId: `naif-${body.parentId}`,
|
|
32328
|
+
offset
|
|
32329
|
+
};
|
|
32330
|
+
}
|
|
32331
|
+
if (id.startsWith("naif-")) return null;
|
|
32332
|
+
}
|
|
32333
|
+
const data = (id.startsWith("naif-") ? await moonRow(id, at) : null) ?? bodyDataFromGlobal(id, await fetchObjectDetail(id, false));
|
|
32334
|
+
const offset = data && elementsOffset(data, jd);
|
|
32335
|
+
return offset ? {
|
|
32336
|
+
data,
|
|
32337
|
+
parentId: data.parentId,
|
|
32338
|
+
offset
|
|
32339
|
+
} : null;
|
|
32340
|
+
}
|
|
32341
|
+
async function place(id, at, above = /* @__PURE__ */ new Set()) {
|
|
32342
|
+
if (above.has(id)) return null;
|
|
32343
|
+
const own = await locate(id, at);
|
|
32344
|
+
if (!own) return null;
|
|
32345
|
+
if (own.parentId === "naif-0") return {
|
|
32346
|
+
data: own.data,
|
|
32347
|
+
centre: own.offset
|
|
32348
|
+
};
|
|
32349
|
+
const parent = await place(own.parentId, at, new Set(above).add(id));
|
|
32350
|
+
if (!parent) return null;
|
|
32351
|
+
const [x, y, z] = parent.centre;
|
|
32352
|
+
return {
|
|
32353
|
+
data: own.data,
|
|
32354
|
+
centre: [
|
|
32355
|
+
x + own.offset[0],
|
|
32356
|
+
y + own.offset[1],
|
|
32357
|
+
z + own.offset[2]
|
|
32358
|
+
]
|
|
32359
|
+
};
|
|
32360
|
+
}
|
|
32361
|
+
async function spinOf(id) {
|
|
32362
|
+
const [detail] = await Promise.all([fetchObjectDetail(id, false), loadSystemsGlobal()]);
|
|
32363
|
+
const orientation = detail.global?.orientation;
|
|
32364
|
+
const sums = detail.global?.nut_prec;
|
|
32365
|
+
const naif = /^naif-(-?\d+)$/.exec(id);
|
|
32366
|
+
const angles = naif ? getNutPrecAngles(ownerIdFor(parseInt(naif[1], 10))) : void 0;
|
|
32367
|
+
return {
|
|
32368
|
+
orientation,
|
|
32369
|
+
nutPrec: sums && angles ? {
|
|
32370
|
+
...sums,
|
|
32371
|
+
angles
|
|
32372
|
+
} : void 0
|
|
32373
|
+
};
|
|
32374
|
+
}
|
|
32375
|
+
async function resolve(anchor, at) {
|
|
32376
|
+
const placed = await place(anchor.body, at);
|
|
32377
|
+
if (!placed) return null;
|
|
32378
|
+
const spin = "latitude" in anchor ? await spinOf(anchor.body) : {};
|
|
32379
|
+
return placeAnchor(anchor, {
|
|
32380
|
+
data: placed.data,
|
|
32381
|
+
...spin
|
|
32382
|
+
}, placed.centre, at.jd);
|
|
32383
|
+
}
|
|
32384
|
+
function offsetKm(from, to, date) {
|
|
32385
|
+
return inTurn(async () => {
|
|
32386
|
+
const at = await open(date);
|
|
32387
|
+
const a = await resolve(from, at);
|
|
32388
|
+
const b = a && await resolve(to, at);
|
|
32389
|
+
return a && b ? sceneToEcliptic([
|
|
32390
|
+
b[0] - a[0],
|
|
32391
|
+
b[1] - a[1],
|
|
32392
|
+
b[2] - a[2]
|
|
32393
|
+
]) : null;
|
|
32394
|
+
});
|
|
32395
|
+
}
|
|
32396
|
+
async function distanceKm(from, to, date) {
|
|
32397
|
+
const offset = await offsetKm(from, to, date);
|
|
32398
|
+
return offset && Math.hypot(...offset);
|
|
32399
|
+
}
|
|
32400
|
+
function subsolarPoint(id, date) {
|
|
32401
|
+
return inTurn(async () => {
|
|
32402
|
+
if (id === "naif-10") return null;
|
|
32403
|
+
const at = await open(date);
|
|
32404
|
+
const body = await place(id, at);
|
|
32405
|
+
const sun = body && await place("naif-10", at);
|
|
32406
|
+
if (!body || !sun) return null;
|
|
32407
|
+
return subsolarAt({
|
|
32408
|
+
data: body.data,
|
|
32409
|
+
...await spinOf(id)
|
|
32410
|
+
}, body.centre, sun.centre, at.jd);
|
|
32411
|
+
});
|
|
32412
|
+
}
|
|
32413
|
+
|
|
31982
32414
|
//#endregion
|
|
31983
32415
|
//#region src/lib/fetch/panoramas.ts
|
|
31984
32416
|
var index = null;
|
|
@@ -32099,5 +32531,5 @@ function applyHost(options) {
|
|
|
32099
32531
|
}
|
|
32100
32532
|
|
|
32101
32533
|
//#endregion
|
|
32102
|
-
export { AttributionControl, FlatAttributionControl, FlatMap, GestureHandler, MAP_LAYERS, PROJECTION_IDS, PanoramaAttributionControl, PanoramaView, SpaceMap, SystemMap, Viewport, bearingDeg, boxRing, circlePoints, configureHost, createFlatMap, createMap, createPanorama, createProjection, createSystemMap, dateToJD, defaultSceneSettings, elements, fetchPanoramaIndex, fetchPanoramas, findPanorama, fixed, graticule, groundDistanceM, isViewable, jdToDate, kmToAu, neighboursOf, panoramaAt, pathFor, planeBasis, projectionAspect, samples, smallCircle, tle };
|
|
32534
|
+
export { AttributionControl, FlatAttributionControl, FlatMap, GestureHandler, MAP_LAYERS, PROJECTION_IDS, PanoramaAttributionControl, PanoramaView, SpaceMap, SystemMap, Viewport, bearingDeg, boxRing, circlePoints, configureHost, createFlatMap, createMap, createPanorama, createProjection, createSystemMap, dateToJD, defaultSceneSettings, distanceKm, elements, fetchPanoramaIndex, fetchPanoramas, findPanorama, fixed, graticule, groundDistanceM, isViewable, jdToDate, kmToAu, neighboursOf, offsetKm, panoramaAt, pathFor, planeBasis, projectionAspect, samples, smallCircle, subsolarPoint, tle };
|
|
32103
32535
|
(function(){if(typeof document==='undefined')return;var s=document.createElement('style');s.textContent=".scene-label{pointer-events:auto;cursor:pointer;-webkit-user-select:none;user-select:none;color:inherit;touch-action:none;z-index:1;width:32px;height:32px;text-decoration:none;display:block;position:relative;left:0}.scene-label__halo{border-radius:50%;width:100%;height:100%;transition:transform .1s}.scene-label__halo--spacecraft,.scene-label__halo--debris{overflow:visible}.scene-label__loader{box-sizing:border-box;pointer-events:none;border:2px solid #fff;border-color:#fff #fff #fff3 #fff3;border-radius:50%;width:32px;height:32px;margin:auto;animation:.9s linear infinite scene-label-loader-spin;position:fixed;inset:0}@keyframes scene-label-loader-spin{to{transform:rotate(360deg)}}.reduce-motion .scene-label__loader{animation-duration:.9s!important;animation-iteration-count:infinite!important}.scene-label__name{white-space:nowrap;pointer-events:auto;cursor:pointer;color:#fff;text-shadow:0 0 4px #000,0 0 4px #000;padding-left:8px;font-size:14px;font-weight:700;text-decoration:none;position:absolute;top:50%;left:32px;transform:translateY(-50%)}.scene-label__name--large{font-size:16px}.scene-label__annotations{top:28px;pointer-events:none;flex-direction:column;padding-inline-start:8px;display:flex;position:absolute;inset-inline-start:32px}.scene-label__annotation{opacity:0;white-space:nowrap;color:#fff9;text-shadow:0 0 3px #000,0 0 3px #000;transition:opacity .15s, display .15s allow-discrete;font-size:11px;line-height:1.3;display:none}.scene-label__annotation--visible{opacity:1;display:block}@starting-style{.scene-label__annotation--visible{opacity:0}}.scene-feature-label{color:#ffffffb3;white-space:nowrap;pointer-events:auto;cursor:pointer;-webkit-user-select:none;user-select:none;text-shadow:0 0 2px #000,0 0 2px #000;z-index:0;font-size:12px;transition:color .1s;left:0}.scene-feature-label:hover{color:#fff;text-shadow:0 0 3px #000,0 0 3px #000}.scene-feature-label--active{color:#fff;font-size:14px;font-weight:600}.scene-path-label{color:#fff;font:inherit;white-space:nowrap;text-align:start;text-shadow:0 0 4px #000,0 0 4px #000;pointer-events:auto;cursor:pointer;-webkit-user-select:none;user-select:none;touch-action:none;z-index:2;background:0 0;border:0;align-items:center;gap:8px;padding:0;line-height:1.15;display:flex;left:0}.scene-path-label--static{pointer-events:none;cursor:default}.scene-path-label__halo{border-radius:50%;flex-shrink:0;width:32px;height:32px;margin-inline-start:-16px;transition:transform .1s}.scene-path-label:hover .scene-path-label__halo{transform:scale(1.15)}.scene-path-label__text{flex-direction:column;gap:1px;display:flex}.scene-path-label__name{font-size:14px;font-weight:700}.scene-path-label__when{opacity:.8;font-variant-numeric:tabular-nums;font-size:12px}.scene-path-label--dim .scene-path-label__text{display:none}.scene-path-label--dim .scene-path-label__halo{transform:scale(.55)}.scene-path-label--dim:hover .scene-path-label__halo{transform:scale(.75)}.scene-path-label--step .scene-path-label__halo{background:0 0;border:0}.scene-path-label--step:hover .scene-path-label__halo{background:#ffffff1f}.scene-path-label--step .scene-path-label__name{font-size:12px;font-weight:600}.scene-path-label--step .scene-path-label__when{font-size:11px}.scene-path-label__hazard{font-size:11px;font-weight:700}.scene-path-label--lit{color:#fff}.scene-path-label--lit .scene-path-label__halo{transform:scale(1.15)}.scene-path-label--lit.scene-path-label--dim .scene-path-label__halo{transform:scale(.75)}.scene-path-label--faint .scene-path-label__text{display:none}.scene-path-label--faint .scene-path-label__halo{opacity:.45;transform:scale(.5)}.scene-path-label--faint:hover .scene-path-label__halo{opacity:1;transform:scale(.75)}.scene-overlay--no-names .scene-label__name,.scene-overlay--no-names .scene-label__annotations{display:none}.scene-hazard-label{white-space:nowrap;pointer-events:none;-webkit-user-select:none;user-select:none;text-shadow:0 0 4px #000,0 0 4px #000;margin-inline-start:16px;font-size:12px;font-weight:700;position:relative;left:0}.user-location-marker{pointer-events:none;background:#1a73e8;border:2px solid #fff;border-radius:50%;width:16px;height:16px;box-shadow:0 0 6px #0006}.sm-drawing-label{white-space:nowrap;color:#fff;text-shadow:0 0 4px #000,0 0 4px #000;-webkit-user-select:none;user-select:none;pointer-events:none;font:700 14px/1.2 system-ui,sans-serif}.sm-drawing-icon{-webkit-user-select:none;user-select:none;pointer-events:none;display:block}.sm-drawing--interactive{pointer-events:auto;cursor:pointer;touch-action:none}.sm-cooperative-hint{z-index:4;color:#fff;text-align:center;pointer-events:none;opacity:0;background:#0000008c;place-content:center;padding:16px;font:15px/1.4 system-ui,sans-serif;transition:opacity .2s;display:grid;position:absolute;inset:0}.sm-cooperative-hint--shown{opacity:1}@media (prefers-reduced-motion:reduce){.sm-cooperative-hint{transition:none}}.sm-ctrl{z-index:2;pointer-events:none;flex-direction:column;gap:6px;max-width:100%;padding:6px;display:flex;position:absolute}.sm-ctrl>*{pointer-events:auto}.sm-ctrl--top-left{align-items:flex-start;top:0;left:0}.sm-ctrl--top-right{align-items:flex-end;top:0;right:0}.sm-ctrl--bottom-left{align-items:flex-start;bottom:0;left:0}.sm-ctrl--bottom-right{align-items:flex-end;bottom:0;right:0}.sm-map{-webkit-user-select:none;user-select:none}:where(.sm-map){width:100%;height:100%;position:relative}.sm-map__canvas{pointer-events:auto;touch-action:none;width:100%;height:100%;display:block}.sm-map__canvas:focus-visible{outline:2px solid var(--ring,Highlight)}.sm-map .scene-overlay{pointer-events:none;z-index:0;position:absolute;inset:0}.sm-flat{touch-action:none;background:#05070e;width:100%;height:100%;position:relative;overflow:hidden}.sm-flat__raster,.sm-flat__vector,.sm-flat__markers{width:100%;height:100%;position:absolute;inset:0}.sm-flat__raster{display:block}.sm-flat__vector,.sm-flat__markers{pointer-events:none}.sm-flat--interactive{cursor:grab}.sm-flat--cooperative{touch-action:pan-x pan-y}.sm-flat--dragging{cursor:grabbing}.sm-flat__graticule{fill:none;stroke:#ffffff47;stroke-width:1px}.sm-flat__frame{fill:none;stroke:#ffffff73;stroke-width:1px}.sm-flat__feature-dot{fill:#fffc}.sm-flat__feature-label{fill:#ffffffd9;paint-order:stroke;stroke:#000000a6;stroke-width:2.5px;font:10px/1 system-ui,sans-serif}.sm-flat__marker-dot{background:#4ea3ff;border:2px solid #fff;border-radius:50%;width:10px;height:10px;box-shadow:0 0 0 1px #00000073}.sm-system-map{border-radius:var(--sm-system-map-radius,6px);background:var(--sm-system-map-background,#ffffff0d);width:100%;color:var(--sm-system-map-ink,#ffffff9e);position:relative;overflow:hidden}.sm-system-map--background{pointer-events:none;background:0 0;border-radius:0;height:100%}.sm-system-map__svg{touch-action:pan-y;width:100%;height:auto;display:block}.sm-system-map--background .sm-system-map__svg{height:100%}.sm-system-map__svg--near :is(a,.sm-system-map__button):not([data-near]){pointer-events:none}.sm-system-map__button{cursor:pointer}.sm-system-map__button:focus{outline:none}.sm-system-map__reference{opacity:.6}.sm-system-map__band--muted{color:var(--sm-system-map-ink,#ffffff9e)}.sm-system-map__band--sky{color:var(--sm-system-map-sky,oklch(74.6% .16 232.661/.7))}.sm-system-map__band--amber{color:var(--sm-system-map-amber,oklch(92.4% .12 95.746/.8))}.sm-system-map__band-label{font-weight:600}.sm-system-map__band-label--muted{fill:var(--sm-system-map-ink,#ffffff9e)}.sm-system-map__band-label--sky{fill:var(--sm-system-map-sky-label,oklch(74.6% .16 232.661))}.sm-system-map__band-label--amber{fill:var(--sm-system-map-amber-label,oklch(92.4% .12 95.746/.9))}.sm-system-map__tip{z-index:10;background:var(--sm-system-map-tip-background,#0a0c14e6);width:max-content;color:var(--sm-system-map-tip-ink,#fffffff2);white-space:nowrap;pointer-events:none;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:.25rem;padding:.25rem .5rem;font-size:.75rem;line-height:1.33333;position:absolute;transform:translate(-50%);box-shadow:0 1px 3px #0000001a,0 1px 2px -1px #0000001a}.sm-system-map__tip[hidden]{display:none}.sm-system-map__tip-title{font-weight:500}.sm-system-map__tip-sub{color:var(--sm-system-map-ink,#ffffff9e)}.sm-ctrl:has(>.sm-attribution:only-child){padding:0}.sm-ctrl--top-left:has(>.sm-attribution:only-child)>.sm-attribution{border-radius:0 0 var(--sm-attribution-radius) 0}.sm-ctrl--top-right:has(>.sm-attribution:only-child)>.sm-attribution{border-radius:0 0 0 var(--sm-attribution-radius)}.sm-ctrl--bottom-left:has(>.sm-attribution:only-child)>.sm-attribution{border-radius:0 var(--sm-attribution-radius) 0 0}.sm-ctrl--bottom-right:has(>.sm-attribution:only-child)>.sm-attribution{border-radius:var(--sm-attribution-radius) 0 0 0}.sm-attribution{--sm-attribution-radius:3px;border-radius:var(--sm-attribution-radius);color:#ffffffbf;white-space:nowrap;background:#0006;align-items:center;gap:.5em;max-width:100%;padding:1px 6px;font:11px/1.45 system-ui,sans-serif;display:flex}.sm-attribution a{color:inherit;text-decoration:none}.sm-attribution a:hover{color:#fff;text-decoration:underline}.sm-attribution__home{font-weight:600}.sm-attribution__group{text-overflow:ellipsis;overflow:hidden}.sm-attribution__label{color:#ffffff80}\n/*$vite$:1*/";document.head.appendChild(s);})();
|