From d6dfa596de22518b493a29fd6bbf90a948c546a2 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Fri, 19 Apr 2024 08:59:28 -0500 Subject: [PATCH] undo points based on order added to polygon (#11035) --- web/src/components/settings/PolygonCanvas.tsx | 82 +++++++++---------- .../settings/PolygonEditControls.tsx | 31 +++++-- web/src/types/canvas.ts | 2 +- 3 files changed, 64 insertions(+), 51 deletions(-) diff --git a/web/src/components/settings/PolygonCanvas.tsx b/web/src/components/settings/PolygonCanvas.tsx index 22c23a226..d21ef01bf 100644 --- a/web/src/components/settings/PolygonCanvas.tsx +++ b/web/src/components/settings/PolygonCanvas.tsx @@ -61,9 +61,20 @@ export function PolygonCanvas({ const addPointToPolygon = (polygon: Polygon, newPoint: number[]) => { const points = polygon.points; + const pointsOrder = polygon.pointsOrder; + const [newPointX, newPointY] = newPoint; const updatedPoints = [...points]; + let updatedPointsOrder: number[]; + if (!pointsOrder) { + updatedPointsOrder = []; + } else { + updatedPointsOrder = [...pointsOrder]; + } + + let insertIndex = points.length; + for (let i = 0; i < points.length; i++) { const [x1, y1] = points[i]; const [x2, y2] = i === points.length - 1 ? points[0] : points[i + 1]; @@ -76,48 +87,16 @@ export function PolygonCanvas({ (y1 <= newPointY && newPointY <= y2) || (y2 <= newPointY && newPointY <= y1) ) { - const insertIndex = i + 1; - updatedPoints.splice(insertIndex, 0, [newPointX, newPointY]); + insertIndex = i + 1; break; } } } - return updatedPoints; - }; + updatedPoints.splice(insertIndex, 0, [newPointX, newPointY]); + updatedPointsOrder.splice(insertIndex, 0, updatedPoints.length); - const isPointNearLineSegment = ( - polygon: Polygon, - mousePos: number[], - radius = 10, - ) => { - const points = polygon.points; - const [x, y] = mousePos; - - for (let i = 0; i < points.length; i++) { - const [x1, y1] = points[i]; - const [x2, y2] = i === points.length - 1 ? points[0] : points[i + 1]; - - const crossProduct = (x - x1) * (x2 - x1) + (y - y1) * (y2 - y1); - if (crossProduct > 0) { - const lengthSquared = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); - const dot = (x - x1) * (x2 - x1) + (y - y1) * (y2 - y1); - if (dot < 0 || dot > lengthSquared) { - continue; - } - const lineSegmentDistance = Math.abs( - ((y2 - y1) * x - (x2 - x1) * y + x2 * y1 - y2 * x1) / - Math.sqrt(Math.pow(y2 - y1, 2) + Math.pow(x2 - x1, 2)), - ); - if (lineSegmentDistance <= radius) { - const midPointX = (x1 + x2) / 2; - const midPointY = (y1 + y2) / 2; - return [midPointX, midPointY]; - } - } - } - - return null; + return { updatedPoints, updatedPointsOrder }; }; const isMouseOverFirstPoint = (polygon: Polygon, mousePos: number[]) => { @@ -176,18 +155,15 @@ export function PolygonCanvas({ !activePolygon.isFinished && !isMouseOverAnyPoint(activePolygon, mousePos) ) { - let updatedPoints; + const { updatedPoints, updatedPointsOrder } = addPointToPolygon( + activePolygon, + mousePos, + ); - if (isPointNearLineSegment(activePolygon, mousePos)) { - // we've clicked near a line segment, so add a new point in the right position - updatedPoints = addPointToPolygon(activePolygon, mousePos); - } else { - // Add a new point to the active polygon - updatedPoints = [...activePolygon.points, mousePos]; - } updatedPolygons[activePolygonIndex] = { ...activePolygon, points: updatedPoints, + pointsOrder: updatedPointsOrder, }; setPolygons(updatedPolygons); } @@ -318,6 +294,24 @@ export function PolygonCanvas({ e.target.getStage()!.container().style.cursor = "crosshair"; }; + useEffect(() => { + if (activePolygonIndex === undefined || !polygons) { + return; + } + + const updatedPolygons = [...polygons]; + const activePolygon = updatedPolygons[activePolygonIndex]; + + // add default points order for already completed polygons + if (!activePolygon.pointsOrder && activePolygon.isFinished) { + updatedPolygons[activePolygonIndex] = { + ...activePolygon, + pointsOrder: activePolygon.points.map((_, index) => index), + }; + setPolygons(updatedPolygons); + } + }, [activePolygonIndex, polygons, setPolygons]); + return ( 0 && + activePolygon.pointsOrder && + activePolygon.pointsOrder.length > 0 + ) { + const lastPointOrderIndex = activePolygon.pointsOrder.indexOf( + Math.max(...activePolygon.pointsOrder), + ); + + updatedPolygons[activePolygonIndex] = { + ...activePolygon, + points: [ + ...activePolygon.points.slice(0, lastPointOrderIndex), + ...activePolygon.points.slice(lastPointOrderIndex + 1), + ], + pointsOrder: [ + ...activePolygon.pointsOrder.slice(0, lastPointOrderIndex), + ...activePolygon.pointsOrder.slice(lastPointOrderIndex + 1), + ], + isFinished: false, + }; + + setPolygons(updatedPolygons); + } }; const reset = () => { diff --git a/web/src/types/canvas.ts b/web/src/types/canvas.ts index 5eb04e98f..4fcf8a46a 100644 --- a/web/src/types/canvas.ts +++ b/web/src/types/canvas.ts @@ -7,8 +7,8 @@ export type Polygon = { type: PolygonType; objects: string[]; points: number[][]; + pointsOrder?: number[]; isFinished: boolean; - // isUnsaved: boolean; color: number[]; };