mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
undo points based on order added to polygon (#11035)
This commit is contained in:
parent
5f15641b1b
commit
d6dfa596de
@ -61,9 +61,20 @@ export function PolygonCanvas({
|
|||||||
|
|
||||||
const addPointToPolygon = (polygon: Polygon, newPoint: number[]) => {
|
const addPointToPolygon = (polygon: Polygon, newPoint: number[]) => {
|
||||||
const points = polygon.points;
|
const points = polygon.points;
|
||||||
|
const pointsOrder = polygon.pointsOrder;
|
||||||
|
|
||||||
const [newPointX, newPointY] = newPoint;
|
const [newPointX, newPointY] = newPoint;
|
||||||
const updatedPoints = [...points];
|
const updatedPoints = [...points];
|
||||||
|
|
||||||
|
let updatedPointsOrder: number[];
|
||||||
|
if (!pointsOrder) {
|
||||||
|
updatedPointsOrder = [];
|
||||||
|
} else {
|
||||||
|
updatedPointsOrder = [...pointsOrder];
|
||||||
|
}
|
||||||
|
|
||||||
|
let insertIndex = points.length;
|
||||||
|
|
||||||
for (let i = 0; i < points.length; i++) {
|
for (let i = 0; i < points.length; i++) {
|
||||||
const [x1, y1] = points[i];
|
const [x1, y1] = points[i];
|
||||||
const [x2, y2] = i === points.length - 1 ? points[0] : points[i + 1];
|
const [x2, y2] = i === points.length - 1 ? points[0] : points[i + 1];
|
||||||
@ -76,48 +87,16 @@ export function PolygonCanvas({
|
|||||||
(y1 <= newPointY && newPointY <= y2) ||
|
(y1 <= newPointY && newPointY <= y2) ||
|
||||||
(y2 <= newPointY && newPointY <= y1)
|
(y2 <= newPointY && newPointY <= y1)
|
||||||
) {
|
) {
|
||||||
const insertIndex = i + 1;
|
insertIndex = i + 1;
|
||||||
updatedPoints.splice(insertIndex, 0, [newPointX, newPointY]);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return updatedPoints;
|
updatedPoints.splice(insertIndex, 0, [newPointX, newPointY]);
|
||||||
};
|
updatedPointsOrder.splice(insertIndex, 0, updatedPoints.length);
|
||||||
|
|
||||||
const isPointNearLineSegment = (
|
return { updatedPoints, updatedPointsOrder };
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const isMouseOverFirstPoint = (polygon: Polygon, mousePos: number[]) => {
|
const isMouseOverFirstPoint = (polygon: Polygon, mousePos: number[]) => {
|
||||||
@ -176,18 +155,15 @@ export function PolygonCanvas({
|
|||||||
!activePolygon.isFinished &&
|
!activePolygon.isFinished &&
|
||||||
!isMouseOverAnyPoint(activePolygon, mousePos)
|
!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] = {
|
updatedPolygons[activePolygonIndex] = {
|
||||||
...activePolygon,
|
...activePolygon,
|
||||||
points: updatedPoints,
|
points: updatedPoints,
|
||||||
|
pointsOrder: updatedPointsOrder,
|
||||||
};
|
};
|
||||||
setPolygons(updatedPolygons);
|
setPolygons(updatedPolygons);
|
||||||
}
|
}
|
||||||
@ -318,6 +294,24 @@ export function PolygonCanvas({
|
|||||||
e.target.getStage()!.container().style.cursor = "crosshair";
|
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 (
|
return (
|
||||||
<Stage
|
<Stage
|
||||||
ref={stageRef}
|
ref={stageRef}
|
||||||
|
@ -21,12 +21,31 @@ export default function PolygonEditControls({
|
|||||||
|
|
||||||
const updatedPolygons = [...polygons];
|
const updatedPolygons = [...polygons];
|
||||||
const activePolygon = updatedPolygons[activePolygonIndex];
|
const activePolygon = updatedPolygons[activePolygonIndex];
|
||||||
updatedPolygons[activePolygonIndex] = {
|
|
||||||
...activePolygon,
|
if (
|
||||||
points: [...activePolygon.points.slice(0, -1)],
|
activePolygon.points.length > 0 &&
|
||||||
isFinished: false,
|
activePolygon.pointsOrder &&
|
||||||
};
|
activePolygon.pointsOrder.length > 0
|
||||||
setPolygons(updatedPolygons);
|
) {
|
||||||
|
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 = () => {
|
const reset = () => {
|
||||||
|
@ -7,8 +7,8 @@ export type Polygon = {
|
|||||||
type: PolygonType;
|
type: PolygonType;
|
||||||
objects: string[];
|
objects: string[];
|
||||||
points: number[][];
|
points: number[][];
|
||||||
|
pointsOrder?: number[];
|
||||||
isFinished: boolean;
|
isFinished: boolean;
|
||||||
// isUnsaved: boolean;
|
|
||||||
color: number[];
|
color: number[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user