frigate/web/src/components/settings/PolygonDrawer.tsx

298 lines
7.8 KiB
TypeScript
Raw Normal View History

import {
RefObject,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
Estimated object speed for zones (#16452) * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * fix duplicates from merge * include max_estimated_speed in api responses * add units to zone edit pane * catch undefined * add average speed * clarify docs * only track average speed when object is active * rename vars * ensure points and distances are ordered clockwise * only store the last 10 speeds like score history * remove max estimated speed * update docs * update docs * fix point ordering * improve readability * docs inertia recommendation * fix point ordering * check object frame time * add velocity angle to frontend * docs clarity * add frontend speed filter * fix mqtt docs * fix mqtt docs * don't try to remove distances if they weren't already defined * don't display estimates on debug view/snapshots if object is not in a speed tracking zone * docs * implement speed_threshold for zone presence * docs for threshold * better ground plane image * improve image zone size * add inertia to speed threshold example
2025-02-10 23:23:42 +03:00
import { Line, Circle, Group, Text, Rect } from "react-konva";
import {
minMax,
toRGBColorString,
dragBoundFunc,
flattenPoints,
} from "@/utils/canvasUtil";
import type { KonvaEventObject } from "konva/lib/Node";
import Konva from "konva";
import { Vector2d } from "konva/lib/types";
type PolygonDrawerProps = {
stageRef: RefObject<Konva.Stage>;
points: number[][];
Estimated object speed for zones (#16452) * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * fix duplicates from merge * include max_estimated_speed in api responses * add units to zone edit pane * catch undefined * add average speed * clarify docs * only track average speed when object is active * rename vars * ensure points and distances are ordered clockwise * only store the last 10 speeds like score history * remove max estimated speed * update docs * update docs * fix point ordering * improve readability * docs inertia recommendation * fix point ordering * check object frame time * add velocity angle to frontend * docs clarity * add frontend speed filter * fix mqtt docs * fix mqtt docs * don't try to remove distances if they weren't already defined * don't display estimates on debug view/snapshots if object is not in a speed tracking zone * docs * implement speed_threshold for zone presence * docs for threshold * better ground plane image * improve image zone size * add inertia to speed threshold example
2025-02-10 23:23:42 +03:00
distances: number[];
isActive: boolean;
isHovered: boolean;
isFinished: boolean;
color: number[];
handlePointDragMove: (e: KonvaEventObject<MouseEvent | TouchEvent>) => void;
handleGroupDragEnd: (e: KonvaEventObject<MouseEvent | TouchEvent>) => void;
Estimated object speed for zones (#16452) * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * fix duplicates from merge * include max_estimated_speed in api responses * add units to zone edit pane * catch undefined * add average speed * clarify docs * only track average speed when object is active * rename vars * ensure points and distances are ordered clockwise * only store the last 10 speeds like score history * remove max estimated speed * update docs * update docs * fix point ordering * improve readability * docs inertia recommendation * fix point ordering * check object frame time * add velocity angle to frontend * docs clarity * add frontend speed filter * fix mqtt docs * fix mqtt docs * don't try to remove distances if they weren't already defined * don't display estimates on debug view/snapshots if object is not in a speed tracking zone * docs * implement speed_threshold for zone presence * docs for threshold * better ground plane image * improve image zone size * add inertia to speed threshold example
2025-02-10 23:23:42 +03:00
activeLine?: number;
snapToLines: (point: number[]) => number[] | null;
snapPoints: boolean;
};
export default function PolygonDrawer({
stageRef,
points,
Estimated object speed for zones (#16452) * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * fix duplicates from merge * include max_estimated_speed in api responses * add units to zone edit pane * catch undefined * add average speed * clarify docs * only track average speed when object is active * rename vars * ensure points and distances are ordered clockwise * only store the last 10 speeds like score history * remove max estimated speed * update docs * update docs * fix point ordering * improve readability * docs inertia recommendation * fix point ordering * check object frame time * add velocity angle to frontend * docs clarity * add frontend speed filter * fix mqtt docs * fix mqtt docs * don't try to remove distances if they weren't already defined * don't display estimates on debug view/snapshots if object is not in a speed tracking zone * docs * implement speed_threshold for zone presence * docs for threshold * better ground plane image * improve image zone size * add inertia to speed threshold example
2025-02-10 23:23:42 +03:00
distances,
isActive,
isHovered,
isFinished,
color,
handlePointDragMove,
handleGroupDragEnd,
Estimated object speed for zones (#16452) * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * fix duplicates from merge * include max_estimated_speed in api responses * add units to zone edit pane * catch undefined * add average speed * clarify docs * only track average speed when object is active * rename vars * ensure points and distances are ordered clockwise * only store the last 10 speeds like score history * remove max estimated speed * update docs * update docs * fix point ordering * improve readability * docs inertia recommendation * fix point ordering * check object frame time * add velocity angle to frontend * docs clarity * add frontend speed filter * fix mqtt docs * fix mqtt docs * don't try to remove distances if they weren't already defined * don't display estimates on debug view/snapshots if object is not in a speed tracking zone * docs * implement speed_threshold for zone presence * docs for threshold * better ground plane image * improve image zone size * add inertia to speed threshold example
2025-02-10 23:23:42 +03:00
activeLine,
snapToLines,
snapPoints,
}: PolygonDrawerProps) {
const vertexRadius = 6;
const flattenedPoints = useMemo(() => flattenPoints(points), [points]);
const [minMaxX, setMinMaxX] = useState([0, 0]);
const [minMaxY, setMinMaxY] = useState([0, 0]);
const groupRef = useRef<Konva.Group>(null);
const [cursor, setCursor] = useState("default");
const handleMouseOverPoint = (
e: KonvaEventObject<MouseEvent | TouchEvent>,
) => {
if (!e.target) return;
if (!isFinished && points.length >= 3 && e.target.name() === "point-0") {
e.target.scale({ x: 2, y: 2 });
setCursor("crosshair");
} else {
setCursor("move");
}
};
const handleMouseOutPoint = (
e: KonvaEventObject<MouseEvent | TouchEvent>,
) => {
if (!e.target) return;
if (isFinished) {
setCursor("default");
} else {
setCursor("crosshair");
}
if (e.target.name() === "point-0") {
e.target.scale({ x: 1, y: 1 });
}
};
const handleGroupDragStart = () => {
const arrX = points.map((p) => p[0]);
const arrY = points.map((p) => p[1]);
setMinMaxX(minMax(arrX));
setMinMaxY(minMax(arrY));
};
const groupDragBound = (pos: Vector2d) => {
if (!stageRef.current) {
return pos;
}
let { x, y } = pos;
const sw = stageRef.current.width();
const sh = stageRef.current.height();
if (minMaxY[0] + y < 0) y = -1 * minMaxY[0];
if (minMaxX[0] + x < 0) x = -1 * minMaxX[0];
if (minMaxY[1] + y > sh) y = sh - minMaxY[1];
if (minMaxX[1] + x > sw) x = sw - minMaxX[1];
return { x, y };
};
const colorString = useCallback(
(darkened: boolean) => {
return toRGBColorString(color, darkened);
},
[color],
);
useEffect(() => {
if (!stageRef.current) {
return;
}
stageRef.current.container().style.cursor = cursor;
}, [stageRef, cursor]);
Estimated object speed for zones (#16452) * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * fix duplicates from merge * include max_estimated_speed in api responses * add units to zone edit pane * catch undefined * add average speed * clarify docs * only track average speed when object is active * rename vars * ensure points and distances are ordered clockwise * only store the last 10 speeds like score history * remove max estimated speed * update docs * update docs * fix point ordering * improve readability * docs inertia recommendation * fix point ordering * check object frame time * add velocity angle to frontend * docs clarity * add frontend speed filter * fix mqtt docs * fix mqtt docs * don't try to remove distances if they weren't already defined * don't display estimates on debug view/snapshots if object is not in a speed tracking zone * docs * implement speed_threshold for zone presence * docs for threshold * better ground plane image * improve image zone size * add inertia to speed threshold example
2025-02-10 23:23:42 +03:00
// Calculate midpoints for distance labels based on sorted points
const midpoints = useMemo(() => {
const midpointsArray = [];
for (let i = 0; i < points.length; i++) {
const p1 = points[i];
const p2 = points[(i + 1) % points.length];
const midpointX = (p1[0] + p2[0]) / 2;
const midpointY = (p1[1] + p2[1]) / 2;
midpointsArray.push([midpointX, midpointY]);
}
return midpointsArray;
}, [points]);
// Determine the points for the active line
const activeLinePoints = useMemo(() => {
if (
activeLine === undefined ||
activeLine < 1 ||
activeLine > points.length
) {
return [];
}
const p1 = points[activeLine - 1];
const p2 = points[activeLine % points.length];
return [p1[0], p1[1], p2[0], p2[1]];
}, [activeLine, points]);
return (
<Group
name="polygon"
ref={groupRef}
draggable={isActive && isFinished}
onDragStart={isActive ? handleGroupDragStart : undefined}
onDragEnd={isActive ? handleGroupDragEnd : undefined}
dragBoundFunc={isActive ? groupDragBound : undefined}
>
<Line
name="filled-line"
points={flattenedPoints}
stroke={colorString(true)}
strokeWidth={3}
hitStrokeWidth={12}
closed={isFinished}
fill={colorString(isActive || isHovered ? true : false)}
onMouseOver={() =>
isActive
? isFinished
? setCursor("move")
: setCursor("crosshair")
: setCursor("default")
}
onMouseOut={() =>
isActive
? isFinished
? setCursor("default")
: setCursor("crosshair")
: setCursor("default")
}
/>
{isFinished && isActive && (
<Line
name="unfilled-line"
points={flattenedPoints}
hitStrokeWidth={12}
closed={isFinished}
fillEnabled={false}
onMouseOver={() => setCursor("crosshair")}
onMouseOut={() =>
isFinished ? setCursor("default") : setCursor("crosshair")
}
/>
)}
Estimated object speed for zones (#16452) * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * fix duplicates from merge * include max_estimated_speed in api responses * add units to zone edit pane * catch undefined * add average speed * clarify docs * only track average speed when object is active * rename vars * ensure points and distances are ordered clockwise * only store the last 10 speeds like score history * remove max estimated speed * update docs * update docs * fix point ordering * improve readability * docs inertia recommendation * fix point ordering * check object frame time * add velocity angle to frontend * docs clarity * add frontend speed filter * fix mqtt docs * fix mqtt docs * don't try to remove distances if they weren't already defined * don't display estimates on debug view/snapshots if object is not in a speed tracking zone * docs * implement speed_threshold for zone presence * docs for threshold * better ground plane image * improve image zone size * add inertia to speed threshold example
2025-02-10 23:23:42 +03:00
{isActive && activeLinePoints.length > 0 && (
<Line
points={activeLinePoints}
stroke="white"
strokeWidth={6}
hitStrokeWidth={12}
/>
)}
{points.map((point, index) => {
if (!isActive) {
return;
}
const x = point[0];
const y = point[1];
return (
<Circle
key={index}
name={`point-${index}`}
x={x}
y={y}
radius={vertexRadius}
stroke={colorString(true)}
fill="#ffffff"
strokeWidth={3}
hitStrokeWidth={index === 0 ? 12 : 9}
onMouseOver={handleMouseOverPoint}
onMouseOut={handleMouseOutPoint}
draggable={isActive}
onDragMove={(e) => {
if (isActive) {
if (snapPoints) {
const snappedPos = snapToLines([e.target.x(), e.target.y()]);
if (snappedPos) {
e.target.position({ x: snappedPos[0], y: snappedPos[1] });
}
}
handlePointDragMove(e);
}
}}
dragBoundFunc={(pos) => {
if (stageRef.current) {
const boundPos = dragBoundFunc(
stageRef.current.width(),
stageRef.current.height(),
vertexRadius,
pos,
);
if (snapPoints) {
const snappedPos = snapToLines([boundPos.x, boundPos.y]);
return snappedPos
? { x: snappedPos[0], y: snappedPos[1] }
: boundPos;
}
return boundPos;
} else {
return pos;
}
}}
/>
);
})}
Estimated object speed for zones (#16452) * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * utility functions * backend config * backend object speed tracking * draw speed on debug view * basic frontend zone editor * remove line sorting * fix types * highlight line on canvas when entering value in zone edit pane * rename vars and add validation * ensure speed estimation is disabled when user adds more than 4 points * pixel velocity in debug * unit_system in config * ability to define unit system in config * save max speed to db * frontend * docs * clarify docs * fix duplicates from merge * include max_estimated_speed in api responses * add units to zone edit pane * catch undefined * add average speed * clarify docs * only track average speed when object is active * rename vars * ensure points and distances are ordered clockwise * only store the last 10 speeds like score history * remove max estimated speed * update docs * update docs * fix point ordering * improve readability * docs inertia recommendation * fix point ordering * check object frame time * add velocity angle to frontend * docs clarity * add frontend speed filter * fix mqtt docs * fix mqtt docs * don't try to remove distances if they weren't already defined * don't display estimates on debug view/snapshots if object is not in a speed tracking zone * docs * implement speed_threshold for zone presence * docs for threshold * better ground plane image * improve image zone size * add inertia to speed threshold example
2025-02-10 23:23:42 +03:00
{isFinished && (
<Group>
{midpoints.map((midpoint, index) => {
const [x, y] = midpoint;
const distance = distances[index];
if (distance === undefined) return null;
const squareSize = 22;
return (
<Group
key={`distance-group-${index}`}
x={x - squareSize / 2}
y={y - squareSize / 2}
>
<Rect
width={squareSize}
height={squareSize}
fill={colorString(true)}
stroke="white"
strokeWidth={1}
/>
<Text
text={`${distance}`}
width={squareSize}
y={4}
fontSize={16}
fontFamily="Arial"
fill="white"
align="center"
verticalAlign="middle"
/>
</Group>
);
})}
</Group>
)}
</Group>
);
}