constants resolution

This commit is contained in:
Val Erastov (xibyte) 2020-03-14 23:51:39 -07:00
parent 68dbb898db
commit dffaef17b3
5 changed files with 75 additions and 77 deletions

View file

@ -47,7 +47,8 @@ export function ConstraintButton({prefix='', constraint: c, ...props}) {
const edit = (constraint) => {
if (constraint.editable) {
editConstraint(ui.$constraintEditRequest, constraint, () => {
viewer.parametricManager.reSolve();
viewer.parametricManager.revalidateConstraint(c);
viewer.parametricManager.invalidate();
});
}
};

View file

@ -804,36 +804,6 @@ export const ConstraintDefinitions = {
},
},
Mirror: {
id: 'Mirror',
name: 'Mirror Objects',
modify: (referenceObjects, managedObjects) => {
const reflectionLine = referenceObjects[0];
const dir = new Vector();
dir.set(-(reflectionLine.b.y - reflectionLine.a.y), reflectionLine.b.x - reflectionLine.a.x, 0)._normalize();
for (let i = 0; i < managedObjects.length; i++) {
let origin = reflectionLine.a.toVector();
const pointMirroring = (x, y) => {
let pt = new Vector(x, y, 0);
let proj = dir.dot(pt.minus(origin));
return dir.multiply(- proj * 2)._plus(pt);
};
referenceObjects[i+1].mirror(managedObjects[i], pointMirroring);
}
},
referenceObjects: objects => objects.slice(0, (objects.length >> 1) + 1),
managedObjects: objects => objects.slice((objects.length + 1) >> 1)
}
};
@ -923,17 +893,11 @@ export class AlgNumConstraint {
}
}
modify() {
this.resolveConstants();
this.schema.modify(this.referenceObjects, this.managedObjects, this.resolvedConstants);
}
collectPolynomials(polynomials) {
this.resolveConstants();
this.schema.collectPolynomials(polynomials, this.params, this.resolvedConstants);
}
resolveConstants() {
resolveConstants(expressionResolver) {
if (this.constants) {
if (!this.resolvedConstants) {
this.resolvedConstants = {};
@ -941,6 +905,7 @@ export class AlgNumConstraint {
Object.keys(this.constants).map(name => {
let def = this.schema.constants[name];
let val = this.constants[name];
val = expressionResolver(val);
if (def.type === 'number') {
val = parseFloat(val);
}

View file

@ -34,9 +34,10 @@ export class AlgNumSubSystem {
stage = null;
constructor(calcVisualLimit, stage) {
constructor(calcVisualLimit, expressionResolver, stage) {
this.calcVisualLimit = calcVisualLimit;
this.expressionResolver = expressionResolver;
this.stage = stage;
this.solveStatus = {
@ -99,6 +100,11 @@ export class AlgNumSubSystem {
}
}
revalidateConstraint(constraint) {
this.conflicting.delete(constraint);
this.redundant.delete(constraint);
}
startTransaction() {
this.inTransaction = true;
}
@ -300,6 +306,8 @@ export class AlgNumSubSystem {
}
}));
this.validConstraints(c => c.resolveConstants(this.expressionResolver));
this.evaluateAndBuildSolver();
this.visualLimit = this.calcVisualLimit();

View file

@ -30,10 +30,10 @@ class ParametricManager {
constructor(viewer) {
this.viewer = viewer;
this.reset();
this.viewer.params.define('constantDefinition', null);
this.viewer.params.subscribe('constantDefinition', 'parametricManager', this.onConstantsExternalChange, this)();
this.constantResolver = this.createConstantResolver();
this.reset();
this.$stages.pipe(this.$update);
this.$stages.attach(() => this.viewer.refresh());
@ -43,7 +43,7 @@ class ParametricManager {
reset() {
this.$stages.next({
list: [new SolveStage(this.viewer)],
list: [new SolveStage(this)],
pointer: 0
});
}
@ -84,33 +84,29 @@ class ParametricManager {
this.add(constr);
}
createConstantResolver() {
return value => {
var _value = this.constantTable[value];
if (_value === undefined && this.externalConstantResolver) {
_value = this.externalConstantResolver(value);
}
if (_value !== undefined) {
value = _value;
} else if (typeof(value) != 'number') {
console.error("unable to resolve constant " + value);
}
return value;
constantResolver = value => {
let _value = this.constantTable[value];
if (_value === undefined && this.externalConstantResolver) {
_value = this.externalConstantResolver(value);
}
}
if (_value !== undefined) {
value = _value;
}
return value;
};
rebuildConstantTable(constantDefinition) {
this.constantTable = {};
if (constantDefinition == null) return;
var lines = constantDefinition.split('\n');
var prefix = "(function() { \n";
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
var m = line.match(/^\s*([^\s]+)\s*=(.+)$/);
let lines = constantDefinition.split('\n');
let prefix = "(function() { \n";
for (let i = 0; i < lines.length; i++) {
let line = lines[i];
let m = line.match(/^\s*([^\s]+)\s*=(.+)$/);
if (m != null && m.length === 3) {
var constant = m[1];
let constant = m[1];
try {
var value = eval(prefix + "return " + m[2] + "; \n})()");
let value = eval(prefix + "return " + m[2] + "; \n})()");
this.constantTable[constant] = value;
prefix += "const " + constant + " = " + value + ";\n"
} catch(e) {
@ -226,7 +222,9 @@ class ParametricManager {
_removeObjects(objects, force = false) {
objects.forEach(obj => {
this._removeObject(obj, force);
if (obj.isRoot) {
this._removeObject(obj, force);
}
});
};
@ -238,13 +236,15 @@ class ParametricManager {
if (obj.isGenerated && !force) {
return;
}
obj.constraints.forEach(c => c.stage.algNumSystem._removeConstraint(c));
obj.traverse(o => o.constraints.forEach(c => c.stage.algNumSystem._removeConstraint(c)));
if (obj.layer != null) {
obj.layer.remove(obj);
}
obj.generators.forEach(gen => {
gen.removeObject(obj, o => this._removeObject(o, true), () => this._removeGenerator(gen));
});
obj.traverse(co => co.generators.forEach(gen => {
gen.removeObject(co, o => this._removeObject(o, true), () => this._removeGenerator(gen));
}));
obj.constraints.clear();
obj.generators.clear();
};
@ -255,6 +255,11 @@ class ParametricManager {
}
}
revalidateConstraint(constraint) {
constraint.stage.algNumSystem.revalidateConstraint(constraint);
this.notify();
}
prepare(interactiveObjects) {
for (let stage of this.stages) {
stage.algNumSystem.prepare(interactiveObjects);
@ -270,11 +275,6 @@ class ParametricManager {
}
}
reSolve() {
this.prepare();
this.solve(false);
}
addGenerator(generator) {
generator.generate(this.viewer);
@ -342,7 +342,7 @@ class ParametricManager {
newStage() {
this.$stages.update(s => ({
pointer: s.pointer + 1,
list: [...s.list, new SolveStage(this.viewer)]
list: [...s.list, new SolveStage(this)]
}));
}
@ -354,7 +354,7 @@ class ParametricManager {
let i = list.length;
const createdStages = [];
for (;i<=uptoIndex;i++) {
createdStages.push(new SolveStage(this.viewer));
createdStages.push(new SolveStage(this));
}
this.$stages.update(s => ({
pointer: uptoIndex,
@ -376,11 +376,15 @@ class SolveStage {
generators = new Set();
objects = new Set();
constructor(viewer) {
this.viewer = viewer;
constructor(parametricManager) {
this.parametricManager = parametricManager;
this.algNumSystem = this.createAlgNumSystem();
}
get viewer() {
return this.parametricManager.viewer;
}
assignObject(object) {
object.stage = this;
this.objects.add(object);
@ -418,7 +422,7 @@ class SolveStage {
return Math.abs(x2 - x1);
};
return new AlgNumSubSystem(calcVisualLimit, this);
return new AlgNumSubSystem(calcVisualLimit, this.parametricManager.constantResolver, this);
}
get index() {

View file

@ -10,6 +10,7 @@ export class SketchObject extends Shape {
constructor() {
super();
this.id = Generator.genID();
this.parent = null;
this.markers = [];
this.children = [];
this.layer = null;
@ -64,6 +65,13 @@ export class SketchObject extends Shape {
return visitor(this);
}
traverse(visitor) {
for (let child of this.children) {
child.accept(visitor);
}
visitor(this);
}
stabilize(viewer) {
}
@ -215,6 +223,18 @@ export class SketchObject extends Shape {
obj = obj.parent;
}
}
root() {
let obj = this;
while (obj.parent) {
obj = obj.parent;
}
return obj;
}
get isRoot() {
return this.parent === null;
}
}
export function pointIterator(shape, func) {