@deck.gl-community/editable-layers 9.0.0-alpha.1

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.
Files changed (295) hide show
  1. package/README.md +82 -0
  2. package/dist/constants.d.ts +14 -0
  3. package/dist/constants.js +14 -0
  4. package/dist/curve-utils.d.ts +2 -0
  5. package/dist/curve-utils.js +61 -0
  6. package/dist/edit-modes/composite-mode.d.ts +14 -0
  7. package/dist/edit-modes/composite-mode.js +47 -0
  8. package/dist/edit-modes/draw-90degree-polygon-mode.d.ts +11 -0
  9. package/dist/edit-modes/draw-90degree-polygon-mode.js +179 -0
  10. package/dist/edit-modes/draw-circle-by-diameter-mode.d.ts +24 -0
  11. package/dist/edit-modes/draw-circle-by-diameter-mode.js +78 -0
  12. package/dist/edit-modes/draw-circle-from-center-mode.d.ts +22 -0
  13. package/dist/edit-modes/draw-circle-from-center-mode.js +70 -0
  14. package/dist/edit-modes/draw-ellipse-by-bounding-box-mode.d.ts +5 -0
  15. package/dist/edit-modes/draw-ellipse-by-bounding-box-mode.js +20 -0
  16. package/dist/edit-modes/draw-ellipse-using-three-points-mode.d.ts +5 -0
  17. package/dist/edit-modes/draw-ellipse-using-three-points-mode.js +16 -0
  18. package/dist/edit-modes/draw-line-string-mode.d.ts +25 -0
  19. package/dist/edit-modes/draw-line-string-mode.js +170 -0
  20. package/dist/edit-modes/draw-point-mode.d.ts +8 -0
  21. package/dist/edit-modes/draw-point-mode.js +28 -0
  22. package/dist/edit-modes/draw-polygon-by-dragging-mode.d.ts +14 -0
  23. package/dist/edit-modes/draw-polygon-by-dragging-mode.js +87 -0
  24. package/dist/edit-modes/draw-polygon-mode.d.ts +10 -0
  25. package/dist/edit-modes/draw-polygon-mode.js +143 -0
  26. package/dist/edit-modes/draw-rectangle-from-center-mode.d.ts +5 -0
  27. package/dist/edit-modes/draw-rectangle-from-center-mode.js +17 -0
  28. package/dist/edit-modes/draw-rectangle-mode.d.ts +5 -0
  29. package/dist/edit-modes/draw-rectangle-mode.js +11 -0
  30. package/dist/edit-modes/draw-rectangle-using-three-points-mode.d.ts +5 -0
  31. package/dist/edit-modes/draw-rectangle-using-three-points-mode.js +28 -0
  32. package/dist/edit-modes/draw-square-from-center-mode.d.ts +5 -0
  33. package/dist/edit-modes/draw-square-from-center-mode.js +35 -0
  34. package/dist/edit-modes/draw-square-mode.d.ts +5 -0
  35. package/dist/edit-modes/draw-square-mode.js +28 -0
  36. package/dist/edit-modes/duplicate-mode.d.ts +7 -0
  37. package/dist/edit-modes/duplicate-mode.js +17 -0
  38. package/dist/edit-modes/edit-mode.d.ts +11 -0
  39. package/dist/edit-modes/edit-mode.js +2 -0
  40. package/dist/edit-modes/elevation-mode.d.ts +13 -0
  41. package/dist/edit-modes/elevation-mode.js +49 -0
  42. package/dist/edit-modes/extend-line-string-mode.d.ts +9 -0
  43. package/dist/edit-modes/extend-line-string-mode.js +72 -0
  44. package/dist/edit-modes/extrude-mode.d.ts +15 -0
  45. package/dist/edit-modes/extrude-mode.js +186 -0
  46. package/dist/edit-modes/geojson-edit-mode.d.ts +33 -0
  47. package/dist/edit-modes/geojson-edit-mode.js +208 -0
  48. package/dist/edit-modes/immutable-feature-collection.d.ts +43 -0
  49. package/dist/edit-modes/immutable-feature-collection.js +300 -0
  50. package/dist/edit-modes/measure-angle-mode.d.ts +11 -0
  51. package/dist/edit-modes/measure-angle-mode.js +99 -0
  52. package/dist/edit-modes/measure-area-mode.d.ts +8 -0
  53. package/dist/edit-modes/measure-area-mode.js +50 -0
  54. package/dist/edit-modes/measure-distance-mode.d.ts +19 -0
  55. package/dist/edit-modes/measure-distance-mode.js +171 -0
  56. package/dist/edit-modes/modify-mode.d.ts +15 -0
  57. package/dist/edit-modes/modify-mode.js +203 -0
  58. package/dist/edit-modes/resize-circle-mode.d.ts +16 -0
  59. package/dist/edit-modes/resize-circle-mode.js +142 -0
  60. package/dist/edit-modes/rotate-mode.d.ts +17 -0
  61. package/dist/edit-modes/rotate-mode.js +151 -0
  62. package/dist/edit-modes/scale-mode.d.ts +27 -0
  63. package/dist/edit-modes/scale-mode.js +173 -0
  64. package/dist/edit-modes/snappable-mode.d.ts +21 -0
  65. package/dist/edit-modes/snappable-mode.js +109 -0
  66. package/dist/edit-modes/split-polygon-mode.d.ts +10 -0
  67. package/dist/edit-modes/split-polygon-mode.js +164 -0
  68. package/dist/edit-modes/three-click-polygon-mode.d.ts +10 -0
  69. package/dist/edit-modes/three-click-polygon-mode.js +72 -0
  70. package/dist/edit-modes/transform-mode.d.ts +9 -0
  71. package/dist/edit-modes/transform-mode.js +63 -0
  72. package/dist/edit-modes/translate-mode.d.ts +13 -0
  73. package/dist/edit-modes/translate-mode.js +113 -0
  74. package/dist/edit-modes/two-click-polygon-mode.d.ts +13 -0
  75. package/dist/edit-modes/two-click-polygon-mode.js +93 -0
  76. package/dist/edit-modes/types.d.ts +86 -0
  77. package/dist/edit-modes/types.js +1 -0
  78. package/dist/edit-modes/utils.d.ts +36 -0
  79. package/dist/edit-modes/utils.js +381 -0
  80. package/dist/edit-modes/view-mode.d.ts +3 -0
  81. package/dist/edit-modes/view-mode.js +3 -0
  82. package/dist/editable-layers/editable-geojson-layer.d.ts +98 -0
  83. package/dist/editable-layers/editable-geojson-layer.js +450 -0
  84. package/dist/editable-layers/editable-h3-cluster-layer.d.ts +34 -0
  85. package/dist/editable-layers/editable-h3-cluster-layer.js +164 -0
  86. package/dist/editable-layers/editable-layer.d.ts +49 -0
  87. package/dist/editable-layers/editable-layer.js +195 -0
  88. package/dist/editable-layers/editable-path-layer.d.ts +9 -0
  89. package/dist/editable-layers/editable-path-layer.js +34 -0
  90. package/dist/editable-layers/elevated-edit-handle-layer.d.ts +7 -0
  91. package/dist/editable-layers/elevated-edit-handle-layer.js +24 -0
  92. package/dist/editable-layers/junction-scatterplot-layer.d.ts +14 -0
  93. package/dist/editable-layers/junction-scatterplot-layer.js +41 -0
  94. package/dist/editable-layers/path-marker-layer/arrow-2d-geometry.d.ts +4 -0
  95. package/dist/editable-layers/path-marker-layer/arrow-2d-geometry.js +55 -0
  96. package/dist/editable-layers/path-marker-layer/create-path-markers.d.ts +16 -0
  97. package/dist/editable-layers/path-marker-layer/create-path-markers.js +75 -0
  98. package/dist/editable-layers/path-marker-layer/path-marker-layer.d.ts +40 -0
  99. package/dist/editable-layers/path-marker-layer/path-marker-layer.js +121 -0
  100. package/dist/editable-layers/path-marker-layer/polyline.d.ts +18 -0
  101. package/dist/editable-layers/path-marker-layer/polyline.js +37 -0
  102. package/dist/editable-layers/path-outline-layer/path-outline-layer.d.ts +26 -0
  103. package/dist/editable-layers/path-outline-layer/path-outline-layer.js +106 -0
  104. package/dist/editable-layers/selection-layer.d.ts +26 -0
  105. package/dist/editable-layers/selection-layer.js +167 -0
  106. package/dist/geojson-types.d.ts +58 -0
  107. package/dist/geojson-types.js +2 -0
  108. package/dist/index.cjs +5825 -0
  109. package/dist/index.cjs.map +7 -0
  110. package/dist/index.d.ts +60 -0
  111. package/dist/index.js +62 -0
  112. package/dist/lib/constants.d.ts +6 -0
  113. package/dist/lib/constants.js +6 -0
  114. package/dist/lib/deck-renderer/deck-cache.d.ts +14 -0
  115. package/dist/lib/deck-renderer/deck-cache.js +51 -0
  116. package/dist/lib/deck-renderer/deck-drawer.d.ts +63 -0
  117. package/dist/lib/deck-renderer/deck-drawer.js +232 -0
  118. package/dist/lib/feature.d.ts +10 -0
  119. package/dist/lib/feature.js +16 -0
  120. package/dist/lib/layer-mouse-event.d.ts +11 -0
  121. package/dist/lib/layer-mouse-event.js +24 -0
  122. package/dist/lib/layers/junctions-layer.d.ts +8 -0
  123. package/dist/lib/layers/junctions-layer.js +33 -0
  124. package/dist/lib/layers/segments-layer.d.ts +18 -0
  125. package/dist/lib/layers/segments-layer.js +94 -0
  126. package/dist/lib/layers/texts-layer.d.ts +8 -0
  127. package/dist/lib/layers/texts-layer.js +32 -0
  128. package/dist/lib/math.d.ts +11 -0
  129. package/dist/lib/math.js +22 -0
  130. package/dist/lib/nebula-layer.d.ts +13 -0
  131. package/dist/lib/nebula-layer.js +26 -0
  132. package/dist/lib/nebula.d.ts +34 -0
  133. package/dist/lib/nebula.js +254 -0
  134. package/dist/lib/style.d.ts +19 -0
  135. package/dist/lib/style.js +20 -0
  136. package/dist/memoize.d.ts +6 -0
  137. package/dist/memoize.js +40 -0
  138. package/dist/mode-handlers/composite-mode-handler.d.ts +24 -0
  139. package/dist/mode-handlers/composite-mode-handler.js +55 -0
  140. package/dist/mode-handlers/draw-90degree-polygon-handler.d.ts +13 -0
  141. package/dist/mode-handlers/draw-90degree-polygon-handler.js +169 -0
  142. package/dist/mode-handlers/draw-circle-by-bounding-box-handler.d.ts +9 -0
  143. package/dist/mode-handlers/draw-circle-by-bounding-box-handler.js +29 -0
  144. package/dist/mode-handlers/draw-circle-from-center-handler.d.ts +9 -0
  145. package/dist/mode-handlers/draw-circle-from-center-handler.js +27 -0
  146. package/dist/mode-handlers/draw-ellipse-by-bounding-box-handler.d.ts +9 -0
  147. package/dist/mode-handlers/draw-ellipse-by-bounding-box-handler.js +30 -0
  148. package/dist/mode-handlers/draw-ellipse-using-three-points-handler.d.ts +9 -0
  149. package/dist/mode-handlers/draw-ellipse-using-three-points-handler.js +37 -0
  150. package/dist/mode-handlers/draw-line-string-handler.d.ts +9 -0
  151. package/dist/mode-handlers/draw-line-string-handler.js +83 -0
  152. package/dist/mode-handlers/draw-point-handler.d.ts +5 -0
  153. package/dist/mode-handlers/draw-point-handler.js +11 -0
  154. package/dist/mode-handlers/draw-polygon-handler.d.ts +11 -0
  155. package/dist/mode-handlers/draw-polygon-handler.js +92 -0
  156. package/dist/mode-handlers/draw-rectangle-handler.d.ts +9 -0
  157. package/dist/mode-handlers/draw-rectangle-handler.js +18 -0
  158. package/dist/mode-handlers/draw-rectangle-using-three-points-handler.d.ts +9 -0
  159. package/dist/mode-handlers/draw-rectangle-using-three-points-handler.js +49 -0
  160. package/dist/mode-handlers/duplicate-handler.d.ts +9 -0
  161. package/dist/mode-handlers/duplicate-handler.js +19 -0
  162. package/dist/mode-handlers/elevation-handler.d.ts +19 -0
  163. package/dist/mode-handlers/elevation-handler.js +48 -0
  164. package/dist/mode-handlers/extrude-handler.d.ts +18 -0
  165. package/dist/mode-handlers/extrude-handler.js +176 -0
  166. package/dist/mode-handlers/mode-handler.d.ts +61 -0
  167. package/dist/mode-handlers/mode-handler.js +286 -0
  168. package/dist/mode-handlers/modify-handler.d.ts +19 -0
  169. package/dist/mode-handlers/modify-handler.js +193 -0
  170. package/dist/mode-handlers/rotate-handler.d.ts +17 -0
  171. package/dist/mode-handlers/rotate-handler.js +74 -0
  172. package/dist/mode-handlers/scale-handler.d.ts +17 -0
  173. package/dist/mode-handlers/scale-handler.js +76 -0
  174. package/dist/mode-handlers/snappable-handler.d.ts +33 -0
  175. package/dist/mode-handlers/snappable-handler.js +133 -0
  176. package/dist/mode-handlers/split-polygon-handler.d.ts +11 -0
  177. package/dist/mode-handlers/split-polygon-handler.js +154 -0
  178. package/dist/mode-handlers/three-click-polygon-handler.d.ts +5 -0
  179. package/dist/mode-handlers/three-click-polygon-handler.js +18 -0
  180. package/dist/mode-handlers/translate-handler.d.ts +17 -0
  181. package/dist/mode-handlers/translate-handler.js +72 -0
  182. package/dist/mode-handlers/two-click-polygon-handler.d.ts +5 -0
  183. package/dist/mode-handlers/two-click-polygon-handler.js +18 -0
  184. package/dist/mode-handlers/view-handler.d.ts +8 -0
  185. package/dist/mode-handlers/view-handler.js +10 -0
  186. package/dist/shaderlib/color/color.d.ts +8 -0
  187. package/dist/shaderlib/color/color.js +51 -0
  188. package/dist/shaderlib/outline/outline.d.ts +8 -0
  189. package/dist/shaderlib/outline/outline.js +97 -0
  190. package/dist/shaderlib/utils/utils.d.ts +8 -0
  191. package/dist/shaderlib/utils/utils.js +28 -0
  192. package/dist/translateFromCenter.d.ts +4 -0
  193. package/dist/translateFromCenter.js +19 -0
  194. package/dist/types.d.ts +35 -0
  195. package/dist/types.js +1 -0
  196. package/dist/utils.d.ts +20 -0
  197. package/dist/utils.js +144 -0
  198. package/package.json +84 -0
  199. package/src/constants.ts +15 -0
  200. package/src/curve-utils.ts +77 -0
  201. package/src/edit-modes/composite-mode.ts +74 -0
  202. package/src/edit-modes/draw-90degree-polygon-mode.ts +220 -0
  203. package/src/edit-modes/draw-circle-by-diameter-mode.ts +88 -0
  204. package/src/edit-modes/draw-circle-from-center-mode.ts +79 -0
  205. package/src/edit-modes/draw-ellipse-by-bounding-box-mode.ts +25 -0
  206. package/src/edit-modes/draw-ellipse-using-three-points-mode.ts +23 -0
  207. package/src/edit-modes/draw-line-string-mode.ts +200 -0
  208. package/src/edit-modes/draw-point-mode.ts +35 -0
  209. package/src/edit-modes/draw-polygon-by-dragging-mode.ts +106 -0
  210. package/src/edit-modes/draw-polygon-mode.ts +171 -0
  211. package/src/edit-modes/draw-rectangle-from-center-mode.ts +23 -0
  212. package/src/edit-modes/draw-rectangle-mode.ts +14 -0
  213. package/src/edit-modes/draw-rectangle-using-three-points-mode.ts +36 -0
  214. package/src/edit-modes/draw-square-from-center-mode.ts +46 -0
  215. package/src/edit-modes/draw-square-mode.ts +36 -0
  216. package/src/edit-modes/duplicate-mode.ts +21 -0
  217. package/src/edit-modes/edit-mode.ts +30 -0
  218. package/src/edit-modes/elevation-mode.ts +86 -0
  219. package/src/edit-modes/extend-line-string-mode.ts +87 -0
  220. package/src/edit-modes/extrude-mode.ts +254 -0
  221. package/src/edit-modes/geojson-edit-mode.ts +283 -0
  222. package/src/edit-modes/immutable-feature-collection.ts +417 -0
  223. package/src/edit-modes/measure-angle-mode.ts +127 -0
  224. package/src/edit-modes/measure-area-mode.ts +62 -0
  225. package/src/edit-modes/measure-distance-mode.ts +215 -0
  226. package/src/edit-modes/modify-mode.ts +293 -0
  227. package/src/edit-modes/resize-circle-mode.ts +202 -0
  228. package/src/edit-modes/rotate-mode.ts +208 -0
  229. package/src/edit-modes/scale-mode.ts +231 -0
  230. package/src/edit-modes/snappable-mode.ts +174 -0
  231. package/src/edit-modes/split-polygon-mode.ts +201 -0
  232. package/src/edit-modes/three-click-polygon-mode.ts +111 -0
  233. package/src/edit-modes/transform-mode.ts +75 -0
  234. package/src/edit-modes/translate-mode.ts +161 -0
  235. package/src/edit-modes/two-click-polygon-mode.ts +132 -0
  236. package/src/edit-modes/types.ts +135 -0
  237. package/src/edit-modes/utils.ts +513 -0
  238. package/src/edit-modes/view-mode.ts +3 -0
  239. package/src/editable-layers/editable-geojson-layer.ts +603 -0
  240. package/src/editable-layers/editable-h3-cluster-layer.ts +226 -0
  241. package/src/editable-layers/editable-layer.ts +252 -0
  242. package/src/editable-layers/editable-path-layer.ts +51 -0
  243. package/src/editable-layers/elevated-edit-handle-layer.ts +33 -0
  244. package/src/editable-layers/junction-scatterplot-layer.ts +53 -0
  245. package/src/editable-layers/path-marker-layer/arrow-2d-geometry.ts +61 -0
  246. package/src/editable-layers/path-marker-layer/create-path-markers.ts +107 -0
  247. package/src/editable-layers/path-marker-layer/path-marker-layer.ts +179 -0
  248. package/src/editable-layers/path-marker-layer/polyline.ts +40 -0
  249. package/src/editable-layers/path-outline-layer/path-outline-layer.ts +147 -0
  250. package/src/editable-layers/selection-layer.ts +209 -0
  251. package/src/geojson-types.ts +89 -0
  252. package/src/index.ts +125 -0
  253. package/src/lib/constants.ts +6 -0
  254. package/src/lib/deck-renderer/deck-cache.ts +61 -0
  255. package/src/lib/deck-renderer/deck-drawer.ts +263 -0
  256. package/src/lib/feature.ts +27 -0
  257. package/src/lib/layer-mouse-event.ts +32 -0
  258. package/src/lib/layers/junctions-layer.ts +40 -0
  259. package/src/lib/layers/segments-layer.ts +108 -0
  260. package/src/lib/layers/texts-layer.ts +43 -0
  261. package/src/lib/math.ts +26 -0
  262. package/src/lib/nebula-layer.ts +33 -0
  263. package/src/lib/nebula.ts +323 -0
  264. package/src/lib/style.ts +22 -0
  265. package/src/memoize.ts +43 -0
  266. package/src/mode-handlers/composite-mode-handler.ts +89 -0
  267. package/src/mode-handlers/draw-90degree-polygon-handler.ts +201 -0
  268. package/src/mode-handlers/draw-circle-by-bounding-box-handler.ts +39 -0
  269. package/src/mode-handlers/draw-circle-from-center-handler.ts +38 -0
  270. package/src/mode-handlers/draw-ellipse-by-bounding-box-handler.ts +41 -0
  271. package/src/mode-handlers/draw-ellipse-using-three-points-handler.ts +46 -0
  272. package/src/mode-handlers/draw-line-string-handler.ts +108 -0
  273. package/src/mode-handlers/draw-point-handler.ts +15 -0
  274. package/src/mode-handlers/draw-polygon-handler.ts +121 -0
  275. package/src/mode-handlers/draw-rectangle-handler.ts +28 -0
  276. package/src/mode-handlers/draw-rectangle-using-three-points-handler.ts +60 -0
  277. package/src/mode-handlers/duplicate-handler.ts +25 -0
  278. package/src/mode-handlers/elevation-handler.ts +88 -0
  279. package/src/mode-handlers/extrude-handler.ts +245 -0
  280. package/src/mode-handlers/mode-handler.ts +394 -0
  281. package/src/mode-handlers/modify-handler.ts +263 -0
  282. package/src/mode-handlers/rotate-handler.ts +107 -0
  283. package/src/mode-handlers/scale-handler.ts +105 -0
  284. package/src/mode-handlers/snappable-handler.ts +184 -0
  285. package/src/mode-handlers/split-polygon-handler.ts +177 -0
  286. package/src/mode-handlers/three-click-polygon-handler.ts +25 -0
  287. package/src/mode-handlers/translate-handler.ts +110 -0
  288. package/src/mode-handlers/two-click-polygon-handler.ts +25 -0
  289. package/src/mode-handlers/view-handler.ts +13 -0
  290. package/src/shaderlib/color/color.ts +56 -0
  291. package/src/shaderlib/outline/outline.ts +101 -0
  292. package/src/shaderlib/utils/utils.ts +33 -0
  293. package/src/translateFromCenter.ts +48 -0
  294. package/src/types.ts +39 -0
  295. package/src/utils.ts +185 -0
