mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-10 02:13:58 +01:00
refactoring of equals elimination
This commit is contained in:
parent
3029bf6a9a
commit
56a025b8d0
1 changed files with 113 additions and 122 deletions
|
|
@ -7,7 +7,6 @@ import * as math from '../math/math'
|
|||
import * as fetch from './fetchers'
|
||||
|
||||
var Constraints = {};
|
||||
var EQUALS_ELIMINATION_ENABLED = true;
|
||||
|
||||
/** @constructor */
|
||||
function SubSystem() {
|
||||
|
|
@ -545,68 +544,55 @@ ParametricManager.__toId = function(v) {
|
|||
return v.id;
|
||||
};
|
||||
|
||||
ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemConstraints, extraConstraints) {
|
||||
|
||||
var pdict = {};
|
||||
var params;
|
||||
var _constrs = [];
|
||||
|
||||
var equalsDict = {};
|
||||
var equalsIndex = [];
|
||||
var eqcElimination = {};
|
||||
|
||||
var system = [];
|
||||
this.__getSolveData(subSystemConstraints, system);
|
||||
if (!!extraConstraints) this.__getSolveData(extraConstraints, system);
|
||||
|
||||
var auxParams = [];
|
||||
var auxDict = {};
|
||||
|
||||
ParametricManager.fetchAuxParams(system, auxParams, auxDict);
|
||||
ParametricManager.reduceSystem = function(system, readOnlyParams) {
|
||||
|
||||
var info = {
|
||||
idToParam : {},
|
||||
linkedParams : [],
|
||||
reducedConstraints : {},
|
||||
reducedParams : {}
|
||||
};
|
||||
|
||||
var links = [];
|
||||
if (EQUALS_ELIMINATION_ENABLED) {
|
||||
var c, pi, paramToConstraints = {};
|
||||
for (i = 0; i < system.length; ++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 = paramToConstraints[param.id];
|
||||
if (paramConstrs === undefined) {
|
||||
paramConstrs = [];
|
||||
paramToConstraints[param.id] = paramConstrs;
|
||||
}
|
||||
paramConstrs.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
function Link(a, b, constr) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.constr = constr;
|
||||
this.invalid = false;
|
||||
this.processed = false;
|
||||
}
|
||||
|
||||
function Link(a, b, constr) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.constr = constr;
|
||||
this.invalid = false;
|
||||
this.processed = false;
|
||||
}
|
||||
|
||||
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];
|
||||
links.push(new Link(cp1, cp2, i));
|
||||
var c, pi, paramToConstraints = {};
|
||||
for (i = 0; i < system.length; ++i) {
|
||||
c = system[i];
|
||||
if (c[3] !== true) {
|
||||
for (pi = 0; pi < c[1].length; pi++) {
|
||||
var param = c[1][pi];
|
||||
var paramConstrs = paramToConstraints[param.id];
|
||||
if (paramConstrs === undefined) {
|
||||
paramConstrs = [];
|
||||
paramToConstraints[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];
|
||||
links.push(new Link(cp1, cp2, i));
|
||||
}
|
||||
}
|
||||
function intersect(array1, array2) {
|
||||
if (!array1 || !array2) return false;
|
||||
return array1.filter(function(n) {
|
||||
return array2.indexOf(n) != -1
|
||||
}).length != 0;
|
||||
}
|
||||
|
||||
|
||||
function shared(param1, param2) {
|
||||
if (param1 == param2) return false;
|
||||
var assoc0 = paramToConstraints[param1];
|
||||
|
|
@ -615,7 +601,7 @@ ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemCons
|
|||
}
|
||||
|
||||
var linkTuples = [];
|
||||
|
||||
|
||||
function mergeLinks(startIndex, into) {
|
||||
var linkI = links[startIndex];
|
||||
if (linkI.processed) return;
|
||||
|
|
@ -632,13 +618,13 @@ ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemCons
|
|||
if (links[i].processed) continue;
|
||||
var linkTuple = [];
|
||||
linkTuples.push(linkTuple);
|
||||
mergeLinks(i, linkTuple)
|
||||
mergeLinks(i, linkTuple)
|
||||
}
|
||||
|
||||
|
||||
function resolveConflicts() {
|
||||
for (var i = 0; i < linkTuples.length; i++) {
|
||||
var tuple = linkTuples[i];
|
||||
|
||||
|
||||
for (var j = 0; j < tuple.length; j++) {
|
||||
var linkA = tuple[j];
|
||||
if (linkA.invalid) continue;
|
||||
|
|
@ -675,23 +661,22 @@ ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemCons
|
|||
var link = linkTuple[j];
|
||||
if (!link.invalid) {
|
||||
_merge(tuple, [link.a.id, link.b.id]);
|
||||
eqcElimination[link.constr] = true;
|
||||
equalsDict[link.a.id] = link.a;
|
||||
equalsDict[link.b.id] = link.b;
|
||||
info.reducedConstraints[link.constr] = true;
|
||||
info.idToParam[link.a.id] = link.a;
|
||||
info.idToParam[link.b.id] = link.b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return tuples;
|
||||
}
|
||||
}
|
||||
var tuples = linksToTuples(linkTuples);
|
||||
|
||||
var readOnlyParams = auxParams.concat(locked);
|
||||
for (var i = 0; i < tuples.length; ++i) {
|
||||
var tuple = tuples[i];
|
||||
equalsIndex.push(tuple);
|
||||
info.linkedParams.push(tuple);
|
||||
for (var mi = 0; mi < readOnlyParams.length; ++mi) {
|
||||
var master = readOnlyParams[mi];
|
||||
var masterIdx = tuple.indexOf(master.id);
|
||||
var masterParam = readOnlyParams[mi];
|
||||
var masterIdx = tuple.indexOf(masterParam.id);
|
||||
if (masterIdx >= 0) {
|
||||
var tmp = tuple[0];
|
||||
tuple[0] = tuple[masterIdx];
|
||||
|
|
@ -701,20 +686,36 @@ ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemCons
|
|||
}
|
||||
}
|
||||
|
||||
var equalsElimination = {};
|
||||
for (ei = 0; ei < equalsIndex.length; ++ei) {
|
||||
var master = equalsIndex[ei][0];
|
||||
for (i = 1; i < equalsIndex[ei].length; ++i) {
|
||||
equalsElimination[equalsIndex[ei][i]] = master;
|
||||
for (var ei = 0; ei < info.linkedParams.length; ++ei) {
|
||||
var master = info.linkedParams[ei][0];
|
||||
for (i = 1; i < info.linkedParams[ei].length; ++i) {
|
||||
info.reducedParams[info.linkedParams[ei][i]] = master;
|
||||
}
|
||||
}
|
||||
return info;
|
||||
};
|
||||
|
||||
ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemConstraints, extraConstraints) {
|
||||
|
||||
var constrs = [];
|
||||
var solverParamsDict = {};
|
||||
var system = [];
|
||||
var auxParams = [];
|
||||
var auxDict = {};
|
||||
|
||||
function getParam(p) {
|
||||
var master = equalsElimination[p.id];
|
||||
this.__getSolveData(subSystemConstraints, system);
|
||||
if (!!extraConstraints) this.__getSolveData(extraConstraints, system);
|
||||
|
||||
ParametricManager.fetchAuxParams(system, auxParams, auxDict);
|
||||
var readOnlyParams = auxParams.concat(locked);
|
||||
var reduceInfo = ParametricManager.reduceSystem(system, readOnlyParams);
|
||||
|
||||
function getSolverParam(p) {
|
||||
var master = reduceInfo.reducedParams[p.id];
|
||||
if (master !== undefined) {
|
||||
p = equalsDict[master];
|
||||
p = reduceInfo.idToParam[master];
|
||||
}
|
||||
var _p = pdict[p.id];
|
||||
var _p = solverParamsDict[p.id];
|
||||
if (_p === undefined) {
|
||||
if (p.__cachedParam__ === undefined) {
|
||||
_p = new Param(p.id, p.get());
|
||||
|
|
@ -725,84 +726,74 @@ ParametricManager.prototype.prepareForSubSystem = function(locked, subSystemCons
|
|||
}
|
||||
|
||||
_p._backingParam = p;
|
||||
pdict[p.id] = _p;
|
||||
solverParamsDict[p.id] = _p;
|
||||
}
|
||||
return _p;
|
||||
}
|
||||
|
||||
var i;
|
||||
var p;
|
||||
var _p;
|
||||
var ei;
|
||||
|
||||
(function pickupAuxiliaryInfoFromSlaves() {
|
||||
for (var i = 0; i < reduceInfo.linkedParams.length; ++i) {
|
||||
var linkedParams = reduceInfo.linkedParams[i];
|
||||
var master = linkedParams[0];
|
||||
if (auxDict[master] !== undefined) continue;
|
||||
for (var j = 1; j < linkedParams.length; j++) {
|
||||
var slave = linkedParams[j];
|
||||
if (auxDict[slave] !== undefined) {
|
||||
auxDict[master] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
var aux = [];
|
||||
for (i = 0; i < system.length; ++i) {
|
||||
|
||||
for (var i = 0; i < system.length; ++i) {
|
||||
|
||||
var sdata = system[i];
|
||||
params = [];
|
||||
var params = [];
|
||||
|
||||
for (p = 0; p < sdata[1].length; ++p) {
|
||||
for (var p = 0; p < sdata[1].length; ++p) {
|
||||
var param = sdata[1][p];
|
||||
_p = getParam(param);
|
||||
params.push(_p);
|
||||
|
||||
(function () {
|
||||
if (auxDict[param.id] !== undefined) {
|
||||
aux.push(_p);
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < equalsIndex.length; ++i) {
|
||||
var eqParms = equalsIndex[i];
|
||||
if (eqParms.indexOf(param.id) != -1) {
|
||||
for (var j = 0; j < eqParms.length; j++) {
|
||||
var eqp = eqParms[j];
|
||||
if (auxDict[eqp] !== undefined) {
|
||||
aux.push(_p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
var solverParam = getSolverParam(param);
|
||||
params.push(solverParam);
|
||||
if (auxDict[param.id] !== undefined) {
|
||||
aux.push(solverParam);
|
||||
}
|
||||
}
|
||||
if (eqcElimination[i] === true) continue;
|
||||
if (reduceInfo.reducedConstraints[i] === true) continue;
|
||||
|
||||
var _constr = createByConstraintName(sdata[0], params, sdata[2]);
|
||||
_constrs.push(_constr);
|
||||
constrs.push(_constr);
|
||||
}
|
||||
|
||||
var _locked = [];
|
||||
if (locked !== undefined) {
|
||||
for (p = 0; p < locked.length; ++p) {
|
||||
_locked[p] = getParam(locked[p]);
|
||||
}
|
||||
var lockedSolverParams = [];
|
||||
for (p = 0; p < locked.length; ++p) {
|
||||
lockedSolverParams[p] = getSolverParam(locked[p]);
|
||||
}
|
||||
|
||||
var solver = prepare(_constrs, _locked, aux);
|
||||
var solver = prepare(constrs, lockedSolverParams, aux);
|
||||
function solve(rough, alg) {
|
||||
return solver.solveSystem(rough, alg);
|
||||
}
|
||||
var viewer = this.viewer;
|
||||
function sync() {
|
||||
for (var p in pdict) {
|
||||
var _p = pdict[p];
|
||||
if (!!_p._backingParam.__aux) continue;
|
||||
_p._backingParam.set(_p.get());
|
||||
for (var paramId in solverParamsDict) {
|
||||
var solverParam = solverParamsDict[paramId];
|
||||
if (!!solverParam._backingParam.aux) continue;
|
||||
solverParam._backingParam.set(solverParam.get());
|
||||
}
|
||||
|
||||
//Make sure all coincident constraints are equal
|
||||
for (var ei = 0; ei < equalsIndex.length; ++ei) {
|
||||
var master = equalsDict[ equalsIndex[ei][0]];
|
||||
for (var i = 1; i < equalsIndex[ei].length; ++i) {
|
||||
var slave = equalsDict[equalsIndex[ei][i]];
|
||||
for (var ei = 0; ei < reduceInfo.linkedParams.length; ++ei) {
|
||||
var master = reduceInfo.idToParam[ reduceInfo.linkedParams[ei][0]];
|
||||
for (var i = 1; i < reduceInfo.linkedParams[ei].length; ++i) {
|
||||
var slave = reduceInfo.idToParam[reduceInfo.linkedParams[ei][i]];
|
||||
slave.set(master.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateParameter(p) {
|
||||
getParam(p).set(p.get());
|
||||
getSolverParam(p).set(p.get());
|
||||
}
|
||||
|
||||
solver.solve = solve;
|
||||
|
|
|
|||
Loading…
Reference in a new issue