From 7af6a23604c6d62fd0b1b30f762617b0181fae22 Mon Sep 17 00:00:00 2001 From: Derick M <58572875+TurtIeSocks@users.noreply.github.com> Date: Thu, 25 Jul 2024 09:13:11 -0400 Subject: [PATCH 1/6] feat: export feature cutouts --- client/src/pages/map/popups/Polygon.tsx | 18 ++++++++++- client/src/services/geoUtils.ts | 40 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/client/src/pages/map/popups/Polygon.tsx b/client/src/pages/map/popups/Polygon.tsx index 1336f30f..521ee0a7 100644 --- a/client/src/pages/map/popups/Polygon.tsx +++ b/client/src/pages/map/popups/Polygon.tsx @@ -41,7 +41,11 @@ import { splitMultiPolygons, } from '@services/utils' import { useImportExport } from '@hooks/useImportExport' -import { filterPoints, filterPolys } from '@services/geoUtils' +import { + filterPoints, + filterPolys, + getFeatureCutouts, +} from '@services/geoUtils' import { usePersist } from '@hooks/usePersist' const { add, remove, updateProperty } = useShapes.getState().setters @@ -312,6 +316,18 @@ export function PolygonPopup({ > Export + { + useImportExport.setState({ + feature: getFeatureCutouts(feature), + open: 'exportPolygon', + }) + handleClose() + }} + > + Export Cutouts + { diff --git a/client/src/services/geoUtils.ts b/client/src/services/geoUtils.ts index 744b8a5e..3c6717d0 100644 --- a/client/src/services/geoUtils.ts +++ b/client/src/services/geoUtils.ts @@ -105,3 +105,43 @@ export function filterPolys( remove(value.geometry.type, key) }) } + +export function getFeatureCutouts( + feature: Feature, +): Feature { + const polygons: Polygon[] = [] + + if (feature.geometry.type === 'Polygon') { + feature.geometry.coordinates.forEach((polygon, i) => { + if (i > 0) { + polygons.push({ + type: 'Polygon', + coordinates: [polygon], + }) + } + }) + } else if (feature.geometry.type === 'MultiPolygon') { + feature.geometry.coordinates.forEach((multi) => { + multi.forEach((polygon, i) => { + if (i > 0) { + polygons.push({ + type: 'Polygon', + coordinates: [polygon], + }) + } + }) + }) + } + return { + type: 'Feature', + id: `${feature.id}-cutouts`, + properties: feature.properties, + geometry: + polygons.length > 1 + ? { + type: 'MultiPolygon', + coordinates: polygons.map((p) => p.coordinates), + } + : polygons[0], + } +} From 9bab2beb14d0c16573be0112a1ea655cff1fe85b Mon Sep 17 00:00:00 2001 From: Derick M <58572875+TurtIeSocks@users.noreply.github.com> Date: Thu, 25 Jul 2024 09:33:19 -0400 Subject: [PATCH 2/6] refactor: clean up code --- client/src/services/geoUtils.ts | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/client/src/services/geoUtils.ts b/client/src/services/geoUtils.ts index 3c6717d0..c1a86e43 100644 --- a/client/src/services/geoUtils.ts +++ b/client/src/services/geoUtils.ts @@ -111,27 +111,19 @@ export function getFeatureCutouts( ): Feature { const polygons: Polygon[] = [] - if (feature.geometry.type === 'Polygon') { - feature.geometry.coordinates.forEach((polygon, i) => { - if (i > 0) { - polygons.push({ - type: 'Polygon', - coordinates: [polygon], - }) - } + const push = (positions: Position[], index: number) => + index > 0 && + polygons.push({ + type: 'Polygon', + coordinates: [positions], }) + + if (feature.geometry.type === 'Polygon') { + feature.geometry.coordinates.forEach(push) } else if (feature.geometry.type === 'MultiPolygon') { - feature.geometry.coordinates.forEach((multi) => { - multi.forEach((polygon, i) => { - if (i > 0) { - polygons.push({ - type: 'Polygon', - coordinates: [polygon], - }) - } - }) - }) + feature.geometry.coordinates.forEach((multi) => multi.forEach(push)) } + return { type: 'Feature', id: `${feature.id}-cutouts`, From ffe00405f48c34a3c5c8431801247362d94cd31d Mon Sep 17 00:00:00 2001 From: Derick M <58572875+TurtIeSocks@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:19:59 -0400 Subject: [PATCH 3/6] fix: handling for features without cutouts --- client/src/pages/map/popups/Polygon.tsx | 5 +++++ client/src/services/geoUtils.ts | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/client/src/pages/map/popups/Polygon.tsx b/client/src/pages/map/popups/Polygon.tsx index 521ee0a7..c21bddcc 100644 --- a/client/src/pages/map/popups/Polygon.tsx +++ b/client/src/pages/map/popups/Polygon.tsx @@ -318,6 +318,11 @@ export function PolygonPopup({ c.length < 2) + : feature.geometry.coordinates.length < 2 + } onClick={() => { useImportExport.setState({ feature: getFeatureCutouts(feature), diff --git a/client/src/services/geoUtils.ts b/client/src/services/geoUtils.ts index c1a86e43..32ddb1a3 100644 --- a/client/src/services/geoUtils.ts +++ b/client/src/services/geoUtils.ts @@ -134,6 +134,9 @@ export function getFeatureCutouts( type: 'MultiPolygon', coordinates: polygons.map((p) => p.coordinates), } - : polygons[0], + : polygons[0] || { + type: '', + coordinates: [], + }, } } From a3ca08e564cdf5140808c71e0a7e8c4cd64c0ec9 Mon Sep 17 00:00:00 2001 From: Derick M <58572875+TurtIeSocks@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:38:01 -0400 Subject: [PATCH 4/6] fix: option to enable or disable cutouts on merge --- client/src/components/drawer/Drawing.tsx | 1 + client/src/hooks/usePersist.ts | 2 ++ client/src/hooks/useShapes.ts | 13 +++++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/client/src/components/drawer/Drawing.tsx b/client/src/components/drawer/Drawing.tsx index cb60ec80..71ff930e 100644 --- a/client/src/components/drawer/Drawing.tsx +++ b/client/src/components/drawer/Drawing.tsx @@ -17,6 +17,7 @@ export default function DrawingTab() { Drawing + ((set, get) => ({ MultiPolygon, setters: { remove, add }, } = get() + const { keepCutoutsOnMerge } = usePersist.getState() + let newPoly: Feature = { geometry: { type: 'MultiPolygon', coordinates: [] }, type: 'Feature', @@ -329,8 +332,14 @@ export const useShapes = create((set, get) => ({ } } }) - if (newPoly.geometry.type === 'Polygon') { - newPoly.geometry.coordinates = [newPoly.geometry.coordinates[0]] + if (!keepCutoutsOnMerge) { + if (newPoly.geometry.type === 'Polygon') { + newPoly.geometry.coordinates = [newPoly.geometry.coordinates[0]] + } else if (newPoly.geometry.type === 'MultiPolygon') { + newPoly.geometry.coordinates = newPoly.geometry.coordinates.map( + (p) => [p[0]], + ) + } } Object.entries( all From 5b5c8bf62453c9f89f083a9b04413a2c544131b1 Mon Sep 17 00:00:00 2001 From: Derick M <58572875+TurtIeSocks@users.noreply.github.com> Date: Tue, 30 Jul 2024 13:15:36 -0400 Subject: [PATCH 5/6] refactor: `Create Shape from Cutouts` --- client/src/pages/map/popups/Polygon.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/client/src/pages/map/popups/Polygon.tsx b/client/src/pages/map/popups/Polygon.tsx index c21bddcc..66a45bd7 100644 --- a/client/src/pages/map/popups/Polygon.tsx +++ b/client/src/pages/map/popups/Polygon.tsx @@ -324,14 +324,11 @@ export function PolygonPopup({ : feature.geometry.coordinates.length < 2 } onClick={() => { - useImportExport.setState({ - feature: getFeatureCutouts(feature), - open: 'exportPolygon', - }) + add(getFeatureCutouts(feature)) handleClose() }} > - Export Cutouts + Create Shape from Cutouts Date: Tue, 30 Jul 2024 13:21:40 -0400 Subject: [PATCH 6/6] chore: client version bump --- client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/package.json b/client/package.json index 8a1e5055..9c9284f5 100644 --- a/client/package.json +++ b/client/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "koji", - "version": "1.3.14", + "version": "1.4.0", "description": "Tool to make RDM routes", "main": "server/dist/index.js", "author": "TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>",