UNPKG

awv3

Version:
303 lines (250 loc) 11.4 kB
import _extends from "@babel/runtime/helpers/extends"; var _class, _temp; import { addCommand, removeCommands, updateCommand } from './command/highlevel'; import { Assign, Member, Sequence, Variable } from './command/lowlevel'; import * as Constraints from './constraint/type'; import { drawArcBy_S_E_CP, getTangent, intersectLines } from './geomutils'; import { ReplaceEntityInConstraints } from "./command/lowlevel"; var FilletProcessor = (_temp = _class = /*#__PURE__*/ function () { function FilletProcessor(sketch) { this.sketch = sketch; } // check if the given position is at the angle that can be filleted // return full information about the angle or null var _proto = FilletProcessor.prototype; _proto.recognizeFilletableAngle = function recognizeFilletableAngle(pos) { // find exactly matching points - children of lines var samePoints = this.findPointsAt(pos); // exactly two curves must end at pos if (samePoints.length !== 2) return null; //both of them must be lines var lines = samePoints.map(function (pnt) { return pnt.parent; }); if (!lines.every(function (ln) { return ln && ln.isLine(); })) return null; // these two points must be marked as incident var incidenceConstr = this.findConstraints(Constraints.incidence.type, samePoints[0], samePoints[1]); if (incidenceConstr.length !== 1) return null; // check that parent lines are not collinear var dirA = getTangent(lines[0].geomParams), dirB = getTangent(lines[1].geomParams); if (Math.abs(dirA.cross(dirB).z) <= FilletProcessor.angularTolerance) return null; // find outer endpoints of the lines var lineEnds = []; for (var i = 0; i < 2; i++) { var vertexAtStart = lines[i].startPoint.id === samePoints[i].id; lineEnds[i] = vertexAtStart ? lines[i].endPoint : lines[i].startPoint; } //return all the found data return { lines: lines, lineStarts: samePoints, lineEnds: lineEnds, incidence: incidenceConstr[0], control: pos }; }; // checks if the given arc is a part of a correct fillet // return full information about the fillet or null _proto.recognizeFilletByArcOrEdge = function recognizeFilletByArcOrEdge(obj) { var res = { obj: obj, objEnds: [], lines: [], lineStarts: [], lineEnds: [], vertex: null }; var lineDirs = []; var _arr = [obj.startPoint, obj.endPoint]; for (var _i = 0; _i < _arr.length; _i++) { var objEnd = _arr[_i]; // find incident line var samePoints = this.findPointsAt(objEnd.pos); samePoints = samePoints.filter(function (point) { return point.parent.id !== obj.id && point.parent.state.class === 'CC_Line'; }); if (samePoints.length !== 1) return null; var lineStart = samePoints[0]; var line = lineStart.parent; var lineEnd = line.startPoint.id === lineStart.id ? line.endPoint : line.startPoint; // check that all constraints are in objEnd if (this.findConstraints(Constraints.incidence.type, objEnd, lineStart).length !== 1) return null; if (obj.state.class === 'CC_Arc' && this.findConstraints(Constraints.tangency.type, obj, line).length !== 1) return null; // check that a line is tangent at a common point var lineDir = lineEnd.pos.sub(lineStart.pos).normalize(); if (obj.state.class === 'CC_Arc') { var arcDir = getTangent(obj.geomParams, objEnd.pos); if (objEnd.state.name === 'startPoint') arcDir.negate(); if (lineDir.distanceTo(arcDir) > FilletProcessor.angularTolerance) return null; } // save found objects res.objEnds.push(objEnd); res.lines.push(line); res.lineStarts.push(lineStart); res.lineEnds.push(lineEnd); lineDirs.push(lineDir); } // check that the fillet angle is in range (0; pi) if (obj.state.class === 'CC_Arc' && Math.abs(obj.state.members.bulge.value) >= 1.0) return null; //arc's angle > pi var angle = lineDirs[0].angleTo(lineDirs[1]); if (angle <= FilletProcessor.angularTolerance || angle >= Math.PI - FilletProcessor.angularTolerance) return null; // calculate the location of the fillet's vertex var vertexPos = intersectLines(res.lineStarts[0].pos, lineDirs[0], res.lineStarts[1].pos, lineDirs[1], FilletProcessor.angularTolerance); if (!vertexPos) return null; // check for a point there var vertices = this.findPointsAt(vertexPos); if (vertices.length !== 1) return null; res.vertex = vertices[0]; res.control = res.vertex.pos; // check incidence of the vertex to lines for (var i = 0; i < 2; ++i) { if (this.findConstraints(Constraints.incidence.type, res.vertex, res.lines[i]).length !== 1) return null; } return res; }; _proto.getAngle = function getAngle(info) { var dirs = []; for (var i = 0; i < 2; i++) { dirs[i] = info.lineEnds[i].pos.sub(info.lineStarts[i].pos).normalize(); } return dirs[0].angleTo(dirs[1]); }; _proto.offsetToRadius = function offsetToRadius(info, offset) { var angle = this.getAngle(info); return offset * Math.tan(angle / 2); }; _proto.radiusToOffset = function radiusToOffset(info, radius) { var angle = this.getAngle(info); return radius / Math.tan(angle / 2); }; // calculate the filleting arc params (center, touch points) by specified radius _proto.calculateFilletParams = function calculateFilletParams(info, options) { var touch = this.getTouchPoints(info, options.radius, options.offset); if (!touch) return null; return _extends({}, drawArcBy_S_E_CP(touch.concat([info.control]), {}), { control: info.control }); }; _proto.calculateChamferParams = function calculateChamferParams(info, options) { var touch = this.getTouchPoints(info, options.radius, options.offset); if (!touch) return null; return { start: touch[0], end: touch[1], control: info.control }; }; _proto.findPointsAt = function findPointsAt(pos) { var samePoints = []; for (var _iterator = this.sketch.descendants, _isArray = Array.isArray(_iterator), _i2 = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { var _ref; if (_isArray) { if (_i2 >= _iterator.length) break; _ref = _iterator[_i2++]; } else { _i2 = _iterator.next(); if (_i2.done) break; _ref = _i2.value; } var _obj = _ref; if (_obj.state.class === 'CC_Point' && _obj.pos.distanceTo(pos) <= FilletProcessor.linearTolerance) samePoints.push(_obj); } return samePoints; }; _proto.findConstraints = function findConstraints(type, objA, objB) { return this.sketch.children.filter(function (constr) { return constr.state.class === type && (constr.entities[0].id === objA.id && constr.entities[1].id === objB.id || constr.entities[0].id === objB.id && constr.entities[1].id === objA.id); }); }; _proto.getTouchPoints = function getTouchPoints(info, radius, distance) { var vertexPos = info.control; var dirs = [], maxDists = []; for (var i = 0; i < 2; i++) { var dir = info.lineEnds[i].pos.sub(info.lineStarts[i].pos).normalize(); var maxDist = info.lineEnds[i].pos.distanceTo(vertexPos); dirs.push(dir); maxDists.push(maxDist); } var angle = dirs[0].angleTo(dirs[1]); var dist = distance !== undefined ? distance : radius / Math.tan(angle / 2); if (dist + FilletProcessor.linearTolerance >= Math.min(maxDists[0], maxDists[1])) return null; // too large fillet return dirs.map(function (dir) { return dir.clone().multiplyScalar(dist).add(vertexPos); }); }; _proto.createNewFilletStatement = function createNewFilletStatement(info, params) { var vertex = Variable(), curve = Variable(); return Sequence.apply(void 0, removeCommands(this.sketch, info.incidence).concat([updateCommand(this.sketch, info.lineStarts[0], { start: params.start }), updateCommand(this.sketch, info.lineStarts[1], { start: params.end }), Assign(vertex, addCommand(this.sketch, { start: info.control })), Assign(curve, addCommand(this.sketch, params)), ReplaceEntityInConstraints(this.sketch, undefined, info.lineStarts[0], vertex), ReplaceEntityInConstraints(this.sketch, undefined, info.lineStarts[1], vertex), addCommand(this.sketch, { class: Constraints.incidence.type, entities: [info.lines[0], vertex], value: {} }), addCommand(this.sketch, { class: Constraints.incidence.type, entities: [info.lines[1], vertex], value: {} }), addCommand(this.sketch, { class: Constraints.incidence.type, entities: [info.lineStarts[0], Member(curve, 'startPoint')], value: {} }), addCommand(this.sketch, { class: Constraints.incidence.type, entities: [info.lineStarts[1], Member(curve, 'endPoint')], value: {} }), addCommand(this.sketch, { class: Constraints.tangency.type, entities: [info.lines[0], curve], value: {} }), addCommand(this.sketch, { class: Constraints.tangency.type, entities: [info.lines[1], curve], value: {} }), addCommand(this.sketch, { class: Constraints.radius.type, entities: [curve], value: {} })])); }; _proto.deleteFilletStatement = function deleteFilletStatement(info) { var constraints = Array.from(this.sketch.descendants).filter(function (obj) { return obj.isConstraint(); }); //note: when moving constraints from fillet's vertex to the resulting angle's vertex, //ignore everything that involves removed geometry, filleting lines and their closer endpoints //the ignored constraints would be removed automatically var blacklist = info.lines.concat(info.lineStarts, [info.obj, info.obj.startPoint, info.obj.endPoint, info.obj.center]); var involves = function involves(constr, obj) { return constr.entities.some(function (e) { return e.id === obj.id; }); }; constraints = constraints.filter(function (constr) { return !blacklist.some(function (t) { return involves(constr, t); }); }); return Sequence.apply(void 0, removeCommands(this.sketch, info.obj).concat([ReplaceEntityInConstraints(this.sketch, constraints, info.vertex, info.lineStarts[0])], removeCommands(this.sketch, info.vertex), [updateCommand(this.sketch, info.lineStarts[0], { start: info.vertex.pos }), updateCommand(this.sketch, info.lineStarts[1], { start: info.vertex.pos }), addCommand(this.sketch, { class: Constraints.incidence.type, entities: [info.lineStarts[0], info.lineStarts[1]], value: {} })])); }; _proto.updateFilletStatement = function updateFilletStatement(info, params) { return Sequence(updateCommand(this.sketch, info.lineStarts[0], { start: params.start }), updateCommand(this.sketch, info.lineStarts[1], { start: params.end }), updateCommand(this.sketch, info.obj, params)); }; return FilletProcessor; }(), Object.defineProperty(_class, "linearTolerance", { configurable: true, enumerable: true, writable: true, value: 1e-3 }), Object.defineProperty(_class, "angularTolerance", { configurable: true, enumerable: true, writable: true, value: 1e-3 }), _temp); export { FilletProcessor as default };