From dffaef17b3a73ab7617a1279ba94544e7a610c07 Mon Sep 17 00:00:00 2001 From: "Val Erastov (xibyte)" Date: Sat, 14 Mar 2020 23:51:39 -0700 Subject: [PATCH] constants resolution --- .../components/ConstraintExplorer.jsx | 3 +- web/app/sketcher/constr/ANConstraints.js | 39 +-------- web/app/sketcher/constr/AlgNumSystem.js | 10 ++- web/app/sketcher/parametric.js | 80 ++++++++++--------- web/app/sketcher/shapes/sketch-object.js | 20 +++++ 5 files changed, 75 insertions(+), 77 deletions(-) diff --git a/web/app/sketcher/components/ConstraintExplorer.jsx b/web/app/sketcher/components/ConstraintExplorer.jsx index c494ee1f..e67329ce 100644 --- a/web/app/sketcher/components/ConstraintExplorer.jsx +++ b/web/app/sketcher/components/ConstraintExplorer.jsx @@ -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(); }); } }; diff --git a/web/app/sketcher/constr/ANConstraints.js b/web/app/sketcher/constr/ANConstraints.js index 25f120d0..c5e627f0 100644 --- a/web/app/sketcher/constr/ANConstraints.js +++ b/web/app/sketcher/constr/ANConstraints.js @@ -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); } diff --git a/web/app/sketcher/constr/AlgNumSystem.js b/web/app/sketcher/constr/AlgNumSystem.js index 9769b724..74c7f518 100644 --- a/web/app/sketcher/constr/AlgNumSystem.js +++ b/web/app/sketcher/constr/AlgNumSystem.js @@ -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(); diff --git a/web/app/sketcher/parametric.js b/web/app/sketcher/parametric.js index 2a1bb290..f52ee91c 100644 --- a/web/app/sketcher/parametric.js +++ b/web/app/sketcher/parametric.js @@ -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() { diff --git a/web/app/sketcher/shapes/sketch-object.js b/web/app/sketcher/shapes/sketch-object.js index dea20212..6cc4b825 100644 --- a/web/app/sketcher/shapes/sketch-object.js +++ b/web/app/sketcher/shapes/sketch-object.js @@ -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) {