fix sketcher solving problems

This commit is contained in:
Val Erastov 2015-11-12 20:01:40 -08:00
parent 06a76f643d
commit 69de018f45
5 changed files with 161 additions and 82 deletions

View file

@ -1,5 +1,7 @@
optim = {};
optim.DEBUG_HANDLER = function() {};
//Added strong wolfe condition to numeric's uncmin
optim.bfgs_ = function(f,x0,tol,gradient,maxit,callback,options) {
var grad = numeric.gradient;
@ -335,6 +337,7 @@ optim.dog_leg = function (subsys, rough) {
var iter = 0, stop = 0, reduce = 0;
//var log = [];
while (stop === 0) {
optim.DEBUG_HANDLER(iter, err);
// check if finished
if (fx_inf <= tolf ) // Success
@ -365,14 +368,12 @@ optim.dog_leg = function (subsys, rough) {
var hitBoundary = false;
var stepKind;
// compute the dogleg step
var gnorm = n.norm2(g);
if (n.norm2(h_gn) < delta) {
var gnNorm = n.norm2(h_gn);
if (gnNorm < delta) {
h_dl = h_gn;
stepKind = 1;
}
else {
} else {
var Jt = n.transpose(Jx);
var B = n.dot(Jt, Jx);
var gBg = n.dot(g, n.dot(B, g));
@ -380,24 +381,26 @@ optim.dog_leg = function (subsys, rough) {
if (alpha * gnorm >= delta) {
h_dl = n.mul(g, - delta / gnorm);
hitBoundary = true;
stepKind = 2;
} else {
var h_sd = n.mul(g, - alpha);
if (isNaN(gnNorm)) {
h_dl = h_sd;
} else {
var d = n.sub(h_gn, h_sd);
var d = n.sub(h_gn, h_sd);
var a = n.dot(d, d);
var b = 2 * n.dot(h_sd, d);
var c = n.dot(h_sd, h_sd) - delta * delta
var a = n.dot(d, d);
var b = 2 * n.dot(h_sd, d);
var c = n.dot(h_sd, h_sd) - delta * delta;
var sqrt_discriminant = Math.sqrt(b * b - 4 * a * c)
var sqrt_discriminant = Math.sqrt(b * b - 4 * a * c);
var beta = (-b + sqrt_discriminant) / (2 * a)
var beta = (-b + sqrt_discriminant) / (2 * a);
// and update h_dl and dL with beta
h_dl = n.add(h_sd, n.mul(beta, d));
hitBoundary = true;
stepKind = 3;
// and update h_dl and dL with beta
h_dl = n.add(h_sd, n.mul(beta, d));
hitBoundary = true;
}
}
}
}

View file

@ -839,11 +839,9 @@ TCAD.TWO.DragTool = function(obj, viewer) {
this._point = {x: 0, y: 0};
this.origin = {x: 0, y: 0};
this.ref = this.obj.getReferencePoint();
this.errorX = 0;
this.errorY = 0;
this.solver = null;
};
TCAD.TWO.DragTool.prototype.snapshots = []
TCAD.TWO.DragTool.prototype.keydown = function(e) {};
TCAD.TWO.DragTool.prototype.keypress = function(e) {};
TCAD.TWO.DragTool.prototype.keyup = function(e) {};
@ -852,29 +850,27 @@ TCAD.TWO.DragTool.prototype.cleanup = function(e) {};
TCAD.TWO.DragTool.prototype.mousemove = function(e) {
var x = this._point.x;
var y = this._point.y;
this.viewer.screenToModel2(e.x, e.y, this._point);
var dx = this._point.x - x - this.errorX;
var dy = this._point.y - y - this.errorY;
var checkX = this.ref.x;
var checkY = this.ref.y;
this.obj.translate(dx, dy);
this.viewer.screenToModel2(e.offsetX, e.offsetY, this._point);
var dx = this._point.x - x;
var dy = this._point.y - y;
if (!e.altKey && !e.ctrlKey) {
for (var i = 0; i < this.lockedShifts.length; i += 2) {
this.lockedValues[i] = this._point.x - this.lockedShifts[i];
this.lockedValues[i + 1] = this._point.y - this.lockedShifts[i + 1];
}
this.solver.updateLock(this.lockedValues);
this.solveRequest(true);
} else {
this.obj.translate(dx, dy);
}
this.errorX = (this.ref.x - dx) - checkX;
this.errorY = (this.ref.y - dy) - checkY;
// console.log("accumulated error X = " + this.errorX);
// console.log("accumulated error Y = " + this.errorY);
this.viewer.refresh();
};
TCAD.TWO.DragTool.prototype.mousedown = function(e) {
this.origin.x = e.x;
this.origin.y = e.y;
this.viewer.screenToModel2(e.x, e.y, this._point);
this.origin.x = e.offsetX;
this.origin.y = e.offsetY;
this.viewer.screenToModel2(e.offsetX, e.offsetY, this._point);
this.prepareSolver();
};
@ -882,10 +878,11 @@ TCAD.TWO.DragTool.prototype.mouseup = function(e) {
this.solveRequest(false);
this.viewer.refresh();
this.viewer.toolManager.releaseControl();
var traveled = TCAD.math.distance(this.origin.x, this.origin.y, e.x, e.y);
var traveled = TCAD.math.distance(this.origin.x, this.origin.y, e.offsetX, e.offsetY);
if (traveled >= 10) {
this.viewer.historyManager.lightCheckpoint(10);
}
//this.animateSolution();
};
TCAD.TWO.DragTool.prototype.mousewheel = function(e) {
@ -896,20 +893,70 @@ TCAD.TWO.DragTool.prototype.solveRequest = function(rough) {
this.solver.sync();
};
TCAD.TWO.DragTool.prototype.getParamsToLock = function() {
var params = [];
this.obj.accept(function(obj) {
if (obj._class === 'TCAD.TWO.EndPoint') {
params.push(obj._x);
params.push(obj._y);
}
return true;
});
return params;
};
TCAD.TWO.DragTool.prototype.prepareSolver = function() {
var locked;
if (this.obj._class === 'TCAD.TWO.EndPoint') {
locked = [this.obj._x, this.obj._y];
// if (this.obj.parent != null
// && this.obj.parent._class === 'TCAD.TWO.Arc') {
//
// if (this.obj.id != this.obj.parent.c.id) {
// locked.push(this.obj.parent.c._x);
// locked.push(this.obj.parent.c._y);
// }
// }
} else {
locked = [];
var locked = this.getParamsToLock();
this.lockedShifts = [];
this.lockedValues = [];
for (var i = 0; i < locked.length; i += 2) {
this.lockedShifts[i] = this._point.x - locked[i].get();
this.lockedShifts[i + 1] = this._point.y - locked[i + 1].get();
}
this.solver = this.viewer.parametricManager.prepare(locked);
//this.enableRecording();
};
TCAD.TWO.DragTool.prototype.enableRecording = function() {
var solver = this.solver;
var snapshots = this.snapshots = [];
optim.DEBUG_HANDLER = function() {
snapshots.push([]);
for (var i = 0; i < solver.solvers.length; i++) {
var sys = solver.solvers[i].system;
snapshots[i].push(sys.params.map(function(p) {return p.get()}))
}
};
};
TCAD.TWO.DragTool.prototype.animateSolution = function() {
if (this.snapshots.length === 0) return;
var stepNum = 0;
var scope = this;
var then = Date.now();
var speed = 3000;
function step() {
var now = Date.now();
var elapsed = now - then;
if (elapsed > speed) {
for (var i = 0; i < scope.solver.solvers.length; i++) {
var sys = scope.solver.solvers[i].system;
if (stepNum >= scope.snapshots[i].length) continue;
var values = scope.snapshots[i][stepNum];
for (var k = 0; k < values.length; k++) {
sys.params[k]._backingParam.set(values[k]);
}
}
stepNum ++;
then = now;
scope.viewer.repaint();
}
if (stepNum < scope.snapshots[0].length) {
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
};

View file

@ -236,6 +236,7 @@ TCAD.constraints.P2PDistance = function(params, distance) {
out[p1y] = dy / d;
out[p2x] = -dx / d;
out[p2y] = -dy / d;
for (var i = 0; i < 4; i++) if (Number.isNaN(out[i])) out[i] = 0;
}
};
@ -267,6 +268,7 @@ TCAD.constraints.P2PDistanceV = function(params) {
out[p2x] = -dx / d;
out[p2y] = -dy / d;
out[D] = -1;
for (var i = 0; i < 4; i++) if (Number.isNaN(out[i])) out[i] = 0;
}
};

View file

@ -250,7 +250,7 @@ TCAD.parametric.prepare = function(constrs, locked, aux, alg) {
returnCode : 1
};
var conflict = TCAD.parametric.diagnose(sys).conflict;
var conflict = false;//TCAD.parametric.diagnose(sys).conflict;
if (conflict) {
console.log("Conflicting or redundant constraints. Please fix your system.");
}
@ -271,6 +271,7 @@ TCAD.parametric.prepare = function(constrs, locked, aux, alg) {
diagnose : function() {return TCAD.parametric.diagnose(sys)},
error : function() {return sys.error()},
solveSystem : solve,
system : sys,
updateLock : function(values) {
for (var i = 0; i < values.length; ++i) {
lockingConstrs[i].constr.value = values[i];

View file

@ -60,7 +60,7 @@ TCAD.TWO.ParametricManager.prototype._add = function(constr) {
};
TCAD.TWO.ParametricManager.prototype.checkRedundancy = function (subSystem, constr) {
var solver = this.prepareForSubSystem([], subSystem);
var solver = this.prepareForSubSystem([], subSystem.constraints);
if (solver.diagnose().conflict) {
alert("Most likely this "+constr.NAME + " constraint is CONFLICTING!")
}
@ -295,14 +295,14 @@ TCAD.TWO.ParametricManager.prototype.coincident = function(objs) {
TCAD.TWO.ParametricManager.prototype.getSolveData = function() {
var sdata = [];
for (var i = 0; i < this.subSystems.length; i++) {
this.__getSolveData(this.subSystems[i], sdata);
this.__getSolveData(this.subSystems[i].constraints, sdata);
}
return sdata;
};
TCAD.TWO.ParametricManager.prototype.__getSolveData = function(subSystem, out) {
for (var i = 0; i < subSystem.constraints.length; ++i) {
var constraint = subSystem.constraints[i];
TCAD.TWO.ParametricManager.prototype.__getSolveData = function(constraints, out) {
for (var i = 0; i < constraints.length; ++i) {
var constraint = constraints[i];
var data = constraint.getSolveData();
for (var j = 0; j < data.length; ++j) {
data[j].push(constraint.reducible !== undefined);
@ -324,21 +324,24 @@ TCAD.TWO.ParametricManager.prototype.solveWithLock = function(lock) {
solver.sync();
};
TCAD.TWO.ParametricManager.prototype.prepare = function(locked) {
return this._prepare(locked, this.subSystems);
TCAD.TWO.ParametricManager.prototype.prepare = function(locked, extraConstraints) {
return this._prepare(locked, this.subSystems, extraConstraints);
};
TCAD.TWO.ParametricManager.prototype._prepare = function(locked, subSystems) {
TCAD.TWO.ParametricManager.prototype._prepare = function(locked, subSystems, extraConstraints) {
var solvers = [];
for (var i = 0; i < subSystems.length; i++) {
solvers.push(this.prepareForSubSystem(locked, subSystems[i]));
solvers.push(this.prepareForSubSystem(locked, subSystems[i].constraints, extraConstraints));
}
if (subSystems.length == 0 && locked.length != 0) {
solvers.push(this.prepareForSubSystem(locked, [], extraConstraints));
}
return {
solvers : solvers,
solve : function(rough) {
for (var i = 0; i < solvers.length; i++) {
var alg = subSystems[i].alg;
var alg = i < subSystems.length ? subSystems[i].alg : 1;
var res = solvers[i].solve(rough, alg);
if (res.returnCode !== 1) {
alg = alg == 1 ? 2 : 1;
@ -354,10 +357,10 @@ TCAD.TWO.ParametricManager.prototype._prepare = function(locked, subSystems) {
solvers[i].sync();
}
},
updateLock : function() {
updateLock : function(values) {
for (var i = 0; i < solvers.length; i++) {
solvers[i].updateLock();
solvers[i].updateLock(values);
}
}
}
@ -393,7 +396,7 @@ TCAD.TWO.ParametricManager.__toId = function(v) {
return v.id;
};
TCAD.TWO.ParametricManager.prototype.prepareForSubSystem = function(locked, subSystem) {
TCAD.TWO.ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemConstraints, extraConstraints) {
var pdict = {};
var params;
@ -401,12 +404,17 @@ TCAD.TWO.ParametricManager.prototype.prepareForSubSystem = function(locked, subS
var equalsDict = {};
var equalsIndex = [];
var eqcElimination = [];
var eqcElimination = {};
var lockedIds = locked.map(function(p) {return p.id});
function peq(p1, p2) {
return Math.abs(p1.get() - p2.get()) <= 0.000001
}
var system = this.__getSolveData(subSystem, []);
var system = [];
this.__getSolveData(subSystemConstraints, system);
if (!!extraConstraints) this.__getSolveData(extraConstraints, system);
// system.sort(function(a, b){
// a = a[0] === 'equal' ? 1 : 2;
// b = b[0] === 'equal' ? 1 : 2;
@ -417,18 +425,49 @@ TCAD.TWO.ParametricManager.prototype.prepareForSubSystem = function(locked, subS
var tuples = [];
if (TCAD.EQUALS_ELIMINATION_ENABLED) {
var c, pi, paramIndex = {};
function intersect(array1, array2) {
if (!array1 || !array2) return false;
return array1.filter(function(n) {
return array2.indexOf(n) != -1
}).length != 0;
}
for (i = 0; i < system.length; ++i) {
var c = system[i];
c = system[i];
if (c[3] !== true) {
var sameParams = {};
for (pi = 0; pi < c[1].length; pi++) {
var param = c[1][pi];
var paramConstrs = paramIndex[param.id];
if (paramConstrs === undefined) {
paramConstrs = [];
paramIndex[param.id] = paramConstrs;
}
paramConstrs.push(i);
}
}
}
for (i = 0; i < system.length; ++i) {
c = system[i];
if (c[3] === true) { //Reduce flag
var cp1 = c[1][0];
var cp2 = c[1][1];
//if (!peq(cp1, cp2)) continue;
var p0 = cp1.id;
var p1 = cp2.id;
eqcElimination.push(i);
var assoc0 = paramIndex[p0];
var assoc1 = paramIndex[p1];
if (intersect(assoc0, assoc1)) {
continue;
}
equalsDict[p0] = cp1;
equalsDict[p1] = cp2;
tuples.push([p0, p1]);
eqcElimination[i] = true;
}
}
}
@ -518,14 +557,10 @@ TCAD.TWO.ParametricManager.prototype.prepareForSubSystem = function(locked, subS
var _p;
var ei;
var ii = 0;
var aux = [];
for (i = 0; i < system.length; ++i) {
if (eqcElimination[ii] === i) {
ii++;
continue;
}
if (eqcElimination[i] === true) continue;
var sdata = system[i];
params = [];
@ -542,23 +577,14 @@ TCAD.TWO.ParametricManager.prototype.prepareForSubSystem = function(locked, subS
}
var _locked = [];
var lockedIds = {};
if (locked !== undefined) {
for (p = 0; p < locked.length; ++p) {
_locked[p] = getParam(locked[p]);
lockedIds[locked[p]] = true;
}
}
var lockedValues = [];
var solver = TCAD.parametric.prepare(_constrs, _locked, aux);
function solve(rough, alg) {
if (_locked.length != 0) {
for (p = 0; p < locked.length; ++p) {
lockedValues[p] = locked[p].get() ;
}
solver.updateLock(lockedValues);
}
for (p in pdict) {
_p = pdict[p];
_p.set(_p._backingParam.get());