@tldraw/editor
Version:
tldraw infinite canvas SDK (editor).
246 lines (245 loc) • 8.74 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var intersect_exports = {};
__export(intersect_exports, {
intersectCircleCircle: () => intersectCircleCircle,
intersectCirclePolygon: () => intersectCirclePolygon,
intersectCirclePolyline: () => intersectCirclePolyline,
intersectLineSegmentCircle: () => intersectLineSegmentCircle,
intersectLineSegmentLineSegment: () => intersectLineSegmentLineSegment,
intersectLineSegmentPolygon: () => intersectLineSegmentPolygon,
intersectLineSegmentPolyline: () => intersectLineSegmentPolyline,
intersectPolygonBounds: () => intersectPolygonBounds,
intersectPolygonPolygon: () => intersectPolygonPolygon,
intersectPolys: () => intersectPolys,
linesIntersect: () => linesIntersect,
polygonIntersectsPolyline: () => polygonIntersectsPolyline,
polygonsIntersect: () => polygonsIntersect
});
module.exports = __toCommonJS(intersect_exports);
var import_utils = require("./utils");
var import_Vec = require("./Vec");
function intersectLineSegmentLineSegment(a1, a2, b1, b2, precision = 1e-10) {
const ABx = a1.x - b1.x;
const ABy = a1.y - b1.y;
const BVx = b2.x - b1.x;
const BVy = b2.y - b1.y;
const AVx = a2.x - a1.x;
const AVy = a2.y - a1.y;
const ua_t = BVx * ABy - BVy * ABx;
const ub_t = AVx * ABy - AVy * ABx;
const u_b = BVy * AVx - BVx * AVy;
if ((0, import_utils.approximately)(ua_t, 0, precision) || (0, import_utils.approximately)(ub_t, 0, precision)) return null;
if ((0, import_utils.approximately)(u_b, 0, precision)) return null;
if (u_b !== 0) {
const ua = ua_t / u_b;
const ub = ub_t / u_b;
if ((0, import_utils.approximatelyLte)(0, ua, precision) && (0, import_utils.approximatelyLte)(ua, 1, precision) && (0, import_utils.approximatelyLte)(0, ub, precision) && (0, import_utils.approximatelyLte)(ub, 1, precision)) {
return import_Vec.Vec.AddXY(a1, ua * AVx, ua * AVy);
}
}
return null;
}
function intersectLineSegmentCircle(a1, a2, c, r) {
const a = (a2.x - a1.x) * (a2.x - a1.x) + (a2.y - a1.y) * (a2.y - a1.y);
const b = 2 * ((a2.x - a1.x) * (a1.x - c.x) + (a2.y - a1.y) * (a1.y - c.y));
const cc = c.x * c.x + c.y * c.y + a1.x * a1.x + a1.y * a1.y - 2 * (c.x * a1.x + c.y * a1.y) - r * r;
const deter = b * b - 4 * a * cc;
if (deter < 0) return null;
if (deter === 0) return null;
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)) {
return null;
}
const result = [];
if (0 <= u1 && u1 <= 1) result.push(import_Vec.Vec.Lrp(a1, a2, u1));
if (0 <= u2 && u2 <= 1) result.push(import_Vec.Vec.Lrp(a1, a2, u2));
if (result.length === 0) return null;
return result;
}
function intersectLineSegmentPolyline(a1, a2, points) {
const result = [];
let segmentIntersection;
for (let i = 0, n = points.length - 1; i < n; i++) {
segmentIntersection = intersectLineSegmentLineSegment(a1, a2, points[i], points[i + 1]);
if (segmentIntersection) result.push(segmentIntersection);
}
if (result.length === 0) return null;
return result;
}
function intersectLineSegmentPolygon(a1, a2, points) {
const result = [];
let segmentIntersection;
for (let i = 1, n = points.length; i < n + 1; i++) {
segmentIntersection = intersectLineSegmentLineSegment(
a1,
a2,
points[i - 1],
points[i % points.length]
);
if (segmentIntersection) result.push(segmentIntersection);
}
if (result.length === 0) return null;
return result;
}
function intersectCircleCircle(c1, r1, c2, r2) {
let dx = c2.x - c1.x;
let dy = c2.y - c1.y;
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 [
new import_Vec.Vec(c1.x + dx * x - dy * y, c1.y + dy * x + dx * y),
new import_Vec.Vec(c1.x + dx * x + dy * y, c1.y + dy * x - dx * y)
];
}
function intersectCirclePolygon(c, r, points) {
const result = [];
let a, b, int;
for (let i = 0, n = points.length; i < n; i++) {
a = points[i];
b = points[(i + 1) % points.length];
int = intersectLineSegmentCircle(a, b, c, r);
if (int) result.push(...int);
}
if (result.length === 0) return null;
return result;
}
function intersectCirclePolyline(c, r, points) {
const result = [];
let a, b, int;
for (let i = 1, n = points.length; i < n; i++) {
a = points[i - 1];
b = points[i];
int = intersectLineSegmentCircle(a, b, c, r);
if (int) result.push(...int);
}
if (result.length === 0) return null;
return result;
}
function intersectPolygonBounds(points, bounds) {
const result = [];
let segmentIntersection;
for (const side of bounds.sides) {
segmentIntersection = intersectLineSegmentPolygon(side[0], side[1], points);
if (segmentIntersection) result.push(...segmentIntersection);
}
if (result.length === 0) return null;
return result;
}
function ccw(A, B, C) {
return (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x);
}
function linesIntersect(A, B, C, D) {
return ccw(A, C, D) !== ccw(B, C, D) && ccw(A, B, C) !== ccw(A, B, D);
}
function intersectPolygonPolygon(polygonA, polygonB) {
const result = /* @__PURE__ */ new Map();
let a, b, c, d;
for (let i = 0, n = polygonA.length; i < n; i++) {
a = polygonA[i];
if ((0, import_utils.pointInPolygon)(a, polygonB)) {
const id = getPointId(a);
if (!result.has(id)) {
result.set(id, a);
}
}
}
for (let i = 0, n = polygonB.length; i < n; i++) {
a = polygonB[i];
if ((0, import_utils.pointInPolygon)(a, polygonA)) {
const id = getPointId(a);
if (!result.has(id)) {
result.set(id, a);
}
}
}
for (let i = 0, n = polygonA.length; i < n; i++) {
a = polygonA[i];
b = polygonA[(i + 1) % polygonA.length];
for (let j = 0, m = polygonB.length; j < m; j++) {
c = polygonB[j];
d = polygonB[(j + 1) % polygonB.length];
const intersection = intersectLineSegmentLineSegment(a, b, c, d);
if (intersection !== null) {
const id = getPointId(intersection);
if (!result.has(id)) {
result.set(id, intersection);
}
}
}
}
if (result.size === 0) return null;
return orderClockwise([...result.values()]);
}
function intersectPolys(polyA, polyB, isAClosed, isBClosed) {
const result = /* @__PURE__ */ new Map();
for (let i = 0, n = isAClosed ? polyA.length : polyA.length - 1; i < n; i++) {
const currentA = polyA[i];
const nextA = polyA[(i + 1) % polyA.length];
for (let j = 0, m = isBClosed ? polyB.length : polyB.length - 1; j < m; j++) {
const currentB = polyB[j];
const nextB = polyB[(j + 1) % polyB.length];
const intersection = intersectLineSegmentLineSegment(currentA, nextA, currentB, nextB);
if (intersection !== null) {
const id = getPointId(intersection);
if (!result.has(id)) {
result.set(id, intersection);
}
}
}
}
return [...result.values()];
}
function getPointId(point) {
return `${point.x},${point.y}`;
}
function orderClockwise(points) {
const C = import_Vec.Vec.Average(points);
return points.sort((A, B) => import_Vec.Vec.Angle(C, A) - import_Vec.Vec.Angle(C, B));
}
function polygonsIntersect(a, b) {
let a0, a1, b0, b1;
for (let i = 0, n = a.length; i < n; i++) {
a0 = a[i];
a1 = a[(i + 1) % n];
for (let j = 0, m = b.length; j < m; j++) {
b0 = b[j];
b1 = b[(j + 1) % m];
if (linesIntersect(a0, a1, b0, b1)) return true;
}
}
return false;
}
function polygonIntersectsPolyline(polygon, polyline) {
let a, b, c, d;
for (let i = 0, n = polygon.length; i < n; i++) {
a = polygon[i];
b = polygon[(i + 1) % n];
for (let j = 1, m = polyline.length; j < m; j++) {
c = polyline[j - 1];
d = polyline[j];
if (linesIntersect(a, b, c, d)) return true;
}
}
return false;
}
//# sourceMappingURL=intersect.js.map