jsketcher/web/app/sketcher/shapes/sketch-object.js
Val Erastov (xibyte) dffaef17b3 constants resolution
2020-03-14 23:51:39 -07:00

251 lines
No EOL
4.6 KiB
JavaScript

import {Generator} from '../id-generator'
import {Shape} from './shape'
import {Types} from '../io';
import {Styles} from "../styles";
import {dfs} from 'gems/traverse';
import {ConstraintDefinitions} from "../constr/ANConstraints";
export class SketchObject extends Shape {
constructor() {
super();
this.id = Generator.genID();
this.parent = null;
this.markers = [];
this.children = [];
this.layer = null;
this.constraints = new Set();
this.readOnly = false;
this.fullyConstrained = false;
this.generator = null;
this.generators = new Set();
this._stage = null;
}
get isGenerated() {
let obj = this;
while (obj) {
if (obj.generator) {
return true;
}
obj = obj.parent;
}
return false;
}
get stage() {
if (this._stage) {
return this._stage;
}
if (this.parent) {
return this.parent.stage;
}
return null;
}
set stage(value) {
this._stage = value;
}
normalDistance(aim, scale) {
return -1;
}
addChild(child) {
this.children.push(child);
child.parent = this;
}
accept(visitor) {
for (let child of this.children) {
if (!child.accept(visitor)) {
return false;
}
}
return visitor(this);
}
traverse(visitor) {
for (let child of this.children) {
child.accept(visitor);
}
visitor(this);
}
stabilize(viewer) {
}
syncGeometry() {
}
recoverIfNecessary() {
return false;
}
visitLinked(cb) {
cb(this);
}
translate(dx, dy) {
// this.translateImpl(dx, dy);
if (this.readOnly) {
return;
}
this.visitLinked(obj => {
obj.translateImpl(dx, dy);
obj.ancestry(a => a.syncGeometry());
});
}
translateImpl(dx, dy) {
this.accept(function (obj) {
if (obj._class === 'TCAD.TWO.EndPoint') {
obj.translate(dx, dy);
}
return true;
});
}
addMarker(style) {
this.markers.push(style);
this.markers.sort((a, b) => (a.priority||99999) - (b.priority||99999))
}
removeMarker(style) {
const index = this.markers.indexOf(style);
if (index !== -1) {
this.markers.splice(index, 1);
}
}
get marked() {
return this.markers.length !== 0;
}
draw(ctx, scale, viewer) {
if (!this.visible) return;
const customStyle = this.getCustomStyle();
if (customStyle !== null) {
ctx.save();
viewer.setStyle(customStyle, ctx);
}
this.drawImpl(ctx, scale, viewer);
if (customStyle !== null) ctx.restore();
}
getCustomStyle() {
const productionKind = this.classify();
if (this.markers.length !== 0) {
return this.markers[0];
} else if (productionKind === PAST) {
return Styles.PAST;
} else if (productionKind === FUTURE) {
return Styles.FUTURE;
} else if (this.isGenerated) {
return Styles.GENERATED;
} else if (this.fullyConstrained) {
return Styles.FULLY_CONSTRAINED;
} else {
}
return null;
}
classify() {
if (!this.stage) {
return CURRENT;
}
const thisIndex = this.stage.index;
const activeIndex = this.stage.viewer.parametricManager.stage.index;
if (thisIndex < activeIndex) {
return PAST;
} else if (thisIndex > activeIndex) {
return FUTURE;
} else {
return CURRENT;
}
}
copy() {
throw 'method not implemented';
}
mirror(dest, mirroringFunc) {
let sourcePoints = [];
pointIterator(this, o => {
sourcePoints.push(o);
});
let i = 0;
pointIterator(dest, o => {
sourcePoints[i++].mirror(o, mirroringFunc);
});
}
visitParams(callback) {
throw 'method not implemented';
}
collectParams(params) {
this.visitParams(p => params.push(p));
}
get simpleClassName() {
return this._class.replace('TCAD.TWO.', '');
}
get effectiveLayer() {
let shape = this;
while (shape) {
if (shape.layer) {
return shape.layer;
}
shape = shape.parent;
}
return null;
}
getConstraintByType(typeId) {
for (let c of this.constraints) {
if (c.schema.id === typeId) {
return c;
}
}
return null;
}
ancestry(cb) {
let obj = this;
while (obj) {
cb(obj);
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) {
shape.accept(o => {
if (o._class === Types.POINT) {
func(o);
}
return true;
});
}
const PAST = 1;
const CURRENT = 2;
const FUTURE = 3;