-
Notifications
You must be signed in to change notification settings - Fork 165
/
elevation-mode.ts
86 lines (75 loc) · 2.85 KB
/
elevation-mode.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import { ModeProps, PointerMoveEvent, StopDraggingEvent } from '../types';
import { Position, FeatureCollection } from '../geojson-types';
import { getPickedEditHandle } from '../utils';
import { ModifyMode } from './modify-mode';
function defaultCalculateElevationChange({
pointerDownScreenCoords,
screenCoords,
}: {
pointerDownScreenCoords: Position;
screenCoords: Position;
}) {
return 10 * (pointerDownScreenCoords[1] - screenCoords[1]);
}
export class ElevationMode extends ModifyMode {
makeElevatedEvent(
event: PointerMoveEvent | StopDraggingEvent,
position: Position,
props: ModeProps<FeatureCollection>
): Record<string, any> {
const {
minElevation = 0,
maxElevation = 20000,
calculateElevationChange = defaultCalculateElevationChange,
} = props.modeConfig || {};
if (!event.pointerDownScreenCoords) {
return event;
}
// $FlowFixMe - really, I know it has something at index 2
let elevation = position.length === 3 ? position[2] : 0;
// calculateElevationChange is configurable because (at this time) modes are not aware of the viewport
elevation += calculateElevationChange({
pointerDownScreenCoords: event.pointerDownScreenCoords,
screenCoords: event.screenCoords,
});
elevation = Math.min(elevation, maxElevation);
elevation = Math.max(elevation, minElevation);
return Object.assign({}, event, {
mapCoords: [position[0], position[1], elevation],
});
}
handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
const editHandle = getPickedEditHandle(event.pointerDownPicks);
const position = editHandle ? editHandle.geometry.coordinates : event.mapCoords;
// @ts-expect-error return type too wide
super.handlePointerMove(this.makeElevatedEvent(event, position, props), props);
}
handleStopDragging(event: StopDraggingEvent, props: ModeProps<FeatureCollection>) {
const editHandle = getPickedEditHandle(event.picks);
const position = editHandle ? editHandle.geometry.coordinates : event.mapCoords;
// @ts-expect-error return type too wide
super.handleStopDragging(this.makeElevatedEvent(event, position, props), props);
}
getCursor(event: PointerMoveEvent): string | null | undefined {
let cursor = super.getCursor(event);
if (cursor === 'cell') {
cursor = 'ns-resize';
}
return cursor;
}
static calculateElevationChangeWithViewport(
viewport: any,
{
pointerDownScreenCoords,
screenCoords,
}: {
pointerDownScreenCoords: Position;
screenCoords: Position;
}
): number {
// Source: https://gis.stackexchange.com/a/127949/111804
const metersPerPixel =
(156543.03392 * Math.cos((viewport.latitude * Math.PI) / 180)) / Math.pow(2, viewport.zoom);
return (metersPerPixel * (pointerDownScreenCoords[1] - screenCoords[1])) / 2;
}
}