awv3
Version:
⚡ AWV3 embedded CAD
303 lines (250 loc) • 11.4 kB
JavaScript
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 };