astro-viewer 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/astroviewer.cjs +18851 -17175
- package/dist/astroviewer.js +1 -1
- package/dist/astroviewer.min.js +1 -1
- package/lib-esm/AstroSphere.d.ts +9 -0
- package/lib-esm/AstroSphere.js +63 -9
- package/lib-esm/AstroViewer.d.ts +18 -0
- package/lib-esm/AstroViewer.js +46 -0
- package/lib-esm/index.d.ts +5 -0
- package/lib-esm/index.js +4 -0
- package/lib-esm/model/AbstractSkyEntity.d.ts +10 -0
- package/lib-esm/model/earth/XYZAncestorMeshCache.d.ts +10 -0
- package/lib-esm/model/earth/XYZAncestorMeshCache.js +31 -0
- package/lib-esm/model/earth/XYZLayer.d.ts +31 -0
- package/lib-esm/model/earth/XYZLayer.js +231 -0
- package/lib-esm/model/earth/XYZMeshBuilder.d.ts +6 -0
- package/lib-esm/model/earth/XYZMeshBuilder.js +97 -0
- package/lib-esm/model/earth/XYZTile.d.ts +39 -0
- package/lib-esm/model/earth/XYZTile.js +187 -0
- package/lib-esm/model/earth/XYZTileBuffer.d.ts +39 -0
- package/lib-esm/model/earth/XYZTileBuffer.js +149 -0
- package/lib-esm/model/earth/XYZTileProvider.d.ts +29 -0
- package/lib-esm/model/earth/XYZTileProvider.js +187 -0
- package/lib-esm/model/earth/XYZTileRequestScheduler.d.ts +25 -0
- package/lib-esm/model/earth/XYZTileRequestScheduler.js +161 -0
- package/lib-esm/model/earth/XYZVisibleTilesManager.d.ts +30 -0
- package/lib-esm/model/earth/XYZVisibleTilesManager.js +208 -0
- package/lib-esm/model/earth/types.d.ts +87 -0
- package/lib-esm/model/earth/types.js +1 -0
- package/lib-esm/model/earth/wmts/WMTSAdapter.d.ts +11 -0
- package/lib-esm/model/earth/wmts/WMTSAdapter.js +85 -0
- package/lib-esm/model/earth/wmts/types.d.ts +1 -0
- package/lib-esm/model/earth/wmts/types.js +1 -0
- package/lib-esm/model/footprints/FootprintSetGL.js +1 -1
- package/lib-esm/model/terra/TerraFootprintSetGL.d.ts +4 -0
- package/lib-esm/model/terra/TerraFootprintSetGL.js +4 -0
- package/lib-esm/model/terra/TerraPointSetGL.d.ts +4 -0
- package/lib-esm/model/terra/TerraPointSetGL.js +4 -0
- package/lib-esm/shader/XYZShaderProgram.d.ts +20 -0
- package/lib-esm/shader/XYZShaderProgram.js +88 -0
- package/package.json +1 -2
package/lib-esm/AstroSphere.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ import { FootprintSetGL, HoveredFootprintDetail } from './model/footprints/Footp
|
|
|
9
9
|
import { EquatorialGrid } from './model/grid/EquatorialGrid.js';
|
|
10
10
|
import { HealpixGrid } from './model/grid/HealpixGrid.js';
|
|
11
11
|
import { ColorMap } from './model/ColorMaps.js';
|
|
12
|
+
import { XYZLayer } from './model/earth/XYZLayer.js';
|
|
13
|
+
import type { WMTSLayerConfig, XYZDebugStats, XYZLayerConfig } from './model/earth/types.js';
|
|
12
14
|
export type PointCoordinates = {
|
|
13
15
|
astroDeg: AstroCoords;
|
|
14
16
|
raHMS: HMS;
|
|
@@ -54,6 +56,8 @@ declare class AstroSphere {
|
|
|
54
56
|
private pointerDownY;
|
|
55
57
|
private pointerDownAt;
|
|
56
58
|
private _activeHiPS;
|
|
59
|
+
private _activeXYZ;
|
|
60
|
+
private _activeBaseLayer;
|
|
57
61
|
private startup;
|
|
58
62
|
private fov;
|
|
59
63
|
private activeCatalogues;
|
|
@@ -83,7 +87,10 @@ declare class AstroSphere {
|
|
|
83
87
|
private emitCameraChanged;
|
|
84
88
|
private addEventListeners;
|
|
85
89
|
getPhiThetaDeg(canvas: HTMLCanvasElement): SphericalCoords;
|
|
90
|
+
private collectViewportSphericalSamples;
|
|
86
91
|
activateHiPS(hipsDescriptor: HiPSDescriptor): void;
|
|
92
|
+
activateXYZ(config: XYZLayerConfig): void;
|
|
93
|
+
activateWMTS(config: WMTSLayerConfig): void;
|
|
87
94
|
showCatalogue(cat: CatalogueGL): Promise<CatalogueGL>;
|
|
88
95
|
deleteCatalogue(catalogue: CatalogueGL): void;
|
|
89
96
|
showFootprintSet(fset: FootprintSetGL): Promise<FootprintSetGL>;
|
|
@@ -107,6 +114,8 @@ declare class AstroSphere {
|
|
|
107
114
|
private prevCentralRaDeg;
|
|
108
115
|
private prevCentralDecDeg;
|
|
109
116
|
get activeHiPS(): HiPS | null;
|
|
117
|
+
get activeXYZ(): XYZLayer | null;
|
|
118
|
+
getXYZDebugStats(): XYZDebugStats;
|
|
110
119
|
draw(canvas: HTMLCanvasElement): void;
|
|
111
120
|
private emitHoveredSourceIfChanged;
|
|
112
121
|
}
|
package/lib-esm/AstroSphere.js
CHANGED
|
@@ -12,6 +12,9 @@ import { EquatorialGrid } from './model/grid/EquatorialGrid.js';
|
|
|
12
12
|
import { HealpixGrid } from './model/grid/HealpixGrid.js';
|
|
13
13
|
import { CoordsType } from './utils/CoordsType.js';
|
|
14
14
|
import ColorMaps from './model/ColorMaps.js';
|
|
15
|
+
import { XYZLayer } from './model/earth/XYZLayer.js';
|
|
16
|
+
import { xyzTileRequestScheduler } from './model/earth/XYZTileRequestScheduler.js';
|
|
17
|
+
import { WMTSAdapter } from './model/earth/wmts/WMTSAdapter.js';
|
|
15
18
|
/**
|
|
16
19
|
* AstroSphere — main WebGL scene controller (TS port)
|
|
17
20
|
*/
|
|
@@ -36,6 +39,8 @@ class AstroSphere {
|
|
|
36
39
|
pointerDownY = null;
|
|
37
40
|
pointerDownAt = 0;
|
|
38
41
|
_activeHiPS = null;
|
|
42
|
+
_activeXYZ = null;
|
|
43
|
+
_activeBaseLayer = null;
|
|
39
44
|
startup = true;
|
|
40
45
|
fov;
|
|
41
46
|
activeCatalogues = [];
|
|
@@ -392,8 +397,35 @@ class AstroSphere {
|
|
|
392
397
|
const pickerPoint = RayPickingUtils.getIntersectionPointWithSingleModel(maxX / 2, maxY / 2, this._healpixGrid, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
393
398
|
return cartesianToSpherical(pickerPoint);
|
|
394
399
|
}
|
|
400
|
+
collectViewportSphericalSamples(sampleCount = 5) {
|
|
401
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
402
|
+
const width = rect.width;
|
|
403
|
+
const height = rect.height;
|
|
404
|
+
const samples = [];
|
|
405
|
+
for (let ix = 0; ix < sampleCount; ix++) {
|
|
406
|
+
const x = sampleCount === 1 ? width / 2 : (ix / (sampleCount - 1)) * width;
|
|
407
|
+
for (let iy = 0; iy < sampleCount; iy++) {
|
|
408
|
+
const y = sampleCount === 1 ? height / 2 : (iy / (sampleCount - 1)) * height;
|
|
409
|
+
const hit = RayPickingUtils.getIntersectionPointWithSingleModel(x, y, this._healpixGrid, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
410
|
+
if (hit && hit.length > 0) {
|
|
411
|
+
samples.push(cartesianToSpherical(hit));
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return samples;
|
|
416
|
+
}
|
|
395
417
|
activateHiPS(hipsDescriptor) {
|
|
396
418
|
this._activeHiPS = new HiPS(1, [0.0, 0.0, 0.0], 0, 0, hipsDescriptor, this._webgl, this._healpixGrid);
|
|
419
|
+
this._activeBaseLayer = 'hips';
|
|
420
|
+
}
|
|
421
|
+
activateXYZ(config) {
|
|
422
|
+
this._activeXYZ = new XYZLayer(config, this._webgl);
|
|
423
|
+
this._activeBaseLayer = 'xyz';
|
|
424
|
+
}
|
|
425
|
+
activateWMTS(config) {
|
|
426
|
+
const adapter = new WMTSAdapter(config);
|
|
427
|
+
this._activeXYZ = new XYZLayer(adapter.toXYZLayerConfig(), this._webgl);
|
|
428
|
+
this._activeBaseLayer = 'xyz';
|
|
397
429
|
}
|
|
398
430
|
// Catalogue section
|
|
399
431
|
async showCatalogue(cat) {
|
|
@@ -524,12 +556,22 @@ class AstroSphere {
|
|
|
524
556
|
get activeHiPS() {
|
|
525
557
|
return this._activeHiPS;
|
|
526
558
|
}
|
|
559
|
+
get activeXYZ() {
|
|
560
|
+
return this._activeXYZ;
|
|
561
|
+
}
|
|
562
|
+
getXYZDebugStats() {
|
|
563
|
+
return {
|
|
564
|
+
activeBaseLayer: this._activeBaseLayer,
|
|
565
|
+
layer: this._activeXYZ?.getDebugStats() ?? null,
|
|
566
|
+
requests: xyzTileRequestScheduler.getDebugStats(),
|
|
567
|
+
};
|
|
568
|
+
}
|
|
527
569
|
draw(canvas) {
|
|
528
570
|
if (this._refreshingStatus)
|
|
529
571
|
return;
|
|
530
572
|
if (!this._webgl)
|
|
531
573
|
return;
|
|
532
|
-
if (!this._activeHiPS)
|
|
574
|
+
if (!this._activeHiPS && !this._activeXYZ)
|
|
533
575
|
return;
|
|
534
576
|
if (!this._healpixGrid || Object.keys(this._healpixGrid).length === 0)
|
|
535
577
|
return;
|
|
@@ -613,15 +655,25 @@ class AstroSphere {
|
|
|
613
655
|
this._webgl.enable(this._webgl.CULL_FACE);
|
|
614
656
|
this._webgl.cullFace(global.insideSphere ? this._webgl.FRONT : this._webgl.BACK);
|
|
615
657
|
this._webgl.blendFunc(this._webgl.SRC_ALPHA, this._webgl.ONE_MINUS_SRC_ALPHA);
|
|
616
|
-
|
|
617
|
-
|
|
658
|
+
if (this._activeBaseLayer === 'hips' && this._activeHiPS) {
|
|
659
|
+
const visibleOrder = Math.min(this._healpixGrid.visibleorder, this._activeHiPS.maxOrder);
|
|
660
|
+
this._healpixGrid.visibleTilesManager.computeVisiblePixels(visibleOrder, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
661
|
+
}
|
|
618
662
|
// DRAW HiPS
|
|
619
663
|
const skyEntityDrawInput = {
|
|
620
664
|
fovDeg: this._healpixGrid.getMinFoV(),
|
|
621
665
|
camera: this._camera,
|
|
622
|
-
pMatrix: this._perspectiveMatrixManager.pMatrix
|
|
666
|
+
pMatrix: this._perspectiveMatrixManager.pMatrix,
|
|
667
|
+
centerSphericalDeg: this.updateCentralPoint().sphericalDeg,
|
|
668
|
+
fovPolygon: this._activeBaseLayer === 'xyz' ? this.getFoVPolygon() : undefined,
|
|
669
|
+
viewportSphericalSamples: this._activeBaseLayer === 'xyz' ? this.collectViewportSphericalSamples(7) : undefined,
|
|
623
670
|
};
|
|
624
|
-
this.
|
|
671
|
+
if (this._activeBaseLayer === 'hips') {
|
|
672
|
+
this._activeHiPS?.draw(skyEntityDrawInput);
|
|
673
|
+
}
|
|
674
|
+
if (this._activeBaseLayer === 'xyz') {
|
|
675
|
+
this._activeXYZ?.draw(skyEntityDrawInput);
|
|
676
|
+
}
|
|
625
677
|
this._healpixGrid.draw(skyEntityDrawInput);
|
|
626
678
|
this._equatorialGrid.draw(skyEntityDrawInput);
|
|
627
679
|
this._webgl.enable(this._webgl.DEPTH_TEST);
|
|
@@ -642,14 +694,16 @@ class AstroSphere {
|
|
|
642
694
|
});
|
|
643
695
|
}
|
|
644
696
|
this.activeCatalogues.forEach(cat => {
|
|
645
|
-
|
|
646
|
-
|
|
697
|
+
const activeModelMatrix = this._activeHiPS?.getModelMatrix() ?? this._activeXYZ?.getModelMatrix();
|
|
698
|
+
if (activeModelMatrix) {
|
|
699
|
+
cat.draw(activeModelMatrix, this.mouseHelper, this._camera.getCameraMatrix(), this._perspectiveMatrixManager.pMatrix);
|
|
647
700
|
}
|
|
648
701
|
});
|
|
649
702
|
this.emitHoveredSourceIfChanged();
|
|
650
703
|
this.activeFootprintSets.forEach(fst => {
|
|
651
|
-
|
|
652
|
-
|
|
704
|
+
const activeModelMatrix = this._activeHiPS?.getModelMatrix() ?? this._activeXYZ?.getModelMatrix();
|
|
705
|
+
if (activeModelMatrix) {
|
|
706
|
+
fst.draw(activeModelMatrix, this.mouseHelper, this._camera.getCameraMatrix(), this._perspectiveMatrixManager.pMatrix);
|
|
653
707
|
}
|
|
654
708
|
});
|
|
655
709
|
}
|
package/lib-esm/AstroViewer.d.ts
CHANGED
|
@@ -9,6 +9,10 @@ import Camera from './Camera.js';
|
|
|
9
9
|
import { ReadonlyMat4 } from 'gl-matrix';
|
|
10
10
|
import { ColorMap, ColorMapName } from './model/ColorMaps.js';
|
|
11
11
|
import { HiPS } from './model/hips/HiPS.js';
|
|
12
|
+
import { XYZLayer } from './model/earth/XYZLayer.js';
|
|
13
|
+
import type { WMTSLayerConfig, XYZDebugStats, XYZLayerConfig } from './model/earth/types.js';
|
|
14
|
+
import { TerraPointSetGL } from './model/terra/TerraPointSetGL.js';
|
|
15
|
+
import { TerraFootprintSetGL } from './model/terra/TerraFootprintSetGL.js';
|
|
12
16
|
export declare class AstroViewer {
|
|
13
17
|
private astroSphere;
|
|
14
18
|
private canvas;
|
|
@@ -32,14 +36,28 @@ export declare class AstroViewer {
|
|
|
32
36
|
showFootprintSet(footprintSet: FootprintSetGL): void;
|
|
33
37
|
hideFootprintSet(footprintSet: FootprintSetGL, isVisible: boolean): void;
|
|
34
38
|
deleteFootprintSet(footprintSet: FootprintSetGL): void;
|
|
39
|
+
createTerraPointSet(pointSetName: string, pointSetDescription: string, providerUrl: string, metadataManager: MetadataManager): TerraPointSetGL;
|
|
40
|
+
showTerraPointSet(pointSet: TerraPointSetGL): void;
|
|
41
|
+
hideTerraPointSet(pointSet: TerraPointSetGL, isVisible: boolean): void;
|
|
42
|
+
deleteTerraPointSet(pointSet: TerraPointSetGL): void;
|
|
43
|
+
createTerraFootprintSet(footprintSetName: string, footprintSetDescription: string, providerUrl: string, metadataManager: MetadataManager): TerraFootprintSetGL;
|
|
44
|
+
showTerraFootprintSet(footprintSet: TerraFootprintSetGL): void;
|
|
45
|
+
hideTerraFootprintSet(footprintSet: TerraFootprintSetGL, isVisible: boolean): void;
|
|
46
|
+
deleteTerraFootprintSet(footprintSet: TerraFootprintSetGL): void;
|
|
35
47
|
changeFootprintSetColor(footprintSet: FootprintSetGL, hexColor: string): void;
|
|
36
48
|
getHoveredFootprints(): HoveredFootprintDetail[];
|
|
37
49
|
getDefaultHiPSURL(): string;
|
|
38
50
|
activateHiPS(hipsDescriptor: HiPSDescriptor): void;
|
|
51
|
+
activateXYZ(config: XYZLayerConfig): void;
|
|
52
|
+
activateWMTS(config: WMTSLayerConfig): void;
|
|
53
|
+
setXYZMaxConcurrentRequests(value: number): void;
|
|
54
|
+
getXYZMaxConcurrentRequests(): number;
|
|
55
|
+
getXYZDebugStats(): XYZDebugStats;
|
|
39
56
|
loadHiPS(baseUrl: string): Promise<string>;
|
|
40
57
|
changeColorMap(colorMapName: ColorMapName): void;
|
|
41
58
|
changeCustomColorMap(colorMap: ColorMap): void;
|
|
42
59
|
getActiveHiPS(): HiPS | null;
|
|
60
|
+
getActiveXYZ(): XYZLayer | null;
|
|
43
61
|
setCamera(camera: Camera): void;
|
|
44
62
|
setCameraPosition(pos: [number, number, number]): void;
|
|
45
63
|
setCameraMatrix(viewMatrix: Float32Array): void;
|
package/lib-esm/AstroViewer.js
CHANGED
|
@@ -5,6 +5,9 @@ import { CatalogueGL } from './model/catalogues/CatalogueGL.js';
|
|
|
5
5
|
import { FootprintSetGL } from './model/footprints/FootprintSetGL.js';
|
|
6
6
|
import { bootSetup } from './Config.js';
|
|
7
7
|
import ColorMaps from './model/ColorMaps.js';
|
|
8
|
+
import { xyzTileRequestScheduler } from './model/earth/XYZTileRequestScheduler.js';
|
|
9
|
+
import { TerraPointSetGL } from './model/terra/TerraPointSetGL.js';
|
|
10
|
+
import { TerraFootprintSetGL } from './model/terra/TerraFootprintSetGL.js';
|
|
8
11
|
// & {
|
|
9
12
|
// viewportWidth: number
|
|
10
13
|
// viewportHeight: number
|
|
@@ -71,6 +74,31 @@ export class AstroViewer {
|
|
|
71
74
|
deleteFootprintSet(footprintSet) {
|
|
72
75
|
this.astroSphere.deleteFootprintSet(footprintSet);
|
|
73
76
|
}
|
|
77
|
+
// TERRA OVERLAYS
|
|
78
|
+
createTerraPointSet(pointSetName, pointSetDescription, providerUrl, metadataManager) {
|
|
79
|
+
return new TerraPointSetGL(pointSetName, pointSetDescription, providerUrl, metadataManager, this.webgl, this.astroSphere.healpixGrid.visibleTilesManager);
|
|
80
|
+
}
|
|
81
|
+
showTerraPointSet(pointSet) {
|
|
82
|
+
this.astroSphere.showCatalogue(pointSet);
|
|
83
|
+
}
|
|
84
|
+
hideTerraPointSet(pointSet, isVisible) {
|
|
85
|
+
pointSet.setIsVisible(isVisible);
|
|
86
|
+
}
|
|
87
|
+
deleteTerraPointSet(pointSet) {
|
|
88
|
+
this.astroSphere.deleteCatalogue(pointSet);
|
|
89
|
+
}
|
|
90
|
+
createTerraFootprintSet(footprintSetName, footprintSetDescription, providerUrl, metadataManager) {
|
|
91
|
+
return new TerraFootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl, this.astroSphere.healpixGrid.visibleTilesManager);
|
|
92
|
+
}
|
|
93
|
+
showTerraFootprintSet(footprintSet) {
|
|
94
|
+
this.astroSphere.showFootprintSet(footprintSet);
|
|
95
|
+
}
|
|
96
|
+
hideTerraFootprintSet(footprintSet, isVisible) {
|
|
97
|
+
footprintSet.setIsVisible(isVisible);
|
|
98
|
+
}
|
|
99
|
+
deleteTerraFootprintSet(footprintSet) {
|
|
100
|
+
this.astroSphere.deleteFootprintSet(footprintSet);
|
|
101
|
+
}
|
|
74
102
|
changeFootprintSetColor(footprintSet, hexColor) {
|
|
75
103
|
// footprintSet.footprintsetProps.changeColor(hexColor)
|
|
76
104
|
footprintSet.changeColor(hexColor);
|
|
@@ -85,6 +113,21 @@ export class AstroViewer {
|
|
|
85
113
|
activateHiPS(hipsDescriptor) {
|
|
86
114
|
this.astroSphere.activateHiPS(hipsDescriptor);
|
|
87
115
|
}
|
|
116
|
+
activateXYZ(config) {
|
|
117
|
+
this.astroSphere.activateXYZ(config);
|
|
118
|
+
}
|
|
119
|
+
activateWMTS(config) {
|
|
120
|
+
this.astroSphere.activateWMTS(config);
|
|
121
|
+
}
|
|
122
|
+
setXYZMaxConcurrentRequests(value) {
|
|
123
|
+
xyzTileRequestScheduler.setMaxConcurrent(value);
|
|
124
|
+
}
|
|
125
|
+
getXYZMaxConcurrentRequests() {
|
|
126
|
+
return xyzTileRequestScheduler.getMaxConcurrent();
|
|
127
|
+
}
|
|
128
|
+
getXYZDebugStats() {
|
|
129
|
+
return this.astroSphere.getXYZDebugStats();
|
|
130
|
+
}
|
|
88
131
|
async loadHiPS(baseUrl) {
|
|
89
132
|
const hipsUrl = baseUrl.endsWith('/') ? baseUrl : baseUrl + '/';
|
|
90
133
|
const resp = await fetch(hipsUrl + 'properties');
|
|
@@ -108,6 +151,9 @@ export class AstroViewer {
|
|
|
108
151
|
getActiveHiPS() {
|
|
109
152
|
return this.astroSphere.activeHiPS;
|
|
110
153
|
}
|
|
154
|
+
getActiveXYZ() {
|
|
155
|
+
return this.astroSphere.activeXYZ;
|
|
156
|
+
}
|
|
111
157
|
// Camera: GOTOs and COORDS
|
|
112
158
|
setCamera(camera) {
|
|
113
159
|
this.astroSphere.setCamera(camera);
|
package/lib-esm/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export { FoV } from './model/FoV.js';
|
|
|
4
4
|
export type { PointCoordinates, CameraChangedDetail } from './AstroSphere.js';
|
|
5
5
|
export { HoveredFootprintDetail, FootprintSetGL } from './model/footprints/FootprintSetGL.js';
|
|
6
6
|
export { CatalogueGL } from './model/catalogues/CatalogueGL.js';
|
|
7
|
+
export { TerraPointSetGL } from './model/terra/TerraPointSetGL.js';
|
|
8
|
+
export { TerraFootprintSetGL } from './model/terra/TerraFootprintSetGL.js';
|
|
7
9
|
export { MetadataManager } from './model/MetadataManager.js';
|
|
8
10
|
export { MetadataColumn, MetadataInit, ColumnType } from './model/MetadataColumn.js';
|
|
9
11
|
export { Point, SphericalOpts, AstroOpts, PointInitOpts, CartesianOpts } from './model/Point.js';
|
|
@@ -12,5 +14,8 @@ export { CoordsType } from './utils/CoordsType.js';
|
|
|
12
14
|
export { ColorMaps, COLOR_MAP_SAMPLE_COUNT, createColorMapFromSamples } from './model/ColorMaps.js';
|
|
13
15
|
export type { ColorMap, ColorMapName } from './model/ColorMaps.js';
|
|
14
16
|
export { HiPS } from './model/hips/HiPS.js';
|
|
17
|
+
export { XYZLayer } from './model/earth/XYZLayer.js';
|
|
18
|
+
export { WMTSAdapter } from './model/earth/wmts/WMTSAdapter.js';
|
|
19
|
+
export type { XYZLayerConfig, XYZTileCoord, XYZTileMesh, WMTSLayerConfig, WMTSRequestEncoding } from './model/earth/types.js';
|
|
15
20
|
export { Source } from './model/Source.js';
|
|
16
21
|
export { Footprint } from './model/footprints/Footprint.js';
|
package/lib-esm/index.js
CHANGED
|
@@ -3,6 +3,8 @@ export { HiPSDescriptor } from './model/hips/HiPSDescriptor.js';
|
|
|
3
3
|
export { FoV } from './model/FoV.js';
|
|
4
4
|
export { FootprintSetGL } from './model/footprints/FootprintSetGL.js';
|
|
5
5
|
export { CatalogueGL } from './model/catalogues/CatalogueGL.js';
|
|
6
|
+
export { TerraPointSetGL } from './model/terra/TerraPointSetGL.js';
|
|
7
|
+
export { TerraFootprintSetGL } from './model/terra/TerraFootprintSetGL.js';
|
|
6
8
|
export { MetadataManager } from './model/MetadataManager.js';
|
|
7
9
|
export { MetadataColumn, ColumnType } from './model/MetadataColumn.js';
|
|
8
10
|
export { Point } from './model/Point.js';
|
|
@@ -10,6 +12,8 @@ export { FoVUtils } from './utils/FoVUtils.js';
|
|
|
10
12
|
export { CoordsType } from './utils/CoordsType.js';
|
|
11
13
|
export { ColorMaps, COLOR_MAP_SAMPLE_COUNT, createColorMapFromSamples } from './model/ColorMaps.js';
|
|
12
14
|
export { HiPS } from './model/hips/HiPS.js';
|
|
15
|
+
export { XYZLayer } from './model/earth/XYZLayer.js';
|
|
16
|
+
export { WMTSAdapter } from './model/earth/wmts/WMTSAdapter.js';
|
|
13
17
|
export { Source } from './model/Source.js';
|
|
14
18
|
export { Footprint } from './model/footprints/Footprint.js';
|
|
15
19
|
console.log('astroviewer UMD loaded');
|
|
@@ -4,11 +4,21 @@
|
|
|
4
4
|
import { vec3, mat4, ReadonlyVec3, ReadonlyMat4 } from "gl-matrix";
|
|
5
5
|
import { HiPSShaderProgram } from '../shader/HiPSShaderProgram.js';
|
|
6
6
|
import Camera from "../Camera.js";
|
|
7
|
+
import { Point } from "./Point.js";
|
|
7
8
|
type GL = WebGLRenderingContext | WebGL2RenderingContext;
|
|
8
9
|
export interface SkyEntityDrawInput {
|
|
9
10
|
fovDeg?: number;
|
|
10
11
|
camera: Camera;
|
|
11
12
|
pMatrix: ReadonlyMat4;
|
|
13
|
+
centerSphericalDeg?: {
|
|
14
|
+
phi: number;
|
|
15
|
+
theta: number;
|
|
16
|
+
};
|
|
17
|
+
fovPolygon?: Point[];
|
|
18
|
+
viewportSphericalSamples?: Array<{
|
|
19
|
+
phi: number;
|
|
20
|
+
theta: number;
|
|
21
|
+
}>;
|
|
12
22
|
}
|
|
13
23
|
export declare abstract class AbstractSkyEntity {
|
|
14
24
|
refreshMe: boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { XYZTileCoord, XYZTileGpuMesh } from './types.js';
|
|
2
|
+
import { XYZMeshBuilder } from './XYZMeshBuilder.js';
|
|
3
|
+
export declare class XYZAncestorMeshCache {
|
|
4
|
+
private _webgl;
|
|
5
|
+
private _meshBuilder;
|
|
6
|
+
private _meshes;
|
|
7
|
+
constructor(webgl: WebGL2RenderingContext, meshBuilder: XYZMeshBuilder);
|
|
8
|
+
getMesh(targetTile: XYZTileCoord, ancestorTile: XYZTileCoord, segmentsPerSide: number): XYZTileGpuMesh;
|
|
9
|
+
dispose(): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export class XYZAncestorMeshCache {
|
|
2
|
+
_webgl;
|
|
3
|
+
_meshBuilder;
|
|
4
|
+
_meshes = new Map();
|
|
5
|
+
constructor(webgl, meshBuilder) {
|
|
6
|
+
this._webgl = webgl;
|
|
7
|
+
this._meshBuilder = meshBuilder;
|
|
8
|
+
}
|
|
9
|
+
getMesh(targetTile, ancestorTile, segmentsPerSide) {
|
|
10
|
+
const key = `${targetTile.z}/${targetTile.x}/${targetTile.y}->${ancestorTile.z}/${ancestorTile.x}/${ancestorTile.y}@${segmentsPerSide}`;
|
|
11
|
+
const existing = this._meshes.get(key);
|
|
12
|
+
if (existing) {
|
|
13
|
+
return existing;
|
|
14
|
+
}
|
|
15
|
+
const mesh = this._meshBuilder.buildAncestorMesh(targetTile, ancestorTile, segmentsPerSide);
|
|
16
|
+
const uploaded = this._meshBuilder.uploadMesh(mesh, this._webgl);
|
|
17
|
+
this._meshes.set(key, uploaded);
|
|
18
|
+
return uploaded;
|
|
19
|
+
}
|
|
20
|
+
dispose() {
|
|
21
|
+
for (const mesh of this._meshes.values()) {
|
|
22
|
+
if (mesh.positionBuffer)
|
|
23
|
+
this._webgl.deleteBuffer(mesh.positionBuffer);
|
|
24
|
+
if (mesh.uvBuffer)
|
|
25
|
+
this._webgl.deleteBuffer(mesh.uvBuffer);
|
|
26
|
+
if (mesh.indexBuffer)
|
|
27
|
+
this._webgl.deleteBuffer(mesh.indexBuffer);
|
|
28
|
+
}
|
|
29
|
+
this._meshes.clear();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AbstractSkyEntity, SkyEntityDrawInput } from '../AbstractSkyEntity.js';
|
|
2
|
+
import type { XYZLayerConfig, XYZLayerDebugStats } from './types.js';
|
|
3
|
+
export declare class XYZLayer extends AbstractSkyEntity {
|
|
4
|
+
private static readonly DEFAULT_MAX_CACHED_TILES;
|
|
5
|
+
private _config;
|
|
6
|
+
private _provider;
|
|
7
|
+
private _visibleTilesManager;
|
|
8
|
+
private _meshBuilder;
|
|
9
|
+
private _xyzShaderProgram;
|
|
10
|
+
private _tileBuffer;
|
|
11
|
+
private _ancestorMeshCache;
|
|
12
|
+
private _visibleTileKeys;
|
|
13
|
+
private _fallbackVisibleTileKeys;
|
|
14
|
+
private _baseVisibleTileKeys;
|
|
15
|
+
private _tilePriorities;
|
|
16
|
+
private _tileSelectionKey;
|
|
17
|
+
private _currentTileCount;
|
|
18
|
+
private _fallbackTileCount;
|
|
19
|
+
private _coreTileCount;
|
|
20
|
+
private _coverageTileCount;
|
|
21
|
+
constructor(config: XYZLayerConfig, webgl: WebGL2RenderingContext);
|
|
22
|
+
get config(): XYZLayerConfig;
|
|
23
|
+
getDebugStats(): XYZLayerDebugStats;
|
|
24
|
+
private bootstrapTiles;
|
|
25
|
+
draw(input: SkyEntityDrawInput): void;
|
|
26
|
+
private evictCache;
|
|
27
|
+
private disposeTiles;
|
|
28
|
+
private getTileKey;
|
|
29
|
+
private parseTileKey;
|
|
30
|
+
private findBestAvailableAncestor;
|
|
31
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { AbstractSkyEntity } from '../AbstractSkyEntity.js';
|
|
2
|
+
import { XYZShaderProgram } from '../../shader/XYZShaderProgram.js';
|
|
3
|
+
import { XYZAncestorMeshCache } from './XYZAncestorMeshCache.js';
|
|
4
|
+
import { XYZMeshBuilder } from './XYZMeshBuilder.js';
|
|
5
|
+
import { XYZTileBuffer } from './XYZTileBuffer.js';
|
|
6
|
+
import { XYZTileProvider } from './XYZTileProvider.js';
|
|
7
|
+
import { XYZVisibleTilesManager } from './XYZVisibleTilesManager.js';
|
|
8
|
+
export class XYZLayer extends AbstractSkyEntity {
|
|
9
|
+
static DEFAULT_MAX_CACHED_TILES = 384;
|
|
10
|
+
_config;
|
|
11
|
+
_provider;
|
|
12
|
+
_visibleTilesManager;
|
|
13
|
+
_meshBuilder;
|
|
14
|
+
_xyzShaderProgram;
|
|
15
|
+
_tileBuffer;
|
|
16
|
+
_ancestorMeshCache;
|
|
17
|
+
_visibleTileKeys = [];
|
|
18
|
+
_fallbackVisibleTileKeys = [];
|
|
19
|
+
_baseVisibleTileKeys = [];
|
|
20
|
+
_tilePriorities = new Map();
|
|
21
|
+
_tileSelectionKey = null;
|
|
22
|
+
_currentTileCount = 0;
|
|
23
|
+
_fallbackTileCount = 0;
|
|
24
|
+
_coreTileCount = 0;
|
|
25
|
+
_coverageTileCount = 0;
|
|
26
|
+
constructor(config, webgl) {
|
|
27
|
+
super(1, [0, 0, 0], 0, 0, 'XYZ Earth Layer', webgl, false);
|
|
28
|
+
this._config = config;
|
|
29
|
+
this._provider = new XYZTileProvider(config);
|
|
30
|
+
this._visibleTilesManager = new XYZVisibleTilesManager(this._provider);
|
|
31
|
+
this._meshBuilder = new XYZMeshBuilder();
|
|
32
|
+
this._xyzShaderProgram = new XYZShaderProgram(webgl);
|
|
33
|
+
this._tileBuffer = new XYZTileBuffer(1, webgl, this._meshBuilder, this._xyzShaderProgram);
|
|
34
|
+
this._ancestorMeshCache = new XYZAncestorMeshCache(webgl, this._meshBuilder);
|
|
35
|
+
this.initGL(webgl);
|
|
36
|
+
this.bootstrapTiles(180, null, null);
|
|
37
|
+
}
|
|
38
|
+
get config() {
|
|
39
|
+
return this._config;
|
|
40
|
+
}
|
|
41
|
+
getDebugStats() {
|
|
42
|
+
let readyTileCount = 0;
|
|
43
|
+
let loadingTileCount = 0;
|
|
44
|
+
let coolingDownTileCount = 0;
|
|
45
|
+
const now = Date.now();
|
|
46
|
+
const allTiles = [
|
|
47
|
+
...Array.from(this._tileBuffer.activeTiles.values(), (entry) => entry.tile),
|
|
48
|
+
...Array.from(this._tileBuffer.cachedTiles.values(), (entry) => entry.tile),
|
|
49
|
+
];
|
|
50
|
+
for (const tile of allTiles) {
|
|
51
|
+
if (tile.ready) {
|
|
52
|
+
readyTileCount += 1;
|
|
53
|
+
}
|
|
54
|
+
if (tile.loading) {
|
|
55
|
+
loadingTileCount += 1;
|
|
56
|
+
}
|
|
57
|
+
if (tile.failedUntil > now) {
|
|
58
|
+
coolingDownTileCount += 1;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const currentZoom = this._visibleTileKeys.reduce((maxZoom, tileKey) => {
|
|
62
|
+
const zoom = Number.parseInt(tileKey.split('/')[0] ?? '', 10);
|
|
63
|
+
if (!Number.isFinite(zoom)) {
|
|
64
|
+
return maxZoom;
|
|
65
|
+
}
|
|
66
|
+
return maxZoom == null ? zoom : Math.max(maxZoom, zoom);
|
|
67
|
+
}, null);
|
|
68
|
+
return {
|
|
69
|
+
cacheSize: this._tileBuffer.size,
|
|
70
|
+
visibleTileCount: this._visibleTileKeys.length,
|
|
71
|
+
currentTileCount: this._currentTileCount,
|
|
72
|
+
fallbackTileCount: this._fallbackTileCount,
|
|
73
|
+
coreTileCount: this._coreTileCount,
|
|
74
|
+
coverageTileCount: this._coverageTileCount,
|
|
75
|
+
readyTileCount,
|
|
76
|
+
loadingTileCount,
|
|
77
|
+
coolingDownTileCount,
|
|
78
|
+
currentZoom,
|
|
79
|
+
tileSelectionKey: this._tileSelectionKey,
|
|
80
|
+
isSettling: false,
|
|
81
|
+
coarseTileCount: 0,
|
|
82
|
+
hasPendingSelection: false,
|
|
83
|
+
pendingSelectionKey: null,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
bootstrapTiles(fovDeg, camera, centerSphericalDeg, fovPolygon = null, viewportSphericalSamples = null) {
|
|
87
|
+
const selection = camera
|
|
88
|
+
? this._visibleTilesManager.selectTiles({
|
|
89
|
+
fovDeg,
|
|
90
|
+
camera,
|
|
91
|
+
pMatrix: new Float32Array(),
|
|
92
|
+
centerSphericalDeg: centerSphericalDeg ?? undefined,
|
|
93
|
+
fovPolygon: fovPolygon ?? undefined,
|
|
94
|
+
viewportSphericalSamples: viewportSphericalSamples ?? undefined,
|
|
95
|
+
})
|
|
96
|
+
: {
|
|
97
|
+
key: 'initial',
|
|
98
|
+
currentTiles: this._provider.getInitialTiles(),
|
|
99
|
+
fallbackTiles: [],
|
|
100
|
+
currentZoom: 1,
|
|
101
|
+
coreTileCount: this._provider.getInitialTiles().length,
|
|
102
|
+
coverageTileCount: 0,
|
|
103
|
+
};
|
|
104
|
+
if (selection.key === this._tileSelectionKey) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
this._tileSelectionKey = selection.key;
|
|
108
|
+
this._currentTileCount = selection.currentTiles.length;
|
|
109
|
+
this._fallbackTileCount = selection.fallbackTiles.length;
|
|
110
|
+
this._coreTileCount = selection.coreTileCount;
|
|
111
|
+
this._coverageTileCount = selection.coverageTileCount;
|
|
112
|
+
const segments = this._config.segmentsPerSide ?? 16;
|
|
113
|
+
const baseTiles = this._provider.getInitialTiles();
|
|
114
|
+
const coreTileKeys = new Set(selection.currentTiles
|
|
115
|
+
.slice(0, selection.coreTileCount)
|
|
116
|
+
.map((tileCoord) => this.getTileKey(tileCoord)));
|
|
117
|
+
const baseTileKeys = new Set(baseTiles.map((tileCoord) => this.getTileKey(tileCoord)));
|
|
118
|
+
const prioritizedBaseTiles = baseTiles.map((tileCoord, index) => ({
|
|
119
|
+
tileCoord,
|
|
120
|
+
priority: 5000 + (baseTiles.length - index),
|
|
121
|
+
role: 'base',
|
|
122
|
+
}));
|
|
123
|
+
const prioritizedCurrentTiles = selection.currentTiles.map((tileCoord, index) => ({
|
|
124
|
+
tileCoord,
|
|
125
|
+
priority: 10000 + (selection.currentTiles.length - index),
|
|
126
|
+
role: coreTileKeys.has(this.getTileKey(tileCoord)) ? 'current' : 'coverage',
|
|
127
|
+
}));
|
|
128
|
+
const prioritizedFallbackTiles = selection.fallbackTiles.map((tileCoord, index) => ({
|
|
129
|
+
tileCoord,
|
|
130
|
+
priority: 1000 + (selection.fallbackTiles.length - index),
|
|
131
|
+
role: 'fallback',
|
|
132
|
+
}));
|
|
133
|
+
const requestedTiles = [...prioritizedBaseTiles, ...prioritizedCurrentTiles, ...prioritizedFallbackTiles];
|
|
134
|
+
this._tilePriorities.clear();
|
|
135
|
+
this._fallbackVisibleTileKeys = [];
|
|
136
|
+
this._baseVisibleTileKeys = [];
|
|
137
|
+
const orderedRequests = requestedTiles
|
|
138
|
+
.sort((a, b) => a.tileCoord.z - b.tileCoord.z)
|
|
139
|
+
.map(({ tileCoord, priority, role }) => {
|
|
140
|
+
const tileKey = this.getTileKey(tileCoord);
|
|
141
|
+
this._tilePriorities.set(tileKey, priority);
|
|
142
|
+
return {
|
|
143
|
+
tileCoord,
|
|
144
|
+
priority,
|
|
145
|
+
url: this._provider.getTileUrl(tileCoord),
|
|
146
|
+
role,
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
const ensuredKeys = this._tileBuffer.ensureTiles(orderedRequests, segments);
|
|
150
|
+
const fallbackKeySet = new Set(selection.fallbackTiles.map((tileCoord) => this.getTileKey(tileCoord)));
|
|
151
|
+
this._baseVisibleTileKeys = ensuredKeys.filter((tileKey) => baseTileKeys.has(tileKey));
|
|
152
|
+
this._fallbackVisibleTileKeys = ensuredKeys.filter((tileKey) => fallbackKeySet.has(tileKey) && !baseTileKeys.has(tileKey));
|
|
153
|
+
this._visibleTileKeys = ensuredKeys.filter((tileKey) => !fallbackKeySet.has(tileKey) && !baseTileKeys.has(tileKey));
|
|
154
|
+
this.evictCache();
|
|
155
|
+
}
|
|
156
|
+
draw(input) {
|
|
157
|
+
const vMatrix = input.camera.getCameraMatrix();
|
|
158
|
+
if (!vMatrix)
|
|
159
|
+
return;
|
|
160
|
+
this.bootstrapTiles(input.fovDeg ?? 180, input.camera, input.centerSphericalDeg ?? null, input.fovPolygon ?? null, input.viewportSphericalSamples ?? null);
|
|
161
|
+
const pMatrix = input.pMatrix;
|
|
162
|
+
const mMatrix = this.getModelMatrix();
|
|
163
|
+
for (const tileKey of this._baseVisibleTileKeys) {
|
|
164
|
+
const tile = this._tileBuffer.getActiveTile(tileKey);
|
|
165
|
+
if (!tile)
|
|
166
|
+
continue;
|
|
167
|
+
tile.draw(pMatrix, vMatrix, mMatrix, this._tilePriorities.get(tileKey) ?? 0);
|
|
168
|
+
}
|
|
169
|
+
for (const tileKey of this._fallbackVisibleTileKeys) {
|
|
170
|
+
const tile = this._tileBuffer.getActiveTile(tileKey);
|
|
171
|
+
if (!tile)
|
|
172
|
+
continue;
|
|
173
|
+
tile.draw(pMatrix, vMatrix, mMatrix, this._tilePriorities.get(tileKey) ?? 0, false);
|
|
174
|
+
}
|
|
175
|
+
for (const tileKey of this._visibleTileKeys) {
|
|
176
|
+
const tile = this._tileBuffer.getActiveTile(tileKey);
|
|
177
|
+
if (tile?.ready) {
|
|
178
|
+
tile.draw(pMatrix, vMatrix, mMatrix, this._tilePriorities.get(tileKey) ?? 0);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const targetCoord = this.parseTileKey(tileKey);
|
|
182
|
+
if (targetCoord) {
|
|
183
|
+
const ancestorTile = this.findBestAvailableAncestor(targetCoord);
|
|
184
|
+
if (ancestorTile) {
|
|
185
|
+
const ancestorMesh = this._ancestorMeshCache.getMesh(targetCoord, ancestorTile.coord, this._config.segmentsPerSide ?? 16);
|
|
186
|
+
ancestorTile.drawRemapped(ancestorMesh, pMatrix, vMatrix, mMatrix);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
tile?.draw(pMatrix, vMatrix, mMatrix, this._tilePriorities.get(tileKey) ?? 0);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
evictCache() {
|
|
193
|
+
const maxCachedTiles = this._config.maxCachedTiles ?? XYZLayer.DEFAULT_MAX_CACHED_TILES;
|
|
194
|
+
this._tileBuffer.evictCached(maxCachedTiles);
|
|
195
|
+
}
|
|
196
|
+
disposeTiles() {
|
|
197
|
+
this._tileBuffer.dispose();
|
|
198
|
+
this._ancestorMeshCache.dispose();
|
|
199
|
+
this._visibleTileKeys = [];
|
|
200
|
+
this._fallbackVisibleTileKeys = [];
|
|
201
|
+
this._baseVisibleTileKeys = [];
|
|
202
|
+
}
|
|
203
|
+
getTileKey(tileCoord) {
|
|
204
|
+
return `${tileCoord.z}/${tileCoord.x}/${tileCoord.y}`;
|
|
205
|
+
}
|
|
206
|
+
parseTileKey(tileKey) {
|
|
207
|
+
const [zRaw, xRaw, yRaw] = tileKey.split('/');
|
|
208
|
+
const z = Number.parseInt(zRaw ?? '', 10);
|
|
209
|
+
const x = Number.parseInt(xRaw ?? '', 10);
|
|
210
|
+
const y = Number.parseInt(yRaw ?? '', 10);
|
|
211
|
+
if (!Number.isFinite(z) || !Number.isFinite(x) || !Number.isFinite(y)) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
return { z, x, y };
|
|
215
|
+
}
|
|
216
|
+
findBestAvailableAncestor(targetCoord) {
|
|
217
|
+
for (let z = targetCoord.z - 1; z >= this._provider.minZoom; z--) {
|
|
218
|
+
const dz = targetCoord.z - z;
|
|
219
|
+
const ancestorCoord = {
|
|
220
|
+
z,
|
|
221
|
+
x: targetCoord.x >> dz,
|
|
222
|
+
y: targetCoord.y >> dz,
|
|
223
|
+
};
|
|
224
|
+
const ancestor = this._tileBuffer.getAnyTile(this.getTileKey(ancestorCoord));
|
|
225
|
+
if (ancestor?.ready) {
|
|
226
|
+
return ancestor;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { XYZTileCoord, XYZTileMesh, XYZTileGpuMesh } from './types.js';
|
|
2
|
+
export declare class XYZMeshBuilder {
|
|
3
|
+
buildTileMesh(tile: XYZTileCoord, segmentsPerSide?: number): XYZTileMesh;
|
|
4
|
+
buildAncestorMesh(targetTile: XYZTileCoord, ancestorTile: XYZTileCoord, segmentsPerSide?: number): XYZTileMesh;
|
|
5
|
+
uploadMesh(mesh: XYZTileMesh, webgl: WebGL2RenderingContext): XYZTileGpuMesh;
|
|
6
|
+
}
|