import { Vec } from '@tldraw/vec' export type TLIntersection = { didIntersect: boolean message: string points: number[][] } export interface TLBounds { minX: number minY: number maxX: number maxY: number width: number height: number rotation?: number } /** * Get an intersection. * @param message * @param points * @internal */ function createIntersection(message: string, ...points: number[][]): TLIntersection { const didIntersect = points.length > 0 return { didIntersect, message, points } } /** * * @param point * @param size * @param rotation * @internal */ function getRectangleSides(point: number[], size: number[], rotation = 0): [string, number[][]][] { const center = [point[0] + size[0] / 2, point[1] + size[1] / 2] const tl = Vec.rotWith(point, center, rotation) const tr = Vec.rotWith(Vec.add(point, [size[0], 0]), center, rotation) const br = Vec.rotWith(Vec.add(point, size), center, rotation) const bl = Vec.rotWith(Vec.add(point, [0, size[1]]), center, rotation) return [ ['top', [tl, tr]], ['right', [tr, br]], ['bottom', [br, bl]], ['left', [bl, tl]], ] } /** * Get whether angle c lies between angles a and b. * @param a * @param b * @param c * @internal */ function isAngleBetween(a: number, b: number, c: number): boolean { if (c === a || c === b) return true const PI2 = Math.PI * 2 const AB = (b - a + PI2) % PI2 const AC = (c - a + PI2) % PI2 return AB <= Math.PI !== AC > AB } /* -------------------------------------------------- */ /* Ray */ /* -------------------------------------------------- */ /** * Find the intersection between a ray and a ray. * @param p0 The first ray's point * @param n0 The first ray's direction vector. * @param p1 The second ray's point. * @param n1 The second ray's direction vector. */ export function intersectRayRay( p0: number[], n0: number[], p1: number[], n1: number[] ): TLIntersection { const dx = p1[0] - p0[0] const dy = p1[1] - p0[1] const det = n1[0] * n0[1] - n1[1] * n0[0] const u = (dy * n1[0] - dx * n1[1]) / det const v = (dy * n0[0] - dx * n0[1]) / det if (u < 0 || v < 0) return createIntersection('miss') const m0 = n0[1] / n0[0] const m1 = n1[1] / n1[0] const b0 = p0[1] - m0 * p0[0] const b1 = p1[1] - m1 * p1[0] const x = (b1 - b0) / (m0 - m1) const y = m0 * x + b0 return Number.isFinite(x) ? createIntersection('intersection', [x, y]) : createIntersection('parallel') } /** * Find the intersections between a ray and a line segment. * @param origin * @param direction * @param a1 * @param a2 */ export function intersectRayLineSegment( origin: number[], direction: number[], a1: number[], a2: number[] ): TLIntersection { const [x, y] = origin const [dx, dy] = direction const [x1, y1] = a1 const [x2, y2] = a2 if (dy / dx !== (y2 - y1) / (x2 - x1)) { const d = dx * (y2 - y1) - dy * (x2 - x1) if (d !== 0) { const r = ((y - y1) * (x2 - x1) - (x - x1) * (y2 - y1)) / d const s = ((y - y1) * dx - (x - x1) * dy) / d if (r >= 0 && s >= 0 && s <= 1) { return createIntersection('intersection', [x + r * dx, y + r * dy]) } } } return createIntersection('no intersection') } /** * Find the intersections between a ray and a rectangle. * @param origin * @param direction * @param point * @param size * @param rotation */ export function intersectRayRectangle( origin: number[], direction: number[], point: number[], size: number[], rotation = 0 ): TLIntersection[] { return intersectRectangleRay(point, size, rotation, origin, direction) } /** * Find the intersections between a ray and an ellipse. * @param origin * @param direction * @param center * @param rx * @param ry * @param rotation */ export function intersectRayEllipse( origin: number[], direction: number[], center: number[], rx: number, ry: number, rotation: number ): TLIntersection { const a1 = origin const a2 = Vec.mul(direction, 999999999) return intersectLineSegmentEllipse(a1, a2, center, rx, ry, rotation) } /** * Find the intersections between a ray and a bounding box. * @param origin * @param direction * @param bounds * @param rotation */ export function intersectRayBounds( origin: number[], direction: number[], bounds: TLBounds, rotation = 0 ): TLIntersection[] { const { minX, minY, width, height } = bounds return intersectRayRectangle(origin, direction, [minX, minY], [width, height], rotation) } /* -------------------------------------------------- */ /* Line Segment */ /* -------------------------------------------------- */ /** * Find the intersection between a line segment and a ray. * @param a1 * @param a2 * @param origin * @param direction */ export function intersectLineSegmentRay( a1: number[], a2: number[], origin: number[], direction: number[] ): TLIntersection { return intersectRayLineSegment(origin, direction, a1, a2) } /** * Find the intersection between a line segment and a line segment. * @param a1 * @param a2 * @param b1 * @param b2 */ export function intersectLineSegmentLineSegment( a1: number[], a2: number[], b1: number[], b2: number[] ): TLIntersection { const AB = Vec.sub(a1, b1) const BV = Vec.sub(b2, b1) const AV = Vec.sub(a2, a1) const ua_t = BV[0] * AB[1] - BV[1] * AB[0] const ub_t = AV[0] * AB[1] - AV[1] * AB[0] const u_b = BV[1] * AV[0] - BV[0] * AV[1] if (ua_t === 0 || ub_t === 0) { return createIntersection('coincident') } if (u_b === 0) { return createIntersection('parallel') } if (u_b !== 0) { const ua = ua_t / u_b const ub = ub_t / u_b if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { return createIntersection('intersection', Vec.add(a1, Vec.mul(AV, ua))) } } return createIntersection('no intersection') } /** * Find the intersections between a line segment and a rectangle. * @param a1 * @param a2 * @param point * @param size */ export function intersectLineSegmentRectangle( a1: number[], a2: number[], point: number[], size: number[] ): TLIntersection[] { return intersectRectangleLineSegment(point, size, a1, a2) } /** * Find the intersections between a line segment and an arc. * @param a1 * @param a2 * @param center * @param radius * @param start * @param end */ export function intersectLineSegmentArc( a1: number[], a2: number[], center: number[], radius: number, start: number[], end: number[] ): TLIntersection { const sa = Vec.angle(center, start) const ea = Vec.angle(center, end) const ellipseTest = intersectEllipseLineSegment(center, radius, radius, 0, a1, a2) if (!ellipseTest.didIntersect) return createIntersection('no intersection') const points = ellipseTest.points.filter((point) => isAngleBetween(sa, ea, Vec.angle(center, point)) ) if (points.length === 0) { return createIntersection('no intersection') } return createIntersection('intersection', ...points) } /** * Find the intersections between a line segment and a circle. * @param a1 * @param a2 * @param c * @param r */ export function intersectLineSegmentCircle( a1: number[], a2: number[], c: number[], r: number ): TLIntersection { const a = (a2[0] - a1[0]) * (a2[0] - a1[0]) + (a2[1] - a1[1]) * (a2[1] - a1[1]) const b = 2 * ((a2[0] - a1[0]) * (a1[0] - c[0]) + (a2[1] - a1[1]) * (a1[1] - c[1])) const cc = c[0] * c[0] + c[1] * c[1] + a1[0] * a1[0] + a1[1] * a1[1] - 2 * (c[0] * a1[0] + c[1] * a1[1]) - r * r const deter = b * b - 4 * a * cc if (deter < 0) { return createIntersection('outside') } if (deter === 0) { return createIntersection('tangent') } const e = Math.sqrt(deter) const u1 = (-b + e) / (2 * a) const u2 = (-b - e) / (2 * a) if ((u1 < 0 || u1 > 1) && (u2 < 0 || u2 > 1)) { if ((u1 < 0 && u2 < 0) || (u1 > 1 && u2 > 1)) { return createIntersection('outside') } else { return createIntersection('inside') } } const results: number[][] = [] if (0 <= u1 && u1 <= 1) results.push(Vec.lrp(a1, a2, u1)) if (0 <= u2 && u2 <= 1) results.push(Vec.lrp(a1, a2, u2)) return createIntersection('intersection', ...results) } /** * Find the intersections between a line segment and an ellipse. * @param a1 * @param a2 * @param center * @param rx * @param ry * @param rotation */ export function intersectLineSegmentEllipse( a1: number[], a2: number[], center: number[], rx: number, ry: number, rotation = 0 ): TLIntersection { // If the ellipse or line segment are empty, return no tValues. if (rx === 0 || ry === 0 || Vec.isEqual(a1, a2)) { return createIntersection('no intersection') } // Get the semimajor and semiminor axes. rx = rx < 0 ? rx : -rx ry = ry < 0 ? ry : -ry // Rotate points and translate so the ellipse is centered at the origin. a1 = Vec.sub(Vec.rotWith(a1, center, -rotation), center) a2 = Vec.sub(Vec.rotWith(a2, center, -rotation), center) // Calculate the quadratic parameters. const diff = Vec.sub(a2, a1) const A = (diff[0] * diff[0]) / rx / rx + (diff[1] * diff[1]) / ry / ry const B = (2 * a1[0] * diff[0]) / rx / rx + (2 * a1[1] * diff[1]) / ry / ry const C = (a1[0] * a1[0]) / rx / rx + (a1[1] * a1[1]) / ry / ry - 1 // Make a list of t values (normalized points on the line where intersections occur). const tValues: number[] = [] // Calculate the discriminant. const discriminant = B * B - 4 * A * C if (discriminant === 0) { // One real solution. tValues.push(-B / 2 / A) } else if (discriminant > 0) { const root = Math.sqrt(discriminant) // Two real solutions. tValues.push((-B + root) / 2 / A) tValues.push((-B - root) / 2 / A) } // Filter to only points that are on the segment. // Solve for points, then counter-rotate points. const points = tValues .filter((t) => t >= 0 && t <= 1) .map((t) => Vec.add(center, Vec.add(a1, Vec.mul(Vec.sub(a2, a1), t)))) .map((p) => Vec.rotWith(p, center, rotation)) return createIntersection('intersection', ...points) } /** * Find the intersections between a line segment and a bounding box. * @param a1 * @param a2 * @param bounds */ export function intersectLineSegmentBounds( a1: number[], a2: number[], bounds: TLBounds ): TLIntersection[] { return intersectBoundsLineSegment(bounds, a1, a2) } /** * Find the intersections between a line segment and a polyline. * @param a1 * @param a2 * @param points */ export function intersectLineSegmentPolyline( a1: number[], a2: number[], points: number[][] ): TLIntersection { const pts: number[][] = [] for (let i = 1; i < points.length; i++) { const int = intersectLineSegmentLineSegment(a1, a2, points[i - 1], points[i]) if (int) { pts.push(...int.points) } } if (pts.length === 0) { return createIntersection('no intersection') } return createIntersection('intersection', ...points) } /** * Find the intersections between a line segment and a closed polygon. * @param a1 * @param a2 * @param points */ export function intersectLineSegmentPolygon( a1: number[], a2: number[], points: number[][] ): TLIntersection { const pts: number[][] = [] for (let i = 1; i < points.length + 1; i++) { const int = intersectLineSegmentLineSegment(a1, a2, points[i - 1], points[i % points.length]) if (int) { pts.push(...int.points) } } if (pts.length === 0) { return createIntersection('no intersection') } return createIntersection('intersection', ...points) } /* -------------------------------------------------- */ /* Rectangle */ /* -------------------------------------------------- */ /** * Find the intersections between a rectangle and a ray. * @param point * @param size * @param rotation * @param origin * @param direction */ export function intersectRectangleRay( point: number[], size: number[], rotation: number, origin: number[], direction: number[] ): TLIntersection[] { const sideIntersections = getRectangleSides(point, size, rotation).reduce( (acc, [message, [a1, a2]]) => { const intersection = intersectRayLineSegment(origin, direction, a1, a2) if (intersection) { acc.push(createIntersection(message, ...intersection.points)) } return acc }, [] ) return sideIntersections.filter((int) => int.didIntersect) } /** * Find the intersections between a rectangle and a line segment. * @param point * @param size * @param a1 * @param a2 */ export function intersectRectangleLineSegment( point: number[], size: number[], a1: number[], a2: number[] ): TLIntersection[] { const sideIntersections = getRectangleSides(point, size).reduce( (acc, [message, [b1, b2]]) => { const intersection = intersectLineSegmentLineSegment(a1, a2, b1, b2) if (intersection) { acc.push(createIntersection(message, ...intersection.points)) } return acc }, [] ) return sideIntersections.filter((int) => int.didIntersect) } /** * Find the intersections between a rectangle and a rectangle. * @param point1 * @param size1 * @param point2 * @param size2 */ export function intersectRectangleRectangle( point1: number[], size1: number[], point2: number[], size2: number[] ): TLIntersection[] { const sideIntersections = getRectangleSides(point1, size1).reduce( (acc, [message, [a1, a2]]) => { const intersections = intersectRectangleLineSegment(point2, size2, a1, a2) acc.push( ...intersections.map((int) => createIntersection(`${message} ${int.message}`, ...int.points) ) ) return acc }, [] ) return sideIntersections.filter((int) => int.didIntersect) } /** * Find the intersections between a rectangle and an arc. * @param point * @param size * @param center * @param radius * @param start * @param end */ export function intersectRectangleArc( point: number[], size: number[], center: number[], radius: number, start: number[], end: number[] ): TLIntersection[] { const sideIntersections = getRectangleSides(point, size).reduce( (acc, [message, [a1, a2]]) => { const intersection = intersectArcLineSegment(center, radius, start, end, a1, a2) if (intersection) { acc.push({ ...intersection, message }) } return acc }, [] ) return sideIntersections.filter((int) => int.didIntersect) } /** * Find the intersections between a rectangle and a circle. * @param point * @param size * @param c * @param r */ export function intersectRectangleCircle( point: number[], size: number[], c: number[], r: number ): TLIntersection[] { const sideIntersections = getRectangleSides(point, size).reduce( (acc, [message, [a1, a2]]) => { const intersection = intersectLineSegmentCircle(a1, a2, c, r) if (intersection) { acc.push({ ...intersection, message }) } return acc }, [] ) return sideIntersections.filter((int) => int.didIntersect) } /** * Find the intersections between a rectangle and an ellipse. * @param point * @param size * @param c * @param rx * @param ry * @param rotation */ export function intersectRectangleEllipse( point: number[], size: number[], c: number[], rx: number, ry: number, rotation = 0 ): TLIntersection[] { const sideIntersections = getRectangleSides(point, size).reduce( (acc, [message, [a1, a2]]) => { const intersection = intersectLineSegmentEllipse(a1, a2, c, rx, ry, rotation) if (intersection) { acc.push({ ...intersection, message }) } return acc }, [] ) return sideIntersections.filter((int) => int.didIntersect) } /** * Find the intersections between a rectangle and a bounding box. * @param point * @param size * @param bounds */ export function intersectRectangleBounds( point: number[], size: number[], bounds: TLBounds ): TLIntersection[] { const { minX, minY, width, height } = bounds return intersectRectangleRectangle(point, size, [minX, minY], [width, height]) } /** * Find the intersections between a rectangle and a polyline. * @param point * @param size * @param points */ export function intersectRectanglePolyline( point: number[], size: number[], points: number[][] ): TLIntersection[] { const sideIntersections = getRectangleSides(point, size).reduce( (acc, [message, [a1, a2]]) => { const intersection = intersectLineSegmentPolyline(a1, a2, points) if (intersection.didIntersect) { acc.push(createIntersection(message, ...intersection.points)) } return acc }, [] ) return sideIntersections.filter((int) => int.didIntersect) } /** * Find the intersections between a rectangle and a polygon. * @param point * @param size * @param points */ export function intersectRectanglePolygon( point: number[], size: number[], points: number[][] ): TLIntersection[] { const sideIntersections = getRectangleSides(point, size).reduce( (acc, [message, [a1, a2]]) => { const intersection = intersectLineSegmentPolygon(a1, a2, points) if (intersection.didIntersect) { acc.push(createIntersection(message, ...intersection.points)) } return acc }, [] ) return sideIntersections.filter((int) => int.didIntersect) } /* -------------------------------------------------- */ /* Arc */ /* -------------------------------------------------- */ /** * Find the intersections between a arc and a line segment. * @param center * @param radius * @param start * @param end * @param a1 * @param a2 */ export function intersectArcLineSegment( center: number[], radius: number, start: number[], end: number[], a1: number[], a2: number[] ): TLIntersection { return intersectLineSegmentArc(a1, a2, center, radius, start, end) } /** * Find the intersections between a arc and a rectangle. * @param center * @param radius * @param start * @param end * @param point * @param size */ export function intersectArcRectangle( center: number[], radius: number, start: number[], end: number[], point: number[], size: number[] ): TLIntersection[] { return intersectRectangleArc(point, size, center, radius, start, end) } /** * Find the intersections between a arc and a bounding box. * @param center * @param radius * @param start * @param end * @param bounds */ export function intersectArcBounds( center: number[], radius: number, start: number[], end: number[], bounds: TLBounds ): TLIntersection[] { const { minX, minY, width, height } = bounds return intersectArcRectangle(center, radius, start, end, [minX, minY], [width, height]) } /* -------------------------------------------------- */ /* Circle */ /* -------------------------------------------------- */ /** * Find the intersections between a circle and a line segment. * @param c * @param r * @param a1 * @param a2 */ export function intersectCircleLineSegment( c: number[], r: number, a1: number[], a2: number[] ): TLIntersection { return intersectLineSegmentCircle(a1, a2, c, r) } /** * Find the intersections between a circle and a circle. * @param c1 * @param r1 * @param c2 * @param r2 */ export function intersectCircleCircle( c1: number[], r1: number, c2: number[], r2: number ): TLIntersection { let dx = c2[0] - c1[0], dy = c2[1] - c1[1] const d = Math.sqrt(dx * dx + dy * dy), x = (d * d - r2 * r2 + r1 * r1) / (2 * d), y = Math.sqrt(r1 * r1 - x * x) dx /= d dy /= d return createIntersection( 'intersection', [c1[0] + dx * x - dy * y, c1[1] + dy * x + dx * y], [c1[0] + dx * x + dy * y, c1[1] + dy * x - dx * y] ) } /** * Find the intersections between a circle and a rectangle. * @param c * @param r * @param point * @param size */ export function intersectCircleRectangle( c: number[], r: number, point: number[], size: number[] ): TLIntersection[] { return intersectRectangleCircle(point, size, c, r) } /** * Find the intersections between a circle and a bounding box. * @param c * @param r * @param bounds */ export function intersectCircleBounds(c: number[], r: number, bounds: TLBounds): TLIntersection[] { const { minX, minY, width, height } = bounds return intersectCircleRectangle(c, r, [minX, minY], [width, height]) } /* -------------------------------------------------- */ /* Ellipse */ /* -------------------------------------------------- */ /** * Find the intersections between an ellipse and a ray. * @param center * @param rx * @param ry * @param rotation * @param point * @param direction */ export function intersectEllipseRay( center: number[], rx: number, ry: number, rotation: number, point: number[], direction: number[] ): TLIntersection { return intersectRayEllipse(point, direction, center, rx, ry, rotation) } /** * Find the intersections between an ellipse and a line segment. * @param center * @param rx * @param ry * @param rotation * @param a1 * @param a2 */ export function intersectEllipseLineSegment( center: number[], rx: number, ry: number, rotation = 0, a1: number[], a2: number[] ): TLIntersection { if (rx === ry) { return intersectLineSegmentCircle(a1, a2, center, rx) } return intersectLineSegmentEllipse(a1, a2, center, rx, ry, rotation) } /** * Find the intersections between an ellipse and a rectangle. * @param center * @param rx * @param ry * @param rotation * @param point * @param size */ export function intersectEllipseRectangle( center: number[], rx: number, ry: number, rotation = 0, point: number[], size: number[] ): TLIntersection[] { if (rx === ry) { return intersectRectangleCircle(point, size, center, rx) } return intersectRectangleEllipse(point, size, center, rx, ry, rotation) } /** * Find the intersections between an ellipse and an ellipse. * Adapted from https://gist.github.com/drawable/92792f59b6ff8869d8b1 * @param _c1 * @param _rx1 * @param _ry1 * @param _r1 * @param _c2 * @param _rx2 * @param _ry2 * @param _r2 */ export function intersectEllipseEllipse( // eslint-disable-next-line @typescript-eslint/no-unused-vars _c1: number[], // eslint-disable-next-line @typescript-eslint/no-unused-vars _rx1: number, // eslint-disable-next-line @typescript-eslint/no-unused-vars _ry1: number, // eslint-disable-next-line @typescript-eslint/no-unused-vars _r1: number, // eslint-disable-next-line @typescript-eslint/no-unused-vars _c2: number[], // eslint-disable-next-line @typescript-eslint/no-unused-vars _rx2: number, // eslint-disable-next-line @typescript-eslint/no-unused-vars _ry2: number, // eslint-disable-next-line @typescript-eslint/no-unused-vars _r2: number ): TLIntersection { // TODO return createIntersection('no intersection') } /** * Find the intersections between an ellipse and a circle. * @param c * @param rx * @param ry * @param rotation * @param c2 * @param r2 */ export function intersectEllipseCircle( c: number[], rx: number, ry: number, rotation: number, c2: number[], r2: number ): TLIntersection { return intersectEllipseEllipse(c, rx, ry, rotation, c2, r2, r2, 0) } /** * Find the intersections between an ellipse and a bounding box. * @param c * @param rx * @param ry * @param rotation * @param bounds */ export function intersectEllipseBounds( c: number[], rx: number, ry: number, rotation: number, bounds: TLBounds ): TLIntersection[] { const { minX, minY, width, height } = bounds return intersectEllipseRectangle(c, rx, ry, rotation, [minX, minY], [width, height]) } /** * Find the intersections between a bounding box and a ray. * @param bounds * @param origin * @param direction */ export function intersectBoundsRay( bounds: TLBounds, origin: number[], direction: number[] ): TLIntersection[] { const { minX, minY, width, height } = bounds return intersectRayRectangle(origin, direction, [minX, minY], [width, height]) } /** * Find the intersections between a bounding box and a line segment. * @param bounds * @param a1 * @param a2 */ export function intersectBoundsLineSegment( bounds: TLBounds, a1: number[], a2: number[] ): TLIntersection[] { const { minX, minY, width, height } = bounds return intersectLineSegmentRectangle(a1, a2, [minX, minY], [width, height]) } /** * Find the intersections between a bounding box and a rectangle. * @param bounds * @param point * @param size */ export function intersectBoundsRectangle( bounds: TLBounds, point: number[], size: number[] ): TLIntersection[] { const { minX, minY, width, height } = bounds return intersectRectangleRectangle(point, size, [minX, minY], [width, height]) } /** * Find the intersections between a bounding box and a bounding box. * @param bounds1 * @param bounds2 */ export function intersectBoundsBounds(bounds1: TLBounds, bounds2: TLBounds): TLIntersection[] { return intersectRectangleRectangle( [bounds1.minX, bounds1.minY], [bounds1.width, bounds1.height], [bounds2.minX, bounds2.minY], [bounds2.width, bounds2.height] ) } /** * Find the intersections between a bounding box and an arc. * @param bounds * @param center * @param radius * @param start * @param end */ export function intersectBoundsArc( bounds: TLBounds, center: number[], radius: number, start: number[], end: number[] ): TLIntersection[] { const { minX, minY, width, height } = bounds return intersectArcRectangle(center, radius, start, end, [minX, minY], [width, height]) } /** * Find the intersections between a bounding box and a circle. * @param bounds * @param c * @param r */ export function intersectBoundsCircle(bounds: TLBounds, c: number[], r: number): TLIntersection[] { const { minX, minY, width, height } = bounds return intersectCircleRectangle(c, r, [minX, minY], [width, height]) } /** * Find the intersections between a bounding box and an ellipse. * @param bounds * @param c * @param rx * @param ry * @param rotation */ export function intersectBoundsEllipse( bounds: TLBounds, c: number[], rx: number, ry: number, rotation = 0 ): TLIntersection[] { const { minX, minY, width, height } = bounds return intersectEllipseRectangle(c, rx, ry, rotation, [minX, minY], [width, height]) } /** * Find the intersections between a bounding box and a polyline. * @param bounds * @param points */ export function intersectBoundsPolyline(bounds: TLBounds, points: number[][]): TLIntersection[] { return intersectPolylineBounds(points, bounds) } /** * Find the intersections between a bounding box and a polygon. * @param bounds * @param points */ export function intersectBoundsPolygon(bounds: TLBounds, points: number[][]): TLIntersection[] { return intersectPolygonBounds(points, bounds) } /* -------------------------------------------------- */ /* Polyline */ /* -------------------------------------------------- */ /** * Find the intersections between a polyline and a line segment. * @param points * @param a1 * @param a2 */ export function intersectPolylineLineSegment( points: number[][], a1: number[], a2: number[] ): TLIntersection { return intersectLineSegmentPolyline(a1, a2, points) } /** * Find the intersections between a polyline and a rectangle. * @param points * @param point * @param size */ export function intersectPolylineRectangle( points: number[][], point: number[], size: number[] ): TLIntersection[] { return intersectRectanglePolyline(point, size, points) } /** * Find the intersections between a polyline and a bounding box. * @param points * @param bounds */ export function intersectPolylineBounds(points: number[][], bounds: TLBounds): TLIntersection[] { return intersectRectanglePolyline( [bounds.minX, bounds.minY], [bounds.width, bounds.height], points ) } /* -------------------------------------------------- */ /* Polygon */ /* -------------------------------------------------- */ /** * Find the intersections between a polygon nd a line segment. * @param points * @param a1 * @param a2 */ export function intersectPolygonLineSegment( points: number[][], a1: number[], a2: number[] ): TLIntersection { return intersectLineSegmentPolyline(a1, a2, points) } /** * Find the intersections between a polygon and a rectangle. * @param points * @param point * @param size */ export function intersectPolygonRectangle( points: number[][], point: number[], size: number[] ): TLIntersection[] { return intersectRectanglePolyline(point, size, points) } /** * Find the intersections between a polygon and a bounding box. * @param points * @param bounds */ export function intersectPolygonBounds(points: number[][], bounds: TLBounds): TLIntersection[] { return intersectRectanglePolygon( [bounds.minX, bounds.minY], [bounds.width, bounds.height], points ) }