isard 2.2.2 → 2.3.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/CHANGELOG.md +17 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/isard_grid_bg.wasm +0 -0
- package/dist/isard_webgl2_bg.wasm +0 -0
- package/dist/isard_webgpu_bg.wasm +0 -0
- package/dist/map/clip-volume.d.ts +60 -0
- package/dist/map/clip-volume.js +352 -0
- package/dist/map/clip-volume.js.map +1 -0
- package/dist/map/events.js +1 -1
- package/dist/map/events.js.map +1 -1
- package/dist/map.d.ts +9 -9
- package/dist/map.js +21 -21
- package/dist/map.js.map +1 -1
- package/dist/react/ClipVolume.d.ts +10 -0
- package/dist/react/ClipVolume.js +22 -0
- package/dist/react/ClipVolume.js.map +1 -0
- package/dist/react/IsardMap.d.ts +1 -1
- package/dist/react/IsardMap.js +1 -1
- package/dist/react/IsardMap.js.map +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/types.d.ts +44 -18
- package/dist/types.js.map +1 -1
- package/dist/ui/style.js +6 -6
- package/dist/ui/style.js.map +1 -1
- package/dist/wasm/isard_webgl2.d.ts +11 -9
- package/dist/wasm/isard_webgl2.js +15 -10
- package/dist/wasm/isard_webgpu.d.ts +11 -9
- package/dist/wasm/isard_webgpu.js +15 -10
- package/package.json +1 -1
- package/dist/map/clip-box.d.ts +0 -52
- package/dist/map/clip-box.js +0 -233
- package/dist/map/clip-box.js.map +0 -1
- package/dist/react/ClipBox.d.ts +0 -9
- package/dist/react/ClipBox.js +0 -21
- package/dist/react/ClipBox.js.map +0 -1
|
@@ -290,9 +290,9 @@ export class Engine {
|
|
|
290
290
|
*/
|
|
291
291
|
camera(): Camera;
|
|
292
292
|
/**
|
|
293
|
-
* Removes the clipping
|
|
293
|
+
* Removes the clipping volume: the layers whole again
|
|
294
294
|
*/
|
|
295
|
-
|
|
295
|
+
clearClipVolume(): void;
|
|
296
296
|
/**
|
|
297
297
|
* Removes the panorama
|
|
298
298
|
*/
|
|
@@ -469,12 +469,14 @@ export class Engine {
|
|
|
469
469
|
*/
|
|
470
470
|
setCircles(id: number, points: Float64Array, feature: Uint32Array): void;
|
|
471
471
|
/**
|
|
472
|
-
* Cuts the 3D layers by a
|
|
473
|
-
* width, length and height (metres), its heading (degrees clockwise from north of
|
|
474
|
-
* inside it (else what is outside), 1 for an altitude above the relief (else
|
|
475
|
-
*
|
|
472
|
+
* Cuts the 3D layers by a volume: `values` its foot's longitude, latitude (degrees) and altitude (metres), its
|
|
473
|
+
* width, length and height (metres; a cylinder's width its diameter), its heading (degrees clockwise from north of
|
|
474
|
+
* a box's length), 1 to cut what is inside it (else what is outside), 1 for an altitude above the relief (else
|
|
475
|
+
* above the ellipsoid), its shape (0 a box, 1 a cylinder, 2 a prism on a polygon); `polygon` the polygon's
|
|
476
|
+
* vertices east and north of its foot's center (metres, 16 at most); `section` the color of the faces the cut
|
|
477
|
+
* opens (RGB 0-1), empty to leave them open
|
|
476
478
|
*/
|
|
477
|
-
|
|
479
|
+
setClipVolume(values: Float64Array, polygon: Float64Array, section: Float32Array): void;
|
|
478
480
|
/**
|
|
479
481
|
* A raster layer draped on the roofs, or all the faces, of a 3D Tiles layer, an extrusion layer, a vector tiles
|
|
480
482
|
* layer's buildings or a model layer (`raster` undefined: none)
|
|
@@ -945,7 +947,7 @@ export interface InitOutput {
|
|
|
945
947
|
readonly engine_backend: (a: number) => [number, number];
|
|
946
948
|
readonly engine_bounds: (a: number) => [number, number];
|
|
947
949
|
readonly engine_camera: (a: number) => any;
|
|
948
|
-
readonly
|
|
950
|
+
readonly engine_clearClipVolume: (a: number) => void;
|
|
949
951
|
readonly engine_clearPanorama: (a: number) => void;
|
|
950
952
|
readonly engine_clearPivot: (a: number) => void;
|
|
951
953
|
readonly engine_clearPreload: (a: number) => void;
|
|
@@ -983,7 +985,7 @@ export interface InitOutput {
|
|
|
983
985
|
readonly engine_setCamera: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
984
986
|
readonly engine_setCircleAlignment: (a: number, b: number, c: number) => void;
|
|
985
987
|
readonly engine_setCircles: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
986
|
-
readonly
|
|
988
|
+
readonly engine_setClipVolume: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
987
989
|
readonly engine_setDrape: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
988
990
|
readonly engine_setExtrusionAnchors: (a: number, b: number, c: number, d: number, e: number) => [number, number];
|
|
989
991
|
readonly engine_setExtrusionBatch: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number) => [number, number];
|
|
@@ -357,10 +357,10 @@ export class Engine {
|
|
|
357
357
|
return ret;
|
|
358
358
|
}
|
|
359
359
|
/**
|
|
360
|
-
* Removes the clipping
|
|
360
|
+
* Removes the clipping volume: the layers whole again
|
|
361
361
|
*/
|
|
362
|
-
|
|
363
|
-
wasm.
|
|
362
|
+
clearClipVolume() {
|
|
363
|
+
wasm.engine_clearClipVolume(this.__wbg_ptr);
|
|
364
364
|
}
|
|
365
365
|
/**
|
|
366
366
|
* Removes the panorama
|
|
@@ -737,19 +737,24 @@ export class Engine {
|
|
|
737
737
|
wasm.engine_setCircles(this.__wbg_ptr, id, ptr0, len0, ptr1, len1);
|
|
738
738
|
}
|
|
739
739
|
/**
|
|
740
|
-
* Cuts the 3D layers by a
|
|
741
|
-
* width, length and height (metres), its heading (degrees clockwise from north of
|
|
742
|
-
* inside it (else what is outside), 1 for an altitude above the relief (else
|
|
743
|
-
*
|
|
740
|
+
* Cuts the 3D layers by a volume: `values` its foot's longitude, latitude (degrees) and altitude (metres), its
|
|
741
|
+
* width, length and height (metres; a cylinder's width its diameter), its heading (degrees clockwise from north of
|
|
742
|
+
* a box's length), 1 to cut what is inside it (else what is outside), 1 for an altitude above the relief (else
|
|
743
|
+
* above the ellipsoid), its shape (0 a box, 1 a cylinder, 2 a prism on a polygon); `polygon` the polygon's
|
|
744
|
+
* vertices east and north of its foot's center (metres, 16 at most); `section` the color of the faces the cut
|
|
745
|
+
* opens (RGB 0-1), empty to leave them open
|
|
744
746
|
* @param {Float64Array} values
|
|
747
|
+
* @param {Float64Array} polygon
|
|
745
748
|
* @param {Float32Array} section
|
|
746
749
|
*/
|
|
747
|
-
|
|
750
|
+
setClipVolume(values, polygon, section) {
|
|
748
751
|
const ptr0 = passArrayF64ToWasm0(values, wasm.__wbindgen_malloc);
|
|
749
752
|
const len0 = WASM_VECTOR_LEN;
|
|
750
|
-
const ptr1 =
|
|
753
|
+
const ptr1 = passArrayF64ToWasm0(polygon, wasm.__wbindgen_malloc);
|
|
751
754
|
const len1 = WASM_VECTOR_LEN;
|
|
752
|
-
|
|
755
|
+
const ptr2 = passArrayF32ToWasm0(section, wasm.__wbindgen_malloc);
|
|
756
|
+
const len2 = WASM_VECTOR_LEN;
|
|
757
|
+
wasm.engine_setClipVolume(this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2);
|
|
753
758
|
}
|
|
754
759
|
/**
|
|
755
760
|
* A raster layer draped on the roofs, or all the faces, of a 3D Tiles layer, an extrusion layer, a vector tiles
|
package/package.json
CHANGED
package/dist/map/clip-box.d.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The clipping box (`GeoMap.setClipBox`): given to the engine, and its handles over the map, an outline of its edges
|
|
3
|
-
* and a disc on each face to size it, one at its middle to move it, placed after every frame.
|
|
4
|
-
*/
|
|
5
|
-
import type { ClipBox, LonLat, Point } from '../types.ts';
|
|
6
|
-
import type { Positioned } from '../ui/overlay.ts';
|
|
7
|
-
import type { Engine } from '../wasm/isard_webgpu.js';
|
|
8
|
-
/** Sets the box in the engine, or clears it without one */
|
|
9
|
-
export declare const applyClipBox: (engine: Engine, box: ClipBox | undefined) => void;
|
|
10
|
-
/** What the handles need from the map */
|
|
11
|
-
export interface ClipBoxHost {
|
|
12
|
-
project(lonLat: LonLat, height?: number): Point | undefined;
|
|
13
|
-
unproject(point: Point): LonLat | undefined;
|
|
14
|
-
elevationAt(lonLat: LonLat): number | undefined;
|
|
15
|
-
getCanvas(): HTMLCanvasElement;
|
|
16
|
-
/** The box changed by a handle: set, and told */
|
|
17
|
-
moved(box: ClipBox): void;
|
|
18
|
-
}
|
|
19
|
-
/** The handles of a box, over the map */
|
|
20
|
-
export declare class ClipBoxHandles implements Positioned {
|
|
21
|
-
private readonly host;
|
|
22
|
-
private box;
|
|
23
|
-
/** Metres of the body's radius (metres to degrees) */
|
|
24
|
-
private readonly radius;
|
|
25
|
-
/** Over the canvas, its drawing within */
|
|
26
|
-
readonly element: HTMLDivElement;
|
|
27
|
-
private readonly lines;
|
|
28
|
-
private readonly discs;
|
|
29
|
-
/** The handle held (its disc), the pointer and the box where it was pressed */
|
|
30
|
-
private held;
|
|
31
|
-
constructor(host: ClipBoxHost, box: ClipBox,
|
|
32
|
-
/** Metres of the body's radius (metres to degrees) */
|
|
33
|
-
radius: number);
|
|
34
|
-
/** The box the handles follow from the next placing (`position`, after each frame) */
|
|
35
|
-
set(box: ClipBox): void;
|
|
36
|
-
position(): void;
|
|
37
|
-
/** A point of the box, metres across and along its heading from its foot's center and up from its foot */
|
|
38
|
-
private at;
|
|
39
|
-
private corners;
|
|
40
|
-
/** Where a handle stands on the screen: a face's center, or the box's */
|
|
41
|
-
private handleAt;
|
|
42
|
-
private local;
|
|
43
|
-
private down;
|
|
44
|
-
private move;
|
|
45
|
-
/** Metres the pointer dragged a face outward: the drag along the face's axis on the screen */
|
|
46
|
-
private dragged;
|
|
47
|
-
/** The box with a face moved `metres` outward, the opposite face where it was */
|
|
48
|
-
private resized;
|
|
49
|
-
/** A position `east` and `north` metres from another */
|
|
50
|
-
private offset;
|
|
51
|
-
private up;
|
|
52
|
-
}
|
package/dist/map/clip-box.js
DELETED
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The clipping box (`GeoMap.setClipBox`): given to the engine, and its handles over the map, an outline of its edges
|
|
3
|
-
* and a disc on each face to size it, one at its middle to move it, placed after every frame.
|
|
4
|
-
*/
|
|
5
|
-
import { rgb } from "../settings.js";
|
|
6
|
-
/** The faces' color by default: plaster, as a section on a plan */
|
|
7
|
-
const SECTION = '#d9cfc1';
|
|
8
|
-
/** Metres a side of the box keeps at least */
|
|
9
|
-
const SMALLEST = 0.2;
|
|
10
|
-
const SVG = 'http://www.w3.org/2000/svg';
|
|
11
|
-
/** Sets the box in the engine, or clears it without one */
|
|
12
|
-
export const applyClipBox = (engine, box) => {
|
|
13
|
-
if (!box) {
|
|
14
|
-
engine.clearClipBox();
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
const [width, length, height] = box.size;
|
|
18
|
-
const section = box.sectionColor === null ? [] : rgb(box.sectionColor ?? SECTION);
|
|
19
|
-
engine.setClipBox(new Float64Array([
|
|
20
|
-
box.position[0],
|
|
21
|
-
box.position[1],
|
|
22
|
-
box.altitude ?? 0,
|
|
23
|
-
width,
|
|
24
|
-
length,
|
|
25
|
-
height,
|
|
26
|
-
box.heading ?? 0,
|
|
27
|
-
box.cut === 'outside' ? 0 : 1,
|
|
28
|
-
box.altitudeReference === 'sea' ? 0 : 1,
|
|
29
|
-
]), new Float32Array(section));
|
|
30
|
-
};
|
|
31
|
-
/** Metres across, along and up from the foot's center of a face's center, `out` metres out of it */
|
|
32
|
-
const faceAt = (box, { axis, side }, out = 0) => {
|
|
33
|
-
const [, , h] = box.size;
|
|
34
|
-
const offset = [0, 0, h / 2];
|
|
35
|
-
offset[axis] = axis === 2 ? (side > 0 ? h : 0) + side * out : side * (box.size[axis] / 2 + out);
|
|
36
|
-
return offset;
|
|
37
|
-
};
|
|
38
|
-
/** The 12 edges of the box, as pairs of corners (bit 0 across, 1 along, 2 up) */
|
|
39
|
-
const EDGES = [
|
|
40
|
-
[0, 1],
|
|
41
|
-
[2, 3],
|
|
42
|
-
[4, 5],
|
|
43
|
-
[6, 7],
|
|
44
|
-
[0, 2],
|
|
45
|
-
[1, 3],
|
|
46
|
-
[4, 6],
|
|
47
|
-
[5, 7],
|
|
48
|
-
[0, 4],
|
|
49
|
-
[1, 5],
|
|
50
|
-
[2, 6],
|
|
51
|
-
[3, 7],
|
|
52
|
-
];
|
|
53
|
-
const HANDLES = [
|
|
54
|
-
{ axis: 0, side: -1 },
|
|
55
|
-
{ axis: 0, side: 1 },
|
|
56
|
-
{ axis: 1, side: -1 },
|
|
57
|
-
{ axis: 1, side: 1 },
|
|
58
|
-
{ axis: 2, side: -1 },
|
|
59
|
-
{ axis: 2, side: 1 },
|
|
60
|
-
'move',
|
|
61
|
-
];
|
|
62
|
-
/** The handles of a box, over the map */
|
|
63
|
-
export class ClipBoxHandles {
|
|
64
|
-
host;
|
|
65
|
-
box;
|
|
66
|
-
radius;
|
|
67
|
-
/** Over the canvas, its drawing within */
|
|
68
|
-
element;
|
|
69
|
-
lines;
|
|
70
|
-
discs;
|
|
71
|
-
/** The handle held (its disc), the pointer and the box where it was pressed */
|
|
72
|
-
held;
|
|
73
|
-
constructor(host, box,
|
|
74
|
-
/** Metres of the body's radius (metres to degrees) */
|
|
75
|
-
radius) {
|
|
76
|
-
this.host = host;
|
|
77
|
-
this.box = box;
|
|
78
|
-
this.radius = radius;
|
|
79
|
-
const svg = document.createElementNS(SVG, 'svg');
|
|
80
|
-
this.element = document.createElement('div');
|
|
81
|
-
this.element.className = 'isard-clipbox';
|
|
82
|
-
this.element.append(svg);
|
|
83
|
-
this.lines = EDGES.map(() => svg.appendChild(document.createElementNS(SVG, 'line')));
|
|
84
|
-
this.discs = HANDLES.map((handle) => {
|
|
85
|
-
const disc = document.createElementNS(SVG, 'circle');
|
|
86
|
-
disc.setAttribute('r', handle === 'move' ? '8' : '6');
|
|
87
|
-
disc.setAttribute('class', handle === 'move' ? 'isard-clipbox-move' : 'isard-clipbox-face');
|
|
88
|
-
disc.addEventListener('pointerdown', (e) => this.down(e, handle, disc));
|
|
89
|
-
disc.addEventListener('pointermove', (e) => this.move(e));
|
|
90
|
-
disc.addEventListener('pointerup', (e) => this.up(e));
|
|
91
|
-
disc.addEventListener('pointercancel', (e) => this.up(e));
|
|
92
|
-
// Safari may let the capture go: the release would then reach the map, not the disc
|
|
93
|
-
disc.addEventListener('lostpointercapture', (e) => this.up(e));
|
|
94
|
-
return svg.appendChild(disc);
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
/** The box the handles follow from the next placing (`position`, after each frame) */
|
|
98
|
-
set(box) {
|
|
99
|
-
this.box = box;
|
|
100
|
-
}
|
|
101
|
-
position() {
|
|
102
|
-
const corners = this.corners(this.box);
|
|
103
|
-
const centers = HANDLES.map((handle) => this.handleAt(this.box, handle));
|
|
104
|
-
EDGES.forEach(([a, b], i) => {
|
|
105
|
-
const [p, q] = [corners[a], corners[b]];
|
|
106
|
-
const line = this.lines[i];
|
|
107
|
-
if (!line)
|
|
108
|
-
return;
|
|
109
|
-
line.style.display = p && q ? '' : 'none';
|
|
110
|
-
if (!p || !q)
|
|
111
|
-
return;
|
|
112
|
-
line.setAttribute('x1', String(p[0]));
|
|
113
|
-
line.setAttribute('y1', String(p[1]));
|
|
114
|
-
line.setAttribute('x2', String(q[0]));
|
|
115
|
-
line.setAttribute('y2', String(q[1]));
|
|
116
|
-
});
|
|
117
|
-
centers.forEach((p, i) => {
|
|
118
|
-
const disc = this.discs[i];
|
|
119
|
-
if (!disc)
|
|
120
|
-
return;
|
|
121
|
-
disc.style.display = p ? '' : 'none';
|
|
122
|
-
if (!p)
|
|
123
|
-
return;
|
|
124
|
-
disc.setAttribute('cx', String(p[0]));
|
|
125
|
-
disc.setAttribute('cy', String(p[1]));
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
/** A point of the box, metres across and along its heading from its foot's center and up from its foot */
|
|
129
|
-
at(box, across, along, up) {
|
|
130
|
-
const heading = ((box.heading ?? 0) * Math.PI) / 180;
|
|
131
|
-
const [sin, cos] = [Math.sin(heading), Math.cos(heading)];
|
|
132
|
-
const lonLat = this.offset(box.position, across * cos + along * sin, along * cos - across * sin);
|
|
133
|
-
// `project` measures from the relief: an altitude above the ellipsoid less the relief under the box
|
|
134
|
-
const ground = box.altitudeReference === 'sea' ? (this.host.elevationAt(box.position) ?? 0) : 0;
|
|
135
|
-
return this.host.project(lonLat, (box.altitude ?? 0) - ground + up);
|
|
136
|
-
}
|
|
137
|
-
corners(box) {
|
|
138
|
-
const [w, l, h] = box.size;
|
|
139
|
-
return Array.from({ length: 8 }, (_, k) => this.at(box, (k & 1 ? 0.5 : -0.5) * w, (k & 2 ? 0.5 : -0.5) * l, k & 4 ? h : 0));
|
|
140
|
-
}
|
|
141
|
-
/** Where a handle stands on the screen: a face's center, or the box's */
|
|
142
|
-
handleAt(box, handle) {
|
|
143
|
-
return handle === 'move' ? this.at(box, 0, 0, box.size[2] / 2) : this.at(box, ...faceAt(box, handle));
|
|
144
|
-
}
|
|
145
|
-
local(e) {
|
|
146
|
-
const rect = this.host.getCanvas().getBoundingClientRect();
|
|
147
|
-
return [e.clientX - rect.left, e.clientY - rect.top];
|
|
148
|
-
}
|
|
149
|
-
down(e, handle, disc) {
|
|
150
|
-
if (e.button !== 0)
|
|
151
|
-
return;
|
|
152
|
-
const start = this.local(e);
|
|
153
|
-
// The spot of the ground grabbed, kept under the pointer as the box moves
|
|
154
|
-
const grab = handle === 'move' ? this.host.unproject(start) : undefined;
|
|
155
|
-
// The map must not pan under the handle
|
|
156
|
-
e.stopPropagation();
|
|
157
|
-
e.preventDefault();
|
|
158
|
-
disc.setPointerCapture(e.pointerId);
|
|
159
|
-
this.held = {
|
|
160
|
-
handle,
|
|
161
|
-
disc,
|
|
162
|
-
start,
|
|
163
|
-
box: { ...this.box, size: [...this.box.size] },
|
|
164
|
-
grab: grab ? [grab[0] - this.box.position[0], grab[1] - this.box.position[1]] : [0, 0],
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
move(e) {
|
|
168
|
-
if (!this.held)
|
|
169
|
-
return;
|
|
170
|
-
// No button held any more: its release was missed (the capture lost), the drag is over
|
|
171
|
-
if (e.buttons === 0) {
|
|
172
|
-
this.up(e);
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
e.stopPropagation();
|
|
176
|
-
const { handle, start, box, grab } = this.held;
|
|
177
|
-
const at = this.local(e);
|
|
178
|
-
if (handle === 'move') {
|
|
179
|
-
// The ground under the pointer, the grabbed spot kept under it
|
|
180
|
-
const lonLat = this.host.unproject(at);
|
|
181
|
-
if (lonLat)
|
|
182
|
-
this.host.moved({ ...box, position: [lonLat[0] - grab[0], lonLat[1] - grab[1]] });
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
const metres = this.dragged(box, handle, [at[0] - start[0], at[1] - start[1]]);
|
|
186
|
-
if (metres !== undefined)
|
|
187
|
-
this.host.moved(this.resized(box, handle, metres));
|
|
188
|
-
}
|
|
189
|
-
/** Metres the pointer dragged a face outward: the drag along the face's axis on the screen */
|
|
190
|
-
dragged(box, face, [dx, dy]) {
|
|
191
|
-
const from = this.at(box, ...faceAt(box, face));
|
|
192
|
-
// Where the face's center goes a metre out, on the screen: pixels per metre along its axis
|
|
193
|
-
const to = this.at(box, ...faceAt(box, face, 1));
|
|
194
|
-
if (!from || !to)
|
|
195
|
-
return undefined;
|
|
196
|
-
const [ax, ay] = [to[0] - from[0], to[1] - from[1]];
|
|
197
|
-
const squared = ax * ax + ay * ay;
|
|
198
|
-
return squared > 1e-6 ? (dx * ax + dy * ay) / squared : undefined;
|
|
199
|
-
}
|
|
200
|
-
/** The box with a face moved `metres` outward, the opposite face where it was */
|
|
201
|
-
resized(box, { axis, side }, metres) {
|
|
202
|
-
const size = [...box.size];
|
|
203
|
-
const grown = Math.max(SMALLEST, size[axis] + metres);
|
|
204
|
-
const moved = grown - size[axis];
|
|
205
|
-
size[axis] = grown;
|
|
206
|
-
if (axis === 2) {
|
|
207
|
-
// The foot lowered when the bottom face goes down
|
|
208
|
-
return side > 0 ? { ...box, size } : { ...box, size, altitude: (box.altitude ?? 0) - moved };
|
|
209
|
-
}
|
|
210
|
-
// The center half-way along the move, on the side of the face moved
|
|
211
|
-
const heading = ((box.heading ?? 0) * Math.PI) / 180;
|
|
212
|
-
const [sin, cos] = [Math.sin(heading), Math.cos(heading)];
|
|
213
|
-
const shift = (side * moved) / 2;
|
|
214
|
-
const [east, north] = axis === 0 ? [shift * cos, -shift * sin] : [shift * sin, shift * cos];
|
|
215
|
-
return { ...box, size, position: this.offset(box.position, east, north) };
|
|
216
|
-
}
|
|
217
|
-
/** A position `east` and `north` metres from another */
|
|
218
|
-
offset([lon, lat], east, north) {
|
|
219
|
-
return [
|
|
220
|
-
lon + (east / (this.radius * Math.cos((lat * Math.PI) / 180))) * (180 / Math.PI),
|
|
221
|
-
lat + (north / this.radius) * (180 / Math.PI),
|
|
222
|
-
];
|
|
223
|
-
}
|
|
224
|
-
up(e) {
|
|
225
|
-
if (!this.held)
|
|
226
|
-
return;
|
|
227
|
-
e.stopPropagation();
|
|
228
|
-
if (this.held.disc.hasPointerCapture(e.pointerId))
|
|
229
|
-
this.held.disc.releasePointerCapture(e.pointerId);
|
|
230
|
-
this.held = undefined;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
//# sourceMappingURL=clip-box.js.map
|
package/dist/map/clip-box.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"clip-box.js","sourceRoot":"","sources":["../../src/map/clip-box.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The clipping box (`GeoMap.setClipBox`): given to the engine, and its handles over the map, an outline of its edges\n * and a disc on each face to size it, one at its middle to move it, placed after every frame.\n */\n\nimport { rgb } from '../settings.ts';\nimport type { ClipBox, LonLat, Point } from '../types.ts';\nimport type { Positioned } from '../ui/overlay.ts';\nimport type { Engine } from '../wasm/isard_webgpu.js';\n\n/** The faces' color by default: plaster, as a section on a plan */\nconst SECTION = '#d9cfc1';\n/** Metres a side of the box keeps at least */\nconst SMALLEST = 0.2;\nconst SVG = 'http://www.w3.org/2000/svg';\n\n/** Sets the box in the engine, or clears it without one */\nexport const applyClipBox = (engine: Engine, box: ClipBox | undefined): void => {\n if (!box) {\n engine.clearClipBox();\n\n return;\n }\n\n const [width, length, height] = box.size;\n const section = box.sectionColor === null ? [] : rgb(box.sectionColor ?? SECTION);\n\n engine.setClipBox(\n new Float64Array([\n box.position[0],\n box.position[1],\n box.altitude ?? 0,\n width,\n length,\n height,\n box.heading ?? 0,\n box.cut === 'outside' ? 0 : 1,\n box.altitudeReference === 'sea' ? 0 : 1,\n ]),\n new Float32Array(section),\n );\n};\n\n/** What the handles need from the map */\nexport interface ClipBoxHost {\n project(lonLat: LonLat, height?: number): Point | undefined;\n unproject(point: Point): LonLat | undefined;\n elevationAt(lonLat: LonLat): number | undefined;\n getCanvas(): HTMLCanvasElement;\n /** The box changed by a handle: set, and told */\n moved(box: ClipBox): void;\n}\n\n/** A face's handle: its axis (0 across, 1 along, 2 up) and side */\ninterface Face {\n axis: 0 | 1 | 2;\n side: -1 | 1;\n}\n\n/** A handle: on a face, or at the middle (moves the box, clear of the bottom face's) */\ntype Handle = Face | 'move';\n\n/** Metres across, along and up from the foot's center of a face's center, `out` metres out of it */\nconst faceAt = (box: ClipBox, { axis, side }: Face, out = 0): [number, number, number] => {\n const [, , h] = box.size;\n const offset: [number, number, number] = [0, 0, h / 2];\n\n offset[axis] = axis === 2 ? (side > 0 ? h : 0) + side * out : side * (box.size[axis] / 2 + out);\n\n return offset;\n};\n\n/** The 12 edges of the box, as pairs of corners (bit 0 across, 1 along, 2 up) */\nconst EDGES: [number, number][] = [\n [0, 1],\n [2, 3],\n [4, 5],\n [6, 7],\n [0, 2],\n [1, 3],\n [4, 6],\n [5, 7],\n [0, 4],\n [1, 5],\n [2, 6],\n [3, 7],\n];\n\nconst HANDLES: Handle[] = [\n { axis: 0, side: -1 },\n { axis: 0, side: 1 },\n { axis: 1, side: -1 },\n { axis: 1, side: 1 },\n { axis: 2, side: -1 },\n { axis: 2, side: 1 },\n 'move',\n];\n\n/** The handles of a box, over the map */\nexport class ClipBoxHandles implements Positioned {\n /** Over the canvas, its drawing within */\n readonly element: HTMLDivElement;\n private readonly lines: SVGLineElement[];\n private readonly discs: SVGCircleElement[];\n /** The handle held (its disc), the pointer and the box where it was pressed */\n private held: { handle: Handle; disc: SVGCircleElement; start: Point; box: ClipBox; grab: Point } | undefined;\n\n constructor(\n private readonly host: ClipBoxHost,\n private box: ClipBox,\n /** Metres of the body's radius (metres to degrees) */\n private readonly radius: number,\n ) {\n const svg = document.createElementNS(SVG, 'svg');\n\n this.element = document.createElement('div');\n this.element.className = 'isard-clipbox';\n this.element.append(svg);\n this.lines = EDGES.map(() => svg.appendChild(document.createElementNS(SVG, 'line')));\n this.discs = HANDLES.map((handle) => {\n const disc = document.createElementNS(SVG, 'circle');\n\n disc.setAttribute('r', handle === 'move' ? '8' : '6');\n disc.setAttribute('class', handle === 'move' ? 'isard-clipbox-move' : 'isard-clipbox-face');\n disc.addEventListener('pointerdown', (e) => this.down(e, handle, disc));\n disc.addEventListener('pointermove', (e) => this.move(e));\n disc.addEventListener('pointerup', (e) => this.up(e));\n disc.addEventListener('pointercancel', (e) => this.up(e));\n // Safari may let the capture go: the release would then reach the map, not the disc\n disc.addEventListener('lostpointercapture', (e) => this.up(e));\n\n return svg.appendChild(disc);\n });\n }\n\n /** The box the handles follow from the next placing (`position`, after each frame) */\n set(box: ClipBox): void {\n this.box = box;\n }\n\n position(): void {\n const corners = this.corners(this.box);\n const centers = HANDLES.map((handle) => this.handleAt(this.box, handle));\n\n EDGES.forEach(([a, b], i) => {\n const [p, q] = [corners[a], corners[b]];\n const line = this.lines[i];\n\n if (!line) return;\n line.style.display = p && q ? '' : 'none';\n if (!p || !q) return;\n line.setAttribute('x1', String(p[0]));\n line.setAttribute('y1', String(p[1]));\n line.setAttribute('x2', String(q[0]));\n line.setAttribute('y2', String(q[1]));\n });\n centers.forEach((p, i) => {\n const disc = this.discs[i];\n\n if (!disc) return;\n disc.style.display = p ? '' : 'none';\n if (!p) return;\n disc.setAttribute('cx', String(p[0]));\n disc.setAttribute('cy', String(p[1]));\n });\n }\n\n /** A point of the box, metres across and along its heading from its foot's center and up from its foot */\n private at(box: ClipBox, across: number, along: number, up: number): Point | undefined {\n const heading = ((box.heading ?? 0) * Math.PI) / 180;\n const [sin, cos] = [Math.sin(heading), Math.cos(heading)];\n const lonLat = this.offset(box.position, across * cos + along * sin, along * cos - across * sin);\n // `project` measures from the relief: an altitude above the ellipsoid less the relief under the box\n const ground = box.altitudeReference === 'sea' ? (this.host.elevationAt(box.position) ?? 0) : 0;\n\n return this.host.project(lonLat, (box.altitude ?? 0) - ground + up);\n }\n\n private corners(box: ClipBox): (Point | undefined)[] {\n const [w, l, h] = box.size;\n\n return Array.from({ length: 8 }, (_, k) =>\n this.at(box, (k & 1 ? 0.5 : -0.5) * w, (k & 2 ? 0.5 : -0.5) * l, k & 4 ? h : 0),\n );\n }\n\n /** Where a handle stands on the screen: a face's center, or the box's */\n private handleAt(box: ClipBox, handle: Handle): Point | undefined {\n return handle === 'move' ? this.at(box, 0, 0, box.size[2] / 2) : this.at(box, ...faceAt(box, handle));\n }\n\n private local(e: PointerEvent): Point {\n const rect = this.host.getCanvas().getBoundingClientRect();\n\n return [e.clientX - rect.left, e.clientY - rect.top];\n }\n\n private down(e: PointerEvent, handle: Handle, disc: SVGCircleElement): void {\n if (e.button !== 0) return;\n\n const start = this.local(e);\n // The spot of the ground grabbed, kept under the pointer as the box moves\n const grab = handle === 'move' ? this.host.unproject(start) : undefined;\n\n // The map must not pan under the handle\n e.stopPropagation();\n e.preventDefault();\n disc.setPointerCapture(e.pointerId);\n this.held = {\n handle,\n disc,\n start,\n box: { ...this.box, size: [...this.box.size] },\n grab: grab ? [grab[0] - this.box.position[0], grab[1] - this.box.position[1]] : [0, 0],\n };\n }\n\n private move(e: PointerEvent): void {\n if (!this.held) return;\n // No button held any more: its release was missed (the capture lost), the drag is over\n if (e.buttons === 0) {\n this.up(e);\n\n return;\n }\n e.stopPropagation();\n\n const { handle, start, box, grab } = this.held;\n const at = this.local(e);\n\n if (handle === 'move') {\n // The ground under the pointer, the grabbed spot kept under it\n const lonLat = this.host.unproject(at);\n\n if (lonLat) this.host.moved({ ...box, position: [lonLat[0] - grab[0], lonLat[1] - grab[1]] });\n\n return;\n }\n\n const metres = this.dragged(box, handle, [at[0] - start[0], at[1] - start[1]]);\n\n if (metres !== undefined) this.host.moved(this.resized(box, handle, metres));\n }\n\n /** Metres the pointer dragged a face outward: the drag along the face's axis on the screen */\n private dragged(box: ClipBox, face: Face, [dx, dy]: Point): number | undefined {\n const from = this.at(box, ...faceAt(box, face));\n // Where the face's center goes a metre out, on the screen: pixels per metre along its axis\n const to = this.at(box, ...faceAt(box, face, 1));\n\n if (!from || !to) return undefined;\n\n const [ax, ay] = [to[0] - from[0], to[1] - from[1]];\n const squared = ax * ax + ay * ay;\n\n return squared > 1e-6 ? (dx * ax + dy * ay) / squared : undefined;\n }\n\n /** The box with a face moved `metres` outward, the opposite face where it was */\n private resized(box: ClipBox, { axis, side }: Face, metres: number): ClipBox {\n const size: [number, number, number] = [...box.size];\n const grown = Math.max(SMALLEST, size[axis] + metres);\n const moved = grown - size[axis];\n\n size[axis] = grown;\n if (axis === 2) {\n // The foot lowered when the bottom face goes down\n return side > 0 ? { ...box, size } : { ...box, size, altitude: (box.altitude ?? 0) - moved };\n }\n\n // The center half-way along the move, on the side of the face moved\n const heading = ((box.heading ?? 0) * Math.PI) / 180;\n const [sin, cos] = [Math.sin(heading), Math.cos(heading)];\n const shift = (side * moved) / 2;\n const [east, north] = axis === 0 ? [shift * cos, -shift * sin] : [shift * sin, shift * cos];\n return { ...box, size, position: this.offset(box.position, east, north) };\n }\n\n /** A position `east` and `north` metres from another */\n private offset([lon, lat]: LonLat, east: number, north: number): LonLat {\n return [\n lon + (east / (this.radius * Math.cos((lat * Math.PI) / 180))) * (180 / Math.PI),\n lat + (north / this.radius) * (180 / Math.PI),\n ];\n }\n\n private up(e: PointerEvent): void {\n if (!this.held) return;\n e.stopPropagation();\n if (this.held.disc.hasPointerCapture(e.pointerId)) this.held.disc.releasePointerCapture(e.pointerId);\n this.held = undefined;\n }\n}\n"]}
|
package/dist/react/ClipBox.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/** `<ClipBox>`: a box cutting the map's 3D layers, its handles' changes told back */
|
|
2
|
-
import { type ReactNode } from 'react';
|
|
3
|
-
import type { ClipBox as ClipBoxOptions } from '../types.ts';
|
|
4
|
-
export interface ClipBoxProps extends ClipBoxOptions {
|
|
5
|
-
/** The box moved or sized by its handles (`handles`): keep it in a state to follow them */
|
|
6
|
-
onChange?: (box: ClipBoxOptions) => void;
|
|
7
|
-
}
|
|
8
|
-
/** The map's clipping box (`GeoMap.setClipBox`) while mounted */
|
|
9
|
-
export declare const ClipBox: ({ onChange, ...box }: ClipBoxProps) => ReactNode;
|
package/dist/react/ClipBox.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/** `<ClipBox>`: a box cutting the map's 3D layers, its handles' changes told back */
|
|
2
|
-
import { useEffect } from 'react';
|
|
3
|
-
import { useMap, useMapEvent } from "./context.js";
|
|
4
|
-
/** The map's clipping box (`GeoMap.setClipBox`) while mounted */
|
|
5
|
-
export const ClipBox = ({ onChange, ...box }) => {
|
|
6
|
-
const map = useMap();
|
|
7
|
-
// Numbers, strings and arrays: compared by value
|
|
8
|
-
const options = JSON.stringify(box);
|
|
9
|
-
// The layers whole again when unmounted
|
|
10
|
-
useEffect(() => {
|
|
11
|
-
if (!map)
|
|
12
|
-
return;
|
|
13
|
-
return () => map.setClipBox(undefined);
|
|
14
|
-
}, [map]);
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
map?.setClipBox(JSON.parse(options));
|
|
17
|
-
}, [map, options]);
|
|
18
|
-
useMapEvent('clipbox', (moved) => onChange?.(moved));
|
|
19
|
-
return null;
|
|
20
|
-
};
|
|
21
|
-
//# sourceMappingURL=ClipBox.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ClipBox.js","sourceRoot":"","sources":["../../src/react/ClipBox.tsx"],"names":[],"mappings":"AAAA,qFAAqF;AAErF,OAAO,EAAkB,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAOnD,iEAAiE;AACjE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,GAAG,EAAgB,EAAa,EAAE;IACvE,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,iDAAiD;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAEpC,wCAAwC;IACxC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,GAAG;YAAE,OAAO;QAEjB,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACV,SAAS,CAAC,GAAG,EAAE;QACb,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAmB,CAAC,CAAC;IACzD,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IACnB,WAAW,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAErD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC","sourcesContent":["/** `<ClipBox>`: a box cutting the map's 3D layers, its handles' changes told back */\n\nimport { type ReactNode, useEffect } from 'react';\nimport type { ClipBox as ClipBoxOptions } from '../types.ts';\nimport { useMap, useMapEvent } from './context.ts';\n\nexport interface ClipBoxProps extends ClipBoxOptions {\n /** The box moved or sized by its handles (`handles`): keep it in a state to follow them */\n onChange?: (box: ClipBoxOptions) => void;\n}\n\n/** The map's clipping box (`GeoMap.setClipBox`) while mounted */\nexport const ClipBox = ({ onChange, ...box }: ClipBoxProps): ReactNode => {\n const map = useMap();\n // Numbers, strings and arrays: compared by value\n const options = JSON.stringify(box);\n\n // The layers whole again when unmounted\n useEffect(() => {\n if (!map) return;\n\n return () => map.setClipBox(undefined);\n }, [map]);\n useEffect(() => {\n map?.setClipBox(JSON.parse(options) as ClipBoxOptions);\n }, [map, options]);\n useMapEvent('clipbox', (moved) => onChange?.(moved));\n\n return null;\n};\n"]}
|