astro-viewer 3.0.0 → 3.2.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 +3082 -1410
- package/dist/astroviewer.js +1 -1
- package/dist/astroviewer.min.js +1 -1
- package/lib-esm/AstroSphere.d.ts +40 -16
- package/lib-esm/AstroSphere.js +359 -93
- package/lib-esm/AstroViewer.d.ts +20 -5
- package/lib-esm/AstroViewer.js +50 -0
- package/lib-esm/Camera.js +28 -14
- package/lib-esm/Config.d.ts +2 -0
- package/lib-esm/Config.js +15 -1
- package/lib-esm/Global.js +12 -0
- package/lib-esm/index.d.ts +8 -4
- package/lib-esm/index.js +17 -3
- package/lib-esm/model/AbstractSkyEntity.d.ts +1 -0
- package/lib-esm/model/AbstractSkyEntity.js +12 -0
- package/lib-esm/model/AstroGL.js +12 -0
- package/lib-esm/model/ColorMaps.js +12 -0
- package/lib-esm/model/MetadataColumn.js +12 -0
- package/lib-esm/model/MetadataManager.d.ts +1 -0
- package/lib-esm/model/MetadataManager.js +16 -1
- package/lib-esm/model/Point.d.ts +9 -1
- package/lib-esm/model/Point.js +30 -0
- package/lib-esm/model/Point2D.js +12 -0
- package/lib-esm/model/Source.js +12 -0
- package/lib-esm/model/SphereFoV.d.ts +30 -0
- package/lib-esm/model/SphereFoV.js +196 -0
- package/lib-esm/model/catalogues/CatalogueGL.js +12 -0
- package/lib-esm/model/catalogues/CatalogueProps.js +13 -1
- package/lib-esm/model/earth/{wmts/WMTSAdapter.d.ts → WMTSAdapter.d.ts} +2 -1
- package/lib-esm/model/earth/{wmts/WMTSAdapter.js → WMTSAdapter.js} +12 -0
- package/lib-esm/model/earth/XYZAnchestorTile.d.ts +17 -0
- package/lib-esm/model/earth/XYZAnchestorTile.js +87 -0
- package/lib-esm/model/earth/{types.d.ts → XYZConfig.d.ts} +6 -17
- package/lib-esm/model/earth/XYZConfig.js +13 -0
- package/lib-esm/model/earth/XYZFoVHelper.d.ts +12 -0
- package/lib-esm/model/earth/XYZFoVHelper.js +138 -0
- package/lib-esm/model/earth/XYZMap.d.ts +31 -0
- package/lib-esm/model/earth/XYZMap.js +208 -0
- package/lib-esm/model/earth/XYZMapDescriptor.d.ts +29 -0
- package/lib-esm/model/earth/XYZMapDescriptor.js +77 -0
- package/lib-esm/model/earth/XYZMeshBuilder.d.ts +1 -1
- package/lib-esm/model/earth/XYZMeshBuilder.js +13 -2
- package/lib-esm/model/earth/XYZTile.d.ts +20 -21
- package/lib-esm/model/earth/XYZTile.js +82 -102
- package/lib-esm/model/earth/XYZTileBuffer.d.ts +24 -26
- package/lib-esm/model/earth/XYZTileBuffer.js +60 -70
- package/lib-esm/model/earth/XYZTileRequestScheduler.d.ts +1 -1
- package/lib-esm/model/earth/XYZTileRequestScheduler.js +13 -2
- package/lib-esm/model/earth/XYZTypes.d.ts +24 -0
- package/lib-esm/model/earth/XYZTypes.js +13 -0
- package/lib-esm/model/earth/XYZVisibleTilesManager.d.ts +16 -27
- package/lib-esm/model/earth/XYZVisibleTilesManager.js +61 -192
- package/lib-esm/model/footprints/Footprint.d.ts +4 -1
- package/lib-esm/model/footprints/Footprint.js +30 -2
- package/lib-esm/model/footprints/FootprintProps.js +13 -1
- package/lib-esm/model/footprints/FootprintSetGL.d.ts +4 -2
- package/lib-esm/model/footprints/FootprintSetGL.js +21 -6
- package/lib-esm/model/grid/EquatorialGrid.d.ts +2 -1
- package/lib-esm/model/grid/EquatorialGrid.js +30 -12
- package/lib-esm/model/grid/GridTextHelper.d.ts +10 -19
- package/lib-esm/model/grid/GridTextHelper.js +70 -67
- package/lib-esm/model/grid/HealpixGrid.d.ts +4 -4
- package/lib-esm/model/grid/HealpixGrid.js +24 -8
- package/lib-esm/model/grid/LonLatGrid.d.ts +43 -0
- package/lib-esm/model/grid/LonLatGrid.js +309 -0
- package/lib-esm/model/hips/AllSky.js +12 -0
- package/lib-esm/model/hips/AncestorTile.js +12 -0
- package/lib-esm/model/hips/FoVHelper.d.ts +5 -2
- package/lib-esm/model/hips/FoVHelper.js +52 -3
- package/lib-esm/model/hips/HiPS.d.ts +2 -0
- package/lib-esm/model/hips/HiPS.js +38 -14
- package/lib-esm/model/hips/HiPSConfig.d.ts +13 -0
- package/lib-esm/model/hips/HiPSDescriptor.js +12 -0
- package/lib-esm/model/hips/Tile.d.ts +1 -0
- package/lib-esm/model/hips/Tile.js +15 -0
- package/lib-esm/model/hips/TileBuffer.d.ts +5 -0
- package/lib-esm/model/hips/TileBuffer.js +61 -0
- package/lib-esm/model/hips/VisibleTilesManager.js +12 -0
- package/lib-esm/model/tap/TapMetadata.js +12 -0
- package/lib-esm/model/tap/TapMetadataList.js +12 -0
- package/lib-esm/model/tap/TapRepo.js +12 -0
- package/lib-esm/model/terra/TerraFootprintSetGL.d.ts +6 -0
- package/lib-esm/model/terra/TerraFootprintSetGL.js +54 -0
- package/lib-esm/model/terra/TerraPointSetGL.js +12 -0
- package/lib-esm/services/SesameService.js +11 -3
- package/lib-esm/services/helpers.js +12 -0
- package/lib-esm/services/hipsNodeService.js +12 -0
- package/lib-esm/services/parse-hipslist.js +12 -0
- package/lib-esm/services/queryCatalogueByFoV.js +13 -1
- package/lib-esm/services/queryFootprintSetByFov.js +13 -1
- package/lib-esm/services/tapRepoService.js +13 -1
- package/lib-esm/services/types.js +12 -0
- package/lib-esm/shader/CatalogueShaderProgram.js +12 -0
- package/lib-esm/shader/FootprintShaderProgram.js +12 -0
- package/lib-esm/shader/GridShaderManager.js +12 -0
- package/lib-esm/shader/HiPSShaderProgram.js +12 -0
- package/lib-esm/shader/ShaderManager.js +12 -1
- package/lib-esm/shader/ShaderManagerMutliHiPS.js +12 -1
- package/lib-esm/shader/XYZShaderProgram.d.ts +14 -1
- package/lib-esm/shader/XYZShaderProgram.js +127 -2
- package/lib-esm/utils/CoordsType.d.ts +2 -1
- package/lib-esm/utils/CoordsType.js +13 -0
- package/lib-esm/utils/FoVUtils.js +12 -0
- package/lib-esm/utils/GeoJSONParser.d.ts +19 -0
- package/lib-esm/utils/GeoJSONParser.js +112 -0
- package/lib-esm/utils/GeomUtils.js +12 -0
- package/lib-esm/utils/MouseHelper.js +12 -0
- package/lib-esm/utils/PerspectiveMatrixManager.js +16 -1
- package/lib-esm/utils/RayPickingUtils.js +12 -0
- package/lib-esm/utils/STCSParser.d.ts +7 -3
- package/lib-esm/utils/STCSParser.js +27 -9
- package/lib-esm/utils/ShaderUtility.js +13 -1
- package/lib-esm/utils/Utils.js +12 -0
- package/lib-esm/utils/XYZRayPickingUtils.d.ts +27 -0
- package/lib-esm/utils/XYZRayPickingUtils.js +226 -0
- package/package.json +2 -2
- package/lib-esm/model/FoV.d.ts +0 -62
- package/lib-esm/model/FoV.js +0 -274
- package/lib-esm/model/earth/XYZAncestorMeshCache.d.ts +0 -10
- package/lib-esm/model/earth/XYZAncestorMeshCache.js +0 -31
- package/lib-esm/model/earth/XYZLayer.d.ts +0 -31
- package/lib-esm/model/earth/XYZLayer.js +0 -231
- package/lib-esm/model/earth/XYZTileProvider.d.ts +0 -29
- package/lib-esm/model/earth/XYZTileProvider.js +0 -187
- package/lib-esm/model/earth/wmts/types.d.ts +0 -1
- package/lib-esm/model/earth/wmts/types.js +0 -1
- /package/lib-esm/model/{earth/types.js → hips/HiPSConfig.js} +0 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* AstroViewer
|
|
3
|
+
* Copyright (C) Fabrizio Giordano
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-AstroViewer-Dual-License
|
|
5
|
+
*
|
|
6
|
+
* This file is part of AstroViewer.
|
|
7
|
+
* AstroViewer is distributed under a dual-license model.
|
|
8
|
+
* Commercial use requires a separate commercial license.
|
|
9
|
+
* Non-commercial use is governed by LICENSE-NONCOMMERCIAL.md.
|
|
10
|
+
*
|
|
11
|
+
* See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
|
|
12
|
+
*/
|
|
13
|
+
import { AbstractSkyEntity } from "../AbstractSkyEntity.js";
|
|
14
|
+
import { XYZVisibleTilesManager } from "./XYZVisibleTilesManager.js";
|
|
15
|
+
import { xyzFovHelper } from "./XYZFoVHelper.js";
|
|
16
|
+
import { ColorMaps } from "../ColorMaps.js";
|
|
17
|
+
import { LatLonGrid } from "../grid/LonLatGrid.js";
|
|
18
|
+
import { XYZShaderProgram } from "../../shader/XYZShaderProgram.js";
|
|
19
|
+
import { XYZTileBuffer } from "./XYZTileBuffer.js";
|
|
20
|
+
import { XYZAnchestorTile } from "./XYZAnchestorTile.js";
|
|
21
|
+
import { XYZMeshBuilder } from "./XYZMeshBuilder.js";
|
|
22
|
+
export class XYZMap extends AbstractSkyEntity {
|
|
23
|
+
_xyzShaderProgram;
|
|
24
|
+
_descriptor;
|
|
25
|
+
_visibleTilesManager;
|
|
26
|
+
_tileBuffer;
|
|
27
|
+
_meshBuilder;
|
|
28
|
+
_baseurl;
|
|
29
|
+
_zoom;
|
|
30
|
+
_latLonGrid;
|
|
31
|
+
_colorMapIdx = 0;
|
|
32
|
+
_colorMap = ColorMaps['native'];
|
|
33
|
+
constructor(radius, position, xrad, yrad, descriptor, webgl) {
|
|
34
|
+
super(radius, position, xrad, yrad, descriptor.name, webgl, false);
|
|
35
|
+
this._descriptor = descriptor;
|
|
36
|
+
this._xyzShaderProgram = new XYZShaderProgram(webgl);
|
|
37
|
+
this._meshBuilder = new XYZMeshBuilder();
|
|
38
|
+
this._tileBuffer = new XYZTileBuffer(1);
|
|
39
|
+
this.initGL(webgl);
|
|
40
|
+
this._latLonGrid = new LatLonGrid(radius, position, xrad, yrad, 'LatLonGrid', this._webgl);
|
|
41
|
+
this._visibleTilesManager = new XYZVisibleTilesManager();
|
|
42
|
+
this._baseurl = descriptor.url;
|
|
43
|
+
this.initShaders();
|
|
44
|
+
const fov = 180;
|
|
45
|
+
this._zoom = xyzFovHelper.getZoom(fov);
|
|
46
|
+
}
|
|
47
|
+
changeColorMap(colorMap) {
|
|
48
|
+
this._colorMap = colorMap;
|
|
49
|
+
switch (colorMap.name) {
|
|
50
|
+
case 'grayscale':
|
|
51
|
+
this._colorMapIdx = 1;
|
|
52
|
+
this._colorMap = ColorMaps['grayscale'];
|
|
53
|
+
break;
|
|
54
|
+
case 'planck':
|
|
55
|
+
this._colorMapIdx = 2;
|
|
56
|
+
this._colorMap = ColorMaps['planck'];
|
|
57
|
+
break;
|
|
58
|
+
case 'cmb':
|
|
59
|
+
this._colorMapIdx = 3;
|
|
60
|
+
this._colorMap = ColorMaps['cmb'];
|
|
61
|
+
break;
|
|
62
|
+
case 'rainbow':
|
|
63
|
+
this._colorMapIdx = 4;
|
|
64
|
+
this._colorMap = ColorMaps['rainbow'];
|
|
65
|
+
break;
|
|
66
|
+
case 'eosb':
|
|
67
|
+
this._colorMapIdx = 5;
|
|
68
|
+
this._colorMap = ColorMaps['eosb'];
|
|
69
|
+
break;
|
|
70
|
+
case 'cubehelix':
|
|
71
|
+
this._colorMapIdx = 6;
|
|
72
|
+
this._colorMap = ColorMaps['cubehelix'];
|
|
73
|
+
break;
|
|
74
|
+
case 'hot':
|
|
75
|
+
this._colorMapIdx = 7;
|
|
76
|
+
this._colorMap = ColorMaps['hot'];
|
|
77
|
+
break;
|
|
78
|
+
case 'gray':
|
|
79
|
+
this._colorMapIdx = 8;
|
|
80
|
+
this._colorMap = ColorMaps['gray'];
|
|
81
|
+
break;
|
|
82
|
+
case 'native':
|
|
83
|
+
this._colorMapIdx = 0;
|
|
84
|
+
this._colorMap = ColorMaps['native'];
|
|
85
|
+
break;
|
|
86
|
+
default:
|
|
87
|
+
this._colorMapIdx = 9;
|
|
88
|
+
this._colorMap = colorMap;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
initShaders() {
|
|
92
|
+
this._xyzShaderProgram.enableProgram();
|
|
93
|
+
}
|
|
94
|
+
isLonLatGridVisible() {
|
|
95
|
+
return this._latLonGrid.isVisible();
|
|
96
|
+
}
|
|
97
|
+
toggleLonLatGrid() {
|
|
98
|
+
return this._latLonGrid.toggleShowGrid();
|
|
99
|
+
}
|
|
100
|
+
getFoV() {
|
|
101
|
+
return this._latLonGrid.getFoV();
|
|
102
|
+
}
|
|
103
|
+
refresh(input) {
|
|
104
|
+
const fov = this._latLonGrid.refreshFoV(input);
|
|
105
|
+
// this._zoom = this.resolveVisibleZoom(fov)
|
|
106
|
+
this._zoom = xyzFovHelper.getZoom(fov);
|
|
107
|
+
}
|
|
108
|
+
draw(input) {
|
|
109
|
+
const vMatrix = input.camera.getCameraMatrix();
|
|
110
|
+
if (!vMatrix)
|
|
111
|
+
return;
|
|
112
|
+
const pMatrix = input.pMatrix;
|
|
113
|
+
if (!pMatrix)
|
|
114
|
+
return;
|
|
115
|
+
this.refresh(input);
|
|
116
|
+
const mMatrix = this.getModelMatrix();
|
|
117
|
+
this._xyzShaderProgram.setRuntimeColorMap(this._colorMap);
|
|
118
|
+
const tileSelection = this._visibleTilesManager.computeVisibleTiles(this._zoom, this, this._webgl, input.camera, input.pMatrix);
|
|
119
|
+
const visibleTiles = tileSelection.visibleTiles;
|
|
120
|
+
const ancestorsMap = tileSelection.ancestorsMap;
|
|
121
|
+
const tileKeys = this._tileBuffer.ensureTiles(this.getTilesToEnsure(visibleTiles, ancestorsMap), (coord) => this.createTile(coord));
|
|
122
|
+
this._tileBuffer.evictCached(this._descriptor.maxCachedTiles);
|
|
123
|
+
for (const tileKey of tileKeys) {
|
|
124
|
+
const tile = this._tileBuffer.getActiveTile(tileKey);
|
|
125
|
+
if (!tile || tile.coord.z !== tileSelection.currentZoom) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const drawn = tile.draw(pMatrix, vMatrix, mMatrix, this._colorMapIdx);
|
|
129
|
+
if (drawn) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const ancestorTile = this.findBestAvailableAncestor(tile.coord);
|
|
133
|
+
ancestorTile?.draw(tileSelection.currentZoom, [tile.coord], ancestorsMap, pMatrix, vMatrix, mMatrix, this._colorMapIdx);
|
|
134
|
+
}
|
|
135
|
+
this._latLonGrid.draw(input);
|
|
136
|
+
}
|
|
137
|
+
createTile(coord) {
|
|
138
|
+
return new XYZAnchestorTile(coord, this.resolveTileUrl(coord), this._webgl, this._xyzShaderProgram, this._meshBuilder, this._descriptor.segmentsPerSide);
|
|
139
|
+
}
|
|
140
|
+
getTilesToEnsure(visibleTiles, ancestorsMap) {
|
|
141
|
+
const tilesByKey = new Map();
|
|
142
|
+
for (const tile of visibleTiles) {
|
|
143
|
+
tilesByKey.set(this.tileKey(tile), tile);
|
|
144
|
+
}
|
|
145
|
+
for (const ancestor of ancestorsMap.values()) {
|
|
146
|
+
tilesByKey.set(this.tileKey(ancestor), ancestor);
|
|
147
|
+
}
|
|
148
|
+
return Array.from(tilesByKey.values());
|
|
149
|
+
}
|
|
150
|
+
findBestAvailableAncestor(targetTile) {
|
|
151
|
+
for (let z = targetTile.z - 1; z >= 0; z--) {
|
|
152
|
+
const dz = targetTile.z - z;
|
|
153
|
+
const ancestorCoord = {
|
|
154
|
+
z,
|
|
155
|
+
x: targetTile.x >> dz,
|
|
156
|
+
y: targetTile.y >> dz,
|
|
157
|
+
};
|
|
158
|
+
const ancestorTile = this._tileBuffer.getAnyTile(this.tileKey(ancestorCoord));
|
|
159
|
+
if (ancestorTile?.ready) {
|
|
160
|
+
return ancestorTile;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
resolveTileUrl(tile) {
|
|
166
|
+
const urlResolver = this._descriptor.urlResolver;
|
|
167
|
+
if (urlResolver) {
|
|
168
|
+
return urlResolver(tile);
|
|
169
|
+
}
|
|
170
|
+
const dim = 2 ** tile.z;
|
|
171
|
+
const y = this._descriptor.flipY ? dim - 1 - tile.y : tile.y;
|
|
172
|
+
const subdomains = this._descriptor.subdomains;
|
|
173
|
+
const subdomain = subdomains.length > 0
|
|
174
|
+
? subdomains[Math.abs(tile.x + tile.y + tile.z) % subdomains.length]
|
|
175
|
+
: '';
|
|
176
|
+
return this._baseurl
|
|
177
|
+
.replace(/\{z\}/g, String(tile.z))
|
|
178
|
+
.replace(/\{x\}/g, String(tile.x))
|
|
179
|
+
.replace(/\{y\}/g, String(y))
|
|
180
|
+
.replace(/\{s\}/g, subdomain ?? '');
|
|
181
|
+
}
|
|
182
|
+
getDebugStats() {
|
|
183
|
+
const activeTiles = Array.from(this._tileBuffer.activeTiles.values(), (entry) => entry.tile);
|
|
184
|
+
const cachedTiles = Array.from(this._tileBuffer.cachedTiles.values(), (entry) => entry.tile);
|
|
185
|
+
const allTiles = [...activeTiles, ...cachedTiles];
|
|
186
|
+
const selection = this._visibleTilesManager.selection;
|
|
187
|
+
return {
|
|
188
|
+
cacheSize: this._tileBuffer.size,
|
|
189
|
+
visibleTileCount: selection.visibleTiles.length,
|
|
190
|
+
currentTileCount: activeTiles.filter((tile) => tile.coord.z === selection.currentZoom).length,
|
|
191
|
+
fallbackTileCount: selection.ancestorsMap.size,
|
|
192
|
+
coreTileCount: selection.visibleTiles.length,
|
|
193
|
+
coverageTileCount: selection.visibleTiles.length,
|
|
194
|
+
readyTileCount: allTiles.filter((tile) => tile.ready).length,
|
|
195
|
+
loadingTileCount: allTiles.filter((tile) => tile.loading).length,
|
|
196
|
+
coolingDownTileCount: 0,
|
|
197
|
+
currentZoom: selection.currentZoom,
|
|
198
|
+
tileSelectionKey: selection.key,
|
|
199
|
+
isSettling: false,
|
|
200
|
+
coarseTileCount: selection.ancestorsMap.size,
|
|
201
|
+
hasPendingSelection: false,
|
|
202
|
+
pendingSelectionKey: null,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
tileKey(tile) {
|
|
206
|
+
return `${tile.z}/${tile.x}/${tile.y}`;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { XYZTileCoord } from './XYZTypes.js';
|
|
2
|
+
export declare class XYZMapDescriptor {
|
|
3
|
+
_name: string;
|
|
4
|
+
_url: string;
|
|
5
|
+
_urlResolver?: (tile: XYZTileCoord) => string;
|
|
6
|
+
_minZoom?: number;
|
|
7
|
+
_maxZoom?: number;
|
|
8
|
+
_segmentsPerSide?: number;
|
|
9
|
+
_tileSize?: number;
|
|
10
|
+
_maxCachedTiles?: number;
|
|
11
|
+
_interactionDebounceMs?: number;
|
|
12
|
+
_subdomains?: string[];
|
|
13
|
+
_attribution?: string;
|
|
14
|
+
_flipY?: boolean;
|
|
15
|
+
_maxConcurrentLoads?: number;
|
|
16
|
+
constructor(name: string, url: string, minZoom?: number, maxZoom?: number, segmentsPerSide?: number, maxCachedTiles?: number, maxConcurrentLoads?: number, urlResolver?: (tile: XYZTileCoord) => string);
|
|
17
|
+
get url(): string;
|
|
18
|
+
get urlResolver(): ((tile: XYZTileCoord) => string) | undefined;
|
|
19
|
+
get name(): string;
|
|
20
|
+
get minZoom(): number;
|
|
21
|
+
get maxZoom(): number;
|
|
22
|
+
get segmentsPerSide(): number;
|
|
23
|
+
get maxCachedTiles(): number;
|
|
24
|
+
get interactionDebounceMs(): number;
|
|
25
|
+
get subdomains(): string[];
|
|
26
|
+
get attribution(): string;
|
|
27
|
+
get flipY(): boolean;
|
|
28
|
+
get maxConcurrentLoads(): number;
|
|
29
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* AstroViewer
|
|
3
|
+
* Copyright (C) Fabrizio Giordano
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-AstroViewer-Dual-License
|
|
5
|
+
*
|
|
6
|
+
* This file is part of AstroViewer.
|
|
7
|
+
* AstroViewer is distributed under a dual-license model.
|
|
8
|
+
* Commercial use requires a separate commercial license.
|
|
9
|
+
* Non-commercial use is governed by LICENSE-NONCOMMERCIAL.md.
|
|
10
|
+
*
|
|
11
|
+
* See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
|
|
12
|
+
*/
|
|
13
|
+
export class XYZMapDescriptor {
|
|
14
|
+
_name;
|
|
15
|
+
_url;
|
|
16
|
+
_urlResolver;
|
|
17
|
+
_minZoom;
|
|
18
|
+
_maxZoom;
|
|
19
|
+
_segmentsPerSide;
|
|
20
|
+
_tileSize;
|
|
21
|
+
_maxCachedTiles;
|
|
22
|
+
_interactionDebounceMs;
|
|
23
|
+
_subdomains;
|
|
24
|
+
_attribution;
|
|
25
|
+
_flipY;
|
|
26
|
+
_maxConcurrentLoads;
|
|
27
|
+
constructor(name, url, minZoom = 0, maxZoom = 8, segmentsPerSide = 16, maxCachedTiles = 384, maxConcurrentLoads = 8, urlResolver) {
|
|
28
|
+
this._name = name;
|
|
29
|
+
this._url = url;
|
|
30
|
+
this._urlResolver = urlResolver;
|
|
31
|
+
this._minZoom = minZoom;
|
|
32
|
+
this._maxZoom = maxZoom;
|
|
33
|
+
this._segmentsPerSide = segmentsPerSide;
|
|
34
|
+
this._maxCachedTiles = maxCachedTiles;
|
|
35
|
+
this._interactionDebounceMs = 100;
|
|
36
|
+
this._subdomains = ['a', 'b', 'c'];
|
|
37
|
+
this._attribution = '';
|
|
38
|
+
this._flipY = false;
|
|
39
|
+
this._maxConcurrentLoads = maxConcurrentLoads;
|
|
40
|
+
}
|
|
41
|
+
get url() {
|
|
42
|
+
return this._url;
|
|
43
|
+
}
|
|
44
|
+
get urlResolver() {
|
|
45
|
+
return this._urlResolver;
|
|
46
|
+
}
|
|
47
|
+
get name() {
|
|
48
|
+
return this._name;
|
|
49
|
+
}
|
|
50
|
+
get minZoom() {
|
|
51
|
+
return this._minZoom;
|
|
52
|
+
}
|
|
53
|
+
get maxZoom() {
|
|
54
|
+
return this._maxZoom;
|
|
55
|
+
}
|
|
56
|
+
get segmentsPerSide() {
|
|
57
|
+
return this._segmentsPerSide;
|
|
58
|
+
}
|
|
59
|
+
get maxCachedTiles() {
|
|
60
|
+
return this._maxCachedTiles;
|
|
61
|
+
}
|
|
62
|
+
get interactionDebounceMs() {
|
|
63
|
+
return this._interactionDebounceMs;
|
|
64
|
+
}
|
|
65
|
+
get subdomains() {
|
|
66
|
+
return this._subdomains;
|
|
67
|
+
}
|
|
68
|
+
get attribution() {
|
|
69
|
+
return this._attribution;
|
|
70
|
+
}
|
|
71
|
+
get flipY() {
|
|
72
|
+
return this._flipY;
|
|
73
|
+
}
|
|
74
|
+
get maxConcurrentLoads() {
|
|
75
|
+
return this._maxConcurrentLoads;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { XYZTileCoord,
|
|
1
|
+
import type { XYZTileCoord, XYZTileGpuMesh, XYZTileMesh } from './XYZTypes.js';
|
|
2
2
|
export declare class XYZMeshBuilder {
|
|
3
3
|
buildTileMesh(tile: XYZTileCoord, segmentsPerSide?: number): XYZTileMesh;
|
|
4
4
|
buildAncestorMesh(targetTile: XYZTileCoord, ancestorTile: XYZTileCoord, segmentsPerSide?: number): XYZTileMesh;
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* AstroViewer
|
|
3
|
+
* Copyright (C) Fabrizio Giordano
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-AstroViewer-Dual-License
|
|
5
|
+
*
|
|
6
|
+
* This file is part of AstroViewer.
|
|
7
|
+
* AstroViewer is distributed under a dual-license model.
|
|
8
|
+
* Commercial use requires a separate commercial license.
|
|
9
|
+
* Non-commercial use is governed by LICENSE-NONCOMMERCIAL.md.
|
|
10
|
+
*
|
|
11
|
+
* See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
|
|
12
|
+
*/
|
|
1
13
|
import { sphericalToCartesian } from '../../utils/Utils.js';
|
|
2
14
|
const MAX_MERCATOR_LAT = 85.0511287798066;
|
|
3
15
|
function mercatorYToLatDeg(yNormalized) {
|
|
@@ -35,8 +47,7 @@ export class XYZMeshBuilder {
|
|
|
35
47
|
uvs[uv++] = 1 - v;
|
|
36
48
|
}
|
|
37
49
|
}
|
|
38
|
-
const
|
|
39
|
-
const rawIndices = new Uint32Array(triangleCount * 3);
|
|
50
|
+
const rawIndices = new Uint32Array(segments * segments * 2 * 3);
|
|
40
51
|
let i = 0;
|
|
41
52
|
for (let row = 0; row < segments; row++) {
|
|
42
53
|
for (let col = 0; col < segments; col++) {
|
|
@@ -1,39 +1,38 @@
|
|
|
1
1
|
import { XYZShaderProgram } from '../../shader/XYZShaderProgram.js';
|
|
2
|
-
import type {
|
|
3
|
-
|
|
2
|
+
import type { XYZBufferedTile } from './XYZTileBuffer.js';
|
|
3
|
+
import { XYZMeshBuilder } from './XYZMeshBuilder.js';
|
|
4
|
+
import type { XYZTileCoord, XYZTileGpuMesh } from './XYZTypes.js';
|
|
5
|
+
type Mat4 = Float32Array;
|
|
6
|
+
export declare class XYZTile implements XYZBufferedTile {
|
|
4
7
|
private _coord;
|
|
5
8
|
private _url;
|
|
6
9
|
private _webgl;
|
|
7
10
|
private _shaderProgram;
|
|
8
|
-
private
|
|
9
|
-
private
|
|
10
|
-
private _indexBuffer;
|
|
11
|
+
private _meshBuilder;
|
|
12
|
+
private _gpuMesh;
|
|
11
13
|
private _texture;
|
|
12
|
-
private
|
|
13
|
-
private _indexType;
|
|
14
|
+
private _image?;
|
|
14
15
|
private _ready;
|
|
15
|
-
private _aborted;
|
|
16
16
|
private _loading;
|
|
17
|
+
private _aborted;
|
|
17
18
|
private _failedUntil;
|
|
18
19
|
private _lastUsedAt;
|
|
19
20
|
private _createdAt;
|
|
20
|
-
|
|
21
|
-
private _objectUrl;
|
|
22
|
-
constructor(coord: XYZTileCoord, url: string, mesh: XYZTileMesh, webgl: WebGL2RenderingContext, shaderProgram: XYZShaderProgram);
|
|
23
|
-
get ready(): boolean;
|
|
21
|
+
constructor(coord: XYZTileCoord, url: string, webgl: WebGL2RenderingContext, shaderProgram: XYZShaderProgram, meshBuilder?: XYZMeshBuilder, segmentsPerSide?: number);
|
|
24
22
|
get coord(): XYZTileCoord;
|
|
25
|
-
get
|
|
23
|
+
get ready(): boolean;
|
|
26
24
|
get loading(): boolean;
|
|
25
|
+
get failedUntil(): number;
|
|
27
26
|
get lastUsedAt(): number;
|
|
28
27
|
get createdAt(): number;
|
|
29
28
|
touch(): void;
|
|
30
|
-
|
|
31
|
-
private
|
|
32
|
-
private
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
drawRemapped(mesh: XYZTileGpuMesh, pMatrix: Float32Array, vMatrix: Float32Array, mMatrix: Float32Array): void;
|
|
36
|
-
private drawWithGpuMesh;
|
|
29
|
+
private initImage;
|
|
30
|
+
private imageLoaded;
|
|
31
|
+
private textureLoaded;
|
|
32
|
+
draw(pMatrix: Mat4, vMatrix: Mat4, mMatrix: Mat4, colorMapIdx: number): boolean;
|
|
33
|
+
drawRemapped(mesh: XYZTileGpuMesh, pMatrix: Mat4, vMatrix: Mat4, mMatrix: Mat4, colorMapIdx: number): boolean;
|
|
37
34
|
dispose(): void;
|
|
38
|
-
private
|
|
35
|
+
private drawWithGpuMesh;
|
|
36
|
+
private get key();
|
|
39
37
|
}
|
|
38
|
+
export {};
|
|
@@ -1,52 +1,53 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
|
+
* AstroViewer
|
|
3
|
+
* Copyright (C) Fabrizio Giordano
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-AstroViewer-Dual-License
|
|
5
|
+
*
|
|
6
|
+
* This file is part of AstroViewer.
|
|
7
|
+
* AstroViewer is distributed under a dual-license model.
|
|
8
|
+
* Commercial use requires a separate commercial license.
|
|
9
|
+
* Non-commercial use is governed by LICENSE-NONCOMMERCIAL.md.
|
|
10
|
+
*
|
|
11
|
+
* See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
|
|
12
|
+
*/
|
|
13
|
+
import { XYZMeshBuilder } from './XYZMeshBuilder.js';
|
|
2
14
|
export class XYZTile {
|
|
3
15
|
_coord;
|
|
4
16
|
_url;
|
|
5
17
|
_webgl;
|
|
6
18
|
_shaderProgram;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
_indexBuffer;
|
|
19
|
+
_meshBuilder;
|
|
20
|
+
_gpuMesh;
|
|
10
21
|
_texture = null;
|
|
11
|
-
|
|
12
|
-
_indexType;
|
|
22
|
+
_image;
|
|
13
23
|
_ready = false;
|
|
14
|
-
_aborted = false;
|
|
15
24
|
_loading = false;
|
|
25
|
+
_aborted = false;
|
|
16
26
|
_failedUntil = 0;
|
|
17
27
|
_lastUsedAt = 0;
|
|
18
28
|
_createdAt = Date.now();
|
|
19
|
-
|
|
20
|
-
_objectUrl = null;
|
|
21
|
-
constructor(coord, url, mesh, webgl, shaderProgram) {
|
|
29
|
+
constructor(coord, url, webgl, shaderProgram, meshBuilder = new XYZMeshBuilder(), segmentsPerSide = 16) {
|
|
22
30
|
this._coord = coord;
|
|
23
31
|
this._url = url;
|
|
24
32
|
this._webgl = webgl;
|
|
25
33
|
this._shaderProgram = shaderProgram;
|
|
26
|
-
this.
|
|
27
|
-
|
|
28
|
-
this.
|
|
29
|
-
this.
|
|
30
|
-
this._indexType = mesh.indices instanceof Uint32Array ? webgl.UNSIGNED_INT : webgl.UNSIGNED_SHORT;
|
|
31
|
-
webgl.bindBuffer(webgl.ARRAY_BUFFER, this._positionBuffer);
|
|
32
|
-
webgl.bufferData(webgl.ARRAY_BUFFER, mesh.positions, webgl.STATIC_DRAW);
|
|
33
|
-
webgl.bindBuffer(webgl.ARRAY_BUFFER, this._uvBuffer);
|
|
34
|
-
webgl.bufferData(webgl.ARRAY_BUFFER, mesh.uvs, webgl.STATIC_DRAW);
|
|
35
|
-
webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
|
|
36
|
-
webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, mesh.indices, webgl.STATIC_DRAW);
|
|
37
|
-
}
|
|
38
|
-
get ready() {
|
|
39
|
-
return this._ready;
|
|
34
|
+
this._meshBuilder = meshBuilder;
|
|
35
|
+
const mesh = this._meshBuilder.buildTileMesh(coord, segmentsPerSide);
|
|
36
|
+
this._gpuMesh = this._meshBuilder.uploadMesh(mesh, this._webgl);
|
|
37
|
+
this.initImage();
|
|
40
38
|
}
|
|
41
39
|
get coord() {
|
|
42
40
|
return this._coord;
|
|
43
41
|
}
|
|
44
|
-
get
|
|
45
|
-
return this.
|
|
42
|
+
get ready() {
|
|
43
|
+
return this._ready;
|
|
46
44
|
}
|
|
47
45
|
get loading() {
|
|
48
46
|
return this._loading;
|
|
49
47
|
}
|
|
48
|
+
get failedUntil() {
|
|
49
|
+
return this._failedUntil;
|
|
50
|
+
}
|
|
50
51
|
get lastUsedAt() {
|
|
51
52
|
return this._lastUsedAt;
|
|
52
53
|
}
|
|
@@ -56,10 +57,7 @@ export class XYZTile {
|
|
|
56
57
|
touch() {
|
|
57
58
|
this._lastUsedAt = Date.now();
|
|
58
59
|
}
|
|
59
|
-
|
|
60
|
-
this.loadTexture(priority);
|
|
61
|
-
}
|
|
62
|
-
loadTexture(priority = 0) {
|
|
60
|
+
initImage() {
|
|
63
61
|
if (this._loading || this._ready || this._aborted) {
|
|
64
62
|
return;
|
|
65
63
|
}
|
|
@@ -68,80 +66,88 @@ export class XYZTile {
|
|
|
68
66
|
return;
|
|
69
67
|
}
|
|
70
68
|
this._loading = true;
|
|
71
|
-
xyzTileRequestScheduler.load(this._url, priority)
|
|
72
|
-
.then((blob) => this.loadImageFromBlob(blob))
|
|
73
|
-
.catch((error) => {
|
|
74
|
-
this._loading = false;
|
|
75
|
-
this._ready = false;
|
|
76
|
-
const cooldownMs = error instanceof XYZTileRequestError ? error.cooldownMs : 10000;
|
|
77
|
-
this._failedUntil = Date.now() + cooldownMs;
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
loadImageFromBlob(blob) {
|
|
81
69
|
const image = new Image();
|
|
82
70
|
this._image = image;
|
|
83
|
-
|
|
84
|
-
image.onload = () => this.
|
|
71
|
+
image.crossOrigin = 'anonymous';
|
|
72
|
+
image.onload = () => this.imageLoaded();
|
|
85
73
|
image.onerror = () => {
|
|
86
|
-
this._loading = false;
|
|
87
74
|
this._ready = false;
|
|
88
|
-
this.
|
|
89
|
-
this.
|
|
75
|
+
this._loading = false;
|
|
76
|
+
this._failedUntil = Date.now() + 30_000;
|
|
90
77
|
};
|
|
91
|
-
image.src = this.
|
|
78
|
+
image.src = this._url;
|
|
92
79
|
}
|
|
93
|
-
|
|
80
|
+
imageLoaded() {
|
|
94
81
|
if (!this._image || this._aborted) {
|
|
95
82
|
return;
|
|
96
83
|
}
|
|
84
|
+
this.textureLoaded(this._image);
|
|
85
|
+
this._loading = false;
|
|
86
|
+
this._failedUntil = 0;
|
|
87
|
+
this._ready = true;
|
|
88
|
+
}
|
|
89
|
+
textureLoaded(image) {
|
|
97
90
|
const gl = this._webgl;
|
|
91
|
+
this._shaderProgram.enableProgram();
|
|
98
92
|
const texture = gl.createTexture();
|
|
99
93
|
if (!texture) {
|
|
100
|
-
throw new Error(
|
|
94
|
+
throw new Error(`Could not create XYZ texture for ${this.key}`);
|
|
101
95
|
}
|
|
102
96
|
this._texture = texture;
|
|
103
97
|
gl.activeTexture(gl.TEXTURE0);
|
|
104
|
-
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
105
98
|
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
|
106
|
-
gl.
|
|
99
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
100
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
|
107
101
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
108
102
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
109
103
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
110
104
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
111
|
-
this._loading = false;
|
|
112
|
-
this._failedUntil = 0;
|
|
113
|
-
this._ready = true;
|
|
114
|
-
this.revokeObjectUrl();
|
|
115
105
|
}
|
|
116
|
-
draw(pMatrix, vMatrix, mMatrix,
|
|
106
|
+
draw(pMatrix, vMatrix, mMatrix, colorMapIdx) {
|
|
117
107
|
this.touch();
|
|
118
|
-
if (!this._ready
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
if (!this._ready || !this._texture) {
|
|
122
|
-
return;
|
|
108
|
+
if (!this._ready || !this._texture || this._aborted) {
|
|
109
|
+
return false;
|
|
123
110
|
}
|
|
124
|
-
this.drawWithGpuMesh(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
indexCount: this._indices.length,
|
|
129
|
-
indexType: this._indexType,
|
|
130
|
-
}, pMatrix, vMatrix, mMatrix);
|
|
131
|
-
}
|
|
132
|
-
drawRemapped(mesh, pMatrix, vMatrix, mMatrix) {
|
|
111
|
+
this.drawWithGpuMesh(this._gpuMesh, pMatrix, vMatrix, mMatrix, colorMapIdx);
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
drawRemapped(mesh, pMatrix, vMatrix, mMatrix, colorMapIdx) {
|
|
133
115
|
this.touch();
|
|
134
|
-
if (!this._ready || !this._texture) {
|
|
135
|
-
return;
|
|
116
|
+
if (!this._ready || !this._texture || this._aborted) {
|
|
117
|
+
return false;
|
|
136
118
|
}
|
|
137
|
-
this.drawWithGpuMesh(mesh, pMatrix, vMatrix, mMatrix);
|
|
119
|
+
this.drawWithGpuMesh(mesh, pMatrix, vMatrix, mMatrix, colorMapIdx);
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
dispose() {
|
|
123
|
+
const gl = this._webgl;
|
|
124
|
+
if (this._texture) {
|
|
125
|
+
gl.deleteTexture(this._texture);
|
|
126
|
+
this._texture = null;
|
|
127
|
+
}
|
|
128
|
+
if (this._gpuMesh.positionBuffer) {
|
|
129
|
+
gl.deleteBuffer(this._gpuMesh.positionBuffer);
|
|
130
|
+
this._gpuMesh.positionBuffer = null;
|
|
131
|
+
}
|
|
132
|
+
if (this._gpuMesh.uvBuffer) {
|
|
133
|
+
gl.deleteBuffer(this._gpuMesh.uvBuffer);
|
|
134
|
+
this._gpuMesh.uvBuffer = null;
|
|
135
|
+
}
|
|
136
|
+
if (this._gpuMesh.indexBuffer) {
|
|
137
|
+
gl.deleteBuffer(this._gpuMesh.indexBuffer);
|
|
138
|
+
this._gpuMesh.indexBuffer = null;
|
|
139
|
+
}
|
|
140
|
+
this._image = undefined;
|
|
141
|
+
this._ready = false;
|
|
142
|
+
this._loading = false;
|
|
143
|
+
this._aborted = true;
|
|
138
144
|
}
|
|
139
|
-
drawWithGpuMesh(mesh, pMatrix, vMatrix, mMatrix) {
|
|
145
|
+
drawWithGpuMesh(mesh, pMatrix, vMatrix, mMatrix, colorMapIdx) {
|
|
140
146
|
if (!this._texture) {
|
|
141
147
|
return;
|
|
142
148
|
}
|
|
143
149
|
const gl = this._webgl;
|
|
144
|
-
this._shaderProgram.enableShaders(pMatrix, vMatrix, mMatrix);
|
|
150
|
+
this._shaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx);
|
|
145
151
|
gl.bindBuffer(gl.ARRAY_BUFFER, mesh.positionBuffer);
|
|
146
152
|
gl.vertexAttribPointer(this._shaderProgram.locations.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
|
|
147
153
|
gl.enableVertexAttribArray(this._shaderProgram.locations.vertexPositionAttribute);
|
|
@@ -155,33 +161,7 @@ export class XYZTile {
|
|
|
155
161
|
gl.disableVertexAttribArray(this._shaderProgram.locations.vertexPositionAttribute);
|
|
156
162
|
gl.disableVertexAttribArray(this._shaderProgram.locations.textureCoordAttribute);
|
|
157
163
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (this._texture) {
|
|
161
|
-
gl.deleteTexture(this._texture);
|
|
162
|
-
this._texture = null;
|
|
163
|
-
}
|
|
164
|
-
if (this._positionBuffer) {
|
|
165
|
-
gl.deleteBuffer(this._positionBuffer);
|
|
166
|
-
this._positionBuffer = null;
|
|
167
|
-
}
|
|
168
|
-
if (this._uvBuffer) {
|
|
169
|
-
gl.deleteBuffer(this._uvBuffer);
|
|
170
|
-
this._uvBuffer = null;
|
|
171
|
-
}
|
|
172
|
-
if (this._indexBuffer) {
|
|
173
|
-
gl.deleteBuffer(this._indexBuffer);
|
|
174
|
-
this._indexBuffer = null;
|
|
175
|
-
}
|
|
176
|
-
this._image = undefined;
|
|
177
|
-
this.revokeObjectUrl();
|
|
178
|
-
this._loading = false;
|
|
179
|
-
this._ready = false;
|
|
180
|
-
}
|
|
181
|
-
revokeObjectUrl() {
|
|
182
|
-
if (this._objectUrl) {
|
|
183
|
-
URL.revokeObjectURL(this._objectUrl);
|
|
184
|
-
this._objectUrl = null;
|
|
185
|
-
}
|
|
164
|
+
get key() {
|
|
165
|
+
return `${this._coord.z}/${this._coord.x}/${this._coord.y}`;
|
|
186
166
|
}
|
|
187
167
|
}
|