import { fuzzyEqual } from '../../../math/float'; import { Vector2D } from '../../Vector2D'; import { intersectLinePoint, intersectLineLine, intersectLineCircle } from '../../intersections'; import { Shape } from '../Shape'; export function intersectPointLineHelper(thisShape: Shape, otherShape: Shape, point: Vector2D, p1: Vector2D, p2: Vector2D, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { const points = intersectLinePoint(p1, p2, point, epsilon); return points !== undefined && (callbackfn === undefined || callbackfn.call(thisArg, points, thisShape, otherShape)); } export function intersectPointCircleHelper(thisShape: Shape, otherShape: Shape, p: Vector2D, c: Vector2D, r: number, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { const dx = p.x - c.x; const dy = p.y - c.y; return fuzzyEqual(dx * dx + dy * dy, r * r, epsilon) && (callbackfn === undefined || callbackfn.call(thisArg, [p], thisShape, otherShape)); } export function intersectPointRectangleHelper(thisShape: Shape, otherShape: Shape, p: Vector2D, topLeft: Vector2D, topRight: Vector2D, bottomRight: Vector2D, bottomLeft: Vector2D, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { return intersectPointLineHelper(thisShape, otherShape, p, topLeft, topRight, callbackfn, thisArg, epsilon) || intersectPointLineHelper(thisShape, otherShape, p, topRight, bottomRight, callbackfn, thisArg, epsilon) || intersectPointLineHelper(thisShape, otherShape, p, bottomRight, bottomLeft, callbackfn, thisArg, epsilon) || intersectPointLineHelper(thisShape, otherShape, p, bottomLeft, topLeft, callbackfn, thisArg, epsilon); } export function intersectPointPolygonHelper(thisShape: Shape, otherShape: Shape, point: Vector2D, points: Vector2D[], callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { if (points.length === 0) return false; const first = points[0]; let p1 = first; for (let i = 1; i < points.length; i++) { const p2 = points[i]; if (intersectPointLineHelper(thisShape, otherShape, point, p1, p2, callbackfn, thisArg, epsilon)) return true; p1 = p2; } return !p1.fuzzyEquals(first, epsilon) // enclosing subpath case && intersectPointLineHelper(thisShape, otherShape, point, p1, first, callbackfn, thisArg, epsilon); } export function intersectPointPolylineHelper(thisShape: Shape, otherShape: Shape, point: Vector2D, points: Vector2D[], callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { if (points.length === 0) return false; let p1 = points[0]; for (let i = 1; i < points.length; i++) { const p2 = points[i]; if (intersectPointLineHelper(thisShape, otherShape, point, p1, p2, callbackfn, thisArg, epsilon)) return true; p1 = p2; } return false; } export function intersectLineLineHelper(thisShape: Shape, otherShape: Shape, p1: Vector2D, p2: Vector2D, p3: Vector2D, p4: Vector2D, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { const points = intersectLineLine(p1, p2, p3, p4, epsilon); return points !== undefined && (callbackfn === undefined || callbackfn.call(thisArg, points, thisShape, otherShape)); } export function intersectLineCircleHelper(thisShape: Shape, otherShape: Shape, p1: Vector2D, p2: Vector2D, c: Vector2D, r: number, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { const points = intersectLineCircle(p1, p2, c, r, epsilon); return points !== undefined && (callbackfn === undefined || callbackfn.call(thisArg, points, thisShape, otherShape)); } export function intersectLineRectangleHelper(thisShape: Shape, otherShape: Shape, p1: Vector2D, p2: Vector2D, topLeft: Vector2D, topRight: Vector2D, bottomRight: Vector2D, bottomLeft: Vector2D, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => boolean, thisArg?: any, epsilon?: number) { return intersectLineLineHelper(thisShape, otherShape, p1, p2, topLeft, topRight, callbackfn, thisArg, epsilon) || intersectLineLineHelper(thisShape, otherShape, p1, p2, topRight, bottomRight, callbackfn, thisArg, epsilon) || intersectLineLineHelper(thisShape, otherShape, p1, p2, bottomRight, bottomLeft, callbackfn, thisArg, epsilon) || intersectLineLineHelper(thisShape, otherShape, p1, p2, bottomLeft, topLeft, callbackfn, thisArg, epsilon); } export function intersectLinePolygonHelper(thisShape: Shape, otherShape: Shape, p1: Vector2D, p2: Vector2D, points: Vector2D[], callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => boolean, thisArg?: any, epsilon?: number) { if (points.length === 0) return false; const first = points[0]; let p3 = first; for (let j = 1; j < points.length; j++) { const p4 = points[j]; if (intersectLineLineHelper(thisShape, otherShape, p1, p2, p3, p4, callbackfn, thisArg, epsilon)) return true; p3 = p4; } return !p3.fuzzyEquals(first, epsilon) // other enclosing subpath case && intersectLineLineHelper(thisShape, otherShape, p1, p2, p3, first, callbackfn, thisArg, epsilon); } export function intersectLinePolylineHelper(thisShape: Shape, otherShape: Shape, p1: Vector2D, p2: Vector2D, points: Vector2D[], callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => boolean, thisArg?: any, epsilon?: number) { let p3 = points[0]; for (let j = 1; j < points.length; j++) { const p4 = points[j]; if (intersectLineLineHelper(thisShape, otherShape, p1, p2, p3, p4, callbackfn, thisArg, epsilon)) return true; p3 = p4; } return false; } export function intersectRectangleCircleHelper(thisShape: Shape, otherShape: Shape, topLeft: Vector2D, topRight: Vector2D, bottomRight: Vector2D, bottomLeft: Vector2D, c: Vector2D, r: number, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number): boolean { return intersectLineCircleHelper(thisShape, otherShape, topLeft, topRight, c, r, callbackfn, thisArg, epsilon) || intersectLineCircleHelper(thisShape, otherShape, topRight, bottomRight, c, r, callbackfn, thisArg, epsilon) || intersectLineCircleHelper(thisShape, otherShape, bottomRight, bottomLeft, c, r, callbackfn, thisArg, epsilon) || intersectLineCircleHelper(thisShape, otherShape, bottomLeft, topLeft, c, r, callbackfn, thisArg, epsilon); } export function intersectPolygonCircleHelper(thisShape: Shape, otherShape: Shape, points: Vector2D[], c: Vector2D, r: number, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { if (points.length === 0) return false; const first = points[0]; let p1 = first; for (let i = 1; i < points.length; i++) { const p2 = points[i]; if (intersectLineCircleHelper(thisShape, otherShape, p1, p2, c, r, callbackfn, thisArg, epsilon)) return true; p1 = p2; } return !p1.fuzzyEquals(first, epsilon) // enclosing subpath case && intersectLineCircleHelper(thisShape, otherShape, p1, first, c, r, callbackfn, thisArg, epsilon); } export function intersectPolygonRectangleHelper(thisShape: Shape, otherShape: Shape, points: Vector2D[], topLeft: Vector2D, topRight: Vector2D, bottomRight: Vector2D, bottomLeft: Vector2D, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { if (points.length === 0) return false; const first = points[0]; let p1 = first; for (let i = 1; i < points.length; i++) { const p2 = points[i]; if (intersectLineRectangleHelper(thisShape, otherShape, p1, p2, topLeft, topRight, bottomRight, bottomLeft, callbackfn, thisArg, epsilon)) return true; p1 = p2; } return !p1.fuzzyEquals(first, epsilon) // enclosing subpath case && intersectLineRectangleHelper(thisShape, otherShape, p1, first, topLeft, topRight, bottomRight, bottomLeft, callbackfn, thisArg, epsilon); } export function intersectPolylinePolygonHelper(thisShape: Shape, otherShape: Shape, polylinePoints: Vector2D[], polygonPoints: Vector2D[], callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { if (polylinePoints.length === 0 || polygonPoints.length === 0) return false; let p1 = polylinePoints[0]; for (let i = 1; i < polylinePoints.length; i++) { const p2 = polylinePoints[i]; if (intersectLinePolygonHelper(thisShape, otherShape, p1, p2, polygonPoints, callbackfn, thisArg, epsilon)) return true; p1 = p2; } return false; } export function intersectPolylineCircleHelper(thisShape: Shape, otherShape: Shape, points: Vector2D[], c: Vector2D, r: number, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { if (points.length === 0) return false; let p1 = points[0]; for (let i = 1; i < points.length; i++) { const p2 = points[i]; if (intersectLineCircleHelper(thisShape, otherShape, p1, p2, c, r, callbackfn, thisArg, epsilon)) return true; p1 = p2; } return false; } export function intersectPolylineRectangleHelper(thisShape: Shape, otherShape: Shape, points: Vector2D[], topLeft: Vector2D, topRight: Vector2D, bottomRight: Vector2D, bottomLeft: Vector2D, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { if (points.length === 0) return false; let p1 = points[0]; for (let i = 1; i < points.length; i++) { const p2 = points[i]; if (intersectLineRectangleHelper(thisShape, otherShape, p1, p2, topLeft, topRight, bottomRight, bottomLeft, callbackfn, thisArg, epsilon)) return true; p1 = p2; } return false; }