offset tool

This commit is contained in:
Val Erastov 2017-01-02 19:17:00 -08:00
parent bb6ff8610b
commit d9e61e273e
5 changed files with 140 additions and 72 deletions

View file

@ -17,6 +17,8 @@ function createByConstraintName(name, params, values) {
return new Perpendicular(params);
case "parallel":
return new Parallel(params);
case "P2LDistanceSigned":
return new P2LDistanceSigned(params, values[0]);
case "P2LDistance":
return new P2LDistance(params, values[0]);
case "P2LDistanceV":
@ -140,9 +142,8 @@ function ConstantWrapper(constr, mask) {
this.params = [];
this.grad = [];
var j;
for (j = 0; j < constr.params.length; j++) {
for (let j = 0; j < constr.params.length; j++) {
if (!mask[j]) {
this.params.push(constr.params[j]);
}
@ -157,7 +158,7 @@ function ConstantWrapper(constr, mask) {
fillArray(this.grad, 0, this.grad.length, 0);
constr.gradient(this.grad);
var jj = 0;
for (j = 0; j < mask.length; j++) {
for (let j = 0; j < mask.length; j++) {
if (!mask[j]) {
out[jj ++] = this.grad[j];
}
@ -212,6 +213,29 @@ function Diff(params, value) {
};
}
function P2LDistanceSigned(params, value) {
const TX = 0;
const TY = 1;
const AX = 2;
const AY = 3;
const BX = 4;
const BY = 5;
this.params = params;
this.value = value;
this.error = function() {
const tx = params[TX].get(), ax = params[AX].get(), bx = params[BX].get();
const ty = params[TY].get(), ay = params[AY].get(), by = params[BY].get();
const d = Math.sqrt(sq(by - ay) + sq(bx - ax));
return (-(by - ay) * (tx - ax) ) / d + ((bx - ax) * (ty - ay)) / d - this.value;
};
this.gradient = NumericGradient;
}
function P2LDistance(params, distance) {
this.params = params;

View file

@ -13,9 +13,11 @@ function Param(id, value, readOnly) {
Param.prototype.reset = function(value) {
this.set(value);
this.j = -1;
this.aux = false;
};
Param.prototype.set = function(value) {
if (this.aux) return;
this.value = value;
};
@ -187,28 +189,27 @@ System.prototype.getValues = function() {
return values;
};
var wrapAux = function(constrs, locked) {
var i, lockedSet = {};
for (i = 0; i < locked.length; i++) {
lockedSet[locked[i].j] = true;
}
for (i = 0; i < constrs.length; i++) {
var c = constrs[i];
var mask = [];
var needWrap = false;
for (var j = 0; j < c.params.length; j++) {
var param = c.params[j];
mask[j] = lockedSet[param.j] === true;
function wrapAux(constrs) {
for (let i = 0; i < constrs.length; i++) {
const c = constrs[i];
const mask = [];
let needWrap = false;
for (let j = 0; j < c.params.length; j++) {
const param = c.params[j];
mask[j] = param.aux === true;
needWrap = needWrap || mask[j];
}
if (needWrap) {
var wrapper = new ConstantWrapper(c, mask);
constrs[i] = wrapper;
constrs[i] = new ConstantWrapper(c, mask);
}
}
};
for (let constr of constrs) {
if (constr.params.length == 0) {
return constrs.filter(c => c.params.length != 0);
}
}
return constrs;
}
var lock2Equals2 = function(constrs, locked) {
var _locked = [];
@ -233,18 +234,17 @@ var diagnose = function(sys) {
}
};
var prepare = function(constrs, locked, aux, alg) {
var prepare = function(constrs, locked) {
var simpleMode = true;
if (!simpleMode) {
var lockingConstrs = lock2Equals2(constrs, locked);
Array.prototype.push.apply( constrs, lockingConstrs );
}
constrs = wrapAux(constrs);
var sys = new System(constrs);
wrapAux(constrs, aux);
var model = function(point) {
sys.setParams(point);
return sys.getValues();

View file

@ -485,29 +485,23 @@ ParametricManager.prototype.__getSolveData = function(constraints, out) {
return out;
};
ParametricManager.prototype.solve = function() {
var solver = this.prepare([]);
ParametricManager.prototype.solve = function(lock, extraConstraints, disabledObjects) {
const solver = this.prepare(lock, extraConstraints, disabledObjects);
solver.solve(false);
solver.sync();
};
ParametricManager.prototype.solveWithLock = function(lock) {
var solver = this.prepare(lock);
solver.solve(false);
solver.sync();
ParametricManager.prototype.prepare = function(locked, extraConstraints, disabledObjects) {
return this._prepare(locked, this.subSystems, extraConstraints, disabledObjects);
};
ParametricManager.prototype.prepare = function(locked, extraConstraints) {
return this._prepare(locked, this.subSystems, extraConstraints);
};
ParametricManager.prototype._prepare = function(locked, subSystems, extraConstraints) {
ParametricManager.prototype._prepare = function(locked, subSystems, extraConstraints, disabledObjects) {
var solvers = [];
for (var i = 0; i < subSystems.length; i++) {
solvers.push(this.prepareForSubSystem(locked, subSystems[i].constraints, extraConstraints));
solvers.push(this.prepareForSubSystem(locked, subSystems[i].constraints, extraConstraints, disabledObjects));
}
if (subSystems.length == 0 && locked.length != 0) {
solvers.push(this.prepareForSubSystem(locked, [], extraConstraints));
solvers.push(this.prepareForSubSystem(locked, [], extraConstraints, disabledObjects));
}
return {
solvers : solvers,
@ -545,9 +539,9 @@ ParametricManager.prototype._prepare = function(locked, subSystems, extraConstra
}
};
ParametricManager.isAux = function(obj) {
ParametricManager.isAux = function(obj, disabledObjects) {
while (!!obj) {
if (!!obj.aux) {
if (!!obj.aux || (disabledObjects !== undefined && disabledObjects.has(obj))) {
return true;
}
obj = obj.parent;
@ -555,12 +549,13 @@ ParametricManager.isAux = function(obj) {
return false;
};
ParametricManager.fetchAuxParams = function(system, auxParams, auxDict) {
ParametricManager.fetchAuxParams = function(system, auxParams, auxDict, disabledObjects) {
disabledObjects = disabledObjects != undefined ? new Set(disabledObjects) : undefined;
for (var i = 0; i < system.length; ++i) {
for (var p = 0; p < system[i][1].length; ++p) {
var parameter = system[i][1][p];
if (parameter.obj !== undefined) {
if (ParametricManager.isAux(parameter.obj)) {
if (ParametricManager.isAux(parameter.obj, disabledObjects)) {
if (auxDict[parameter.id] === undefined) {
auxDict[parameter.id] = parameter;
auxParams.push(parameter);
@ -726,7 +721,9 @@ ParametricManager.reduceSystem = function(system, readOnlyParams) {
return info;
};
ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemConstraints, extraConstraints) {
ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemConstraints, extraConstraints, disabledObjects) {
locked = locked || [];
var constrs = [];
var solverParamsDict = {};
@ -737,7 +734,7 @@ ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemCons
this.__getSolveData(subSystemConstraints, system);
if (!!extraConstraints) this.__getSolveData(extraConstraints, system);
ParametricManager.fetchAuxParams(system, auxParams, auxDict);
ParametricManager.fetchAuxParams(system, auxParams, auxDict, disabledObjects);
var readOnlyParams = auxParams.concat(locked);
var reduceInfo = ParametricManager.reduceSystem(system, readOnlyParams);
@ -777,19 +774,16 @@ ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemCons
}
})();
var aux = [];
for (var i = 0; i < system.length; ++i) {
var sdata = system[i];
var params = [];
for (var p = 0; p < sdata[1].length; ++p) {
var param = sdata[1][p];
var solverParam = getSolverParam(param);
for (let p = 0; p < sdata[1].length; ++p) {
const param = sdata[1][p];
const solverParam = getSolverParam(param);
solverParam.aux = auxDict[param.id] !== undefined;
params.push(solverParam);
if (auxDict[param.id] !== undefined) {
aux.push(solverParam);
}
}
if (reduceInfo.reducedConstraints[i] === true) continue;
@ -798,11 +792,11 @@ ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemCons
}
var lockedSolverParams = [];
for (p = 0; p < locked.length; ++p) {
for (let p = 0; p < locked.length; ++p) {
lockedSolverParams[p] = getSolverParam(locked[p]);
}
var solver = prepare(constrs, lockedSolverParams, aux);
var solver = prepare(constrs, lockedSolverParams);
function solve(rough, alg) {
return solver.solveSystem(rough, alg);
}
@ -1015,6 +1009,45 @@ Constraints.Perpendicular.prototype.getObjects = function() {
// ------------------------------------------------------------------------------------------------------------------ //
/** @constructor */
Constraints.P2LDistanceSigned = function(p, a, b, d) {
this.p = p;
this.a = a;
this.b = b;
this.d = d;
};
Constraints.P2LDistanceSigned.prototype.NAME = 'P2LDistanceSigned';
Constraints.P2LDistanceSigned.prototype.UI_NAME = 'Distance P & L';
Constraints.P2LDistanceSigned.prototype.getSolveData = function(resolver) {
var params = [];
this.p.collectParams(params);
this.a.collectParams(params);
this.b.collectParams(params);
return [[this.NAME, params, [resolver(this.d)]]];
};
Constraints.P2LDistanceSigned.prototype.serialize = function() {
return [this.NAME, [this.p.id, this.a.id, this.b.id, this.d]];
};
Constraints.Factory[Constraints.P2LDistanceSigned.prototype.NAME] = function(refs, data) {
return new Constraints.P2LDistanceSigned(refs(data[0]), refs(data[1]), refs(data[2]), data[3]);
};
Constraints.P2LDistanceSigned.prototype.getObjects = function() {
const collector = new Constraints.ParentsCollector();
collector.check(this.a);
collector.check(this.b);
collector.parents.push(this.p);
return collector.parents;
};
Constraints.P2LDistanceSigned.prototype.SettableFields = {'d' : "Enter the distance"};
// ------------------------------------------------------------------------------------------------------------------ //
/** @constructor */
Constraints.P2LDistance = function(p, l, d) {
this.p = p;

View file

@ -83,8 +83,8 @@ export class FilletTool extends Tool {
//pm._add(new Constraints.LockConvex(arc.c, arc.a, otherEnd(point1)));
//pm._add(new Constraints.LockConvex(otherEnd(point2), arc.b, arc.c));
var solver = pm.solveWithLock([]);
// var solver = pm.solveWithLock([point1._x, point1._y, point2._x, point2._y]);
var solver = pm.solve();
// var solver = pm.solve([point1._x, point1._y, point2._x, point2._y]);
pm.notify();
this.viewer.refresh();
}

View file

@ -25,8 +25,11 @@ export class OffsetTool extends LoopPickTool {
}
}
let delta = parseInt(prompt('offset distance?', 100));
if (isNaN(delta)) {
return;
}
const absDelta = Math.abs(delta);
const edges = [];
const startPoint = findLowestPoint(loopPoints);
const start = loopPoints.indexOf(startPoint);
@ -38,15 +41,14 @@ export class OffsetTool extends LoopPickTool {
return (i + start) % length;
}
if (!math.isCCW([loopPoints[pos(0)], loopPoints[pos(1)], loopPoints[pos(length - 1)]])) {
const inverse = this.twoConnectedArcs() || !math.isCCW([loopPoints[pos(0)], loopPoints[pos(1)], loopPoints[pos(length - 1)]]);
if (inverse) {
delta *= -1;
}
const arcs = [];
for (let i = 0; i < length; ++i) {
const a = loopPoints[pos(i)];
const b = loopPoints[pos(i + 1)];
let a = loopPoints[pos(i)];
let b = loopPoints[pos(i + 1)];
const normal = new Vector(-(b.y - a.y), (b.x - a.x))._normalize();
const offVector = normal._multiply(delta);
const origEdge = loopEdges[pos(i)];
@ -58,33 +60,39 @@ export class OffsetTool extends LoopPickTool {
const segment = this.viewer.addSegment(aOffX, aOffY,
bOffX, bOffY, this.viewer.activeLayer);
this.viewer.parametricManager._add(new Constraints.Parallel(origEdge, segment));
this.viewer.parametricManager._add(new Constraints.P2LDistance(a, segment, absDelta));
this.viewer.parametricManager._add(new Constraints.P2LDistanceSigned(a, segment.b, segment.a, delta));
edges.push(segment);
} else if (origEdge._class == 'TCAD.TWO.Arc') {
const connectionEdge = new SimpleEdge(new EndPoint(aOffX, aOffY), new EndPoint(bOffX, bOffY));
edges.push(connectionEdge);
const arcEdge = inverse ? connectionEdge.reverse() : connectionEdge;
const arc = new Arc(
new EndPoint(aOffX, aOffY),
new EndPoint(bOffX, bOffY),
arcEdge.a,
arcEdge.b,
new EndPoint(origEdge.c.x + offVector.x, origEdge.c.y + offVector.y)
);
arc.stabilize(this.viewer);
this.viewer.parametricManager._linkObjects([origEdge.c, arc.c]);
this.viewer.parametricManager._add(new Constraints.RadiusOffset(origEdge, arc, delta));
this.viewer.parametricManager._linkObjects([arc.c, origEdge.c]);
this.viewer.parametricManager._add(new Constraints.RadiusOffset(inverse?arc:origEdge, inverse?origEdge:arc, delta));
this.viewer.activeLayer.add(arc);
edges.push(arc);
arcs.push(arc);
}
}
arcs.forEach(e => e.c.aux = true);
for (let i = 0; i < edges.length; i++) {
this.viewer.parametricManager._linkObjects([edges[i].b, edges[(i + 1) % edges.length].a]);
}
loopEdges.forEach(e => e.aux = true);
this.viewer.parametricManager.solve(undefined, undefined, loopEdges);
this.viewer.parametricManager.refresh();
loopEdges.forEach(e => e.aux = false);
arcs.forEach(e => e.c.aux = false);
this.viewer.toolManager.releaseControl();
}
twoConnectedArcs() {
function isArc(edge) {
return edge._class == 'TCAD.TWO.Arc';
}
const edges = this.pickedLoop.edges;
return edges.length == 2 && isArc(edges[0]) && isArc(edges[1]);
}
}
@ -96,9 +104,12 @@ const SUPPORTED_OBJECTS = new Set();
SUPPORTED_OBJECTS.add('TCAD.TWO.Segment');
SUPPORTED_OBJECTS.add('TCAD.TWO.Arc');
function SimpleSegment(a, b) {
function SimpleEdge(a, b) {
this.a = a;
this.b = b;
this.reverse = function() {
return new SimpleEdge(b, a);
}
}
function findLowestPoint(poly) {