Tldraw/packages/intersect/src/index.ts

1242 wiersze
29 KiB
TypeScript

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<TLIntersection[]>(
(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<TLIntersection[]>(
(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<TLIntersection[]>(
(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<TLIntersection[]>(
(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<TLIntersection[]>(
(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<TLIntersection[]>(
(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<TLIntersection[]>(
(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<TLIntersection[]>(
(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
)
}