@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,151 @@
1
+ import bbox from '@turf/bbox';
2
+ import turfCentroid from '@turf/centroid';
3
+ import turfBearing from '@turf/bearing';
4
+ import bboxPolygon from '@turf/bbox-polygon';
5
+ import turfDistance from '@turf/distance';
6
+ import { coordEach } from '@turf/meta';
7
+ import { getGeom } from '@turf/invariant';
8
+ import { point, featureCollection, lineString } from '@turf/helpers';
9
+ import turfTransformRotate from '@turf/transform-rotate';
10
+ import polygonToLine from '@turf/polygon-to-line';
11
+ import { getPickedEditHandle } from './utils';
12
+ import { GeoJsonEditMode, getIntermediatePosition } from './geojson-edit-mode';
13
+ import { ImmutableFeatureCollection } from './immutable-feature-collection';
14
+ export class RotateMode extends GeoJsonEditMode {
15
+ _selectedEditHandle;
16
+ _geometryBeingRotated;
17
+ _isRotating = false;
18
+ _isSinglePointGeometrySelected = (geometry) => {
19
+ const { features } = geometry || {};
20
+ if (Array.isArray(features) && features.length === 1) {
21
+ // @ts-expect-error turf type diff
22
+ const { type } = getGeom(features[0]);
23
+ return type === 'Point';
24
+ }
25
+ return false;
26
+ };
27
+ getIsRotating = () => this._isRotating;
28
+ getGuides(props) {
29
+ const selectedGeometry = this._geometryBeingRotated || this.getSelectedFeaturesAsFeatureCollection(props);
30
+ if (this._isSinglePointGeometrySelected(selectedGeometry)) {
31
+ return { type: 'FeatureCollection', features: [] };
32
+ }
33
+ if (this._isRotating) {
34
+ // Display rotate pivot
35
+ // @ts-expect-error turf types diff
36
+ return featureCollection([turfCentroid(selectedGeometry)]);
37
+ }
38
+ const boundingBox = bboxPolygon(bbox(selectedGeometry));
39
+ let previousCoord = null;
40
+ let topEdgeMidpointCoords = null;
41
+ let longestEdgeLength = 0;
42
+ coordEach(boundingBox, (coord) => {
43
+ if (previousCoord) {
44
+ const edgeMidpoint = getIntermediatePosition(coord, previousCoord);
45
+ if (!topEdgeMidpointCoords || edgeMidpoint[1] > topEdgeMidpointCoords[1]) {
46
+ // Get the top edge midpoint of the enveloping box
47
+ topEdgeMidpointCoords = edgeMidpoint;
48
+ }
49
+ // Get the length of the longest edge of the enveloping box
50
+ const edgeDistance = turfDistance(coord, previousCoord);
51
+ longestEdgeLength = Math.max(longestEdgeLength, edgeDistance);
52
+ }
53
+ previousCoord = coord;
54
+ });
55
+ // Scale the length of the line between the rotate handler and the enveloping box
56
+ // relative to the length of the longest edge of the enveloping box
57
+ const rotateHandleCoords = topEdgeMidpointCoords && [
58
+ topEdgeMidpointCoords[0],
59
+ topEdgeMidpointCoords[1] + longestEdgeLength / 1000,
60
+ ];
61
+ const lineFromEnvelopeToRotateHandle = lineString([topEdgeMidpointCoords, rotateHandleCoords]);
62
+ const rotateHandle = point(rotateHandleCoords, {
63
+ guideType: 'editHandle',
64
+ editHandleType: 'rotate',
65
+ });
66
+ const outFeatures = [polygonToLine(boundingBox), rotateHandle, lineFromEnvelopeToRotateHandle];
67
+ // @ts-expect-error turf type diff
68
+ return featureCollection(outFeatures);
69
+ }
70
+ handleDragging(event, props) {
71
+ if (!this._isRotating) {
72
+ return;
73
+ }
74
+ const rotateAction = this.getRotateAction(event.pointerDownMapCoords, event.mapCoords, 'rotating', props);
75
+ if (rotateAction) {
76
+ props.onEdit(rotateAction);
77
+ }
78
+ event.cancelPan();
79
+ }
80
+ handlePointerMove(event, props) {
81
+ if (!this._isRotating) {
82
+ const selectedEditHandle = getPickedEditHandle(event.picks);
83
+ this._selectedEditHandle =
84
+ selectedEditHandle && selectedEditHandle.properties.editHandleType === 'rotate'
85
+ ? selectedEditHandle
86
+ : null;
87
+ }
88
+ this.updateCursor(props);
89
+ }
90
+ handleStartDragging(event, props) {
91
+ if (this._selectedEditHandle) {
92
+ this._isRotating = true;
93
+ this._geometryBeingRotated = this.getSelectedFeaturesAsFeatureCollection(props);
94
+ }
95
+ }
96
+ handleStopDragging(event, props) {
97
+ if (this._isRotating) {
98
+ // Rotate the geometry
99
+ const rotateAction = this.getRotateAction(event.pointerDownMapCoords, event.mapCoords, 'rotated', props);
100
+ if (rotateAction) {
101
+ props.onEdit(rotateAction);
102
+ }
103
+ this._geometryBeingRotated = null;
104
+ this._selectedEditHandle = null;
105
+ this._isRotating = false;
106
+ }
107
+ }
108
+ updateCursor(props) {
109
+ if (this._selectedEditHandle) {
110
+ // TODO: look at doing SVG cursors to get a better "rotate" cursor
111
+ props.onUpdateCursor('crosshair');
112
+ }
113
+ else {
114
+ props.onUpdateCursor(null);
115
+ }
116
+ }
117
+ getRotateAction(startDragPoint, currentPoint, editType, props) {
118
+ if (!this._geometryBeingRotated) {
119
+ return null;
120
+ }
121
+ // @ts-expect-error turf types diff
122
+ const centroid = turfCentroid(this._geometryBeingRotated);
123
+ // @ts-expect-error turf types diff
124
+ const angle = getRotationAngle(centroid, startDragPoint, currentPoint);
125
+ // @ts-expect-error turf types too wide
126
+ const rotatedFeatures = turfTransformRotate(
127
+ // @ts-expect-error turf types too wide
128
+ this._geometryBeingRotated, angle, {
129
+ pivot: centroid,
130
+ });
131
+ let updatedData = new ImmutableFeatureCollection(props.data);
132
+ const selectedIndexes = props.selectedIndexes;
133
+ for (let i = 0; i < selectedIndexes.length; i++) {
134
+ const selectedIndex = selectedIndexes[i];
135
+ const movedFeature = rotatedFeatures.features[i];
136
+ updatedData = updatedData.replaceGeometry(selectedIndex, movedFeature.geometry);
137
+ }
138
+ return {
139
+ updatedData: updatedData.getObject(),
140
+ editType,
141
+ editContext: {
142
+ featureIndexes: selectedIndexes,
143
+ },
144
+ };
145
+ }
146
+ }
147
+ function getRotationAngle(centroid, startDragPoint, currentPoint) {
148
+ const bearing1 = turfBearing(centroid, startDragPoint);
149
+ const bearing2 = turfBearing(centroid, currentPoint);
150
+ return bearing2 - bearing1;
151
+ }
@@ -0,0 +1,27 @@
1
+ import { FeatureCollection, Position } from '../geojson-types';
2
+ import { ModeProps, PointerMoveEvent, StartDraggingEvent, StopDraggingEvent, DraggingEvent, EditHandleFeature, GuideFeatureCollection } from './types';
3
+ import { GeoJsonEditMode } from './geojson-edit-mode';
4
+ export declare class ScaleMode extends GeoJsonEditMode {
5
+ _geometryBeingScaled: FeatureCollection | null | undefined;
6
+ _selectedEditHandle: EditHandleFeature | null | undefined;
7
+ _cornerGuidePoints: Array<EditHandleFeature>;
8
+ _cursor: string | null | undefined;
9
+ _isScaling: boolean;
10
+ _isSinglePointGeometrySelected: (geometry: FeatureCollection | null | undefined) => boolean;
11
+ _getOppositeScaleHandle: (selectedHandle: EditHandleFeature) => EditHandleFeature | null;
12
+ _getUpdatedData: (props: ModeProps<FeatureCollection>, editedData: FeatureCollection) => FeatureCollection;
13
+ isEditHandleSelected: () => boolean;
14
+ getScaleAction: (startDragPoint: Position, currentPoint: Position, editType: string, props: ModeProps<FeatureCollection>) => {
15
+ updatedData: FeatureCollection;
16
+ editType: string;
17
+ editContext: {
18
+ featureIndexes: number[];
19
+ };
20
+ };
21
+ updateCursor: (props: ModeProps<FeatureCollection>) => void;
22
+ handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>): void;
23
+ handleStartDragging(event: StartDraggingEvent, props: ModeProps<FeatureCollection>): void;
24
+ handleDragging(event: DraggingEvent, props: ModeProps<FeatureCollection>): void;
25
+ handleStopDragging(event: StopDraggingEvent, props: ModeProps<FeatureCollection>): void;
26
+ getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection;
27
+ }
@@ -0,0 +1,173 @@
1
+ import bbox from '@turf/bbox';
2
+ import turfCentroid from '@turf/centroid';
3
+ import turfBearing from '@turf/bearing';
4
+ import bboxPolygon from '@turf/bbox-polygon';
5
+ import { point, featureCollection } from '@turf/helpers';
6
+ import polygonToLine from '@turf/polygon-to-line';
7
+ import { coordEach } from '@turf/meta';
8
+ import turfDistance from '@turf/distance';
9
+ import turfTransformScale from '@turf/transform-scale';
10
+ import { getCoord, getGeom } from '@turf/invariant';
11
+ import { getPickedEditHandle } from './utils';
12
+ import { GeoJsonEditMode } from './geojson-edit-mode';
13
+ import { ImmutableFeatureCollection } from './immutable-feature-collection';
14
+ export class ScaleMode extends GeoJsonEditMode {
15
+ _geometryBeingScaled;
16
+ _selectedEditHandle;
17
+ _cornerGuidePoints = [];
18
+ _cursor;
19
+ _isScaling = false;
20
+ _isSinglePointGeometrySelected = (geometry) => {
21
+ const { features } = geometry || {};
22
+ if (Array.isArray(features) && features.length === 1) {
23
+ // @ts-expect-error turf types diff
24
+ const { type } = getGeom(features[0]);
25
+ return type === 'Point';
26
+ }
27
+ return false;
28
+ };
29
+ _getOppositeScaleHandle = (selectedHandle) => {
30
+ const selectedHandleIndex = selectedHandle &&
31
+ selectedHandle.properties &&
32
+ Array.isArray(selectedHandle.properties.positionIndexes) &&
33
+ selectedHandle.properties.positionIndexes[0];
34
+ if (typeof selectedHandleIndex !== 'number') {
35
+ return null;
36
+ }
37
+ const guidePointCount = this._cornerGuidePoints.length;
38
+ const oppositeIndex = (selectedHandleIndex + guidePointCount / 2) % guidePointCount;
39
+ return this._cornerGuidePoints.find((p) => {
40
+ if (!Array.isArray(p.properties.positionIndexes)) {
41
+ return false;
42
+ }
43
+ return p.properties.positionIndexes[0] === oppositeIndex;
44
+ }) || null;
45
+ };
46
+ _getUpdatedData = (props, editedData) => {
47
+ let updatedData = new ImmutableFeatureCollection(props.data);
48
+ const selectedIndexes = props.selectedIndexes;
49
+ for (let i = 0; i < selectedIndexes.length; i++) {
50
+ const selectedIndex = selectedIndexes[i];
51
+ const movedFeature = editedData.features[i];
52
+ updatedData = updatedData.replaceGeometry(selectedIndex, movedFeature.geometry);
53
+ }
54
+ return updatedData.getObject();
55
+ };
56
+ isEditHandleSelected = () => Boolean(this._selectedEditHandle);
57
+ getScaleAction = (startDragPoint, currentPoint, editType, props) => {
58
+ if (!this._selectedEditHandle) {
59
+ return null;
60
+ }
61
+ const oppositeHandle = this._getOppositeScaleHandle(this._selectedEditHandle);
62
+ const origin = getCoord(oppositeHandle);
63
+ const scaleFactor = getScaleFactor(origin, startDragPoint, currentPoint);
64
+ // @ts-expect-error turf types diff
65
+ const scaledFeatures = turfTransformScale(
66
+ // @ts-expect-error turf types diff
67
+ this._geometryBeingScaled, scaleFactor, { origin });
68
+ return {
69
+ updatedData: this._getUpdatedData(props, scaledFeatures),
70
+ editType,
71
+ editContext: {
72
+ featureIndexes: props.selectedIndexes,
73
+ },
74
+ };
75
+ };
76
+ updateCursor = (props) => {
77
+ if (this._selectedEditHandle) {
78
+ if (this._cursor) {
79
+ props.onUpdateCursor(this._cursor);
80
+ }
81
+ const cursorGeometry = this.getSelectedFeaturesAsFeatureCollection(props);
82
+ // Get resize cursor direction from the hovered scale editHandle (e.g. nesw or nwse)
83
+ // @ts-expect-error turf types diff
84
+ const centroid = turfCentroid(cursorGeometry);
85
+ const bearing = turfBearing(centroid, this._selectedEditHandle);
86
+ const positiveBearing = bearing < 0 ? bearing + 180 : bearing;
87
+ if ((positiveBearing >= 0 && positiveBearing <= 90) ||
88
+ (positiveBearing >= 180 && positiveBearing <= 270)) {
89
+ this._cursor = 'nesw-resize';
90
+ props.onUpdateCursor('nesw-resize');
91
+ }
92
+ else {
93
+ this._cursor = 'nwse-resize';
94
+ props.onUpdateCursor('nwse-resize');
95
+ }
96
+ }
97
+ else {
98
+ props.onUpdateCursor(null);
99
+ this._cursor = null;
100
+ }
101
+ };
102
+ handlePointerMove(event, props) {
103
+ if (!this._isScaling) {
104
+ const selectedEditHandle = getPickedEditHandle(event.picks);
105
+ this._selectedEditHandle =
106
+ selectedEditHandle && selectedEditHandle.properties.editHandleType === 'scale'
107
+ ? selectedEditHandle
108
+ : null;
109
+ this.updateCursor(props);
110
+ }
111
+ }
112
+ handleStartDragging(event, props) {
113
+ if (this._selectedEditHandle) {
114
+ this._isScaling = true;
115
+ this._geometryBeingScaled = this.getSelectedFeaturesAsFeatureCollection(props);
116
+ }
117
+ }
118
+ handleDragging(event, props) {
119
+ if (!this._isScaling) {
120
+ return;
121
+ }
122
+ props.onUpdateCursor(this._cursor);
123
+ const scaleAction = this.getScaleAction(event.pointerDownMapCoords, event.mapCoords, 'scaling', props);
124
+ if (scaleAction) {
125
+ props.onEdit(scaleAction);
126
+ }
127
+ event.cancelPan();
128
+ }
129
+ handleStopDragging(event, props) {
130
+ if (this._isScaling) {
131
+ // Scale the geometry
132
+ const scaleAction = this.getScaleAction(event.pointerDownMapCoords, event.mapCoords, 'scaled', props);
133
+ if (scaleAction) {
134
+ props.onEdit(scaleAction);
135
+ }
136
+ props.onUpdateCursor(null);
137
+ this._geometryBeingScaled = null;
138
+ this._selectedEditHandle = null;
139
+ this._cursor = null;
140
+ this._isScaling = false;
141
+ }
142
+ }
143
+ getGuides(props) {
144
+ this._cornerGuidePoints = [];
145
+ const selectedGeometry = this.getSelectedFeaturesAsFeatureCollection(props);
146
+ // Add buffer to the enveloping box if a single Point feature is selected
147
+ if (this._isSinglePointGeometrySelected(selectedGeometry)) {
148
+ return { type: 'FeatureCollection', features: [] };
149
+ }
150
+ const boundingBox = bboxPolygon(bbox(selectedGeometry));
151
+ boundingBox.properties.mode = 'scale';
152
+ const cornerGuidePoints = [];
153
+ coordEach(boundingBox, (coord, coordIndex) => {
154
+ if (coordIndex < 4) {
155
+ // Get corner midpoint guides from the enveloping box
156
+ const cornerPoint = point(coord, {
157
+ guideType: 'editHandle',
158
+ editHandleType: 'scale',
159
+ positionIndexes: [coordIndex],
160
+ });
161
+ cornerGuidePoints.push(cornerPoint);
162
+ }
163
+ });
164
+ this._cornerGuidePoints = cornerGuidePoints;
165
+ // @ts-expect-error turf types diff
166
+ return featureCollection([polygonToLine(boundingBox), ...this._cornerGuidePoints]);
167
+ }
168
+ }
169
+ function getScaleFactor(centroid, startDragPoint, currentPoint) {
170
+ const startDistance = turfDistance(centroid, startDragPoint);
171
+ const endDistance = turfDistance(centroid, currentPoint);
172
+ return endDistance / startDistance;
173
+ }
@@ -0,0 +1,21 @@
1
+ import { Feature, FeatureCollection } from '../geojson-types';
2
+ import { PointerMoveEvent, StartDraggingEvent, StopDraggingEvent, DraggingEvent, ModeProps, Pick, GuideFeatureCollection, EditHandleFeature } from './types';
3
+ import { GeoJsonEditMode } from './geojson-edit-mode';
4
+ type MovementTypeEvent = PointerMoveEvent | StartDraggingEvent | StopDraggingEvent | DraggingEvent;
5
+ export declare class SnappableMode extends GeoJsonEditMode {
6
+ _handler: GeoJsonEditMode;
7
+ constructor(handler: GeoJsonEditMode);
8
+ _getSnappedMouseEvent<T extends MovementTypeEvent>(event: T, snapSource: EditHandleFeature, snapTarget: EditHandleFeature): T;
9
+ _getPickedSnapTarget(picks: Pick[]): EditHandleFeature | null | undefined;
10
+ _getPickedSnapSource(pointerDownPicks: Pick[] | null | undefined): EditHandleFeature | null | undefined;
11
+ _getUpdatedSnapSourceHandle(snapSourceHandle: EditHandleFeature, data: FeatureCollection): EditHandleFeature;
12
+ _getSnapTargets(props: ModeProps<FeatureCollection>): Feature[];
13
+ _getSnapTargetHandles(props: ModeProps<FeatureCollection>): EditHandleFeature[];
14
+ getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection;
15
+ _getSnapAwareEvent<T extends MovementTypeEvent>(event: T, props: ModeProps<FeatureCollection>): T;
16
+ handleStartDragging(event: StartDraggingEvent, props: ModeProps<FeatureCollection>): void;
17
+ handleStopDragging(event: StopDraggingEvent, props: ModeProps<FeatureCollection>): void;
18
+ handleDragging(event: DraggingEvent, props: ModeProps<FeatureCollection>): void;
19
+ handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>): void;
20
+ }
21
+ export {};
@@ -0,0 +1,109 @@
1
+ import { getPickedSnapSourceEditHandle, getPickedEditHandles, getEditHandlesForGeometry, } from './utils';
2
+ import { GeoJsonEditMode } from './geojson-edit-mode';
3
+ export class SnappableMode extends GeoJsonEditMode {
4
+ _handler;
5
+ constructor(handler) {
6
+ super();
7
+ this._handler = handler;
8
+ }
9
+ _getSnappedMouseEvent(event, snapSource, snapTarget) {
10
+ return Object.assign(event, {
11
+ mapCoords: snapTarget.geometry.coordinates,
12
+ pointerDownMapCoords: snapSource && snapSource.geometry.coordinates,
13
+ });
14
+ }
15
+ _getPickedSnapTarget(picks) {
16
+ return getPickedEditHandles(picks).find((handle) => handle.properties.editHandleType === 'snap-target');
17
+ }
18
+ _getPickedSnapSource(pointerDownPicks) {
19
+ return getPickedSnapSourceEditHandle(pointerDownPicks);
20
+ }
21
+ _getUpdatedSnapSourceHandle(snapSourceHandle, data) {
22
+ const { featureIndex, positionIndexes } = snapSourceHandle.properties;
23
+ if (!Array.isArray(positionIndexes)) {
24
+ return snapSourceHandle;
25
+ }
26
+ const snapSourceFeature = data.features[featureIndex];
27
+ // $FlowFixMe
28
+ const snapSourceCoordinates = positionIndexes.reduce((a, b) => a[b], snapSourceFeature.geometry.coordinates);
29
+ return {
30
+ ...snapSourceHandle,
31
+ geometry: {
32
+ type: 'Point',
33
+ coordinates: snapSourceCoordinates,
34
+ },
35
+ };
36
+ }
37
+ // If additionalSnapTargets is present in modeConfig and is populated, this
38
+ // method will return those features along with the features
39
+ // that live in the current layer. Otherwise, this method will simply return the
40
+ // features from the current layer
41
+ _getSnapTargets(props) {
42
+ let { additionalSnapTargets } = props.modeConfig || {};
43
+ additionalSnapTargets = additionalSnapTargets || [];
44
+ const features = [...props.data.features, ...additionalSnapTargets];
45
+ return features;
46
+ }
47
+ _getSnapTargetHandles(props) {
48
+ const handles = [];
49
+ const features = this._getSnapTargets(props);
50
+ for (let i = 0; i < features.length; i++) {
51
+ // Filter out the currently selected feature(s)
52
+ const isCurrentIndexFeatureNotSelected = !props.selectedIndexes.includes(i);
53
+ if (isCurrentIndexFeatureNotSelected) {
54
+ const { geometry } = features[i];
55
+ handles.push(...getEditHandlesForGeometry(geometry, i, 'snap-target'));
56
+ }
57
+ }
58
+ return handles;
59
+ }
60
+ // If no snap handle has been picked, only display the edit handles of the
61
+ // selected feature. If a snap handle has been picked, display said snap handle
62
+ // along with all snappable points on all non-selected features.
63
+ getGuides(props) {
64
+ const { modeConfig, lastPointerMoveEvent } = props;
65
+ const { enableSnapping } = modeConfig || {};
66
+ const guides = {
67
+ type: 'FeatureCollection',
68
+ features: [...this._handler.getGuides(props).features],
69
+ };
70
+ if (!enableSnapping) {
71
+ return guides;
72
+ }
73
+ const snapSourceHandle = lastPointerMoveEvent && this._getPickedSnapSource(lastPointerMoveEvent.pointerDownPicks);
74
+ // They started dragging a handle
75
+ // So render the picked handle (in its updated location) and all possible snap targets
76
+ if (snapSourceHandle) {
77
+ guides.features.push(...this._getSnapTargetHandles(props), this._getUpdatedSnapSourceHandle(snapSourceHandle, props.data));
78
+ return guides;
79
+ }
80
+ // Render the possible snap source handles
81
+ const { features } = props.data;
82
+ for (const index of props.selectedIndexes) {
83
+ if (index < features.length) {
84
+ const { geometry } = features[index];
85
+ guides.features.push(...getEditHandlesForGeometry(geometry, index, 'snap-source'));
86
+ }
87
+ }
88
+ return guides;
89
+ }
90
+ _getSnapAwareEvent(event, props) {
91
+ const snapSource = this._getPickedSnapSource(props.lastPointerMoveEvent.pointerDownPicks);
92
+ const snapTarget = this._getPickedSnapTarget(event.picks);
93
+ return snapSource && snapTarget
94
+ ? this._getSnappedMouseEvent(event, snapSource, snapTarget)
95
+ : event;
96
+ }
97
+ handleStartDragging(event, props) {
98
+ this._handler.handleStartDragging(event, props);
99
+ }
100
+ handleStopDragging(event, props) {
101
+ this._handler.handleStopDragging(this._getSnapAwareEvent(event, props), props);
102
+ }
103
+ handleDragging(event, props) {
104
+ this._handler.handleDragging(this._getSnapAwareEvent(event, props), props);
105
+ }
106
+ handlePointerMove(event, props) {
107
+ this._handler.handlePointerMove(this._getSnapAwareEvent(event, props), props);
108
+ }
109
+ }
@@ -0,0 +1,10 @@
1
+ import { FeatureCollection } from '../geojson-types';
2
+ import { ClickEvent, PointerMoveEvent, ModeProps, GuideFeatureCollection, TentativeFeature } from './types';
3
+ import { GeoJsonEditMode, GeoJsonEditAction } from './geojson-edit-mode';
4
+ export declare class SplitPolygonMode extends GeoJsonEditMode {
5
+ calculateMapCoords(clickSequence: any, mapCoords: any, props: ModeProps<FeatureCollection>): any;
6
+ getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection;
7
+ handleClick(event: ClickEvent, props: ModeProps<FeatureCollection>): void;
8
+ handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>): void;
9
+ splitPolygon(tentativeFeature: TentativeFeature, props: ModeProps<FeatureCollection>): GeoJsonEditAction;
10
+ }
@@ -0,0 +1,164 @@
1
+ import booleanPointInPolygon from '@turf/boolean-point-in-polygon';
2
+ import turfDifference from '@turf/difference';
3
+ import turfBuffer from '@turf/buffer';
4
+ import lineIntersect from '@turf/line-intersect';
5
+ import { lineString } from '@turf/helpers';
6
+ import turfBearing from '@turf/bearing';
7
+ import turfDistance from '@turf/distance';
8
+ import turfDestination from '@turf/destination';
9
+ import turfPolygonToLine from '@turf/polygon-to-line';
10
+ import nearestPointOnLine from '@turf/nearest-point-on-line';
11
+ import { generatePointsParallelToLinePoints } from './utils';
12
+ import { GeoJsonEditMode } from './geojson-edit-mode';
13
+ import { ImmutableFeatureCollection } from './immutable-feature-collection';
14
+ export class SplitPolygonMode extends GeoJsonEditMode {
15
+ calculateMapCoords(clickSequence, mapCoords, props) {
16
+ const modeConfig = props.modeConfig;
17
+ if (!modeConfig || !modeConfig.lock90Degree || !clickSequence.length) {
18
+ return mapCoords;
19
+ }
20
+ if (clickSequence.length === 1) {
21
+ // if first point is clicked, then find closest polygon point and build ~90deg vector
22
+ const firstPoint = clickSequence[0];
23
+ const selectedGeometry = this.getSelectedGeometry(props);
24
+ // @ts-expect-error turf types diff
25
+ const feature = turfPolygonToLine(selectedGeometry);
26
+ const lines = feature.type === 'FeatureCollection' ? feature.features : [feature];
27
+ let minDistance = Number.MAX_SAFE_INTEGER;
28
+ let closestPoint = null;
29
+ // If Multipolygon, then we should find nearest polygon line and stick split to it.
30
+ lines.forEach((line) => {
31
+ const snapPoint = nearestPointOnLine(line, firstPoint);
32
+ const distanceFromOrigin = turfDistance(snapPoint, firstPoint);
33
+ if (minDistance > distanceFromOrigin) {
34
+ minDistance = distanceFromOrigin;
35
+ closestPoint = snapPoint;
36
+ }
37
+ });
38
+ if (closestPoint) {
39
+ // closest point is used as 90degree entry to the polygon
40
+ const lastBearing = turfBearing(firstPoint, closestPoint);
41
+ const currentDistance = turfDistance(firstPoint, mapCoords, { units: 'meters' });
42
+ return turfDestination(firstPoint, currentDistance, lastBearing, {
43
+ units: 'meters',
44
+ }).geometry.coordinates;
45
+ }
46
+ return mapCoords;
47
+ }
48
+ // Allow only 90 degree turns
49
+ const lastPoint = clickSequence[clickSequence.length - 1];
50
+ const [approximatePoint] = generatePointsParallelToLinePoints(clickSequence[clickSequence.length - 2], lastPoint, mapCoords);
51
+ // align point with current ground
52
+ const nearestPt = nearestPointOnLine(lineString([lastPoint, approximatePoint]), mapCoords)
53
+ .geometry.coordinates;
54
+ return nearestPt;
55
+ }
56
+ getGuides(props) {
57
+ const clickSequence = this.getClickSequence();
58
+ const guides = {
59
+ type: 'FeatureCollection',
60
+ features: [],
61
+ };
62
+ if (clickSequence.length === 0 || !props.lastPointerMoveEvent) {
63
+ // nothing to do yet
64
+ return guides;
65
+ }
66
+ const { mapCoords } = props.lastPointerMoveEvent;
67
+ guides.features.push({
68
+ type: 'Feature',
69
+ properties: {
70
+ guideType: 'tentative',
71
+ },
72
+ geometry: {
73
+ type: 'LineString',
74
+ coordinates: [...clickSequence, this.calculateMapCoords(clickSequence, mapCoords, props)],
75
+ },
76
+ });
77
+ return guides;
78
+ }
79
+ handleClick(event, props) {
80
+ const tentativeFeature = this.getTentativeGuide(props);
81
+ const selectedGeometry = this.getSelectedGeometry(props);
82
+ if (!selectedGeometry) {
83
+ // eslint-disable-next-line no-console,no-undef
84
+ console.warn('A polygon must be selected for splitting');
85
+ return;
86
+ }
87
+ const clickSequence = this.getClickSequence();
88
+ if (tentativeFeature && tentativeFeature.geometry.type === 'LineString') {
89
+ clickSequence.push(tentativeFeature.geometry.coordinates[tentativeFeature.geometry.coordinates.length - 1]);
90
+ }
91
+ else {
92
+ this.addClickSequence(event);
93
+ }
94
+ const pt = {
95
+ type: 'Point',
96
+ coordinates: clickSequence[clickSequence.length - 1],
97
+ };
98
+ // @ts-expect-error turf types diff
99
+ const isPointInPolygon = booleanPointInPolygon(pt, selectedGeometry);
100
+ if (clickSequence.length > 1 && tentativeFeature && !isPointInPolygon) {
101
+ this.resetClickSequence();
102
+ // @ts-expect-error narrow type
103
+ const isLineInterectingWithPolygon = lineIntersect(tentativeFeature, selectedGeometry);
104
+ if (isLineInterectingWithPolygon.features.length === 0) {
105
+ return;
106
+ }
107
+ const editAction = this.splitPolygon(tentativeFeature, props);
108
+ if (editAction) {
109
+ props.onEdit(editAction);
110
+ }
111
+ }
112
+ }
113
+ handlePointerMove(event, props) {
114
+ props.onUpdateCursor('cell');
115
+ }
116
+ splitPolygon(tentativeFeature, props) {
117
+ const selectedGeometry = this.getSelectedGeometry(props);
118
+ const featureIndex = props.selectedIndexes[0];
119
+ const modeConfig = props.modeConfig || {};
120
+ // Default gap in between the polygon
121
+ let { gap = 0.1, units = 'centimeters' } = modeConfig;
122
+ if (gap === 0) {
123
+ gap = 0.1;
124
+ units = 'centimeters';
125
+ }
126
+ const buffer = turfBuffer(tentativeFeature, gap, { units });
127
+ // @ts-expect-error turf types diff
128
+ const updatedGeometry = turfDifference(selectedGeometry, buffer);
129
+ if (!updatedGeometry) {
130
+ // eslint-disable-next-line no-console,no-undef
131
+ console.warn('Canceling edit. Split Polygon erased');
132
+ return null;
133
+ }
134
+ const { type, coordinates } = updatedGeometry.geometry;
135
+ let updatedCoordinates = []; // TODO
136
+ if (type === 'Polygon') {
137
+ // Update the coordinates as per Multipolygon
138
+ updatedCoordinates = coordinates.map((c) => [c]);
139
+ }
140
+ else {
141
+ // Handle Case when Multipolygon has holes
142
+ updatedCoordinates = coordinates.reduce((agg, prev) => {
143
+ prev.forEach((p) => {
144
+ // @ts-expect-error revisit coordinates type here
145
+ agg.push([p]);
146
+ });
147
+ return agg;
148
+ }, []);
149
+ }
150
+ // Update the type to Mulitpolygon
151
+ const updatedData = new ImmutableFeatureCollection(props.data).replaceGeometry(featureIndex, {
152
+ type: 'MultiPolygon',
153
+ coordinates: updatedCoordinates,
154
+ });
155
+ const editAction = {
156
+ updatedData: updatedData.getObject(),
157
+ editType: 'split',
158
+ editContext: {
159
+ featureIndexes: [featureIndex],
160
+ },
161
+ };
162
+ return editAction;
163
+ }
164
+ }
@@ -0,0 +1,10 @@
1
+ import { ClickEvent, PointerMoveEvent, ModeProps, GuideFeatureCollection, TentativeFeature } from './types';
2
+ import { Position, Polygon, FeatureOf, FeatureCollection } from '../geojson-types';
3
+ import { GeoJsonEditMode } from './geojson-edit-mode';
4
+ export declare class ThreeClickPolygonMode extends GeoJsonEditMode {
5
+ handleClick(event: ClickEvent, props: ModeProps<FeatureCollection>): void;
6
+ getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection;
7
+ getThreeClickPolygon(coord1: Position, coord2: Position, coord3: Position, modeConfig: any): FeatureOf<Polygon> | null | undefined;
8
+ handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>): void;
9
+ createTentativeFeature(props: ModeProps<FeatureCollection>): TentativeFeature;
10
+ }