@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,201 @@
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, Point } 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, { NearestPointOnLine } from '@turf/nearest-point-on-line';
11
+ import { generatePointsParallelToLinePoints } from './utils';
12
+ import { FeatureCollection } from '../geojson-types';
13
+ import {
14
+ ClickEvent,
15
+ PointerMoveEvent,
16
+ ModeProps,
17
+ GuideFeatureCollection,
18
+ TentativeFeature,
19
+ } from './types';
20
+ import { GeoJsonEditMode, GeoJsonEditAction } from './geojson-edit-mode';
21
+ import { ImmutableFeatureCollection } from './immutable-feature-collection';
22
+
23
+ export class SplitPolygonMode extends GeoJsonEditMode {
24
+ calculateMapCoords(clickSequence: any, mapCoords: any, props: ModeProps<FeatureCollection>) {
25
+ const modeConfig = props.modeConfig;
26
+ if (!modeConfig || !modeConfig.lock90Degree || !clickSequence.length) {
27
+ return mapCoords;
28
+ }
29
+ if (clickSequence.length === 1) {
30
+ // if first point is clicked, then find closest polygon point and build ~90deg vector
31
+ const firstPoint = clickSequence[0];
32
+ const selectedGeometry = this.getSelectedGeometry(props);
33
+ // @ts-expect-error turf types diff
34
+ const feature = turfPolygonToLine(selectedGeometry);
35
+
36
+ const lines = feature.type === 'FeatureCollection' ? feature.features : [feature];
37
+ let minDistance = Number.MAX_SAFE_INTEGER;
38
+ let closestPoint: NearestPointOnLine | null = null;
39
+ // If Multipolygon, then we should find nearest polygon line and stick split to it.
40
+ lines.forEach((line) => {
41
+ const snapPoint = nearestPointOnLine(line, firstPoint);
42
+ const distanceFromOrigin = turfDistance(snapPoint, firstPoint);
43
+ if (minDistance > distanceFromOrigin) {
44
+ minDistance = distanceFromOrigin;
45
+ closestPoint = snapPoint;
46
+ }
47
+ });
48
+
49
+ if (closestPoint) {
50
+ // closest point is used as 90degree entry to the polygon
51
+ const lastBearing = turfBearing(firstPoint, closestPoint);
52
+ const currentDistance = turfDistance(firstPoint, mapCoords, { units: 'meters' });
53
+ return turfDestination(firstPoint, currentDistance, lastBearing, {
54
+ units: 'meters',
55
+ }).geometry.coordinates;
56
+ }
57
+ return mapCoords;
58
+ }
59
+ // Allow only 90 degree turns
60
+ const lastPoint = clickSequence[clickSequence.length - 1];
61
+ const [approximatePoint] = generatePointsParallelToLinePoints(
62
+ clickSequence[clickSequence.length - 2],
63
+ lastPoint,
64
+ mapCoords
65
+ );
66
+ // align point with current ground
67
+ const nearestPt = nearestPointOnLine(lineString([lastPoint, approximatePoint]), mapCoords)
68
+ .geometry.coordinates;
69
+ return nearestPt;
70
+ }
71
+
72
+ getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection {
73
+ const clickSequence = this.getClickSequence();
74
+
75
+ const guides: GuideFeatureCollection = {
76
+ type: 'FeatureCollection',
77
+ features: [],
78
+ };
79
+
80
+ if (clickSequence.length === 0 || !props.lastPointerMoveEvent) {
81
+ // nothing to do yet
82
+ return guides;
83
+ }
84
+
85
+ const { mapCoords } = props.lastPointerMoveEvent;
86
+
87
+ guides.features.push({
88
+ type: 'Feature',
89
+ properties: {
90
+ guideType: 'tentative',
91
+ },
92
+ geometry: {
93
+ type: 'LineString',
94
+ coordinates: [...clickSequence, this.calculateMapCoords(clickSequence, mapCoords, props)],
95
+ },
96
+ });
97
+
98
+ return guides;
99
+ }
100
+
101
+ handleClick(event: ClickEvent, props: ModeProps<FeatureCollection>) {
102
+ const tentativeFeature = this.getTentativeGuide(props);
103
+
104
+ const selectedGeometry = this.getSelectedGeometry(props);
105
+
106
+ if (!selectedGeometry) {
107
+ // eslint-disable-next-line no-console,no-undef
108
+ console.warn('A polygon must be selected for splitting');
109
+ return;
110
+ }
111
+
112
+ const clickSequence = this.getClickSequence();
113
+ if (tentativeFeature && tentativeFeature.geometry.type === 'LineString') {
114
+ clickSequence.push(
115
+ tentativeFeature.geometry.coordinates[tentativeFeature.geometry.coordinates.length - 1]
116
+ );
117
+ } else {
118
+ this.addClickSequence(event);
119
+ }
120
+
121
+ const pt: Point = {
122
+ type: 'Point',
123
+ coordinates: clickSequence[clickSequence.length - 1],
124
+ };
125
+
126
+ // @ts-expect-error turf types diff
127
+ const isPointInPolygon = booleanPointInPolygon(pt, selectedGeometry);
128
+ if (clickSequence.length > 1 && tentativeFeature && !isPointInPolygon) {
129
+ this.resetClickSequence();
130
+ // @ts-expect-error narrow type
131
+ const isLineInterectingWithPolygon = lineIntersect(tentativeFeature, selectedGeometry);
132
+ if (isLineInterectingWithPolygon.features.length === 0) {
133
+ return;
134
+ }
135
+
136
+ const editAction = this.splitPolygon(tentativeFeature, props);
137
+
138
+ if (editAction) {
139
+ props.onEdit(editAction);
140
+ }
141
+ }
142
+ }
143
+
144
+ handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
145
+ props.onUpdateCursor('cell');
146
+ }
147
+
148
+ splitPolygon(tentativeFeature: TentativeFeature, props: ModeProps<FeatureCollection>) {
149
+ const selectedGeometry = this.getSelectedGeometry(props);
150
+ const featureIndex = props.selectedIndexes[0];
151
+ const modeConfig = props.modeConfig || {};
152
+
153
+ // Default gap in between the polygon
154
+ let { gap = 0.1, units = 'centimeters' } = modeConfig;
155
+ if (gap === 0) {
156
+ gap = 0.1;
157
+ units = 'centimeters';
158
+ }
159
+
160
+ const buffer = turfBuffer(tentativeFeature, gap, { units });
161
+ // @ts-expect-error turf types diff
162
+ const updatedGeometry = turfDifference(selectedGeometry, buffer);
163
+ if (!updatedGeometry) {
164
+ // eslint-disable-next-line no-console,no-undef
165
+ console.warn('Canceling edit. Split Polygon erased');
166
+ return null;
167
+ }
168
+
169
+ const { type, coordinates } = updatedGeometry.geometry;
170
+ let updatedCoordinates: any[] = []; // TODO
171
+ if (type === 'Polygon') {
172
+ // Update the coordinates as per Multipolygon
173
+ updatedCoordinates = coordinates.map((c) => [c]);
174
+ } else {
175
+ // Handle Case when Multipolygon has holes
176
+ updatedCoordinates = coordinates.reduce((agg, prev) => {
177
+ prev.forEach((p) => {
178
+ // @ts-expect-error revisit coordinates type here
179
+ agg.push([p]);
180
+ });
181
+ return agg;
182
+ }, []);
183
+ }
184
+
185
+ // Update the type to Mulitpolygon
186
+ const updatedData = new ImmutableFeatureCollection(props.data).replaceGeometry(featureIndex, {
187
+ type: 'MultiPolygon',
188
+ coordinates: updatedCoordinates,
189
+ });
190
+
191
+ const editAction: GeoJsonEditAction = {
192
+ updatedData: updatedData.getObject(),
193
+ editType: 'split',
194
+ editContext: {
195
+ featureIndexes: [featureIndex],
196
+ },
197
+ };
198
+
199
+ return editAction;
200
+ }
201
+ }
@@ -0,0 +1,111 @@
1
+ import {
2
+ ClickEvent,
3
+ PointerMoveEvent,
4
+ ModeProps,
5
+ GuideFeatureCollection,
6
+ TentativeFeature,
7
+ } from './types';
8
+ import { Position, Polygon, FeatureOf, FeatureCollection } from '../geojson-types';
9
+ import { GeoJsonEditMode } from './geojson-edit-mode';
10
+
11
+ export class ThreeClickPolygonMode extends GeoJsonEditMode {
12
+ handleClick(event: ClickEvent, props: ModeProps<FeatureCollection>) {
13
+ this.addClickSequence(event);
14
+ const clickSequence = this.getClickSequence();
15
+ const tentativeFeature = this.getTentativeGuide(props);
16
+
17
+ if (
18
+ clickSequence.length > 2 &&
19
+ tentativeFeature &&
20
+ tentativeFeature.geometry.type === 'Polygon'
21
+ ) {
22
+ const editAction = this.getAddFeatureOrBooleanPolygonAction(tentativeFeature.geometry, props);
23
+ this.resetClickSequence();
24
+
25
+ if (editAction) {
26
+ props.onEdit(editAction);
27
+ }
28
+ }
29
+ }
30
+
31
+ getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection {
32
+ const { lastPointerMoveEvent, modeConfig } = props;
33
+ const clickSequence = this.getClickSequence();
34
+
35
+ const guides: GuideFeatureCollection = {
36
+ type: 'FeatureCollection',
37
+ features: [],
38
+ };
39
+
40
+ if (clickSequence.length === 0) {
41
+ // nothing to do yet
42
+ return guides;
43
+ }
44
+
45
+ const hoveredCoord = lastPointerMoveEvent.mapCoords;
46
+
47
+ if (clickSequence.length === 1) {
48
+ guides.features.push({
49
+ type: 'Feature',
50
+ properties: {
51
+ guideType: 'tentative',
52
+ },
53
+ geometry: {
54
+ type: 'LineString',
55
+ coordinates: [clickSequence[0], hoveredCoord],
56
+ },
57
+ });
58
+ } else {
59
+ const polygon = this.getThreeClickPolygon(
60
+ clickSequence[0],
61
+ clickSequence[1],
62
+ hoveredCoord,
63
+ modeConfig
64
+ );
65
+ if (polygon) {
66
+ guides.features.push({
67
+ type: 'Feature',
68
+ properties: {
69
+ guideType: 'tentative',
70
+ },
71
+ geometry: polygon.geometry,
72
+ });
73
+ }
74
+ }
75
+
76
+ return guides;
77
+ }
78
+
79
+ getThreeClickPolygon(
80
+ coord1: Position,
81
+ coord2: Position,
82
+ coord3: Position,
83
+ modeConfig: any
84
+ ): FeatureOf<Polygon> | null | undefined {
85
+ return null;
86
+ }
87
+
88
+ handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
89
+ props.onUpdateCursor('cell');
90
+ super.handlePointerMove(event, props);
91
+ }
92
+
93
+ createTentativeFeature(props: ModeProps<FeatureCollection>): TentativeFeature {
94
+ const { lastPointerMoveEvent } = props;
95
+ const clickSequence = this.getClickSequence();
96
+
97
+ const lastCoords = lastPointerMoveEvent ? [lastPointerMoveEvent.mapCoords] : [];
98
+
99
+ let tentativeFeature;
100
+ if (clickSequence.length === 2) {
101
+ tentativeFeature = this.getThreeClickPolygon(
102
+ clickSequence[0],
103
+ clickSequence[1],
104
+ lastCoords[0],
105
+ props.modeConfig
106
+ );
107
+ }
108
+
109
+ return tentativeFeature;
110
+ }
111
+ }
@@ -0,0 +1,75 @@
1
+ import { featureCollection } from '@turf/helpers';
2
+ import { PointerMoveEvent, ModeProps, StartDraggingEvent } from './types';
3
+ import { FeatureCollection } from '../geojson-types';
4
+ import { TranslateMode } from './translate-mode';
5
+ import { ScaleMode } from './scale-mode';
6
+ import { RotateMode } from './rotate-mode';
7
+
8
+ import { CompositeMode } from './composite-mode';
9
+ import { GeoJsonEditMode } from './geojson-edit-mode';
10
+
11
+ export class TransformMode extends CompositeMode {
12
+ constructor() {
13
+ super([new TranslateMode(), new ScaleMode(), new RotateMode()]);
14
+ }
15
+
16
+ handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
17
+ let updatedCursor: string | null = null;
18
+ super.handlePointerMove(event, {
19
+ ...props,
20
+ onUpdateCursor: (cursor) => {
21
+ updatedCursor = cursor || updatedCursor;
22
+ },
23
+ });
24
+ props.onUpdateCursor(updatedCursor);
25
+ }
26
+
27
+ handleStartDragging(event: StartDraggingEvent, props: ModeProps<FeatureCollection>) {
28
+ let scaleMode: ScaleMode | null = null;
29
+ let translateMode: TranslateMode | null = null;
30
+ const filteredModes: GeoJsonEditMode[] = [];
31
+
32
+ // If the user selects a scaling edit handle that overlaps with part of the selected feature,
33
+ // it is possible for both scale and translate actions to be triggered. This logic prevents
34
+ // this simultaneous action trigger from happening by putting a higher priority on scaling
35
+ // since the user needs to be more precise to hover over a scaling edit handle.
36
+ this._modes.forEach((mode) => {
37
+ if (mode instanceof TranslateMode) {
38
+ translateMode = mode;
39
+ } else {
40
+ if (mode instanceof ScaleMode) {
41
+ scaleMode = mode;
42
+ }
43
+ filteredModes.push(mode);
44
+ }
45
+ });
46
+
47
+ if (scaleMode instanceof ScaleMode && !scaleMode.isEditHandleSelected()) {
48
+ filteredModes.push(translateMode!);
49
+ }
50
+
51
+ filteredModes.filter(Boolean).forEach((mode) => mode.handleStartDragging(event, props));
52
+ }
53
+
54
+ getGuides(props: ModeProps<FeatureCollection>) {
55
+ let compositeGuides = super.getGuides(props);
56
+ const rotateMode = (this._modes || []).find((mode) => mode instanceof RotateMode);
57
+
58
+ if (rotateMode instanceof RotateMode) {
59
+ const nonEnvelopeGuides = compositeGuides.features.filter((guide) => {
60
+ const { editHandleType, mode } = (guide.properties as any) || {};
61
+ // Both scale and rotate modes have the same enveloping box as a guide - only need one
62
+ const guidesToFilterOut = [mode];
63
+ // Do not render scaling edit handles if rotating
64
+ if (rotateMode.getIsRotating()) {
65
+ guidesToFilterOut.push(editHandleType);
66
+ }
67
+ return !guidesToFilterOut.includes('scale');
68
+ });
69
+
70
+ // @ts-expect-error turf types
71
+ compositeGuides = featureCollection(nonEnvelopeGuides);
72
+ }
73
+ return compositeGuides;
74
+ }
75
+ }
@@ -0,0 +1,161 @@
1
+ import turfBearing from '@turf/bearing';
2
+ import turfDistance from '@turf/distance';
3
+ import clone from '@turf/clone';
4
+ import { point, Feature as TurfFeature, Geometry as TurfGeometry } from '@turf/helpers';
5
+ import WebMercatorViewport from 'viewport-mercator-project';
6
+ import { FeatureCollection, Position, Geometry } from '../geojson-types';
7
+ import {
8
+ PointerMoveEvent,
9
+ StartDraggingEvent,
10
+ StopDraggingEvent,
11
+ DraggingEvent,
12
+ ModeProps,
13
+ } from './types';
14
+ import { mapCoords } from './utils';
15
+ import { translateFromCenter } from '../translateFromCenter';
16
+ import { GeoJsonEditMode, GeoJsonEditAction } from './geojson-edit-mode';
17
+ import { ImmutableFeatureCollection } from './immutable-feature-collection';
18
+
19
+ export class TranslateMode extends GeoJsonEditMode {
20
+ _geometryBeforeTranslate: FeatureCollection | null | undefined;
21
+ _isTranslatable: boolean = undefined!;
22
+
23
+ handleDragging(event: DraggingEvent, props: ModeProps<FeatureCollection>) {
24
+ if (!this._isTranslatable) {
25
+ // Nothing to do
26
+ return;
27
+ }
28
+
29
+ if (this._geometryBeforeTranslate) {
30
+ // Translate the geometry
31
+ const editAction = this.getTranslateAction(
32
+ event.pointerDownMapCoords,
33
+ event.mapCoords,
34
+ 'translating',
35
+ props
36
+ );
37
+
38
+ if (editAction) {
39
+ props.onEdit(editAction);
40
+ }
41
+ }
42
+
43
+ // cancel map panning
44
+ event.cancelPan();
45
+ }
46
+
47
+ handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
48
+ this._isTranslatable = this.isSelectionPicked(event.pointerDownPicks || event.picks, props);
49
+
50
+ this.updateCursor(props);
51
+ }
52
+
53
+ handleStartDragging(event: StartDraggingEvent, props: ModeProps<FeatureCollection>) {
54
+ if (!this._isTranslatable) {
55
+ return;
56
+ }
57
+
58
+ this._geometryBeforeTranslate = this.getSelectedFeaturesAsFeatureCollection(props);
59
+ }
60
+
61
+ handleStopDragging(event: StopDraggingEvent, props: ModeProps<FeatureCollection>) {
62
+ if (this._geometryBeforeTranslate) {
63
+ // Translate the geometry
64
+ const editAction = this.getTranslateAction(
65
+ event.pointerDownMapCoords,
66
+ event.mapCoords,
67
+ 'translated',
68
+ props
69
+ );
70
+
71
+ if (editAction) {
72
+ props.onEdit(editAction);
73
+ }
74
+
75
+ this._geometryBeforeTranslate = null;
76
+ }
77
+ }
78
+
79
+ updateCursor(props: ModeProps<FeatureCollection>) {
80
+ if (this._isTranslatable) {
81
+ props.onUpdateCursor('move');
82
+ } else {
83
+ props.onUpdateCursor(null);
84
+ }
85
+ }
86
+
87
+ // eslint-disable-next-line max-statements
88
+ getTranslateAction(
89
+ startDragPoint: Position,
90
+ currentPoint: Position,
91
+ editType: string,
92
+ props: ModeProps<FeatureCollection>
93
+ ): GeoJsonEditAction | null | undefined {
94
+ if (!this._geometryBeforeTranslate) {
95
+ return null;
96
+ }
97
+
98
+ let updatedData = new ImmutableFeatureCollection(props.data);
99
+ const selectedIndexes = props.selectedIndexes;
100
+
101
+ const { viewport: viewportDesc, screenSpace } = props.modeConfig || {};
102
+
103
+ // move features without adapting to mercator projection
104
+ if (viewportDesc && screenSpace) {
105
+ const viewport = viewportDesc.project ? viewportDesc : new WebMercatorViewport(viewportDesc);
106
+
107
+ const from = viewport.project(startDragPoint);
108
+ const to = viewport.project(currentPoint);
109
+ const dx = to[0] - from[0];
110
+ const dy = to[1] - from[1];
111
+
112
+ for (let i = 0; i < selectedIndexes.length; i++) {
113
+ const selectedIndex = selectedIndexes[i];
114
+ const feature = this._geometryBeforeTranslate.features[i];
115
+
116
+ let coordinates = feature.geometry.coordinates;
117
+ if (coordinates) {
118
+ coordinates = mapCoords(coordinates, (coord) => {
119
+ const pixels = viewport.project(coord);
120
+ if (pixels) {
121
+ pixels[0] += dx;
122
+ pixels[1] += dy;
123
+ return viewport.unproject(pixels);
124
+ }
125
+ return null;
126
+ });
127
+
128
+ // @ts-expect-error turf types
129
+ updatedData = updatedData.replaceGeometry(selectedIndex, {
130
+ type: feature.geometry.type,
131
+ coordinates,
132
+ });
133
+ }
134
+ }
135
+ } else {
136
+ const p1 = point(startDragPoint);
137
+ const p2 = point(currentPoint);
138
+
139
+ const distanceMoved = turfDistance(p1, p2);
140
+ const direction = turfBearing(p1, p2);
141
+
142
+ const movedFeatures = this._geometryBeforeTranslate.features.map((feature) =>
143
+ translateFromCenter(clone(feature as TurfFeature<TurfGeometry>), distanceMoved, direction)
144
+ );
145
+
146
+ for (let i = 0; i < selectedIndexes.length; i++) {
147
+ const selectedIndex = selectedIndexes[i];
148
+ const movedFeature = movedFeatures[i];
149
+ updatedData = updatedData.replaceGeometry(selectedIndex, movedFeature.geometry as Geometry);
150
+ }
151
+ }
152
+
153
+ return {
154
+ updatedData: updatedData.getObject(),
155
+ editType,
156
+ editContext: {
157
+ featureIndexes: selectedIndexes,
158
+ },
159
+ };
160
+ }
161
+ }
@@ -0,0 +1,132 @@
1
+ import {
2
+ ClickEvent,
3
+ StartDraggingEvent,
4
+ StopDraggingEvent,
5
+ PointerMoveEvent,
6
+ ModeProps,
7
+ GuideFeatureCollection,
8
+ TentativeFeature,
9
+ } from './types';
10
+ import { Polygon, FeatureCollection, FeatureOf, Position } from '../geojson-types';
11
+ import { GeoJsonEditMode } from './geojson-edit-mode';
12
+
13
+ export class TwoClickPolygonMode extends GeoJsonEditMode {
14
+ handleClick(event: ClickEvent, props: ModeProps<FeatureCollection>) {
15
+ if (props.modeConfig && props.modeConfig.dragToDraw) {
16
+ // handled in drag handlers
17
+ return;
18
+ }
19
+
20
+ this.addClickSequence(event);
21
+
22
+ this.checkAndFinishPolygon(props);
23
+ }
24
+
25
+ handleStartDragging(event: StartDraggingEvent, props: ModeProps<FeatureCollection>): void {
26
+ if (!props.modeConfig || !props.modeConfig.dragToDraw) {
27
+ // handled in click handlers
28
+ return;
29
+ }
30
+
31
+ this.addClickSequence(event);
32
+ event.cancelPan();
33
+ }
34
+
35
+ handleStopDragging(event: StopDraggingEvent, props: ModeProps<FeatureCollection>): void {
36
+ if (!props.modeConfig || !props.modeConfig.dragToDraw) {
37
+ // handled in click handlers
38
+ return;
39
+ }
40
+ this.addClickSequence(event);
41
+
42
+ this.checkAndFinishPolygon(props);
43
+ }
44
+
45
+ checkAndFinishPolygon(props: ModeProps<FeatureCollection>) {
46
+ const clickSequence = this.getClickSequence();
47
+ const tentativeFeature = this.getTentativeGuide(props);
48
+
49
+ if (
50
+ clickSequence.length > 1 &&
51
+ tentativeFeature &&
52
+ tentativeFeature.geometry.type === 'Polygon'
53
+ ) {
54
+ const feature: FeatureOf<Polygon> = {
55
+ type: 'Feature',
56
+ properties: {
57
+ shape: tentativeFeature.properties.shape,
58
+ },
59
+ geometry: {
60
+ type: 'Polygon',
61
+ coordinates: tentativeFeature.geometry.coordinates,
62
+ },
63
+ };
64
+ const editAction = this.getAddFeatureOrBooleanPolygonAction(feature, props);
65
+
66
+ this.resetClickSequence();
67
+
68
+ if (editAction) {
69
+ props.onEdit(editAction);
70
+ }
71
+ }
72
+ }
73
+
74
+ getGuides(props: ModeProps<FeatureCollection>): GuideFeatureCollection {
75
+ const { lastPointerMoveEvent, modeConfig } = props;
76
+ const clickSequence = this.getClickSequence();
77
+
78
+ const guides: GuideFeatureCollection = {
79
+ type: 'FeatureCollection',
80
+ features: [],
81
+ };
82
+
83
+ if (clickSequence.length === 0 || !lastPointerMoveEvent) {
84
+ // nothing to do yet
85
+ return guides;
86
+ }
87
+
88
+ const corner1 = clickSequence[0];
89
+ const corner2 = lastPointerMoveEvent.mapCoords;
90
+
91
+ const polygon = this.getTwoClickPolygon(corner1, corner2, modeConfig);
92
+ if (polygon) {
93
+ guides.features.push({
94
+ type: 'Feature',
95
+ properties: {
96
+ shape: polygon.properties && polygon.properties.shape,
97
+ guideType: 'tentative',
98
+ },
99
+ geometry: polygon.geometry,
100
+ });
101
+ }
102
+
103
+ return guides;
104
+ }
105
+
106
+ getTwoClickPolygon(
107
+ coord1: Position,
108
+ coord2: Position,
109
+ modeConfig: any
110
+ ): FeatureOf<Polygon> | null | undefined {
111
+ return null;
112
+ }
113
+
114
+ handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>) {
115
+ props.onUpdateCursor('cell');
116
+ super.handlePointerMove(event, props);
117
+ }
118
+
119
+ createTentativeFeature(props: ModeProps<FeatureCollection>): TentativeFeature {
120
+ const { lastPointerMoveEvent } = props;
121
+ const clickSequence = this.getClickSequence();
122
+
123
+ const lastCoords = lastPointerMoveEvent ? [lastPointerMoveEvent.mapCoords] : [];
124
+
125
+ let tentativeFeature;
126
+ if (clickSequence.length === 1) {
127
+ tentativeFeature = this.getTwoClickPolygon(clickSequence[0], lastCoords[0], props.modeConfig);
128
+ }
129
+
130
+ return tentativeFeature;
131
+ }
132
+ }