UNPKG

jakke-graphics-ts

Version:

My common graphics utils for building my aec apps.

191 lines 8.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LineEvaluation = void 0; const vectorUtils_1 = require("./vectorUtils"); const TOLERANCE_LINE_EVALUATION = 1e-6; /** * Get point on line which is distanced from given distance. * @param line Endpoints of line. * @param dist Distance from endpoint. * @param fromStart When true, anchor point will be start of line. Otherwise, end of line. * @returns {Vertex3d} Point */ function getPointOnLine(line, dist, fromStart = true) { const { p0, p1 } = line; const lineVector = vectorUtils_1.VectorUtils.subtract(p1, p0); const lineDirection = vectorUtils_1.VectorUtils.chain(lineVector).normalize().value(); const moveVector = vectorUtils_1.VectorUtils.scale(lineDirection, dist); const anchor = fromStart ? p0 : p1; const point = vectorUtils_1.VectorUtils.add(anchor, moveVector); return point; } /** * Get intersection point from lines. * @param li0 First line of lines. * @param li1 Second line of lines. * @param fromExtended When it's true, intersection will be calculated including extended lines of li0, li1. Otherwise, only within li0, li1 boundary. * @returns When the intersection exists, result will be true and pt will be that point. Otherwise, result false and message will include the reason of it. */ function getIntersection(li0, li1, fromExtended = false) { if (vectorUtils_1.VectorUtils.isParallelLines(li0, li1)) return { result: false, message: "Parallel or same Lines" }; // Projection on XY Plane const p1p3 = { x: li1.p1.x - li0.p1.x, y: li1.p1.y - li0.p1.y, z: 0 }; const d0 = { x: vectorUtils_1.VectorUtils.normalize(vectorUtils_1.VectorUtils.subtract(li0.p1, li0.p0)).x, y: vectorUtils_1.VectorUtils.normalize(vectorUtils_1.VectorUtils.subtract(li0.p1, li0.p0)).y, z: vectorUtils_1.VectorUtils.normalize(vectorUtils_1.VectorUtils.subtract(li0.p1, li0.p0)).z, }; const d1 = { x: vectorUtils_1.VectorUtils.normalize(vectorUtils_1.VectorUtils.subtract(li1.p1, li1.p0)).x, y: vectorUtils_1.VectorUtils.normalize(vectorUtils_1.VectorUtils.subtract(li1.p1, li1.p0)).y, z: vectorUtils_1.VectorUtils.normalize(vectorUtils_1.VectorUtils.subtract(li1.p1, li1.p0)).z, }; const d0PlaneXY = vectorUtils_1.VectorUtils.normalize({ x: d0.x, y: d0.y, z: 0 }); const d1PlaneXY = vectorUtils_1.VectorUtils.normalize({ x: d1.x, y: d1.y, z: 0 }); const det = -(d0PlaneXY.x * d1PlaneXY.y) + (d1PlaneXY.x * d0PlaneXY.y); if (Math.abs(det) < TOLERANCE_LINE_EVALUATION) { return { result: false, message: "Det is zero (parallel lines)" }; } const dx = p1p3.x; const dy = p1p3.y; const t = -((d1PlaneXY.y * dx) - (d1PlaneXY.x * dy)) / det; const u = -((d0PlaneXY.y * dx) - (d0PlaneXY.x * dy)) / det; // Move ptQ at plane (z = li0.p0.z); const ptLi0StartOnXY = { x: li0.p0.x, y: li0.p0.y, z: 0 }; const ptLi0EndOnXY = { x: li0.p1.x, y: li0.p1.y, z: 0 }; // Move ptR at plane (z = li1.p0.z) const ptLi1StartOnXY = { x: li1.p0.x, y: li1.p0.y, z: 0 }; const ptLi1EndOnXY = { x: li1.p1.x, y: li1.p1.y, z: 0 }; const ptQ = vectorUtils_1.VectorUtils.add(ptLi0EndOnXY, vectorUtils_1.VectorUtils.scale(d0PlaneXY, t)); const ptR = vectorUtils_1.VectorUtils.add(ptLi1EndOnXY, vectorUtils_1.VectorUtils.scale(d1PlaneXY, u)); const dist = vectorUtils_1.VectorUtils.getDist(ptQ, ptR); if (dist > TOLERANCE_LINE_EVALUATION) return { result: false, message: "Each points on XY Plane is not same." }; // Place ptQ on li0 const tLi0 = vectorUtils_1.VectorUtils.dot(vectorUtils_1.VectorUtils.subtract(ptQ, ptLi0StartOnXY), d0PlaneXY); const ratioLi0 = vectorUtils_1.VectorUtils.getDist(li0.p1, li0.p0) / vectorUtils_1.VectorUtils.getDist(ptLi0EndOnXY, ptLi0StartOnXY); const vLi0 = tLi0 * ratioLi0; const ptQ2 = { x: li0.p0.x + vLi0 * d0.x, y: li0.p0.y + vLi0 * d0.y, z: li0.p0.z + vLi0 * d0.z }; // Place ptR on li1 const tLi1 = vectorUtils_1.VectorUtils.dot(vectorUtils_1.VectorUtils.subtract(ptR, ptLi1StartOnXY), d1PlaneXY); const ratioLi1 = vectorUtils_1.VectorUtils.getDist(li1.p1, li1.p0) / vectorUtils_1.VectorUtils.getDist(ptLi1EndOnXY, ptLi1StartOnXY); const vLi1 = tLi1 * ratioLi1; const ptR2 = { x: li1.p0.x + vLi1 * d1.x, y: li1.p0.y + vLi1 * d1.y, z: li1.p0.z + vLi1 * d1.z }; if (vectorUtils_1.VectorUtils.getDist(ptQ2, ptR2) > TOLERANCE_LINE_EVALUATION) return { result: false, message: "Two line's are on skew position." }; if (fromExtended) { return { result: true, pt: ptQ2 }; } else { const paramPtQ2 = getParameterOnLine(li0.p0, li0.p1, ptQ2); const paramPtR2 = getParameterOnLine(li1.p0, li1.p1, ptR2); if ((-TOLERANCE_LINE_EVALUATION <= paramPtQ2 && paramPtQ2 <= 1 + TOLERANCE_LINE_EVALUATION) && (-TOLERANCE_LINE_EVALUATION <= paramPtR2 && paramPtR2 <= 1 + TOLERANCE_LINE_EVALUATION)) { return { result: true, pt: ptQ2 }; } else { return { result: false, message: "One of the points are placed on outside the line's domain." }; } } } /** * Evaluate the parameter of given line and point. * @param p0 Start point of Line * @param p1 End point of Line * @param ptTest Point to test * @returns {number|undefined} * When the given point is on the line between endpoints, the result will be 0 ~ 1. * When it is on the line but outside the endpoints, the result will be negative float or larger than 1. * When it is determined that the point actually not placed on the line, it will return undefined. */ function getParameterOnLine(p0, p1, ptTest) { const direction = vectorUtils_1.VectorUtils.subtract(p1, p0); const toTest = vectorUtils_1.VectorUtils.subtract(ptTest, p0); const lengthSquared = vectorUtils_1.VectorUtils.dot(direction, direction); // |d|^2 if (lengthSquared === 0) return 0; // zero length line const t = vectorUtils_1.VectorUtils.dot(toTest, direction) / lengthSquared; return t; } /** * Find foot point on line passing, which has direction as given. * @param direction Direction of line. * @param pt Point to foot on line. * @returns If you set direction as zero vector, it will return origin and param as 0. */ function getFootPointOnDirection(direction, pt) { if (vectorUtils_1.VectorUtils.getSize(direction) < TOLERANCE_LINE_EVALUATION) return; const norm = vectorUtils_1.VectorUtils.normalize(direction); const dSize = vectorUtils_1.VectorUtils.getSize(norm); const dot = vectorUtils_1.VectorUtils.dot(norm, pt); const t = dot / Math.pow(dSize, 2); return { pt: vectorUtils_1.VectorUtils.scale(norm, t), t }; } /** * Find foot point on line. * @param line Line passing two points. * @param pt Point to foot on line. * @returns If you set each point of the line which has almost same coordinate each other, it will return origin and param as 0. */ function getFootPointOnLine(line, pt) { const direction = vectorUtils_1.VectorUtils.subtract(line.p1, line.p0); if (vectorUtils_1.VectorUtils.getSize(direction) < TOLERANCE_LINE_EVALUATION) return; const anchor = line.p0; const ptMoved = vectorUtils_1.VectorUtils.subtract(pt, anchor); const norm = vectorUtils_1.VectorUtils.normalize(direction); const dSize = vectorUtils_1.VectorUtils.getSize(norm); if (dSize === 0) return; const dot = vectorUtils_1.VectorUtils.dot(norm, ptMoved); const t = dot / vectorUtils_1.VectorUtils.getSize(direction); const ptOnMovedLine = vectorUtils_1.VectorUtils.scale(norm, dot); const ptFooting = vectorUtils_1.VectorUtils.add(ptOnMovedLine, anchor); return { pt: ptFooting, t }; } exports.LineEvaluation = { getPointOnLine, getIntersection, getParameterOnLine, getFootPointOnLine, getFootPointOnDirection }; //# sourceMappingURL=lineEvaluationUtils.js.map