awv3
Version:
⚡ AWV3 embedded CAD
259 lines (218 loc) • 12.5 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _getIterator2 = require('babel-runtime/core-js/get-iterator');
var _getIterator3 = _interopRequireDefault(_getIterator2);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _highlevel = require('./command/highlevel');
var _lowlevel = require('./command/lowlevel');
var _type = require('./constraint/type');
var _geomutils = require('./geomutils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var FilletProcessor = function () {
function FilletProcessor(sketch) {
(0, _classCallCheck3.default)(this, FilletProcessor);
this.sketch = sketch;
}
// check if the given position is at the angle that can be filleted
// return full information about the angle or null
(0, _createClass3.default)(FilletProcessor, [{
key: 'recognizeFilletableAngle',
value: function recognizeFilletableAngle(pos) {
// find exactly matching points - children of lines
var samePoints = this.findPointsAt(pos).filter(function (obj) {
return obj.parent.isLine();
});
// exactly two curves must end at pos
if (samePoints.length !== 2) return null;
// these two points must be marked as incident
var incidenceConstr = this.findConstraints(_type.incidence.type, samePoints[0], samePoints[1]);
if (incidenceConstr.length !== 1) return null;
// check that parent lines are not collinear
var dirA = (0, _geomutils.getTangent)(lines[0].geomParams),
dirB = (0, _geomutils.getTangent)(lines[1].geomParams);
if (Math.abs(dirA.cross(dirB).z) <= FilletProcessor.angularTolerance) return null;
//return all the found data
return {
lines: samePoints.map(function (p) {
return p.parent;
}),
lineEnds: samePoints,
vertex: samePoints[0],
incidenceConstr: incidenceConstr
};
}
// checks if the given arc is a part of a correct fillet
// return full information about the fillet or null
}, {
key: 'RecognizeFilletByArcOrEdge',
value: function RecognizeFilletByArcOrEdge(obj) {
var res = { obj: obj, objEnds: [], lines: [], 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 lineEnd = samePoints[0];
var line = lineEnd.parent;
var reversed = lineEnd.state.name === 'endPoint';
// check that all constraints are in objEnd
if (this.findConstraints(_type.incidence.type, objEnd, lineEnd).length !== 1) return null;
if (obj.state.class === 'CC_Arc' && this.findConstraints(_type.tangency.type, obj, line).length !== 1) return null;
// check that a line is tangent at a common point
var lineDir = (0, _geomutils.getTangent)(line.geomParams);
if (reversed) lineDir.negate();
if (obj.state.class === 'CC_Arc') {
var arcDir = (0, _geomutils.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.lineEnds.push(lineEnd);
lineDirs.push(lineDir);
}
/* check that the fillet angle is in range (0; pi) TODO
if (obj.state.class === 'CC_Arc') {
var angle = Math.PI - obj.getAngle();
} else {
var angle = lineDirs[0].angleTo(lineDirs[1]);
}
if (angle <= this.angularTolerance || angle >= Math.PI - FilletProcessor.angularTolerance)
return null;
*/
// calculate the location of the fillet's vertex
var vertexPos = (0, _geomutils.intersectLines)(res.lineEnds[0].pos, lineDirs[0], res.lineEnds[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];
// check incidence of the vertex to lines
for (var i = 0; i < 2; ++i) {
if (this.findConstraints(_type.incidence.type, res.vertex, res.lines[i]).length !== 1) return null;
}return res;
}
// calculate the filleting arc params (center, touch points) by specified radius
}, {
key: 'calculateFilletParamsByRadius',
value: function calculateFilletParamsByRadius(info, radius) {
var touch = this.getTouchPoints(info, radius, undefined);
if (!touch) return null;
return (0, _extends3.default)({}, (0, _geomutils.drawArcBy_S_E_CPh)(touch[0], touch[1], info.vertex.pos), { control: info.vertex.pos });
}
}, {
key: 'calculateChamferParamsByOffset',
value: function calculateChamferParamsByOffset(info, offset) {
var touch = this.getTouchPoints(info, undefined, offset);
if (!touch) return null;
return { start: touch[0], end: touch[1], control: info.vertex.pos };
}
}, {
key: 'findPointsAt',
value: function findPointsAt(pos) {
var samePoints = [];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = (0, _getIterator3.default)(this.sketch.descendants), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var obj = _step.value;
if (obj.state.class === 'CC_Point' && obj.pos.distanceTo(pos) <= FilletProcessor.linearTolerance) samePoints.push(obj);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return samePoints;
}
}, {
key: 'findConstraints',
value: 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);
});
}
}, {
key: 'getTouchPoints',
value: function getTouchPoints(info, radius, distance) {
var vertexPos = info.vertex.pos;
var dirs = [],
dists = [];
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = (0, _getIterator3.default)(info.lineEnds), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var lineEnd = _step2.value;
var lineGeomParams = lineEnd.parent.geomParams;
dir.push((0, _geomutils.getTangent)(lineGeomParams));
if (lineEnd.state.name === 'endPoint') dir[dir.length - 1].negate();
dists.push(vertexPos.distanceTo(lineEnd) + lineGeomParams.start.distanceTo(lineGeomParams.end));
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
var angle = dirs[0].angleTo(dirs[1]),
dist = distance !== undefined ? distance : radius / Math.tan(angle / 2);
if (dist + FilletProcessor.linearTolerance >= Math.max(dists[0], dists[1])) return null; // too large fillet
return dirs.map(function (dir) {
return dir.clone().multiplyScalar(dist).add(vertexPos);
});
}
}, {
key: 'createNewFilletStatement',
value: function createNewFilletStatement(info, params) {
var vertex = (0, _lowlevel.Variable)(),
curve = (0, _lowlevel.Variable)();
return (0, _lowlevel.Sequence)((0, _highlevel.removeCommand)(this.sketch, info.incidenceConstr), (0, _highlevel.updateCommand)(this.sketch, info.lineEnds[0], { start: params.start }), (0, _highlevel.updateCommand)(this.sketch, info.lineEnds[1], { start: params.end }), (0, _lowlevel.Assign)(vertex, (0, _highlevel.addCommand)(this.sketch, { start: params.vertexPos })), (0, _lowlevel.Assign)(curve, (0, _highlevel.addCommand)(this.sketch, params)), (0, _highlevel.addCommand)(this.sketch, { type: _type.incidence.type, entities: [info.lines[0], vertex], value: {} }), (0, _highlevel.addCommand)(this.sketch, { type: _type.incidence.type, entities: [info.lines[1], vertex], value: {} }), (0, _highlevel.addCommand)(this.sketch, { type: _type.incidence.type, entities: [info.lines[0], (0, _lowlevel.Member)(curve, 'startPoint')], value: {} }), (0, _highlevel.addCommand)(this.sketch, { type: _type.incidence.type, entities: [info.lines[1], (0, _lowlevel.Member)(curve, 'endPoint')], value: {} }), (0, _highlevel.addCommand)(this.sketch, { type: _type.tangency.type, entities: [info.lines[0], curve], value: {} }), (0, _highlevel.addCommand)(this.sketch, { type: _type.tangency.type, entities: [info.lines[1], curve], value: {} }));
}
}, {
key: 'deleteFilletStatement',
value: function deleteFilletStatement(info) {
return (0, _lowlevel.Sequence)((0, _highlevel.removeCommand)(this.sketch, info.obj), (0, _highlevel.removeCommand)(this.sketch, info.vertex), (0, _highlevel.updateCommand)(this.sketch, info.lineEnds[1], { start: info.vertex.pos }), (0, _highlevel.updateCommand)(this.sketch, info.lineEnds[0], { start: info.vertex.pos }), (0, _highlevel.addCommand)(this.sketch, { type: _type.incidence.type, entities: [info.lineEnds[0], info.lineEnds[1]], value: {} }));
}
}, {
key: 'updateFilletStatement',
value: function updateFilletStatement(info, params) {
return (0, _lowlevel.Sequence)((0, _highlevel.updateCommand)(this.sketch, info.lineEnds[0], { start: params.start }), (0, _highlevel.updateCommand)(this.sketch, info.lineEnds[1], { start: params.end }), (0, _highlevel.updateCommand)(this.sketch, info.obj, params));
}
}]);
return FilletProcessor;
}();
FilletProcessor.linearTolerance = 1e-3;
FilletProcessor.angularTolerance = 1e-3;
exports.default = FilletProcessor;