mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-09 18:02:50 +01:00
constants resolution
This commit is contained in:
parent
68dbb898db
commit
dffaef17b3
5 changed files with 75 additions and 77 deletions
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue