UNPKG

@mlightcad/geometry-engine

Version:

The geometry-engine package provides comprehensive geometric entities, mathematical operations, and transformations for 2D and 3D space. This package mimics AutoCAD ObjectARX's AcGe (Geometry) classes and provides the mathematical foundation for CAD opera

172 lines 7.17 kB
var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; import { calculateCurveLength, evaluateNurbsPoint, generateChordKnots, generateSqrtChordKnots, generateUniformKnots } from '../util'; import { AcGeCatmullRomCurve3d } from './AcGeCatmullRomCurve3d'; /** * A NURBS curve implementation that can be used by other curve classes */ var AcGeNurbsCurve = /** @class */ (function () { function AcGeNurbsCurve(degree, knots, controlPoints, weights) { this._degree = degree; this._knots = __spreadArray([], __read(knots), false); this._controlPoints = controlPoints.map(function (p) { return ({ x: p.x, y: p.y, z: p.z }); }); this._weights = weights ? __spreadArray([], __read(weights), false) : new Array(controlPoints.length).fill(1.0); } /** * Get the degree of the NURBS curve */ AcGeNurbsCurve.prototype.degree = function () { return this._degree; }; /** * Get the knot vector */ AcGeNurbsCurve.prototype.knots = function () { return __spreadArray([], __read(this._knots), false); }; /** * Get the control points */ AcGeNurbsCurve.prototype.controlPoints = function () { return this._controlPoints.map(function (p) { return ({ x: p.x, y: p.y, z: p.z }); }); }; /** * Get the weights */ AcGeNurbsCurve.prototype.weights = function () { return __spreadArray([], __read(this._weights), false); }; /** * Calculate a point on the curve at parameter u */ AcGeNurbsCurve.prototype.point = function (u) { // Convert AcGePoint3dLike[] to number[][] for utility functions var controlPointsArray = this._controlPoints.map(function (p) { return [p.x, p.y, p.z]; }); return evaluateNurbsPoint(u, this._degree, this._knots, controlPointsArray, this._weights); }; /** * Calculate curve length using numerical integration */ AcGeNurbsCurve.prototype.length = function () { // Convert AcGePoint3dLike[] to number[][] for utility functions var controlPointsArray = this._controlPoints.map(function (p) { return [p.x, p.y, p.z]; }); return calculateCurveLength(this._degree, this._knots, controlPointsArray, this._weights); }; /** * Create a NURBS curve from control points and knots */ AcGeNurbsCurve.byKnotsControlPointsWeights = function (degree, knots, controlPoints, weights) { return new AcGeNurbsCurve(degree, knots, controlPoints, weights); }; /** * Create a NURBS curve from fit points using interpolation */ AcGeNurbsCurve.byPoints = function (points, degree, parameterization) { if (parameterization === void 0) { parameterization = 'Uniform'; } // Generate knots based on parameterization type var knots; switch (parameterization) { case 'Chord': knots = generateChordKnots(degree, points); break; case 'SqrtChord': knots = generateSqrtChordKnots(degree, points); break; case 'Uniform': default: knots = generateUniformKnots(degree, points.length); break; } // Convert number[][] to AcGePoint3dLike[] for control points var controlPoints = points.map(function (p) { return ({ x: p[0], y: p[1], z: p[2] }); }); var weights = new Array(controlPoints.length).fill(1.0); return new AcGeNurbsCurve(degree, knots, controlPoints, weights); }; /** * Get the valid parameter range for this curve */ AcGeNurbsCurve.prototype.getParameterRange = function () { var startParam = this._knots[this._degree]; var endParam = this._knots[this._knots.length - this._degree - 1]; return { start: startParam, end: endParam }; }; /** * Get points along the curve * @param divisions - Number of divisions to create * @returns Array of points along the curve */ AcGeNurbsCurve.prototype.getPoints = function (divisions) { var points = []; var _a = this.getParameterRange(), start = _a.start, end = _a.end; for (var i = 0; i <= divisions; i++) { var t = start + (end - start) * (i / divisions); points.push(this.point(t)); } return points; }; /** * Check if the curve is closed by comparing start and end points */ AcGeNurbsCurve.prototype.isClosed = function (tolerance) { if (tolerance === void 0) { tolerance = 1e-6; } var _a = this.getParameterRange(), start = _a.start, end = _a.end; var startPoint = this.point(start); var endPoint = this.point(end); var dx = startPoint[0] - endPoint[0]; var dy = startPoint[1] - endPoint[1]; var dz = startPoint[2] - endPoint[2]; return Math.sqrt(dx * dx + dy * dy + dz * dz) < tolerance; }; /** * Create fit points for a closed NURBS curve using Catmull-Rom interpolation */ AcGeNurbsCurve.createFitPointsForClosedCurve = function (points) { if (points.length < 4) { throw new Error('At least 4 points are required for a closed NURBS curve'); } // Create a closed Catmull-Rom curve var catmullRomCurve = new AcGeCatmullRomCurve3d(points, true, 'centripetal'); // Get points along the curve for NURBS interpolation // Use more divisions for smoother curve var divisions = Math.max(50, points.length * 2); return catmullRomCurve.getPoints(divisions); }; /** * Create a closed NURBS curve using Catmull-Rom interpolation for smooth closure */ AcGeNurbsCurve.createClosedCurve = function (points, degree, parameterization) { if (parameterization === void 0) { parameterization = 'Chord'; } var curvePoints = this.createFitPointsForClosedCurve(points); // Convert AcGePoint3d[] back to number[][] var nurbsPoints = curvePoints.map(function (point) { return [point.x, point.y, point.z]; }); // Create NURBS curve from the interpolated points return AcGeNurbsCurve.byPoints(nurbsPoints, degree, parameterization); }; return AcGeNurbsCurve; }()); export { AcGeNurbsCurve }; //# sourceMappingURL=AcGeNurbsCurve.js.map