@@ -0,0 +1,215 @@
1
+ import turfDistance from '@turf/distance';
2
+ import turfMidpoint from '@turf/midpoint';
3
+ import { FeatureCollection, Position } from '../geojson-types';
4
+ import {
5
+ ClickEvent,
6
+ PointerMoveEvent,
7
+ ModeProps,
8
+ GuideFeatureCollection,
9
+ Tooltip,
10
+ GuideFeature,
11
+ } from './types';
12
+ import { getPickedEditHandle } from './utils';
13
+ import { GeoJsonEditMode } from './geojson-edit-mode';
14
+
15
+ export class MeasureDistanceMode extends GeoJsonEditMode {
16
+ _isMeasuringSessionFinished = false;
17
+ _currentTooltips: Tooltip[] = [];
18
+ _currentDistance = 0;
19
+
20
+ _calculateDistanceForTooltip = ({ positionA, positionB, modeConfig }) => {
21
+ const { turfOptions, measurementCallback } = modeConfig || {};
22
+ const distance = turfDistance(positionA, positionB, turfOptions);
23
+
24
+ if (measurementCallback) {
25
+ measurementCallback(distance);
26
+ }
27
+
28
+ return distance;
29
+ };
30
+
31
+ _formatTooltip(distance, modeConfig?) {
32
+ const { formatTooltip, turfOptions } = modeConfig || {};
33
+ const units = (turfOptions && turfOptions.units) || 'kilometers';
34
+
35
+ let text;
36
+ if (formatTooltip) {
37
+ text = formatTooltip(distance);
38
+ } else {
39
+ // By default, round to 2 decimal places and append units
40
+ text = `${parseFloat(distance).toFixed(2)} ${units}`;
41
+ }
42
+
43
+ return text;
44
+ }
45
+
46
+ handleClick(event: ClickEvent, props: ModeProps<FeatureCollection>) {
47
+ const { modeConfig, data, onEdit } = props;
48
+ const { centerTooltipsOnLine = false } = modeConfig || {};
49
+
50
+ // restart measuring session
51
+ if (this._isMeasuringSessionFinished) {
52
+ this._isMeasuringSessionFinished = false;
53
+ this.resetClickSequence();
54
+ this._currentTooltips = [];
55
+ this._currentDistance = 0;
56
+ }
57
+
58
+ const { picks } = event;
59
+ const clickedEditHandle = getPickedEditHandle(picks);
60
+
61
+ let positionAdded = false;
62
+ if (!clickedEditHandle) {
63
+ // Don't add another point right next to an existing one
64
+ this.addClickSequence(event);
65
+ positionAdded = true;
66
+ }
67
+ const clickSequence = this.getClickSequence();
68
+
69
+ if (
70
+ clickSequence.length > 1 &&
71
+ clickedEditHandle &&
72
+ Array.isArray(clickedEditHandle.properties.positionIndexes) &&
73
+ clickedEditHandle.properties.positionIndexes[0] === clickSequence.length - 1
74
+ ) {
75
+ // They clicked the last point (or double-clicked), so add the LineString
76
+ this._isMeasuringSessionFinished = true;
77
+ } else if (positionAdded) {
78
+ if (clickSequence.length > 1) {
79
+ this._currentDistance += this._calculateDistanceForTooltip({
80
+ positionA: clickSequence[clickSequence.length - 2],
81
+ positionB: clickSequence[clickSequence.length - 1],
82
+ modeConfig,
83
+ });
84
+
85
+ const tooltipPosition = centerTooltipsOnLine
86
+ ? turfMidpoint(
87
+ clickSequence[clickSequence.length - 2],
88
+ clickSequence[clickSequence.length - 1]
89
+ ).geometry.coordinates
90
+ : event.mapCoords;
91
+
92
+ this._currentTooltips.push({
93
+ position: tooltipPosition as Position,
94
+ text: this._formatTooltip(this._currentDistance, modeConfig),
95
+ });
96
+ }
97
+
98
+ // new tentative point
99
+ onEdit({
100
+ // data is the same
101
+ updatedData: data,
102
+ editType: 'addTentativePosition',
103
+ editContext: {
104
+ position: event.mapCoords,
105
+ },
106
+ });
107
+ }
108
+ }
109
+
110
+ handleKeyUp(event: KeyboardEvent, props: ModeProps<FeatureCollection>) {
111
+ if (this._isMeasuringSessionFinished) return;
112
+
113
+ event.stopPropagation();
114
+ const { key } = event;
115
+
116
+ const clickSequenceLength = this.getClickSequence().length;
117
+
118
+ switch (key) {
119
+ case 'Escape':
120
+ this._isMeasuringSessionFinished = true;
121
+ if (clickSequenceLength === 1) {
122
+ this.resetClickSequence();
123
+ this._currentTooltips = [];
124
+ }
125
+ // force update drawings
126
+ props.onUpdateCursor('cell');
127
+ break;
128
+ case 'Enter':
129
+ this.handleClick(props.lastPointerMoveEvent, props);
130
+ this._isMeasuringSessionFinished = true;
131
+ break;
132
+ default:
133
+ break;
134
+ }
135
+ }
136
+
137
+ getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection {
138
+ const { lastPointerMoveEvent } = props;
139
+ const clickSequence = this.getClickSequence();
140
+
141
+ const lastCoords =
142
+ lastPointerMoveEvent && !this._isMeasuringSessionFinished
143
+ ? [lastPointerMoveEvent.mapCoords]
144
+ : [];
145
+
146
+ const guides: GuideFeatureCollection = {
147
+ type: 'FeatureCollection',
148
+ features: [],
149
+ };
150
+
151
+ if (clickSequence.length > 0) {
152
+ guides.features.push({
153
+ type: 'Feature',
154
+ properties: {
155
+ guideType: 'tentative',
156
+ },
157
+ geometry: {
158
+ type: 'LineString',
159
+ coordinates: [...clickSequence, ...lastCoords],
160
+ },
161
+ });
162
+ }
163
+
164
+ const editHandles: GuideFeature[] = clickSequence.map((clickedCoord, index) => ({
165
+ type: 'Feature',
166
+ properties: {
167
+ guideType: 'editHandle',
168
+ editHandleType: 'existing',
169
+ featureIndex: -1,
170
+ positionIndexes: [index],
171
+ },
172
+ geometry: {
173
+ type: 'Point',
174
+ coordinates: clickedCoord,
175
+ },
176
+ }));
177
+
178
+ guides.features.push(...editHandles);
179
+
180
+ return guides;
181
+ }
182
+
183
+ handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
184
+ props.onUpdateCursor('cell');
185
+ }
186
+
187
+ getTooltips(props: ModeProps<FeatureCollection>): Tooltip[] {
188
+ const { lastPointerMoveEvent, modeConfig } = props;
189
+ const { centerTooltipsOnLine = false } = modeConfig || {};
190
+ const positions = this.getClickSequence();
191
+
192
+ if (positions.length > 0 && lastPointerMoveEvent && !this._isMeasuringSessionFinished) {
193
+ const distance = this._calculateDistanceForTooltip({
194
+ positionA: positions[positions.length - 1],
195
+ positionB: lastPointerMoveEvent.mapCoords,
196
+ modeConfig: props.modeConfig,
197
+ });
198
+
199
+ const tooltipPosition = centerTooltipsOnLine
200
+ ? turfMidpoint(positions[positions.length - 1], lastPointerMoveEvent.mapCoords).geometry
201
+ .coordinates as Position
202
+ : lastPointerMoveEvent.mapCoords;
203
+
204
+ return [
205
+ ...this._currentTooltips,
206
+ {
207
+ position: tooltipPosition,
208
+ text: this._formatTooltip(this._currentDistance + distance, modeConfig),
209
+ },
210
+ ];
211
+ }
212
+
213
+ return this._currentTooltips;
214
+ }
215
+ }
@@ -0,0 +1,293 @@
1
+ import { point, lineString as toLineString } from '@turf/helpers';
2
+ import {
3
+ recursivelyTraverseNestedArrays,
4
+ nearestPointOnProjectedLine,
5
+ nearestPointOnLine,
6
+ getEditHandlesForGeometry,
7
+ getPickedEditHandles,
8
+ getPickedEditHandle,
9
+ getPickedExistingEditHandle,
10
+ getPickedIntermediateEditHandle,
11
+ updateRectanglePosition,
12
+ NearestPointType,
13
+ } from './utils';
14
+ import { LineString, Point, Polygon, FeatureCollection, FeatureOf } from '../geojson-types';
15
+ import {
16
+ ModeProps,
17
+ ClickEvent,
18
+ PointerMoveEvent,
19
+ StartDraggingEvent,
20
+ StopDraggingEvent,
21
+ DraggingEvent,
22
+ Viewport,
23
+ GuideFeatureCollection,
24
+ EditHandleFeature,
25
+ GuideFeature,
26
+ } from './types';
27
+ import { GeoJsonEditMode } from './geojson-edit-mode';
28
+ import { ImmutableFeatureCollection } from './immutable-feature-collection';
29
+
30
+ export class ModifyMode extends GeoJsonEditMode {
31
+ // eslint-disable-next-line complexity
32
+ getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection {
33
+ const handles: GuideFeature[] = [];
34
+
35
+ const { data, lastPointerMoveEvent } = props;
36
+ const { features } = data;
37
+ const picks = lastPointerMoveEvent && lastPointerMoveEvent.picks;
38
+ const mapCoords = lastPointerMoveEvent && lastPointerMoveEvent.mapCoords;
39
+
40
+ for (const index of props.selectedIndexes) {
41
+ if (index < features.length) {
42
+ const { geometry } = features[index];
43
+ handles.push(...getEditHandlesForGeometry(geometry, index));
44
+ } else {
45
+ console.warn(`selectedFeatureIndexes out of range ${index}`); // eslint-disable-line no-console,no-undef
46
+ }
47
+ }
48
+
49
+ // intermediate edit handle
50
+ if (picks && picks.length && mapCoords) {
51
+ const existingEditHandle = getPickedExistingEditHandle(picks);
52
+ // don't show intermediate point when too close to an existing edit handle
53
+ const featureAsPick = !existingEditHandle && picks.find((pick) => !pick.isGuide);
54
+
55
+ // is the feature in the pick selected
56
+ if (
57
+ featureAsPick &&
58
+ !featureAsPick.object.geometry.type.includes('Point') &&
59
+ !(
60
+ props.modeConfig?.lockRectangles && featureAsPick.object.properties.shape === 'Rectangle'
61
+ ) &&
62
+ props.selectedIndexes.includes(featureAsPick.index)
63
+ ) {
64
+ let intermediatePoint: NearestPointType | null | undefined = null;
65
+ let positionIndexPrefix: number[] = [];
66
+ const referencePoint = point(mapCoords);
67
+ // process all lines of the (single) feature
68
+ recursivelyTraverseNestedArrays(
69
+ featureAsPick.object.geometry.coordinates,
70
+ [],
71
+ (lineString, prefix) => {
72
+ const lineStringFeature = toLineString(lineString);
73
+ const candidateIntermediatePoint = this.getNearestPoint(
74
+ // @ts-expect-error turf types too wide
75
+ lineStringFeature,
76
+ referencePoint,
77
+ props.modeConfig && props.modeConfig.viewport
78
+ );
79
+ if (
80
+ !intermediatePoint ||
81
+ candidateIntermediatePoint.properties.dist < intermediatePoint.properties.dist
82
+ ) {
83
+ intermediatePoint = candidateIntermediatePoint;
84
+ positionIndexPrefix = prefix;
85
+ }
86
+ }
87
+ );
88
+ // tack on the lone intermediate point to the set of handles
89
+ if (intermediatePoint) {
90
+ const {
91
+ geometry: { coordinates: position },
92
+ properties: { index },
93
+ } = intermediatePoint as NearestPointType;
94
+ handles.push({
95
+ type: 'Feature',
96
+ properties: {
97
+ guideType: 'editHandle',
98
+ editHandleType: 'intermediate',
99
+ featureIndex: featureAsPick.index,
100
+ positionIndexes: [...positionIndexPrefix, index + 1],
101
+ },
102
+ geometry: {
103
+ type: 'Point',
104
+ coordinates: position,
105
+ },
106
+ });
107
+ }
108
+ }
109
+ }
110
+
111
+ return {
112
+ type: 'FeatureCollection',
113
+ features: handles,
114
+ };
115
+ }
116
+
117
+ // turf.js does not support elevation for nearestPointOnLine
118
+ getNearestPoint(
119
+ line: FeatureOf<LineString>,
120
+ inPoint: FeatureOf<Point>,
121
+ viewport: Viewport | null | undefined
122
+ ): NearestPointType {
123
+ const { coordinates } = line.geometry;
124
+ if (coordinates.some((coord) => coord.length > 2)) {
125
+ if (viewport) {
126
+ // This line has elevation, we need to use alternative algorithm
127
+ return nearestPointOnProjectedLine(line, inPoint, viewport);
128
+ }
129
+ // eslint-disable-next-line no-console,no-undef
130
+ console.log(
131
+ 'Editing 3D point but modeConfig.viewport not provided. Falling back to 2D logic.'
132
+ );
133
+ }
134
+ return nearestPointOnLine(line, inPoint, viewport!);
135
+ }
136
+
137
+ handleClick(event: ClickEvent, props: ModeProps<FeatureCollection>) {
138
+ const pickedExistingHandle = getPickedExistingEditHandle(event.picks);
139
+ const pickedIntermediateHandle = getPickedIntermediateEditHandle(event.picks);
140
+
141
+ if (pickedExistingHandle) {
142
+ const { featureIndex, positionIndexes } = pickedExistingHandle.properties;
143
+
144
+ let updatedData;
145
+ try {
146
+ updatedData = new ImmutableFeatureCollection(props.data)
147
+ .removePosition(featureIndex, positionIndexes)
148
+ .getObject();
149
+ } catch (ignored) {
150
+ // This happens if user attempts to remove the last point
151
+ }
152
+
153
+ if (updatedData) {
154
+ props.onEdit({
155
+ updatedData,
156
+ editType: 'removePosition',
157
+ editContext: {
158
+ featureIndexes: [featureIndex],
159
+ positionIndexes,
160
+ position: pickedExistingHandle.geometry.coordinates,
161
+ },
162
+ });
163
+ }
164
+ } else if (pickedIntermediateHandle) {
165
+ const { featureIndex, positionIndexes } = pickedIntermediateHandle.properties;
166
+
167
+ const feature = props.data.features[featureIndex];
168
+ const canAddPosition = !(
169
+ props.modeConfig?.lockRectangles && feature?.properties!.shape === 'Rectangle'
170
+ );
171
+
172
+ if (canAddPosition) {
173
+ const updatedData = new ImmutableFeatureCollection(props.data)
174
+ .addPosition(featureIndex, positionIndexes, pickedIntermediateHandle.geometry.coordinates)
175
+ .getObject();
176
+
177
+ if (updatedData) {
178
+ props.onEdit({
179
+ updatedData,
180
+ editType: 'addPosition',
181
+ editContext: {
182
+ featureIndexes: [featureIndex],
183
+ positionIndexes,
184
+ position: pickedIntermediateHandle.geometry.coordinates,
185
+ },
186
+ });
187
+ }
188
+ }
189
+ }
190
+ }
191
+
192
+ handleDragging(event: DraggingEvent, props: ModeProps<FeatureCollection>): void {
193
+ const editHandle = getPickedEditHandle(event.pointerDownPicks);
194
+
195
+ if (editHandle) {
196
+ // Cancel map panning if pointer went down on an edit handle
197
+ event.cancelPan();
198
+
199
+ this._dragEditHandle('movePosition', props, editHandle, event);
200
+ }
201
+ }
202
+
203
+ _dragEditHandle(
204
+ editType: string,
205
+ props: ModeProps<FeatureCollection>,
206
+ editHandle: EditHandleFeature,
207
+ event: StopDraggingEvent | DraggingEvent
208
+ ) {
209
+ const editHandleProperties = editHandle.properties;
210
+ const editedFeature = props.data.features[editHandleProperties.featureIndex];
211
+
212
+ let updatedData;
213
+ if (props.modeConfig?.lockRectangles && editedFeature.properties!.shape === 'Rectangle') {
214
+ const coordinates = updateRectanglePosition(
215
+ editedFeature as FeatureOf<Polygon>,
216
+ editHandleProperties.positionIndexes![1],
217
+ event.mapCoords
218
+ ) as any; // TODO
219
+
220
+ updatedData = new ImmutableFeatureCollection(props.data)
221
+ .replaceGeometry(editHandleProperties.featureIndex, { coordinates, type: 'Polygon' })
222
+ .getObject();
223
+ } else {
224
+ updatedData = new ImmutableFeatureCollection(props.data)
225
+ .replacePosition(
226
+ editHandleProperties.featureIndex,
227
+ editHandleProperties.positionIndexes,
228
+ event.mapCoords
229
+ )
230
+ .getObject();
231
+ }
232
+
233
+ props.onEdit({
234
+ updatedData,
235
+ editType,
236
+ editContext: {
237
+ featureIndexes: [editHandleProperties.featureIndex],
238
+ positionIndexes: editHandleProperties.positionIndexes,
239
+ position: event.mapCoords,
240
+ },
241
+ });
242
+ }
243
+
244
+ handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>): void {
245
+ const cursor = this.getCursor(event);
246
+ props.onUpdateCursor(cursor);
247
+ }
248
+
249
+ handleStartDragging(event: StartDraggingEvent, props: ModeProps<FeatureCollection>) {
250
+ const selectedFeatureIndexes = props.selectedIndexes;
251
+
252
+ const editHandle = getPickedIntermediateEditHandle(event.picks);
253
+ if (selectedFeatureIndexes.length && editHandle) {
254
+ const editHandleProperties = editHandle.properties;
255
+
256
+ const updatedData = new ImmutableFeatureCollection(props.data)
257
+ .addPosition(
258
+ editHandleProperties.featureIndex,
259
+ editHandleProperties.positionIndexes,
260
+ event.mapCoords
261
+ )
262
+ .getObject();
263
+
264
+ props.onEdit({
265
+ updatedData,
266
+ editType: 'addPosition',
267
+ editContext: {
268
+ featureIndexes: [editHandleProperties.featureIndex],
269
+ positionIndexes: editHandleProperties.positionIndexes,
270
+ position: event.mapCoords,
271
+ },
272
+ });
273
+ }
274
+ }
275
+
276
+ handleStopDragging(event: StopDraggingEvent, props: ModeProps<FeatureCollection>) {
277
+ const selectedFeatureIndexes = props.selectedIndexes;
278
+ const editHandle = getPickedEditHandle(event.picks);
279
+ if (selectedFeatureIndexes.length && editHandle) {
280
+ this._dragEditHandle('finishMovePosition', props, editHandle, event);
281
+ }
282
+ }
283
+
284
+ getCursor(event: PointerMoveEvent): string | null | undefined {
285
+ const picks = (event && event.picks) || [];
286
+
287
+ const handlesPicked = getPickedEditHandles(picks);
288
+ if (handlesPicked.length) {
289
+ return 'cell';
290
+ }
291
+ return null;
292
+ }
293
+ }
@@ -0,0 +1,202 @@
1
+ import nearestPointOnLine from '@turf/nearest-point-on-line';
2
+ import {point, lineString as toLineString} from '@turf/helpers';
3
+ import circle from '@turf/circle';
4
+ import distance from '@turf/distance';
5
+ import turfCenter from '@turf/center';
6
+ import {
7
+ recursivelyTraverseNestedArrays,
8
+ nearestPointOnProjectedLine,
9
+ getPickedEditHandles,
10
+ getPickedEditHandle,
11
+ NearestPointType
12
+ } from './utils';
13
+ import {LineString, Point, FeatureCollection, FeatureOf} from '../geojson-types';
14
+ import {Viewport} from '../types';
15
+ import {
16
+ ModeProps,
17
+ PointerMoveEvent,
18
+ StartDraggingEvent,
19
+ StopDraggingEvent,
20
+ DraggingEvent,
21
+ EditHandleFeature,
22
+ GuideFeatureCollection,
23
+ GuideFeature
24
+ } from './types';
25
+ import {GeoJsonEditMode} from './geojson-edit-mode';
26
+ import {ImmutableFeatureCollection} from './immutable-feature-collection';
27
+
28
+ export class ResizeCircleMode extends GeoJsonEditMode {
29
+ _selectedEditHandle: EditHandleFeature | null | undefined;
30
+ _isResizing = false;
31
+
32
+ // eslint-disable-next-line complexity
33
+ getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection {
34
+ const handles: GuideFeature[] = [];
35
+ const selectedFeatureIndexes = props.selectedIndexes;
36
+
37
+ const {lastPointerMoveEvent} = props;
38
+ const picks = lastPointerMoveEvent && lastPointerMoveEvent.picks;
39
+ const mapCoords = lastPointerMoveEvent && lastPointerMoveEvent.mapCoords;
40
+
41
+ // intermediate edit handle
42
+ if (
43
+ picks &&
44
+ picks.length &&
45
+ mapCoords &&
46
+ selectedFeatureIndexes.length === 1 &&
47
+ !this._isResizing
48
+ ) {
49
+ const featureAsPick = picks.find((pick) => !pick.isGuide);
50
+
51
+ // is the feature in the pick selected
52
+ if (
53
+ featureAsPick &&
54
+ featureAsPick.object.properties.shape &&
55
+ featureAsPick.object.properties.shape.includes('Circle') &&
56
+ props.selectedIndexes.includes(featureAsPick.index)
57
+ ) {
58
+ let intermediatePoint: NearestPointType | null = null;
59
+ let positionIndexPrefix: number[] = [];
60
+ const referencePoint = point(mapCoords);
61
+ // process all lines of the (single) feature
62
+ recursivelyTraverseNestedArrays(
63
+ featureAsPick.object.geometry.coordinates,
64
+ [],
65
+ (lineString, prefix) => {
66
+ const lineStringFeature = toLineString(lineString);
67
+ const candidateIntermediatePoint = this.getNearestPoint(
68
+ // @ts-expect-error turf types too wide
69
+ lineStringFeature,
70
+ referencePoint,
71
+ props.modeConfig && props.modeConfig.viewport
72
+ );
73
+ if (
74
+ !intermediatePoint ||
75
+ candidateIntermediatePoint.properties.dist < intermediatePoint.properties.dist
76
+ ) {
77
+ intermediatePoint = candidateIntermediatePoint;
78
+ positionIndexPrefix = prefix;
79
+ }
80
+ }
81
+ );
82
+ // tack on the lone intermediate point to the set of handles
83
+ if (intermediatePoint) {
84
+ const {
85
+ geometry: {coordinates: position},
86
+ properties: {index}
87
+ } = intermediatePoint as NearestPointType;
88
+ handles.push({
89
+ type: 'Feature',
90
+ properties: {
91
+ guideType: 'editHandle',
92
+ editHandleType: 'intermediate',
93
+ featureIndex: featureAsPick.index,
94
+ positionIndexes: [...positionIndexPrefix, index + 1]
95
+ },
96
+ geometry: {
97
+ type: 'Point',
98
+ coordinates: position
99
+ }
100
+ });
101
+ }
102
+ }
103
+ }
104
+
105
+ return {
106
+ type: 'FeatureCollection',
107
+ features: handles
108
+ };
109
+ }
110
+
111
+ // turf.js does not support elevation for nearestPointOnLine
112
+ getNearestPoint(
113
+ line: FeatureOf<LineString>,
114
+ inPoint: FeatureOf<Point>,
115
+ viewport: Viewport | null | undefined
116
+ ): NearestPointType {
117
+ const {coordinates} = line.geometry;
118
+ if (coordinates.some((coord) => coord.length > 2)) {
119
+ if (viewport) {
120
+ // This line has elevation, we need to use alternative algorithm
121
+ return nearestPointOnProjectedLine(line, inPoint, viewport);
122
+ }
123
+ // eslint-disable-next-line no-console,no-undef
124
+ console.log(
125
+ 'Editing 3D point but modeConfig.viewport not provided. Falling back to 2D logic.'
126
+ );
127
+ }
128
+ // @ts-expect-error turf types diff
129
+ return nearestPointOnLine(line, inPoint);
130
+ }
131
+
132
+ handleDragging(event: DraggingEvent, props: ModeProps<FeatureCollection>): void {
133
+ const editHandle = getPickedEditHandle(event.pointerDownPicks);
134
+
135
+ if (editHandle) {
136
+ // Cancel map panning if pointer went down on an edit handle
137
+ event.cancelPan();
138
+
139
+ const editHandleProperties = editHandle.properties;
140
+
141
+ const feature = this.getSelectedFeature(props)!;
142
+ // @ts-expect-error turf types diff
143
+ const center = turfCenter(feature).geometry.coordinates;
144
+ const numberOfSteps = Object.entries(feature.geometry.coordinates[0]).length - 1;
145
+ const radius = Math.max(distance(center, event.mapCoords), 0.001);
146
+
147
+ const {steps = numberOfSteps} = {};
148
+ const options = {steps};
149
+ const updatedFeature = circle(center, radius, options);
150
+ const geometry = updatedFeature.geometry;
151
+
152
+ const updatedData = new ImmutableFeatureCollection(props.data)
153
+ // @ts-expect-error turf types diff
154
+ .replaceGeometry(editHandleProperties.featureIndex, geometry)
155
+ .getObject();
156
+
157
+ props.onEdit({
158
+ updatedData,
159
+ editType: 'unionGeometry',
160
+ editContext: {
161
+ featureIndexes: [editHandleProperties.featureIndex]
162
+ }
163
+ });
164
+ }
165
+ }
166
+
167
+ handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>): void {
168
+ if (!this._isResizing) {
169
+ const selectedEditHandle = getPickedEditHandle(event.picks);
170
+ this._selectedEditHandle =
171
+ selectedEditHandle && selectedEditHandle.properties.editHandleType === 'intermediate'
172
+ ? selectedEditHandle
173
+ : null;
174
+ }
175
+
176
+ const cursor = this.getCursor(event);
177
+ props.onUpdateCursor(cursor);
178
+ }
179
+
180
+ handleStartDragging(event: StartDraggingEvent, props: ModeProps<FeatureCollection>) {
181
+ if (this._selectedEditHandle) {
182
+ this._isResizing = true;
183
+ }
184
+ }
185
+
186
+ handleStopDragging(event: StopDraggingEvent, props: ModeProps<FeatureCollection>) {
187
+ if (this._isResizing) {
188
+ this._selectedEditHandle = null;
189
+ this._isResizing = false;
190
+ }
191
+ }
192
+
193
+ getCursor(event: PointerMoveEvent): string | null | undefined {
194
+ const picks = (event && event.picks) || [];
195
+
196
+ const handlesPicked = getPickedEditHandles(picks);
197
+ if (handlesPicked.length) {
198
+ return 'cell';
199
+ }
200
+ return null;
201
+ }
202
+ }