chore: Refactor doBoundsIntersect (#9657)

This commit is contained in:
Márk Tolmács
2025-06-16 12:30:42 +02:00
committed by GitHub
parent 058918f8e5
commit 958597dfaa
8 changed files with 172 additions and 105 deletions

View File

@@ -1,9 +1,6 @@
import { type Bounds } from "@excalidraw/element";
import { isPoint, pointDistance, pointFrom, pointFromVector } from "./point";
import { vector, vectorNormal, vectorNormalize, vectorScale } from "./vector";
import { LegendreGaussN24CValues, LegendreGaussN24TValues } from "./constants";
import { doBoundsIntersect } from "./utils";
import type { Curve, GlobalPoint, LineSegment, LocalPoint } from "./types";
@@ -105,19 +102,6 @@ export const bezierEquation = <Point extends GlobalPoint | LocalPoint>(
export function curveIntersectLineSegment<
Point extends GlobalPoint | LocalPoint,
>(c: Curve<Point>, l: LineSegment<Point>): Point[] {
// Optimize by doing a cheap bounding box check first
const b1 = curveBounds(c);
const b2 = [
Math.min(l[0][0], l[1][0]),
Math.min(l[0][1], l[1][1]),
Math.max(l[0][0], l[1][0]),
Math.max(l[0][1], l[1][1]),
] as Bounds;
if (!doBoundsIntersect(b1, b2)) {
return [];
}
const line = (s: number) =>
pointFrom<Point>(
l[0][0] + s * (l[1][0] - l[0][0]),
@@ -295,15 +279,6 @@ export function curveTangent<Point extends GlobalPoint | LocalPoint>(
);
}
function curveBounds<Point extends GlobalPoint | LocalPoint>(
c: Curve<Point>,
): Bounds {
const [P0, P1, P2, P3] = c;
const x = [P0[0], P1[0], P2[0], P3[0]];
const y = [P0[1], P1[1], P2[1], P3[1]];
return [Math.min(...x), Math.min(...y), Math.max(...x), Math.max(...y)];
}
export function curveCatmullRomQuadraticApproxPoints(
points: GlobalPoint[],
tension = 0.5,

View File

@@ -10,6 +10,12 @@ export function rectangle<P extends GlobalPoint | LocalPoint>(
return [topLeft, bottomRight] as Rectangle<P>;
}
export function rectangleFromNumberSequence<
Point extends LocalPoint | GlobalPoint,
>(minX: number, minY: number, maxX: number, maxY: number) {
return rectangle(pointFrom<Point>(minX, minY), pointFrom<Point>(maxX, maxY));
}
export function rectangleIntersectLineSegment<
Point extends LocalPoint | GlobalPoint,
>(r: Rectangle<Point>, l: LineSegment<Point>): Point[] {
@@ -22,3 +28,12 @@ export function rectangleIntersectLineSegment<
.map((s) => lineSegmentIntersectionPoints(l, s))
.filter((i): i is Point => !!i);
}
export function rectangleIntersectRectangle<
Point extends LocalPoint | GlobalPoint,
>(rectangle1: Rectangle<Point>, rectangle2: Rectangle<Point>): boolean {
const [[minX1, minY1], [maxX1, maxY1]] = rectangle1;
const [[minX2, minY2], [maxX2, maxY2]] = rectangle2;
return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2;
}

View File

@@ -1,5 +1,3 @@
import { type Bounds } from "@excalidraw/element";
export const PRECISION = 10e-5;
export const clamp = (value: number, min: number, max: number) => {
@@ -33,17 +31,3 @@ export const isFiniteNumber = (value: any): value is number => {
export const isCloseTo = (a: number, b: number, precision = PRECISION) =>
Math.abs(a - b) < precision;
export const doBoundsIntersect = (
bounds1: Bounds | null,
bounds2: Bounds | null,
): boolean => {
if (bounds1 == null || bounds2 == null) {
return false;
}
const [minX1, minY1, maxX1, maxY1] = bounds1;
const [minX2, minY2, maxX2, maxY2] = bounds2;
return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2;
};