bruce-cesium 7.7.7 → 7.7.8
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/bruce-cesium.es5.js +2292 -69
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +2271 -66
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +6 -1
- package/dist/lib/bruce-cesium.js.map +1 -1
- package/dist/lib/rendering/entity-render-engine-model3d.js +2 -2
- package/dist/lib/rendering/entity-render-engine-model3d.js.map +1 -1
- package/dist/lib/rendering/entity-render-engine-polygon.js +5 -4
- package/dist/lib/rendering/entity-render-engine-polygon.js.map +1 -1
- package/dist/lib/rendering/entity-render-engine-polyline.js +2 -1
- package/dist/lib/rendering/entity-render-engine-polyline.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/entity-simulation.js +1 -1
- package/dist/lib/rendering/render-managers/common/entity-simulation.js.map +1 -1
- package/dist/lib/rendering/tileset-render-engine.js +47 -14
- package/dist/lib/rendering/tileset-render-engine.js.map +1 -1
- package/dist/lib/rendering/view-render-engine.js +30 -24
- package/dist/lib/rendering/view-render-engine.js.map +1 -1
- package/dist/lib/rendering/visuals-register.js +93 -8
- package/dist/lib/rendering/visuals-register.js.map +1 -1
- package/dist/lib/rendering/xgrids-render-engine.js +20 -3
- package/dist/lib/rendering/xgrids-render-engine.js.map +1 -1
- package/dist/lib/utils/cesium-map-grid.js +807 -0
- package/dist/lib/utils/cesium-map-grid.js.map +1 -0
- package/dist/lib/utils/device-profile.js +302 -0
- package/dist/lib/utils/device-profile.js.map +1 -0
- package/dist/lib/utils/gltf-generator.js +307 -0
- package/dist/lib/utils/gltf-generator.js.map +1 -0
- package/dist/lib/utils/gltf-gizmo.js +136 -0
- package/dist/lib/utils/gltf-gizmo.js.map +1 -0
- package/dist/lib/utils/view-utils.js +9 -0
- package/dist/lib/utils/view-utils.js.map +1 -1
- package/dist/lib/viewer/camera-controls.js +544 -0
- package/dist/lib/viewer/camera-controls.js.map +1 -0
- package/dist/lib/viewer/viewer-utils.js +9 -1
- package/dist/lib/viewer/viewer-utils.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +6 -1
- package/dist/types/rendering/tileset-render-engine.d.ts +10 -2
- package/dist/types/rendering/view-render-engine.d.ts +4 -0
- package/dist/types/rendering/visuals-register.d.ts +4 -0
- package/dist/types/rendering/xgrids-render-engine.d.ts +2 -0
- package/dist/types/utils/cesium-map-grid.d.ts +23 -0
- package/dist/types/utils/device-profile.d.ts +84 -0
- package/dist/types/utils/gltf-generator.d.ts +104 -0
- package/dist/types/utils/gltf-gizmo.d.ts +18 -0
- package/dist/types/utils/view-utils.d.ts +4 -0
- package/dist/types/viewer/camera-controls.d.ts +19 -0
- package/dist/types/viewer/viewer-utils.d.ts +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,807 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CesiumMapGrid = void 0;
|
|
4
|
+
const bruce_models_1 = require("bruce-models");
|
|
5
|
+
const Cesium = require("cesium");
|
|
6
|
+
const viewer_utils_1 = require("../viewer/viewer-utils");
|
|
7
|
+
const view_utils_1 = require("./view-utils");
|
|
8
|
+
const gltf_gizmo_1 = require("./gltf-gizmo");
|
|
9
|
+
// viewer[CLASS_INSTANCE_KEY] will point at an instance of MapGridHandler.
|
|
10
|
+
const CLASS_INSTANCE_KEY = "nextspace-navigator-grid-handler";
|
|
11
|
+
// viewer[UPDATE_MARKER_KEY] will point at a number that is incremented every time the grid is updated.
|
|
12
|
+
// This is used to determine if the grid is still valid or if it needs to be redrawn.
|
|
13
|
+
const UPDATE_MARKER_KEY = "nextspace-marker-grid";
|
|
14
|
+
// viewer[LAST_SETTINGS_KEY] will point at the last settings used for the grid.
|
|
15
|
+
const LAST_SETTINGS_KEY = "nextspace-navigator-last-settings-grid";
|
|
16
|
+
/*
|
|
17
|
+
* The point a distance in metres along a heading in degrees from another, over a spherical earth.
|
|
18
|
+
*/
|
|
19
|
+
function offsetPoint(point, distance, heading) {
|
|
20
|
+
// Radius of earth.
|
|
21
|
+
const radius = 6371e3;
|
|
22
|
+
const δ = distance / radius;
|
|
23
|
+
const θ = Cesium.Math.toRadians(heading);
|
|
24
|
+
const φ1 = Cesium.Math.toRadians(point.latitude);
|
|
25
|
+
const λ1 = Cesium.Math.toRadians(point.longitude);
|
|
26
|
+
const sinφ2 = Math.sin(φ1) * Math.cos(δ) + Math.cos(φ1) * Math.sin(δ) * Math.cos(θ);
|
|
27
|
+
const φ2 = Math.asin(sinφ2);
|
|
28
|
+
const y = Math.sin(θ) * Math.sin(δ) * Math.cos(φ1);
|
|
29
|
+
const x = Math.cos(δ) - Math.sin(φ1) * sinφ2;
|
|
30
|
+
const λ2 = λ1 + Math.atan2(y, x);
|
|
31
|
+
return {
|
|
32
|
+
altitude: point.altitude,
|
|
33
|
+
latitude: Cesium.Math.toDegrees(φ2),
|
|
34
|
+
longitude: Cesium.Math.toDegrees(λ2)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Handler for drawing a grid of lines on the map with a specified spacing.
|
|
39
|
+
* Initially this grid is for model-space viewing which means we start at 0,0 lat/lon and have it expand from there.
|
|
40
|
+
* However, it should be a general-use tool for drawing a grid anywhere.
|
|
41
|
+
*
|
|
42
|
+
* It reacts to camera changes and draws the grid within view with padding.
|
|
43
|
+
* This helps avoid performance issues around drawing too many lines.
|
|
44
|
+
*/
|
|
45
|
+
class MapGridHandler {
|
|
46
|
+
constructor(viewer, spacingInMeters = 100, modelSpace = false) {
|
|
47
|
+
this.gridCenterGizmoPieces = [];
|
|
48
|
+
this.maxCacheSize = 1000;
|
|
49
|
+
// === Thresholds for grid stability.
|
|
50
|
+
// As a fraction of current grid extent.
|
|
51
|
+
this.CAMERA_MOVE_THRESHOLD = 0.5;
|
|
52
|
+
// 40% change in camera height triggers redraw.
|
|
53
|
+
this.HEIGHT_CHANGE_THRESHOLD = 0.4;
|
|
54
|
+
// 40% change in grid extent triggers redraw.
|
|
55
|
+
this.GRID_EXTENT_CHANGE_THRESHOLD = 0.4;
|
|
56
|
+
// 5km - distance that triggers origin reset.
|
|
57
|
+
this.EXTREME_DISTANCE_THRESHOLD = 5000;
|
|
58
|
+
// Grid limits to prevent drawing too many lines.
|
|
59
|
+
this.MAX_LINES = 500;
|
|
60
|
+
// 50% padding around visible area.
|
|
61
|
+
this.VIEW_PADDING_FACTOR = 0.5;
|
|
62
|
+
// Minimum pixels between grid lines to show them.
|
|
63
|
+
this.MIN_GRID_PIXEL_SIZE = 20;
|
|
64
|
+
// Base ratio - will be adjusted dynamically based on spacing size and camera height.
|
|
65
|
+
this.BASE_MAX_VISIBILITY_RATIO = 30;
|
|
66
|
+
// Height to spacing ratio.
|
|
67
|
+
this.HEIGHT_TO_SPACING_RATIO = 100;
|
|
68
|
+
// === Label settings
|
|
69
|
+
// Label every nth intersection.
|
|
70
|
+
this.LABEL_INTERVAL = 2;
|
|
71
|
+
// Maximum number of labels to show.
|
|
72
|
+
this.MAX_LABELS = 100;
|
|
73
|
+
// Spacing levels to use for adaptive spacing.
|
|
74
|
+
this.SPACING_LEVELS = [
|
|
75
|
+
1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 300, 400, 500, 1000, 2000, 2500, 5000, 10000, 20000, 25000, 50000, 100000
|
|
76
|
+
];
|
|
77
|
+
// Minimum zoom distance to prevent precision issues.
|
|
78
|
+
this.MINIMUM_ZOOM_DISTANCE = 40;
|
|
79
|
+
// Base spacing to use for adaptive spacing.
|
|
80
|
+
this.BASE_SPACING = 1;
|
|
81
|
+
// Maximum number of attempts to find a suitable spacing.
|
|
82
|
+
this.MAX_ADAPTIVE_ATTEMPTS = 5;
|
|
83
|
+
this.viewer = viewer;
|
|
84
|
+
this.spacingInMeters = spacingInMeters;
|
|
85
|
+
this.isUpdating = false;
|
|
86
|
+
this.modelSpace = modelSpace;
|
|
87
|
+
this.lastCameraPosition = null;
|
|
88
|
+
this.fixedGridOrigin = null;
|
|
89
|
+
this.lastGridExtent = 0;
|
|
90
|
+
this.offsetCache = new Map();
|
|
91
|
+
this.gridPrimitives = new Cesium.PrimitiveCollection();
|
|
92
|
+
this.viewer.scene.primitives.add(this.gridPrimitives);
|
|
93
|
+
this.currentMarker = viewer[UPDATE_MARKER_KEY] || 1;
|
|
94
|
+
const isMac = typeof navigator !== "undefined" && (navigator.platform.toUpperCase().indexOf("MAC") !== -1 ||
|
|
95
|
+
navigator.userAgent.toUpperCase().indexOf("MAC") !== -1);
|
|
96
|
+
if (modelSpace && isMac) {
|
|
97
|
+
console.log("[MAC-FIX] Applying camera distance limits for Mac");
|
|
98
|
+
viewer.scene.screenSpaceCameraController.minimumZoomDistance = this.MINIMUM_ZOOM_DISTANCE;
|
|
99
|
+
}
|
|
100
|
+
const manager = viewer_utils_1.ViewerUtils.GetManager({
|
|
101
|
+
viewer: this.viewer,
|
|
102
|
+
createIfMissing: false
|
|
103
|
+
});
|
|
104
|
+
if (manager) {
|
|
105
|
+
this.cameraChangeRemoval = manager.Monitor.Updated().Subscribe(() => {
|
|
106
|
+
this.onCameraChanged();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
// Initial grid draw.
|
|
110
|
+
this.onCameraChanged();
|
|
111
|
+
}
|
|
112
|
+
Update(spacingInMeters, modelSpace) {
|
|
113
|
+
this.currentMarker = this.viewer[UPDATE_MARKER_KEY] || 1;
|
|
114
|
+
let needsUpdate = false;
|
|
115
|
+
if (this.spacingInMeters !== spacingInMeters) {
|
|
116
|
+
this.spacingInMeters = spacingInMeters;
|
|
117
|
+
needsUpdate = true;
|
|
118
|
+
}
|
|
119
|
+
if (modelSpace !== undefined && this.modelSpace !== modelSpace) {
|
|
120
|
+
this.modelSpace = modelSpace;
|
|
121
|
+
needsUpdate = true;
|
|
122
|
+
}
|
|
123
|
+
if (needsUpdate) {
|
|
124
|
+
this.clearGrid();
|
|
125
|
+
// When spacing or model space changes, clear the cached origin to force recalculation
|
|
126
|
+
// This ensures grid alignment at the new spacing.
|
|
127
|
+
this.fixedGridOrigin = null;
|
|
128
|
+
this.offsetCache.clear();
|
|
129
|
+
this.onCameraChanged();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
Dispose() {
|
|
133
|
+
this.clearGrid();
|
|
134
|
+
this.clearGizmoPieces();
|
|
135
|
+
if (this.cameraChangeRemoval) {
|
|
136
|
+
this.cameraChangeRemoval();
|
|
137
|
+
this.cameraChangeRemoval = null;
|
|
138
|
+
}
|
|
139
|
+
if (this.gridPrimitives) {
|
|
140
|
+
this.viewer.scene.primitives.remove(this.gridPrimitives);
|
|
141
|
+
this.gridPrimitives = null;
|
|
142
|
+
}
|
|
143
|
+
if (this.viewer) {
|
|
144
|
+
this.viewer = null;
|
|
145
|
+
}
|
|
146
|
+
this.offsetCache.clear();
|
|
147
|
+
this.fixedGridOrigin = null;
|
|
148
|
+
}
|
|
149
|
+
clearGrid() {
|
|
150
|
+
if (this.gridPrimitives) {
|
|
151
|
+
this.gridPrimitives.removeAll();
|
|
152
|
+
this.gridLines = null;
|
|
153
|
+
this.gridLabels = null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
calculateAdaptiveSpacing(cameraHeight, baseSpacing) {
|
|
157
|
+
// Define spacing levels that look good (powers of 2, 5, and 10)
|
|
158
|
+
const spacingLevels = this.SPACING_LEVELS;
|
|
159
|
+
// Ensure base spacing is at least 1m
|
|
160
|
+
const adjustedBaseSpacing = Math.max(this.BASE_SPACING, baseSpacing);
|
|
161
|
+
// For very close cameras, use much smaller spacing regardless of base
|
|
162
|
+
if (cameraHeight < 10) {
|
|
163
|
+
// Find the smallest reasonable spacing for this height
|
|
164
|
+
// Rule: spacing should be roughly 1/20th to 1/50th of camera height, but at least 1m
|
|
165
|
+
const targetSpacing = Math.max(this.BASE_SPACING, cameraHeight / 30);
|
|
166
|
+
// Find the closest spacing level to our target
|
|
167
|
+
let bestSpacing = this.BASE_SPACING; // Start with minimum
|
|
168
|
+
let bestDifference = Math.abs(1 - targetSpacing);
|
|
169
|
+
for (const spacing of spacingLevels) {
|
|
170
|
+
if (spacing >= this.BASE_SPACING) { // Only consider valid spacings
|
|
171
|
+
const difference = Math.abs(spacing - targetSpacing);
|
|
172
|
+
if (difference < bestDifference) {
|
|
173
|
+
bestSpacing = spacing;
|
|
174
|
+
bestDifference = difference;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return bestSpacing;
|
|
179
|
+
}
|
|
180
|
+
// For medium distances (10m - 200m), scale more gradually
|
|
181
|
+
if (cameraHeight < 200) {
|
|
182
|
+
const targetSpacing = cameraHeight / 10; // More conservative scaling// Find closest spacing level, but prefer going up from base spacing
|
|
183
|
+
let bestSpacing = adjustedBaseSpacing;
|
|
184
|
+
let bestDifference = Math.abs(adjustedBaseSpacing - targetSpacing);
|
|
185
|
+
for (const spacing of spacingLevels) {
|
|
186
|
+
if (spacing >= Math.min(adjustedBaseSpacing, targetSpacing)) {
|
|
187
|
+
const difference = Math.abs(spacing - targetSpacing);
|
|
188
|
+
if (difference < bestDifference) {
|
|
189
|
+
bestSpacing = spacing;
|
|
190
|
+
bestDifference = difference;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return bestSpacing;
|
|
195
|
+
}
|
|
196
|
+
// For far distances (100m+), scale up aggressively
|
|
197
|
+
const targetSpacing = cameraHeight / 20;
|
|
198
|
+
// Find the spacing level that's closest to target but not smaller than base
|
|
199
|
+
let bestSpacing = adjustedBaseSpacing;
|
|
200
|
+
let bestDifference = Math.abs(adjustedBaseSpacing - targetSpacing);
|
|
201
|
+
for (const spacing of spacingLevels) {
|
|
202
|
+
if (spacing >= adjustedBaseSpacing) {
|
|
203
|
+
const difference = Math.abs(spacing - targetSpacing);
|
|
204
|
+
if (difference < bestDifference) {
|
|
205
|
+
bestSpacing = spacing;
|
|
206
|
+
bestDifference = difference;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return bestSpacing;
|
|
211
|
+
}
|
|
212
|
+
/*
|
|
213
|
+
* The point model-space treats as 0,0,0: the UCS in UCS placement, otherwise 0,0 lat/lon at sea level.
|
|
214
|
+
*/
|
|
215
|
+
modelSpaceOrigin() {
|
|
216
|
+
const origin = view_utils_1.ViewUtils.IsModelSpaceUcs(this.viewer) ? view_utils_1.ViewUtils.GetModelSpaceOrigin(this.viewer) : null;
|
|
217
|
+
return origin !== null && origin !== void 0 ? origin : { latitude: 0, longitude: 0, altitude: 0 };
|
|
218
|
+
}
|
|
219
|
+
/*
|
|
220
|
+
* The origin as a scene position, where the axis gizmo sits.
|
|
221
|
+
*/
|
|
222
|
+
modelSpaceOriginPos3d() {
|
|
223
|
+
const origin = this.modelSpaceOrigin();
|
|
224
|
+
return Cesium.Cartesian3.fromDegrees(origin.longitude, origin.latitude, origin.altitude);
|
|
225
|
+
}
|
|
226
|
+
drawGizmoPieces() {
|
|
227
|
+
if (this.gridCenterGizmoPieces.length) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
// X.
|
|
231
|
+
{
|
|
232
|
+
const pos3d = this.modelSpaceOriginPos3d();
|
|
233
|
+
const scale = new Cesium.CallbackProperty(() => Cesium.Cartesian3.distance(this.viewer.camera.position, pos3d) * 0.0002, false);
|
|
234
|
+
const orientation = Cesium.Transforms.headingPitchRollQuaternion(pos3d, new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(90), 0, 0));
|
|
235
|
+
const entity = this.viewer.entities.add(new Cesium.Entity({
|
|
236
|
+
model: {
|
|
237
|
+
uri: gltf_gizmo_1.GltfGizmo.GetUri(gltf_gizmo_1.GltfGizmo.EPiece.X),
|
|
238
|
+
heightReference: Cesium.HeightReference.NONE,
|
|
239
|
+
shadows: Cesium.ShadowMode.DISABLED,
|
|
240
|
+
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, Number.MAX_VALUE),
|
|
241
|
+
scale
|
|
242
|
+
},
|
|
243
|
+
position: pos3d,
|
|
244
|
+
orientation: new Cesium.ConstantProperty(orientation)
|
|
245
|
+
}));
|
|
246
|
+
this.gridCenterGizmoPieces.push(entity);
|
|
247
|
+
}
|
|
248
|
+
// Y.
|
|
249
|
+
{
|
|
250
|
+
const pos3d = this.modelSpaceOriginPos3d();
|
|
251
|
+
const scale = new Cesium.CallbackProperty(() => Cesium.Cartesian3.distance(this.viewer.camera.position, pos3d) * 0.0002, false);
|
|
252
|
+
const orientation = Cesium.Transforms.headingPitchRollQuaternion(pos3d, new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(90), 0, 0));
|
|
253
|
+
const entity = this.viewer.entities.add(new Cesium.Entity({
|
|
254
|
+
model: {
|
|
255
|
+
uri: gltf_gizmo_1.GltfGizmo.GetUri(gltf_gizmo_1.GltfGizmo.EPiece.Y),
|
|
256
|
+
heightReference: Cesium.HeightReference.NONE,
|
|
257
|
+
shadows: Cesium.ShadowMode.DISABLED,
|
|
258
|
+
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, Number.MAX_VALUE),
|
|
259
|
+
scale
|
|
260
|
+
},
|
|
261
|
+
position: pos3d,
|
|
262
|
+
orientation: new Cesium.ConstantProperty(orientation)
|
|
263
|
+
}));
|
|
264
|
+
this.gridCenterGizmoPieces.push(entity);
|
|
265
|
+
}
|
|
266
|
+
// Z.
|
|
267
|
+
{
|
|
268
|
+
const pos3d = this.modelSpaceOriginPos3d();
|
|
269
|
+
const scale = new Cesium.CallbackProperty(() => Cesium.Cartesian3.distance(this.viewer.camera.position, pos3d) * 0.0002, false);
|
|
270
|
+
const orientation = Cesium.Transforms.headingPitchRollQuaternion(pos3d, new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(90), 0, 0));
|
|
271
|
+
const entity = this.viewer.entities.add(new Cesium.Entity({
|
|
272
|
+
model: {
|
|
273
|
+
uri: gltf_gizmo_1.GltfGizmo.GetUri(gltf_gizmo_1.GltfGizmo.EPiece.Z),
|
|
274
|
+
heightReference: Cesium.HeightReference.NONE,
|
|
275
|
+
shadows: Cesium.ShadowMode.DISABLED,
|
|
276
|
+
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, Number.MAX_VALUE),
|
|
277
|
+
scale
|
|
278
|
+
},
|
|
279
|
+
position: pos3d,
|
|
280
|
+
orientation: new Cesium.ConstantProperty(orientation)
|
|
281
|
+
}));
|
|
282
|
+
this.gridCenterGizmoPieces.push(entity);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
clearGizmoPieces() {
|
|
286
|
+
for (const piece of this.gridCenterGizmoPieces) {
|
|
287
|
+
if (piece && this.viewer.entities.contains(piece)) {
|
|
288
|
+
this.viewer.entities.remove(piece);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
this.gridCenterGizmoPieces = [];
|
|
292
|
+
}
|
|
293
|
+
onCameraChanged() {
|
|
294
|
+
if (this.isUpdating) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
else if (this.currentMarker !== this.viewer[UPDATE_MARKER_KEY]) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
this.isUpdating = true;
|
|
301
|
+
// Small delay to avoid excessive updates during camera movement.
|
|
302
|
+
setTimeout(() => {
|
|
303
|
+
if (this.currentMarker !== this.viewer[UPDATE_MARKER_KEY]) {
|
|
304
|
+
this.isUpdating = false;
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
try {
|
|
308
|
+
// The grid goes first, since it notices when the origin has moved and the gizmo has to follow.
|
|
309
|
+
this.updateGrid();
|
|
310
|
+
if (this.modelSpace) {
|
|
311
|
+
this.drawGizmoPieces();
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
this.clearGizmoPieces();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
catch (e) {
|
|
318
|
+
console.error(e);
|
|
319
|
+
}
|
|
320
|
+
finally {
|
|
321
|
+
this.isUpdating = false;
|
|
322
|
+
}
|
|
323
|
+
}, 100);
|
|
324
|
+
}
|
|
325
|
+
cachedOffsetPoint(point, distance, heading) {
|
|
326
|
+
const key = `${point.latitude.toFixed(8)},${point.longitude.toFixed(8)},${distance.toFixed(1)},${heading}`;
|
|
327
|
+
if (this.offsetCache.has(key)) {
|
|
328
|
+
return this.offsetCache.get(key);
|
|
329
|
+
}
|
|
330
|
+
const result = offsetPoint(point, distance, heading);
|
|
331
|
+
this.offsetCache.set(key, result);
|
|
332
|
+
if (this.offsetCache.size > this.maxCacheSize) {
|
|
333
|
+
const keys = Array.from(this.offsetCache.keys());
|
|
334
|
+
for (let i = 0; i < 100; i++) {
|
|
335
|
+
this.offsetCache.delete(keys[i]);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return result;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Calculates a dynamic visibility ratio based on spacing size.
|
|
342
|
+
* For small grid spacings, we can show the grid from farther away.
|
|
343
|
+
* For large grid spacings, we need to hide it sooner to prevent performance issues.
|
|
344
|
+
*/
|
|
345
|
+
getMaxVisibilityRatio() {
|
|
346
|
+
if (this.spacingInMeters <= 10) {
|
|
347
|
+
return this.BASE_MAX_VISIBILITY_RATIO;
|
|
348
|
+
}
|
|
349
|
+
if (this.spacingInMeters <= 100) {
|
|
350
|
+
const factor = 1 - ((this.spacingInMeters - 10) / 90);
|
|
351
|
+
return this.BASE_MAX_VISIBILITY_RATIO * (0.5 + (factor * 0.5));
|
|
352
|
+
}
|
|
353
|
+
const largeGridFactor = Math.min(1, 100 / this.spacingInMeters);
|
|
354
|
+
return this.BASE_MAX_VISIBILITY_RATIO * 0.5 * largeGridFactor;
|
|
355
|
+
}
|
|
356
|
+
updateGrid() {
|
|
357
|
+
const cameraPosition = this.viewer.camera.position;
|
|
358
|
+
const cameraCartographic = Cesium.Cartographic.fromCartesian(cameraPosition);
|
|
359
|
+
const cameraHeight = cameraCartographic.height;
|
|
360
|
+
let adaptiveSpacing = this.calculateAdaptiveSpacing(cameraHeight, this.spacingInMeters);
|
|
361
|
+
// Calculate visible area.
|
|
362
|
+
const visibleArea = this.calculateVisibleArea();
|
|
363
|
+
if (!visibleArea) {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
let densityCheckPassed = false;
|
|
367
|
+
let attempts = 0;
|
|
368
|
+
while (!densityCheckPassed && attempts < this.MAX_ADAPTIVE_ATTEMPTS) {
|
|
369
|
+
if (this.isGridDensityAcceptable(visibleArea, cameraHeight, adaptiveSpacing)) {
|
|
370
|
+
densityCheckPassed = true;
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
adaptiveSpacing *= 2;
|
|
374
|
+
attempts++;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
// The origin follows the UCS of what is shown, so the grid moves with it when that changes.
|
|
378
|
+
if (this.modelSpace && this.fixedGridOrigin && !bruce_models_1.Carto.IsEqual(this.fixedGridOrigin, this.modelSpaceOrigin())) {
|
|
379
|
+
this.fixedGridOrigin = null;
|
|
380
|
+
this.lastCameraPosition = null;
|
|
381
|
+
this.clearGizmoPieces();
|
|
382
|
+
}
|
|
383
|
+
// Calculate grid origin if we don't have one yet.
|
|
384
|
+
if (!this.fixedGridOrigin) {
|
|
385
|
+
if (this.modelSpace) {
|
|
386
|
+
this.fixedGridOrigin = this.modelSpaceOrigin();
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
const centerCartographic = Cesium.Cartographic.fromCartesian(visibleArea.centerCartesian);
|
|
390
|
+
const centerPoint = {
|
|
391
|
+
latitude: Cesium.Math.toDegrees(centerCartographic.latitude),
|
|
392
|
+
longitude: Cesium.Math.toDegrees(centerCartographic.longitude),
|
|
393
|
+
altitude: 0
|
|
394
|
+
};
|
|
395
|
+
// Simple attempt at snapping to the grid, should do something smarter.
|
|
396
|
+
this.fixedGridOrigin = {
|
|
397
|
+
latitude: Math.round(centerPoint.latitude * 100000) / 100000,
|
|
398
|
+
longitude: Math.round(centerPoint.longitude * 100000) / 100000,
|
|
399
|
+
altitude: 0
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
// Calculate appropriate grid extent based on camera height.
|
|
404
|
+
// For larger grid spacings, we use a tighter extent to prevent performance issues.
|
|
405
|
+
const scaledExtentFactor = Math.max(0.5, Math.min(3, 3 - Math.log10(Math.max(1, adaptiveSpacing)) * 0.5));
|
|
406
|
+
const visibilityRadius = Math.min(cameraHeight * scaledExtentFactor, Infinity);
|
|
407
|
+
// Check if we should redraw the grid.
|
|
408
|
+
const shouldRedraw = this.shouldRedrawGrid(cameraPosition, cameraHeight, visibilityRadius, adaptiveSpacing);
|
|
409
|
+
if (!shouldRedraw) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
// Remember current settings for next comparison.
|
|
413
|
+
this.lastCameraHeight = cameraHeight;
|
|
414
|
+
this.lastCameraPosition = cameraPosition.clone();
|
|
415
|
+
this.lastGridExtent = visibilityRadius;
|
|
416
|
+
// Clear existing grid and create a new one.
|
|
417
|
+
this.clearGrid();
|
|
418
|
+
this.gridLines = new Cesium.PolylineCollection();
|
|
419
|
+
this.gridLabels = new Cesium.LabelCollection({
|
|
420
|
+
scene: this.viewer.scene
|
|
421
|
+
});
|
|
422
|
+
this.gridPrimitives.add(this.gridLines);
|
|
423
|
+
this.gridPrimitives.add(this.gridLabels);
|
|
424
|
+
// Generate grid lines and labels using our fixed origin.
|
|
425
|
+
this.generateGridLines(this.fixedGridOrigin, visibilityRadius, adaptiveSpacing);
|
|
426
|
+
}
|
|
427
|
+
shouldRedrawGrid(cameraPosition, cameraHeight, gridExtent, currentSpacing) {
|
|
428
|
+
// check if the spacing has changed
|
|
429
|
+
if (this.lastUsedSpacing && this.lastUsedSpacing !== currentSpacing) {
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
// Always draw if we don't have a grid yet.
|
|
433
|
+
if (!this.gridLines || !this.lastCameraPosition || !this.fixedGridOrigin) {
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
// Check for significant height change.
|
|
437
|
+
const heightRatio = cameraHeight / this.lastCameraHeight;
|
|
438
|
+
if (heightRatio > (1 + this.HEIGHT_CHANGE_THRESHOLD) ||
|
|
439
|
+
heightRatio < (1 - this.HEIGHT_CHANGE_THRESHOLD)) {
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
// Check for significant position change relative to current grid extent.
|
|
443
|
+
const distance = Cesium.Cartesian3.distance(cameraPosition, this.lastCameraPosition);
|
|
444
|
+
const moveThreshold = gridExtent * this.CAMERA_MOVE_THRESHOLD;
|
|
445
|
+
if (distance > moveThreshold) {
|
|
446
|
+
return true;
|
|
447
|
+
}
|
|
448
|
+
// Check for significant grid extent change.
|
|
449
|
+
const extentRatio = gridExtent / this.lastGridExtent;
|
|
450
|
+
if (extentRatio > (1 + this.GRID_EXTENT_CHANGE_THRESHOLD) ||
|
|
451
|
+
extentRatio < (1 - this.GRID_EXTENT_CHANGE_THRESHOLD)) {
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
// No significant changes, keep current grid.
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
isGridDensityAcceptable(visibleArea, cameraHeight, spacingToCheck = this.spacingInMeters) {
|
|
458
|
+
const lonRange = visibleArea.eastLon - visibleArea.westLon;
|
|
459
|
+
const latRange = visibleArea.northLat - visibleArea.southLat;
|
|
460
|
+
// Convert to approximate meters at center
|
|
461
|
+
const centerCartographic = Cesium.Cartographic.fromCartesian(visibleArea.centerCartesian);
|
|
462
|
+
const metersPerDegreeLon = 111319.9 * Math.cos(centerCartographic.latitude);
|
|
463
|
+
const metersPerDegreeLat = 111319.9;
|
|
464
|
+
const widthInMeters = lonRange * metersPerDegreeLon;
|
|
465
|
+
const heightInMeters = latRange * metersPerDegreeLat;
|
|
466
|
+
const canvas = this.viewer.scene.canvas;
|
|
467
|
+
const spacingInDegrees = spacingToCheck / metersPerDegreeLon;
|
|
468
|
+
const canvasWidth = canvas.clientWidth;
|
|
469
|
+
const pixelsPerDegree = canvasWidth / lonRange;
|
|
470
|
+
const pixelsBetweenGridLines = pixelsPerDegree * spacingInDegrees;
|
|
471
|
+
const minPixelSize = 1;
|
|
472
|
+
return pixelsBetweenGridLines >= minPixelSize;
|
|
473
|
+
}
|
|
474
|
+
calculateVisibleArea() {
|
|
475
|
+
const scene = this.viewer.scene;
|
|
476
|
+
const camera = scene.camera;
|
|
477
|
+
const globe = scene.globe;
|
|
478
|
+
// Get the corners of the view frustum
|
|
479
|
+
const canvas = scene.canvas;
|
|
480
|
+
const corners = [
|
|
481
|
+
new Cesium.Cartesian2(0, 0),
|
|
482
|
+
new Cesium.Cartesian2(canvas.clientWidth, 0),
|
|
483
|
+
new Cesium.Cartesian2(0, canvas.clientHeight),
|
|
484
|
+
new Cesium.Cartesian2(canvas.clientWidth, canvas.clientHeight),
|
|
485
|
+
new Cesium.Cartesian2(canvas.clientWidth / 2, canvas.clientHeight / 2) // Center
|
|
486
|
+
];
|
|
487
|
+
// Project corners to the globe
|
|
488
|
+
const cartographicCorners = [];
|
|
489
|
+
for (const corner of corners) {
|
|
490
|
+
const ray = camera.getPickRay(corner);
|
|
491
|
+
if (!ray) {
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
const position = globe.pick(ray, scene);
|
|
495
|
+
if (!position) {
|
|
496
|
+
continue;
|
|
497
|
+
}
|
|
498
|
+
cartographicCorners.push(Cesium.Cartographic.fromCartesian(position));
|
|
499
|
+
}
|
|
500
|
+
if (cartographicCorners.length === 0) {
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
// Find the bounding rectangle
|
|
504
|
+
let westLon = Number.POSITIVE_INFINITY;
|
|
505
|
+
let eastLon = Number.NEGATIVE_INFINITY;
|
|
506
|
+
let southLat = Number.POSITIVE_INFINITY;
|
|
507
|
+
let northLat = Number.NEGATIVE_INFINITY;
|
|
508
|
+
for (const corner of cartographicCorners) {
|
|
509
|
+
westLon = Math.min(westLon, corner.longitude);
|
|
510
|
+
eastLon = Math.max(eastLon, corner.longitude);
|
|
511
|
+
southLat = Math.min(southLat, corner.latitude);
|
|
512
|
+
northLat = Math.max(northLat, corner.latitude);
|
|
513
|
+
}
|
|
514
|
+
// Add some padding around the visible area
|
|
515
|
+
const lonPadding = (eastLon - westLon) * this.VIEW_PADDING_FACTOR;
|
|
516
|
+
const latPadding = (northLat - southLat) * this.VIEW_PADDING_FACTOR;
|
|
517
|
+
westLon -= lonPadding;
|
|
518
|
+
eastLon += lonPadding;
|
|
519
|
+
southLat -= latPadding;
|
|
520
|
+
northLat += latPadding;
|
|
521
|
+
// Get center position for reference
|
|
522
|
+
const centerCartographic = new Cesium.Cartographic((westLon + eastLon) / 2, (southLat + northLat) / 2);
|
|
523
|
+
const centerCartesian = Cesium.Cartesian3.fromRadians(centerCartographic.longitude, centerCartographic.latitude, 0);
|
|
524
|
+
return {
|
|
525
|
+
westLon: Cesium.Math.toDegrees(westLon),
|
|
526
|
+
eastLon: Cesium.Math.toDegrees(eastLon),
|
|
527
|
+
southLat: Cesium.Math.toDegrees(southLat),
|
|
528
|
+
northLat: Cesium.Math.toDegrees(northLat),
|
|
529
|
+
centerCartesian: centerCartesian
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
generateGridLines(originPoint, visibilityRadius, actualSpacing = this.spacingInMeters) {
|
|
533
|
+
// Number of grid cells in each direction (add 1 for edge lines).
|
|
534
|
+
const gridCellCount = Math.ceil(visibilityRadius / actualSpacing) + 1;
|
|
535
|
+
const maxCells = Math.min(gridCellCount, Math.floor(this.MAX_LINES / 2));
|
|
536
|
+
// Calculate interval to skip lines for density control.
|
|
537
|
+
const spacingFactor = actualSpacing / 100;
|
|
538
|
+
const heightFactor = this.lastCameraHeight / 500;
|
|
539
|
+
let lineSkipInterval = Math.floor(spacingFactor * heightFactor);
|
|
540
|
+
lineSkipInterval = Math.min(Math.max(lineSkipInterval, 1), 10); // Clamp between 1 and 10
|
|
541
|
+
const intersections = [];
|
|
542
|
+
// Generate north-south grid lines (longitude lines)
|
|
543
|
+
for (let i = -maxCells; i <= maxCells; i++) {
|
|
544
|
+
if (i % lineSkipInterval !== 0) {
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
const positions = [];
|
|
548
|
+
// Create a vertical line at this longitude offset.
|
|
549
|
+
// East heading for longitude.
|
|
550
|
+
const startPoint = this.cachedOffsetPoint(originPoint, i * actualSpacing, 90);
|
|
551
|
+
// Draw the line from south to north
|
|
552
|
+
for (let j = -maxCells; j <= maxCells; j++) {
|
|
553
|
+
if (j % lineSkipInterval !== 0) {
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
// North heading for latitude.
|
|
557
|
+
const linePoint = this.cachedOffsetPoint(startPoint, j * actualSpacing, 0);
|
|
558
|
+
const position = Cesium.Cartesian3.fromDegrees(linePoint.longitude, linePoint.latitude, linePoint.altitude);
|
|
559
|
+
positions.push(position);
|
|
560
|
+
intersections.push({
|
|
561
|
+
position: position,
|
|
562
|
+
i: i,
|
|
563
|
+
j: j
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
if (positions.length >= 2) {
|
|
567
|
+
// Check if this is the primary Y axis (i=0) in model space
|
|
568
|
+
const isPrimaryYAxis = this.modelSpace && i === 0;
|
|
569
|
+
this.addGridLine(positions, isPrimaryYAxis ? "y" : null);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
// Generate east-west grid lines (latitude lines).
|
|
573
|
+
for (let j = -maxCells; j <= maxCells; j++) {
|
|
574
|
+
if (j % lineSkipInterval !== 0) {
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
577
|
+
const positions = [];
|
|
578
|
+
// Create a horizontal line at this latitude offset
|
|
579
|
+
// North heading for latitude.
|
|
580
|
+
const startPoint = this.cachedOffsetPoint(originPoint, j * actualSpacing, 0);
|
|
581
|
+
// Draw the line from west to east.
|
|
582
|
+
for (let i = -maxCells; i <= maxCells; i++) {
|
|
583
|
+
if (i % lineSkipInterval !== 0) {
|
|
584
|
+
continue;
|
|
585
|
+
}
|
|
586
|
+
// East heading for longitude.
|
|
587
|
+
const linePoint = this.cachedOffsetPoint(startPoint, i * actualSpacing, 90);
|
|
588
|
+
const position = Cesium.Cartesian3.fromDegrees(linePoint.longitude, linePoint.latitude, linePoint.altitude);
|
|
589
|
+
positions.push(position);
|
|
590
|
+
}
|
|
591
|
+
if (positions.length >= 2) {
|
|
592
|
+
// Check if this is the primary X axis (j=0) in model space
|
|
593
|
+
const isPrimaryXAxis = this.modelSpace && j === 0;
|
|
594
|
+
this.addGridLine(positions, isPrimaryXAxis ? "x" : null);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
this.addGridLabels(intersections, actualSpacing);
|
|
598
|
+
}
|
|
599
|
+
addGridLabels(intersections, actualSpacing) {
|
|
600
|
+
if (!this.gridLabels) {
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
// Determine label interval based on number of intersections.
|
|
604
|
+
// Use higher interval for more intersections to prevent crowding.
|
|
605
|
+
const totalIntersections = intersections.length;
|
|
606
|
+
let labelInterval = this.LABEL_INTERVAL;
|
|
607
|
+
if (totalIntersections > 1000) {
|
|
608
|
+
labelInterval = 5;
|
|
609
|
+
}
|
|
610
|
+
else if (totalIntersections > 500) {
|
|
611
|
+
labelInterval = 3;
|
|
612
|
+
}
|
|
613
|
+
let labelCount = 0;
|
|
614
|
+
// Filter intersections to only those at the labelInterval.
|
|
615
|
+
const labelPoints = intersections.filter(point => {
|
|
616
|
+
// Always label the origin (0,0).
|
|
617
|
+
if (point.i === 0 && point.j === 0) {
|
|
618
|
+
return true;
|
|
619
|
+
}
|
|
620
|
+
return (point.i % labelInterval === 0 && point.j % labelInterval === 0);
|
|
621
|
+
});
|
|
622
|
+
// Sort points by distance from origin.
|
|
623
|
+
labelPoints.sort((a, b) => {
|
|
624
|
+
const distA = Math.abs(a.i) + Math.abs(a.j);
|
|
625
|
+
const distB = Math.abs(b.i) + Math.abs(b.j);
|
|
626
|
+
return distA - distB;
|
|
627
|
+
});
|
|
628
|
+
// Add labels, prioritizing those closest to the origin.
|
|
629
|
+
for (const point of labelPoints) {
|
|
630
|
+
if (labelCount >= this.MAX_LABELS) {
|
|
631
|
+
// Limit reached.
|
|
632
|
+
break;
|
|
633
|
+
}
|
|
634
|
+
let labelText;
|
|
635
|
+
// Model space coordinates (meters from origin).
|
|
636
|
+
if (this.modelSpace) {
|
|
637
|
+
const xMeters = point.i * actualSpacing;
|
|
638
|
+
const yMeters = point.j * actualSpacing;
|
|
639
|
+
if (point.i === 0 && point.j === 0) {
|
|
640
|
+
labelText = "0,0,0";
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
labelText = `${xMeters},${yMeters}`;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
// Geographic coordinates (degrees).
|
|
647
|
+
else {
|
|
648
|
+
const cartographic = Cesium.Cartographic.fromCartesian(point.position);
|
|
649
|
+
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
|
|
650
|
+
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
|
|
651
|
+
const latFormatted = latitude.toFixed(5);
|
|
652
|
+
const lonFormatted = longitude.toFixed(5);
|
|
653
|
+
labelText = `${latFormatted}, ${lonFormatted}`;
|
|
654
|
+
}
|
|
655
|
+
this.gridLabels.add({
|
|
656
|
+
position: point.position,
|
|
657
|
+
text: labelText,
|
|
658
|
+
font: this.modelSpace && point.i === 0 && point.j === 0 ? "20px sans-serif" : "14px sans-serif",
|
|
659
|
+
fillColor: this.modelSpace && point.i === 0 && point.j === 0 ? Cesium.Color.WHITE : Cesium.Color.WHITE.withAlpha(0.5),
|
|
660
|
+
style: Cesium.LabelStyle.FILL,
|
|
661
|
+
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
662
|
+
verticalOrigin: Cesium.VerticalOrigin.TOP,
|
|
663
|
+
pixelOffset: new Cesium.Cartesian2(0, 10),
|
|
664
|
+
// Fade out with distance.
|
|
665
|
+
translucencyByDistance: new Cesium.NearFarScalar(1000, 1.0, 15000, 0.4)
|
|
666
|
+
});
|
|
667
|
+
labelCount++;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
addGridLine(positions, primaryAxis = null) {
|
|
671
|
+
if (!this.gridLines || positions.length < 2) {
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
let lineColor;
|
|
675
|
+
let lineWidth = 1.0;
|
|
676
|
+
let lineAlpha = 0.2;
|
|
677
|
+
// Red for X axis.
|
|
678
|
+
if (primaryAxis === "x") {
|
|
679
|
+
lineColor = Cesium.Color.RED;
|
|
680
|
+
lineAlpha = 0.5;
|
|
681
|
+
lineWidth = 1.5;
|
|
682
|
+
}
|
|
683
|
+
// Green for Y axis.
|
|
684
|
+
else if (primaryAxis === "y") {
|
|
685
|
+
lineColor = Cesium.Color.GREEN;
|
|
686
|
+
lineAlpha = 0.5;
|
|
687
|
+
lineWidth = 1.5;
|
|
688
|
+
}
|
|
689
|
+
// Default gray for regular grid lines.
|
|
690
|
+
else {
|
|
691
|
+
lineColor = Cesium.Color.LIGHTGRAY;
|
|
692
|
+
}
|
|
693
|
+
this.gridLines.add({
|
|
694
|
+
positions: positions,
|
|
695
|
+
width: lineWidth,
|
|
696
|
+
material: Cesium.Material.fromType("Color", {
|
|
697
|
+
color: lineColor.withAlpha(lineAlpha)
|
|
698
|
+
})
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
// Grid square size used when settings name none, in metres.
|
|
703
|
+
const DEFAULT_SPACING = 50;
|
|
704
|
+
var CesiumMapGrid;
|
|
705
|
+
(function (CesiumMapGrid) {
|
|
706
|
+
function GetCurrentSpacing(viewer) {
|
|
707
|
+
if (!viewer || viewer.isDestroyed()) {
|
|
708
|
+
return 0;
|
|
709
|
+
}
|
|
710
|
+
const handler = viewer[CLASS_INSTANCE_KEY];
|
|
711
|
+
return handler ? handler.getCurrentSpacing() : 0;
|
|
712
|
+
}
|
|
713
|
+
CesiumMapGrid.GetCurrentSpacing = GetCurrentSpacing;
|
|
714
|
+
function Remove(viewer) {
|
|
715
|
+
if (!viewer || viewer.isDestroyed()) {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
else if (!viewer[LAST_SETTINGS_KEY]) {
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
if (!viewer[UPDATE_MARKER_KEY]) {
|
|
722
|
+
viewer[UPDATE_MARKER_KEY] = 1;
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
viewer[UPDATE_MARKER_KEY]++;
|
|
726
|
+
}
|
|
727
|
+
// Dispose of the handler.
|
|
728
|
+
if (viewer[CLASS_INSTANCE_KEY]) {
|
|
729
|
+
viewer[CLASS_INSTANCE_KEY].Dispose();
|
|
730
|
+
viewer[CLASS_INSTANCE_KEY] = null;
|
|
731
|
+
}
|
|
732
|
+
viewer[LAST_SETTINGS_KEY] = {
|
|
733
|
+
...viewer[LAST_SETTINGS_KEY],
|
|
734
|
+
enabled: false
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
CesiumMapGrid.Remove = Remove;
|
|
738
|
+
function Draw(viewer, spacingInMeters, modelSpace = true) {
|
|
739
|
+
if (!viewer || viewer.isDestroyed()) {
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
let settings = viewer[LAST_SETTINGS_KEY];
|
|
743
|
+
if (settings) {
|
|
744
|
+
// See if the settings are the same as the last time.
|
|
745
|
+
if (settings.spacing === spacingInMeters &&
|
|
746
|
+
settings.modelSpace === modelSpace &&
|
|
747
|
+
settings.enabled) {
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
if (!viewer[UPDATE_MARKER_KEY]) {
|
|
752
|
+
viewer[UPDATE_MARKER_KEY] = 1;
|
|
753
|
+
}
|
|
754
|
+
else {
|
|
755
|
+
viewer[UPDATE_MARKER_KEY]++;
|
|
756
|
+
}
|
|
757
|
+
settings = {
|
|
758
|
+
...settings,
|
|
759
|
+
enabled: true,
|
|
760
|
+
spacing: spacingInMeters,
|
|
761
|
+
modelSpace: modelSpace
|
|
762
|
+
};
|
|
763
|
+
viewer[LAST_SETTINGS_KEY] = settings;
|
|
764
|
+
// Create or update the handler.
|
|
765
|
+
if (viewer[CLASS_INSTANCE_KEY]) {
|
|
766
|
+
viewer[CLASS_INSTANCE_KEY].Update(spacingInMeters, modelSpace);
|
|
767
|
+
}
|
|
768
|
+
else {
|
|
769
|
+
viewer[CLASS_INSTANCE_KEY] = new MapGridHandler(viewer, spacingInMeters, modelSpace);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
CesiumMapGrid.Draw = Draw;
|
|
773
|
+
/**
|
|
774
|
+
* Draws a bookmark's grid, or removes the grid when it has none; only model-space draws one.
|
|
775
|
+
*/
|
|
776
|
+
function Apply(viewer, grid, modelSpace) {
|
|
777
|
+
if ((grid === null || grid === void 0 ? void 0 : grid.enabled) && modelSpace) {
|
|
778
|
+
Draw(viewer, Number(grid.spacing) || DEFAULT_SPACING, modelSpace);
|
|
779
|
+
}
|
|
780
|
+
else {
|
|
781
|
+
Remove(viewer);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
CesiumMapGrid.Apply = Apply;
|
|
785
|
+
function GetIsEnabled(viewer) {
|
|
786
|
+
if (!viewer || viewer.isDestroyed()) {
|
|
787
|
+
return false;
|
|
788
|
+
}
|
|
789
|
+
const settings = viewer[LAST_SETTINGS_KEY];
|
|
790
|
+
if (settings) {
|
|
791
|
+
return Boolean(settings.enabled);
|
|
792
|
+
}
|
|
793
|
+
return false;
|
|
794
|
+
}
|
|
795
|
+
CesiumMapGrid.GetIsEnabled = GetIsEnabled;
|
|
796
|
+
/**
|
|
797
|
+
* Returns the last applied grid settings.
|
|
798
|
+
*/
|
|
799
|
+
function GetSettings(viewer) {
|
|
800
|
+
if (!viewer || viewer.isDestroyed()) {
|
|
801
|
+
return null;
|
|
802
|
+
}
|
|
803
|
+
return viewer[LAST_SETTINGS_KEY];
|
|
804
|
+
}
|
|
805
|
+
CesiumMapGrid.GetSettings = GetSettings;
|
|
806
|
+
})(CesiumMapGrid = exports.CesiumMapGrid || (exports.CesiumMapGrid = {}));
|
|
807
|
+
//# sourceMappingURL=cesium-map-grid.js.map
|