mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 16:33:15 +01:00
assembly infrastructure
This commit is contained in:
parent
06682ab003
commit
4ddf018fc6
85 changed files with 1951 additions and 504 deletions
2
modules/lstream/index.d.ts
vendored
2
modules/lstream/index.d.ts
vendored
|
|
@ -52,7 +52,7 @@ export function distinctState<T>(initialValue: T): StateStream<T>;
|
||||||
|
|
||||||
export function externalState<T>(get: any, set: any): StateStream<T>;
|
export function externalState<T>(get: any, set: any): StateStream<T>;
|
||||||
|
|
||||||
export function never<T>(): Stream<T>
|
export function never<T>(): Emitter<T>
|
||||||
|
|
||||||
export function constant<T>(value: T): Stream<T>
|
export function constant<T>(value: T): Stream<T>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@ export class NeverStream extends StreamBase {
|
||||||
attach(observer) {
|
attach(observer) {
|
||||||
return NOOP;
|
return NOOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next(value) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NeverStream.INSTANCE = new NeverStream();
|
NeverStream.INSTANCE = new NeverStream();
|
||||||
|
|
|
||||||
|
|
@ -30,25 +30,27 @@ export default class CSys {
|
||||||
w() {
|
w() {
|
||||||
return this.z.dot(this.origin);
|
return this.z.dot(this.origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get outTransformation3x3() {
|
||||||
|
return new Matrix3().setBasisAxises(this.x, this.y, this.z);
|
||||||
|
}
|
||||||
|
|
||||||
get outTransformation() {
|
get outTransformation() {
|
||||||
if (!this._outTr) {
|
const mx = new Matrix3().setBasisAxises(this.x, this.y, this.z);
|
||||||
const mx = new Matrix3().setBasisAxises(this.x, this.y, this.z);
|
mx.tx = this.origin.x;
|
||||||
mx.tx = this.origin.x;
|
mx.ty = this.origin.y;
|
||||||
mx.ty = this.origin.y;
|
mx.tz = this.origin.z;
|
||||||
mx.tz = this.origin.z;
|
return mx;
|
||||||
this._outTr = mx;
|
}
|
||||||
}
|
|
||||||
return this._outTr;
|
get inTransformation3x3() {
|
||||||
|
return this.outTransformation3x3.invert();
|
||||||
}
|
}
|
||||||
|
|
||||||
get inTransformation() {
|
get inTransformation() {
|
||||||
if (!this._inTr) {
|
return this.outTransformation.invert();
|
||||||
this._inTr = this.outTransformation.invert();
|
|
||||||
}
|
|
||||||
return this._inTr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(csys) {
|
copy(csys) {
|
||||||
this.origin.setV(csys.origin);
|
this.origin.setV(csys.origin);
|
||||||
this.x.setV(csys.x);
|
this.x.setV(csys.x);
|
||||||
|
|
@ -65,7 +67,16 @@ export default class CSys {
|
||||||
this.origin.set(x, y, z);
|
this.origin.set(x, y, z);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
invert() {
|
||||||
|
const tr = this.inTransformation;
|
||||||
|
return new CSys(
|
||||||
|
new Vector(tr.tx, tr.ty, tr.tz),
|
||||||
|
new Vector(tr.mxx, tr.myx, tr.mzx),
|
||||||
|
new Vector(tr.mxy, tr.myy, tr.mzy),
|
||||||
|
new Vector(tr.mxz, tr.myz, tr.mzz)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSys.ORIGIN = CSys.origin();
|
CSys.ORIGIN = CSys.origin();
|
||||||
371
modules/math/l3space.ts
Normal file
371
modules/math/l3space.ts
Normal file
|
|
@ -0,0 +1,371 @@
|
||||||
|
import Vector from 'math/vector';
|
||||||
|
|
||||||
|
export type Basis = [Vector, Vector, Vector];
|
||||||
|
|
||||||
|
export type Vec3 = [number, number, number];
|
||||||
|
|
||||||
|
const freeze = Object.freeze;
|
||||||
|
|
||||||
|
const ORIGIN = freeze(new Vector(0, 0, 0));
|
||||||
|
|
||||||
|
const AXIS = freeze({
|
||||||
|
X: freeze(new Vector(1, 0, 0)),
|
||||||
|
Y: freeze(new Vector(0, 1, 0)),
|
||||||
|
Z: freeze(new Vector(0, 0, 1))
|
||||||
|
});
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const IDENTITY_BASIS: Basis = Object.freeze([AXIS.X, AXIS.Y, AXIS.Z]);
|
||||||
|
|
||||||
|
export const STANDARD_BASES = freeze({
|
||||||
|
'XY': IDENTITY_BASIS,
|
||||||
|
'XZ': [AXIS.X, AXIS.Z, AXIS.Y],
|
||||||
|
'ZY': [AXIS.Z, AXIS.Y, AXIS.X]
|
||||||
|
});
|
||||||
|
|
||||||
|
export class Matrix3 {
|
||||||
|
|
||||||
|
mxx: number = 1;
|
||||||
|
mxy: number = 0;
|
||||||
|
mxz: number = 0;
|
||||||
|
tx: number = 0;
|
||||||
|
myx: number = 0;
|
||||||
|
myy: number = 1;
|
||||||
|
myz: number = 0;
|
||||||
|
ty: number = 0;
|
||||||
|
mzx: number = 0;
|
||||||
|
mzy: number = 0;
|
||||||
|
mzz: number = 1;
|
||||||
|
tz: number = 0;
|
||||||
|
|
||||||
|
reset(): Matrix3 {
|
||||||
|
this.mxx = 1;
|
||||||
|
this.mxy = 0;
|
||||||
|
this.mxz = 0;
|
||||||
|
this.tx = 0;
|
||||||
|
this.myx = 0;
|
||||||
|
this.myy = 1;
|
||||||
|
this.myz = 0;
|
||||||
|
this.ty = 0;
|
||||||
|
this.mzx = 0;
|
||||||
|
this.mzy = 0;
|
||||||
|
this.mzz = 1;
|
||||||
|
this.tz = 0;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
setBasis(basis: [Vector, Vector, Vector]): Matrix3 {
|
||||||
|
var b = basis;
|
||||||
|
this.mxx = b[0].x;
|
||||||
|
this.mxy = b[1].x;
|
||||||
|
this.mxz = b[2].x;
|
||||||
|
this.tx = 0;
|
||||||
|
this.myx = b[0].y;
|
||||||
|
this.myy = b[1].y;
|
||||||
|
this.myz = b[2].y;
|
||||||
|
this.ty = 0;
|
||||||
|
this.mzx = b[0].z;
|
||||||
|
this.mzy = b[1].z;
|
||||||
|
this.mzz = b[2].z;
|
||||||
|
this.tz = 0;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
setBasisAxises(x: Vector, y: Vector, z: Vector): Matrix3 {
|
||||||
|
this.mxx = x.x;
|
||||||
|
this.mxy = y.x;
|
||||||
|
this.mxz = z.x;
|
||||||
|
this.tx = 0;
|
||||||
|
this.myx = x.y;
|
||||||
|
this.myy = y.y;
|
||||||
|
this.myz = z.y;
|
||||||
|
this.ty = 0;
|
||||||
|
this.mzx = x.z;
|
||||||
|
this.mzy = y.z;
|
||||||
|
this.mzz = z.z;
|
||||||
|
this.tz = 0;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
setBasisAndTranslation(basis: [Vector, Vector, Vector], translation: Vector): Matrix3 {
|
||||||
|
this.setBasis(basis);
|
||||||
|
this.tx = translation.x;
|
||||||
|
this.ty = translation.y;
|
||||||
|
this.tz = translation.z;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
scale(dx: number, dy: number, dz: number): Matrix3{
|
||||||
|
this.mxx *= dx;
|
||||||
|
this.myy *= dy;
|
||||||
|
this.mzz *= dz;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
translate(dx: number, dy: number, dz: number): Matrix3 {
|
||||||
|
this.tx += dx;
|
||||||
|
this.ty += dy;
|
||||||
|
this.tz += dz;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
set3(
|
||||||
|
mxx: number, mxy: number, mxz: number,
|
||||||
|
myx: number, myy: number, myz: number,
|
||||||
|
mzx: number, mzy: number, mzz: number
|
||||||
|
): Matrix3 {
|
||||||
|
this.mxx = mxx;
|
||||||
|
this.mxy = mxy;
|
||||||
|
this.mxz = mxz;
|
||||||
|
this.myx = myx;
|
||||||
|
this.myy = myy;
|
||||||
|
this.myz = myz;
|
||||||
|
this.mzx = mzx;
|
||||||
|
this.mzy = mzy;
|
||||||
|
this.mzz = mzz;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
set34(
|
||||||
|
mxx: number, mxy: number, mxz: number, tx: number,
|
||||||
|
myx: number, myy: number, myz: number, ty: number,
|
||||||
|
mzx: number, mzy: number, mzz: number, tz: number
|
||||||
|
): Matrix3 {
|
||||||
|
this.mxx = mxx;
|
||||||
|
this.mxy = mxy;
|
||||||
|
this.mxz = mxz;
|
||||||
|
this.tx = tx;
|
||||||
|
this.myx = myx;
|
||||||
|
this.myy = myy;
|
||||||
|
this.myz = myz;
|
||||||
|
this.ty = ty;
|
||||||
|
this.mzx = mzx;
|
||||||
|
this.mzy = mzy;
|
||||||
|
this.mzz = mzz;
|
||||||
|
this.tz = tz;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
setMatrix(m: Matrix3): Matrix3 {
|
||||||
|
this.mxx = m.mxx;
|
||||||
|
this.mxy = m.mxy;
|
||||||
|
this.mxz = m.mxz;
|
||||||
|
this.tx = m.tx;
|
||||||
|
this.myx = m.myx;
|
||||||
|
this.myy = m.myy;
|
||||||
|
this.myz = m.myz;
|
||||||
|
this.ty = m.ty;
|
||||||
|
this.mzx = m.mzx;
|
||||||
|
this.mzy = m.mzy;
|
||||||
|
this.mzz = m.mzz;
|
||||||
|
this.tz = m.tz;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
setToMatrix(m: any): void {
|
||||||
|
m.set(
|
||||||
|
this.mxx, this.mxy, this.mxz, this.tx,
|
||||||
|
this.myx, this.myy, this.myz, this.ty,
|
||||||
|
this.mzx, this.mzy, this.mzz, this.tz,
|
||||||
|
0, 0, 0, 1
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
toArray(): [[number, number, number, number],[number, number, number, number],[number, number, number, number]] {
|
||||||
|
return [
|
||||||
|
[this.mxx, this.mxy, this.mxz, this.tx],
|
||||||
|
[this.myx, this.myy, this.myz, this.ty],
|
||||||
|
[this.mzx, this.mzy, this.mzz, this.tz]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
invert(): Matrix3 {
|
||||||
|
return this.__invert(new Matrix3());
|
||||||
|
};
|
||||||
|
|
||||||
|
_invert(): Matrix3 {
|
||||||
|
return this.__invert(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
__invert(out: Matrix3): Matrix3 {
|
||||||
|
|
||||||
|
var det =
|
||||||
|
this.mxx * (this.myy * this.mzz - this.mzy * this.myz) +
|
||||||
|
this.mxy * (this.myz * this.mzx - this.mzz * this.myx) +
|
||||||
|
this.mxz * (this.myx * this.mzy - this.mzx * this.myy);
|
||||||
|
|
||||||
|
if (det == 0.0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cxx = this.myy * this.mzz - this.myz * this.mzy;
|
||||||
|
var cyx = -this.myx * this.mzz + this.myz * this.mzx;
|
||||||
|
var czx = this.myx * this.mzy - this.myy * this.mzx;
|
||||||
|
var cxt = -this.mxy * (this.myz * this.tz - this.mzz * this.ty)
|
||||||
|
- this.mxz * (this.ty * this.mzy - this.tz * this.myy)
|
||||||
|
- this.tx * (this.myy * this.mzz - this.mzy * this.myz);
|
||||||
|
var cxy = -this.mxy * this.mzz + this.mxz * this.mzy;
|
||||||
|
var cyy = this.mxx * this.mzz - this.mxz * this.mzx;
|
||||||
|
var czy = -this.mxx * this.mzy + this.mxy * this.mzx;
|
||||||
|
var cyt = this.mxx * (this.myz * this.tz - this.mzz * this.ty)
|
||||||
|
+ this.mxz * (this.ty * this.mzx - this.tz * this.myx)
|
||||||
|
+ this.tx * (this.myx * this.mzz - this.mzx * this.myz);
|
||||||
|
var cxz = this.mxy * this.myz - this.mxz * this.myy;
|
||||||
|
var cyz = -this.mxx * this.myz + this.mxz * this.myx;
|
||||||
|
var czz = this.mxx * this.myy - this.mxy * this.myx;
|
||||||
|
var czt = -this.mxx * (this.myy * this.tz - this.mzy * this.ty)
|
||||||
|
- this.mxy * (this.ty * this.mzx - this.tz * this.myx)
|
||||||
|
- this.tx * (this.myx * this.mzy - this.mzx * this.myy);
|
||||||
|
|
||||||
|
out.mxx = cxx / det;
|
||||||
|
out.mxy = cxy / det;
|
||||||
|
out.mxz = cxz / det;
|
||||||
|
out.tx = cxt / det;
|
||||||
|
out.myx = cyx / det;
|
||||||
|
out.myy = cyy / det;
|
||||||
|
out.myz = cyz / det;
|
||||||
|
out.ty = cyt / det;
|
||||||
|
out.mzx = czx / det;
|
||||||
|
out.mzy = czy / det;
|
||||||
|
out.mzz = czz / det;
|
||||||
|
out.tz = czt / det;
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
combine(transform: Matrix3, out?: Matrix3): Matrix3 {
|
||||||
|
var txx = transform.mxx;
|
||||||
|
var txy = transform.mxy;
|
||||||
|
var txz = transform.mxz;
|
||||||
|
var ttx = transform.tx;
|
||||||
|
var tyx = transform.myx;
|
||||||
|
var tyy = transform.myy;
|
||||||
|
var tyz = transform.myz;
|
||||||
|
var tty = transform.ty;
|
||||||
|
var tzx = transform.mzx;
|
||||||
|
var tzy = transform.mzy;
|
||||||
|
var tzz = transform.mzz;
|
||||||
|
var ttz = transform.tz;
|
||||||
|
|
||||||
|
var m = out || new Matrix3();
|
||||||
|
m.mxx = (this.mxx * txx + this.mxy * tyx + this.mxz * tzx);
|
||||||
|
m.mxy = (this.mxx * txy + this.mxy * tyy + this.mxz * tzy);
|
||||||
|
m.mxz = (this.mxx * txz + this.mxy * tyz + this.mxz * tzz);
|
||||||
|
m.tx = (this.mxx * ttx + this.mxy * tty + this.mxz * ttz + this.tx);
|
||||||
|
m.myx = (this.myx * txx + this.myy * tyx + this.myz * tzx);
|
||||||
|
m.myy = (this.myx * txy + this.myy * tyy + this.myz * tzy);
|
||||||
|
m.myz = (this.myx * txz + this.myy * tyz + this.myz * tzz);
|
||||||
|
m.ty = (this.myx * ttx + this.myy * tty + this.myz * ttz + this.ty);
|
||||||
|
m.mzx = (this.mzx * txx + this.mzy * tyx + this.mzz * tzx);
|
||||||
|
m.mzy = (this.mzx * txy + this.mzy * tyy + this.mzz * tzy);
|
||||||
|
m.mzz = (this.mzx * txz + this.mzy * tyz + this.mzz * tzz);
|
||||||
|
m.tz = (this.mzx * ttx + this.mzy * tty + this.mzz * ttz + this.tz);
|
||||||
|
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
_apply(vector: Vector): Vector {
|
||||||
|
return this.__apply(vector, vector);
|
||||||
|
};
|
||||||
|
|
||||||
|
__apply(vector: Vector, out: Vector): Vector {
|
||||||
|
let x = vector.x;
|
||||||
|
let y = vector.y;
|
||||||
|
let z = vector.z;
|
||||||
|
out.x = this.mxx * x + this.mxy * y + this.mxz * z + this.tx;
|
||||||
|
out.y = this.myx * x + this.myy * y + this.myz * z + this.ty;
|
||||||
|
out.z = this.mzx * x + this.mzy * y + this.mzz * z + this.tz;
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
apply3(data: Vec3): Vec3 {
|
||||||
|
return this.__apply3(data, [0,0,0])
|
||||||
|
};
|
||||||
|
|
||||||
|
_apply3(data: Vec3): Vec3 {
|
||||||
|
return this.__apply3(data, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
__apply3([x, y, z]: Vec3, out: Vec3): Vec3 {
|
||||||
|
out[0] = this.mxx * x + this.mxy * y + this.mxz * z + this.tx;
|
||||||
|
out[1] = this.myx * x + this.myy * y + this.myz * z + this.ty;
|
||||||
|
out[2] = this.mzx * x + this.mzy * y + this.mzz * z + this.tz;
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
rotateWithSphericalAxis(axisAzimuth: number, axisInclination: number, angle: number, pivot: Vector) {
|
||||||
|
|
||||||
|
const axis = new Vector(
|
||||||
|
Math.sin(axisAzimuth) * Math.cos(axisInclination),
|
||||||
|
Math.sin(axisAzimuth) * Math.sin(axisInclination),
|
||||||
|
Math.cos(axisAzimuth)
|
||||||
|
);
|
||||||
|
|
||||||
|
return Matrix3.rotateMatrix(angle, axis, pivot, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
rotate(angle: number, axis: Vector, pivot: Vector) {
|
||||||
|
return Matrix3.rotateMatrix(angle, axis, pivot, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
static rotateMatrix(angle: number, axis: Vector, pivot: Vector, matrix: Matrix3): Matrix3 {
|
||||||
|
var sin = Math.sin(angle);
|
||||||
|
var cos = Math.cos(angle);
|
||||||
|
var axisX, axisY, axisZ;
|
||||||
|
var m = matrix || new Matrix3();
|
||||||
|
|
||||||
|
if (axis === AXIS.X || axis === AXIS.Y || axis === AXIS.Z) {
|
||||||
|
axisX = axis.x;
|
||||||
|
axisY = axis.y;
|
||||||
|
axisZ = axis.z;
|
||||||
|
} else {
|
||||||
|
// normalize
|
||||||
|
var mag = axis.length();
|
||||||
|
|
||||||
|
if (mag == 0.0) {
|
||||||
|
return m;
|
||||||
|
} else {
|
||||||
|
axisX = axis.x / mag;
|
||||||
|
axisY = axis.y / mag;
|
||||||
|
axisZ = axis.z / mag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var px = pivot.x;
|
||||||
|
var py = pivot.y;
|
||||||
|
var pz = pivot.z;
|
||||||
|
|
||||||
|
m.mxx = cos + axisX * axisX * (1 - cos);
|
||||||
|
m.mxy = axisX * axisY * (1 - cos) - axisZ * sin;
|
||||||
|
m.mxz = axisX * axisZ * (1 - cos) + axisY * sin;
|
||||||
|
|
||||||
|
m.tx = px * (1 - m.mxx) - py * m.mxy - pz * m.mxz;
|
||||||
|
|
||||||
|
m.myx = axisY * axisX * (1 - cos) + axisZ * sin;
|
||||||
|
m.myy = cos + axisY * axisY * (1 - cos);
|
||||||
|
m.myz = axisY * axisZ * (1 - cos) - axisX * sin;
|
||||||
|
m.ty = py * (1 - m.myy) - px * m.myx - pz * m.myz;
|
||||||
|
|
||||||
|
m.mzx = axisZ * axisX * (1 - cos) - axisY * sin;
|
||||||
|
m.mzy = axisZ * axisY * (1 - cos) + axisX * sin;
|
||||||
|
m.mzz = cos + axisZ * axisZ * (1 - cos);
|
||||||
|
m.tz = pz * (1 - m.mzz) - px * m.mzx - py * m.mzy;
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
apply = vector => this.__apply(vector, new Vector());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function BasisForPlane(normal: Vector, alignY: Vector = AXIS.Y, alignZ: Vector = AXIS.Z): [number, number, Vector] {
|
||||||
|
let alignPlane, x, y;
|
||||||
|
if (Math.abs(normal.dot(alignY)) < 0.5) {
|
||||||
|
alignPlane = normal.cross(alignY);
|
||||||
|
} else {
|
||||||
|
alignPlane = normal.cross(alignZ);
|
||||||
|
}
|
||||||
|
y = alignPlane.cross(normal);
|
||||||
|
x = y.cross(normal);
|
||||||
|
return [x, y, normal];
|
||||||
|
}
|
||||||
|
|
||||||
|
export {ORIGIN, IDENTITY_BASIS, AXIS, BasisForPlane};
|
||||||
34
modules/math/quaternion.ts
Normal file
34
modules/math/quaternion.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
|
||||||
|
export class Quaternion {
|
||||||
|
|
||||||
|
x: number = 0;
|
||||||
|
y: number = 0;
|
||||||
|
z: number = 0;
|
||||||
|
w: number = 1;
|
||||||
|
|
||||||
|
|
||||||
|
setAxisAndAngle(axisX, axisY, axisZ, angle) {
|
||||||
|
const halfAngle = angle/2;
|
||||||
|
const sin = Math.sin(halfAngle);
|
||||||
|
this.x = axisX*sin;
|
||||||
|
this.y = axisY*sin;
|
||||||
|
this.z = axisZ*sin;
|
||||||
|
this.w = Math.cos(halfAngle);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSphericalAxisAndAngle(azimuth, inclination, angle) {
|
||||||
|
|
||||||
|
this.setAxisAndAngle(
|
||||||
|
Math.sin(azimuth) * Math.cos(inclination),
|
||||||
|
Math.sin(azimuth) * Math.sin(inclination),
|
||||||
|
Math.cos(azimuth),
|
||||||
|
angle
|
||||||
|
);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ import {AmbientLight, PerspectiveCamera, Scene, SpotLight, WebGLRenderer} from '
|
||||||
import DPR from '../dpr';
|
import DPR from '../dpr';
|
||||||
import {MeshArrow} from './objects/auxiliary';
|
import {MeshArrow} from './objects/auxiliary';
|
||||||
import * as SceneGraph from './sceneGraph';
|
import * as SceneGraph from './sceneGraph';
|
||||||
import {AXIS} from '../../web/app/math/l3space';
|
import {AXIS} from '../math/l3space';
|
||||||
|
|
||||||
export default function(container) {
|
export default function(container) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import {advancePseudoFrenetFrame, frenetFrame, pseudoFrenetFrame} from '../../..
|
||||||
import * as vec from 'math/vec';
|
import * as vec from 'math/vec';
|
||||||
import {viewScaleFactor} from '../scaleHelper';
|
import {viewScaleFactor} from '../scaleHelper';
|
||||||
import {arrToThree} from 'math/vectorAdapters';
|
import {arrToThree} from 'math/vectorAdapters';
|
||||||
import {ORIGIN} from '../../../web/app/math/l3space';
|
import {ORIGIN} from '../../math/l3space';
|
||||||
import {getSceneSetup} from '../sceneSetup';
|
import {getSceneSetup} from '../sceneSetup';
|
||||||
import calcFaceNormal from '../utils/calcFaceNormal';
|
import calcFaceNormal from '../utils/calcFaceNormal';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
@import "~ui/styles/theme.less";
|
@import "~ui/styles/theme.less";
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
background-color: @bg-color-2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
|
|
||||||
44
modules/ui/components/GenericWizard.tsx
Normal file
44
modules/ui/components/GenericWizard.tsx
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import React from 'react';
|
||||||
|
import Window, {WindowControlButton, WindowProps} from 'ui/components/Window';
|
||||||
|
import {DocumentationTopic$} from "doc/DocumentationWindow";
|
||||||
|
import {IoMdHelp} from "react-icons/io";
|
||||||
|
import cx from 'classnames';
|
||||||
|
import Stack from "ui/components/Stack";
|
||||||
|
import ButtonGroup from "ui/components/controls/ButtonGroup";
|
||||||
|
import Button from "ui/components/controls/Button";
|
||||||
|
|
||||||
|
export function GenericWizard({topicId, title, left, className, children, onCancel, onOK, infoText, ...props}: {
|
||||||
|
topicId: string,
|
||||||
|
title: string,
|
||||||
|
left?: number,
|
||||||
|
onCancel: () => any,
|
||||||
|
onOK: () => any,
|
||||||
|
infoText: string
|
||||||
|
} & WindowProps ) {
|
||||||
|
|
||||||
|
return <Window initWidth={250}
|
||||||
|
initLeft={left || 15}
|
||||||
|
title={(title||'').toUpperCase()}
|
||||||
|
className={cx('mid-typography', className)}
|
||||||
|
controlButtons={<>
|
||||||
|
<WindowControlButton title='help' onClick={(e) => DocumentationTopic$.next({
|
||||||
|
topic: topicId,
|
||||||
|
x: e.pageX + 40,
|
||||||
|
y: e.pageY
|
||||||
|
})}>
|
||||||
|
<IoMdHelp />
|
||||||
|
</WindowControlButton>
|
||||||
|
</>} {...props} >
|
||||||
|
{children}
|
||||||
|
<Stack>
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button className='dialog-cancel' onClick={onCancel}>Cancel</Button>
|
||||||
|
<Button className='dialog-ok' type='accent' onClick={onOK}>OK</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
{infoText}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
</Window>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -323,7 +323,7 @@ function _maskTest(mask, value) {
|
||||||
export function WindowControlButton({danger, ...props}: {
|
export function WindowControlButton({danger, ...props}: {
|
||||||
danger?: boolean;
|
danger?: boolean;
|
||||||
children: any;
|
children: any;
|
||||||
onClick: () => void;
|
onClick: (e: any) => any;
|
||||||
} & JSX.IntrinsicAttributes) {
|
} & React.HTMLAttributes<HTMLSpanElement>) {
|
||||||
return <span className={cx(ls.button, danger&&ls.danger)} {...props} />;
|
return <span className={cx(ls.button, danger&&ls.danger)} {...props} />;
|
||||||
}
|
}
|
||||||
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
||||||
import ls from './ButtonGroup.less'
|
import ls from './ButtonGroup.less'
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
|
|
||||||
export default function ButtonGroup({className, ...props}) {
|
export default function ButtonGroup({className, ...props}: React.HTMLAttributes<HTMLSpanElement>) {
|
||||||
|
|
||||||
return <div className={cx(ls.root, className)} {...props}/>;
|
return <div className={cx(ls.root, className)} {...props}/>;
|
||||||
|
|
||||||
|
|
@ -1,52 +1,59 @@
|
||||||
import React from 'react';
|
import React, {useCallback, useRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import InputControl from './InputControl';
|
import InputControl from './InputControl';
|
||||||
|
|
||||||
export default class NumberControl extends React.Component {
|
export default function NumberControl(props) {
|
||||||
|
|
||||||
render() {
|
let {onChange, onFocus, value} = props;
|
||||||
let {onChange, onFocus, value} = this.props;
|
|
||||||
return <InputControl type='number'
|
const onChangeFromTarget = e => {
|
||||||
onWheel={this.onWheel}
|
onChange(e.target.value);
|
||||||
value={ value }
|
|
||||||
onChange={this.onChange}
|
|
||||||
onFocus={onFocus}
|
|
||||||
inputRef={input => this.input = input} />
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange = e => {
|
|
||||||
this.props.onChange(e.target.value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onWheel = (e) => {
|
const attachWheelListener = useCallback((input) => {
|
||||||
let {baseStep, round, min, max, onChange, accelerator} = this.props;
|
if (!input) {
|
||||||
let delta = e.deltaY;
|
return;
|
||||||
let step = baseStep * (e.shiftKey ? accelerator : 1);
|
|
||||||
let val = parseFloat(e.target.value);
|
|
||||||
if (isNaN(val)) val = 0;
|
|
||||||
val = val + (delta < 0 ? -step : step);
|
|
||||||
if (min !== undefined && val < min) {
|
|
||||||
val = min;
|
|
||||||
}
|
}
|
||||||
if (max !== undefined && val > max) {
|
const onWheel = (e) => {
|
||||||
val = max;
|
let {baseStep, round, min, max, onChange, accelerator} = props;
|
||||||
}
|
let delta = e.shiftKey ? e.deltaX : e.deltaY;
|
||||||
if (round !== 0) {
|
let step = baseStep * (e.shiftKey ? accelerator : 1);
|
||||||
val = val.toFixed(round);
|
let val = parseFloat(e.target.value);
|
||||||
}
|
if (isNaN(val)) val = 0;
|
||||||
this.input.value = val;
|
val = val + (delta < 0 ? -step : step);
|
||||||
onChange(val);
|
if (min !== undefined && val < min) {
|
||||||
// e.preventDefault();
|
val = min;
|
||||||
e.stopPropagation();
|
}
|
||||||
}
|
if (max !== undefined && val > max) {
|
||||||
|
val = max;
|
||||||
|
}
|
||||||
|
if (round !== 0) {
|
||||||
|
val = val.toFixed(round);
|
||||||
|
}
|
||||||
|
input.value = val;
|
||||||
|
onChange(val);
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
};
|
||||||
|
input.addEventListener('wheel', onWheel, {passive: false});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return <InputControl type='number'
|
||||||
|
value={value}
|
||||||
|
onChange={onChangeFromTarget}
|
||||||
|
onFocus={onFocus}
|
||||||
|
inputRef={attachWheelListener}/>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NumberControl.propTypes = {
|
NumberControl.propTypes = {
|
||||||
baseStep: PropTypes.number,
|
baseStep: PropTypes.number,
|
||||||
round: PropTypes.number,
|
round: PropTypes.number,
|
||||||
min: PropTypes.number,
|
min: PropTypes.number,
|
||||||
max: PropTypes.number,
|
max: PropTypes.number,
|
||||||
accelerator: PropTypes.number,
|
accelerator: PropTypes.number,
|
||||||
onChange: PropTypes.func.isRequired
|
onChange: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,14 @@ export function useStream<T>(getStream: (ctx: ApplicationContext) => Stream<T>)
|
||||||
const basicStreams = useContext(StreamsContext);
|
const basicStreams = useContext(StreamsContext);
|
||||||
const [state, setState] = useState<{data: T}>();
|
const [state, setState] = useState<{data: T}>();
|
||||||
|
|
||||||
const stream = typeof getStream === 'function' ? getStream(basicStreams) : getStream;
|
const stream = resolveStream(getStream, basicStreams);
|
||||||
|
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
console.log(getStream);
|
console.log(getStream);
|
||||||
throw "no stream ^";
|
throw "no stream ^";
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => stream.attach(data => setState({data})), EMPTY_ARR);
|
useEffect(() => stream.attach(data => setState({data})), [stream]);
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return state ? state.data : (stream.value !== undefined ? stream.value : null);
|
return state ? state.data : (stream.value !== undefined ? stream.value : null);
|
||||||
|
|
@ -26,7 +26,7 @@ export function useStreamWithUpdater<T>(getStream: (ctx: ApplicationContext) =>
|
||||||
const data = useStream(getStream);
|
const data = useStream(getStream);
|
||||||
const basicStreams = useContext(StreamsContext);
|
const basicStreams = useContext(StreamsContext);
|
||||||
|
|
||||||
const stream = typeof getStream === 'function' ? getStream(basicStreams) : getStream;
|
const stream = resolveStream(getStream, basicStreams);
|
||||||
|
|
||||||
const updater = useCallback((val) => {
|
const updater = useCallback((val) => {
|
||||||
|
|
||||||
|
|
@ -41,5 +41,6 @@ export function useStreamWithUpdater<T>(getStream: (ctx: ApplicationContext) =>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveStream(getStream, basicStreams) {
|
||||||
const EMPTY_ARR = [];
|
return typeof getStream === 'function' ? getStream(basicStreams) : getStream
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import * as test from '../../test'
|
import * as test from '../../test'
|
||||||
import {deepMerge} from '../coreTests/utils/deep-merge'
|
import {deepMerge} from '../coreTests/utils/deep-merge'
|
||||||
import {Matrix3} from '../../../../web/app/math/l3space'
|
import {Matrix3} from '../../../../modules/math/l3space'
|
||||||
|
|
||||||
const OPERANDS_MODE = false;
|
const OPERANDS_MODE = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import {Face} from './topo/face';
|
||||||
import {Edge} from './topo/edge';
|
import {Edge} from './topo/edge';
|
||||||
import BrepCurve from './geom/curves/brepCurve';
|
import BrepCurve from './geom/curves/brepCurve';
|
||||||
import {Plane} from './geom/impl/plane';
|
import {Plane} from './geom/impl/plane';
|
||||||
import {BasisForPlane, Matrix3} from '../math/l3space';
|
import {BasisForPlane, Matrix3} from 'math/l3space';
|
||||||
import * as cad_utils from '../cad/cad-utils';
|
import * as cad_utils from '../cad/cad-utils';
|
||||||
import * as math from '../math/math';
|
import * as math from '../math/math';
|
||||||
import {createBoundingSurface} from './brep-builder';
|
import {createBoundingSurface} from './brep-builder';
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import {Point} from './geom/point'
|
import {Point} from './geom/point'
|
||||||
import {Plane} from './geom/impl/plane'
|
import {Plane} from './geom/impl/plane'
|
||||||
import {createPrism, enclose} from './brep-enclose'
|
import {createPrism, enclose} from './brep-enclose'
|
||||||
import {AXIS, Matrix3} from '../math/l3space'
|
import {AXIS, Matrix3} from 'math/l3space'
|
||||||
import {Circle} from '../cad/sketch/sketchModel'
|
import {Circle} from '../cad/sketch/sketchModel'
|
||||||
import CSys from '../math/csys';
|
import CSys from 'math/csys';
|
||||||
|
|
||||||
export function box(w, h, d, tr) {
|
export function box(w, h, d, tr) {
|
||||||
const wh = w * 0.5;
|
const wh = w * 0.5;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import NurbsCurve from "./nurbsCurve";
|
import NurbsCurve from "./nurbsCurve";
|
||||||
import {Matrix3} from '../../../math/l3space'
|
import {Matrix3} from '../../../../../modules/math/l3space'
|
||||||
import {areEqual} from '../../../math/math'
|
import {areEqual} from '../../../math/math'
|
||||||
|
|
||||||
import {eqSqTol, ueq, veq, veq3, veqNeg} from "../tolerance";
|
import {eqSqTol, ueq, veq, veq3, veqNeg} from "../tolerance";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {Point} from '../point';
|
import {Point} from '../point';
|
||||||
import {Line} from './line';
|
import {Line} from './line';
|
||||||
import {AXIS, BasisForPlane, Matrix3} from '../../../math/l3space';
|
import {AXIS, BasisForPlane, Matrix3} from '../../../../../modules/math/l3space';
|
||||||
import {eqTol, veq} from '../tolerance';
|
import {eqTol, veq} from '../tolerance';
|
||||||
|
|
||||||
export class Plane {
|
export class Plane {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import {AXIS, ORIGIN} from '../../math/l3space';
|
import {AXIS, ORIGIN} from '../../../../modules/math/l3space';
|
||||||
import Vector from 'math/vector';
|
import Vector from 'math/vector';
|
||||||
import {RiCamera2Line} from "react-icons/ri";
|
import {RiCamera2Line} from "react-icons/ri";
|
||||||
|
|
||||||
|
|
|
||||||
145
web/app/cad/assembly/assembly.ts
Normal file
145
web/app/cad/assembly/assembly.ts
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
import {MObject} from "../model/mobject";
|
||||||
|
import {Param} from "../../sketcher/shapes/param";
|
||||||
|
import Vector from "math/vector";
|
||||||
|
import {Matrix3} from "math/l3space";
|
||||||
|
import {ISolveStage, SolvableObject} from "../../sketcher/constr/solvableObject";
|
||||||
|
import {AlgNumConstraint} from "../../sketcher/constr/ANConstraints";
|
||||||
|
import {Constraints3D} from "./constraints3d";
|
||||||
|
|
||||||
|
export abstract class AssemblyNode implements SolvableObject {
|
||||||
|
|
||||||
|
constraints: Set<AlgNumConstraint> = new Set();
|
||||||
|
|
||||||
|
model: MObject;
|
||||||
|
|
||||||
|
stage: ISolveStage;
|
||||||
|
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
protected constructor(model: MObject) {
|
||||||
|
this.model = model;
|
||||||
|
this.id = 'assembly-node:' + model.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract visitParams(cb);
|
||||||
|
|
||||||
|
abstract reset();
|
||||||
|
|
||||||
|
createConsistencyConstraints(): AlgNumConstraint[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
createRigidBodyLink(body: AssemblyCSysNode): AlgNumConstraint[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
get params(): Param[] {
|
||||||
|
const paramArray = [];
|
||||||
|
this.visitParams(p => paramArray.push(p));
|
||||||
|
return paramArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AssemblyUnitVectorNode extends AssemblyNode {
|
||||||
|
|
||||||
|
x = new Param(0, 'X');
|
||||||
|
y = new Param(0, 'Y');
|
||||||
|
z = new Param(0, 'Z');
|
||||||
|
getVector: () => Vector;
|
||||||
|
|
||||||
|
constructor(model: MObject, getVector: () => Vector) {
|
||||||
|
super(model);
|
||||||
|
this.getVector = getVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitParams(cb) {
|
||||||
|
cb(this.x);
|
||||||
|
cb(this.y);
|
||||||
|
cb(this.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
const {x, y, z} = this.getVector();
|
||||||
|
this.x.set(x);
|
||||||
|
this.y.set(y);
|
||||||
|
this.z.set(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
createConsistencyConstraints() {
|
||||||
|
return [
|
||||||
|
new AlgNumConstraint(Constraints3D.UnitVectorConsistency, [this])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
createRigidBodyLink(body: AssemblyCSysNode) {
|
||||||
|
return [
|
||||||
|
new AlgNumConstraint(Constraints3D.RigidBodyLink3x3, [body, this])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AssemblyCSysNode extends AssemblyNode {
|
||||||
|
|
||||||
|
ox = new Param(0, 'X');
|
||||||
|
oy = new Param(0, 'Y');
|
||||||
|
oz = new Param(0, 'Z');
|
||||||
|
ix = new Param(1, 'X');
|
||||||
|
iy = new Param(0, 'Y');
|
||||||
|
iz = new Param(0, 'Z');
|
||||||
|
jx = new Param(0, 'X');
|
||||||
|
jy = new Param(1, 'Y');
|
||||||
|
jz = new Param(0, 'Z');
|
||||||
|
kx = new Param(0, 'X');
|
||||||
|
ky = new Param(0, 'Y');
|
||||||
|
kz = new Param(1, 'Z');
|
||||||
|
getTransformation: () => Matrix3;
|
||||||
|
|
||||||
|
constructor(model: MObject, getTransformation: () => Matrix3) {
|
||||||
|
super(model);
|
||||||
|
this.getTransformation = getTransformation;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitParams(cb) {
|
||||||
|
cb(this.ox);
|
||||||
|
cb(this.oy);
|
||||||
|
cb(this.oz);
|
||||||
|
cb(this.ix);
|
||||||
|
cb(this.iy);
|
||||||
|
cb(this.iz);
|
||||||
|
cb(this.jx);
|
||||||
|
cb(this.jy);
|
||||||
|
cb(this.jz);
|
||||||
|
cb(this.kx);
|
||||||
|
cb(this.ky);
|
||||||
|
cb(this.kz);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
const mx = this.getTransformation();
|
||||||
|
this.ox.set(mx.tx);
|
||||||
|
this.oy.set(mx.ty);
|
||||||
|
this.oz.set(mx.tz);
|
||||||
|
|
||||||
|
this.ix.set(mx.mxx);
|
||||||
|
this.iy.set(mx.myx);
|
||||||
|
this.iz.set(mx.mzx);
|
||||||
|
|
||||||
|
this.jx.set(mx.mxy);
|
||||||
|
this.jy.set(mx.myy);
|
||||||
|
this.jz.set(mx.mzy);
|
||||||
|
|
||||||
|
this.kx.set(mx.mxz);
|
||||||
|
this.ky.set(mx.myz);
|
||||||
|
this.kz.set(mx.mzz);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
createConsistencyConstraints() {
|
||||||
|
return [
|
||||||
|
new AlgNumConstraint(Constraints3D.CSysConsistency, [this])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
111
web/app/cad/assembly/assemblySolver.ts
Normal file
111
web/app/cad/assembly/assemblySolver.ts
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
import {AlgNumConstraint} from "../../sketcher/constr/ANConstraints";
|
||||||
|
import {AlgNumSubSystem} from "../../sketcher/constr/AlgNumSystem";
|
||||||
|
import Vector from "math/vector";
|
||||||
|
import CSys from "math/csys";
|
||||||
|
import {AssemblyCSysNode, AssemblyNode} from "./assembly";
|
||||||
|
import {ISolveStage} from "../../sketcher/constr/solvableObject";
|
||||||
|
import {MObject} from "../model/mobject";
|
||||||
|
import {MShell} from "../model/mshell";
|
||||||
|
import {Constraints3D} from "./constraints3d";
|
||||||
|
|
||||||
|
export function solveAssembly(constraints: AlgNumConstraint[]) {
|
||||||
|
|
||||||
|
const objects = new Set<AssemblyNode>();
|
||||||
|
|
||||||
|
constraints.forEach(c => c.objects.forEach(o => objects.add(o)));
|
||||||
|
|
||||||
|
const stage: ISolveStage = {
|
||||||
|
objects: objects,
|
||||||
|
index: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
const roots = new Set<MShell>();
|
||||||
|
objects.forEach(o => {
|
||||||
|
const root = o.model.root;
|
||||||
|
if (root instanceof MShell) {
|
||||||
|
roots.add(root);
|
||||||
|
objects.add(root.assemblyNodes.location)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
objects.forEach(o => {
|
||||||
|
o.stage = stage;
|
||||||
|
o.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
// const algNumConstraint = new AlgNumConstraint(Constraints3D.FaceParallel, objects);
|
||||||
|
|
||||||
|
const system = new AlgNumSubSystem(() => 0.001, val => val, stage);
|
||||||
|
// __DEBUG__.AddNormal(face1.csys.origin, new Vector().set3(objects[0].normal.map(p => p.get())))
|
||||||
|
// __DEBUG__.AddNormal(face2.csys.origin, new Vector().set3(objects[1].normal.map(p => p.get())))
|
||||||
|
|
||||||
|
system.startTransaction();
|
||||||
|
constraints.forEach(c => system.addConstraint(c));
|
||||||
|
objects.forEach(assemblyNode => {
|
||||||
|
const internalConstraints = assemblyNode.createConsistencyConstraints();
|
||||||
|
internalConstraints.forEach(c => {
|
||||||
|
c.internal = true;
|
||||||
|
system.addConstraint(c);
|
||||||
|
});
|
||||||
|
|
||||||
|
const root = assemblyNode.model.root;
|
||||||
|
if (root instanceof MShell) {
|
||||||
|
const rigidBodyLinks = assemblyNode.createRigidBodyLink(root.assemblyNodes.location);
|
||||||
|
rigidBodyLinks.forEach(c => {
|
||||||
|
c.internal = true;
|
||||||
|
system.addConstraint(c);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw 'unsupported: needs location implementation';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
system.prepare();
|
||||||
|
system.solveFine();
|
||||||
|
system.finishTransaction();
|
||||||
|
|
||||||
|
// __DEBUG__.AddNormal(face1.csys.origin, new Vector().set3(objects[0].normal.map(p => p.get())))
|
||||||
|
// __DEBUG__.AddNormal(face2.csys.origin, new Vector().set3(objects[1].normal.map(p => p.get())))
|
||||||
|
|
||||||
|
roots.forEach(root => {
|
||||||
|
applyResults(root, root.assemblyNodes.location);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function applyResults(shell: MShell, targetCsysParams: AssemblyCSysNode): void {
|
||||||
|
const [
|
||||||
|
ox, oy, oz, ix, iy, iz, jx, jy, jz, kx, ky, kz
|
||||||
|
] = targetCsysParams.params.map(p => p.get());
|
||||||
|
|
||||||
|
const targetCsys = new CSys(
|
||||||
|
new Vector(ox, oy, oz),
|
||||||
|
new Vector(ix, iy, iz),
|
||||||
|
new Vector(jx, jy, jz),
|
||||||
|
new Vector(kx, ky, kz),
|
||||||
|
);
|
||||||
|
|
||||||
|
const basis = [
|
||||||
|
new Vector(ix, iy, iz),
|
||||||
|
new Vector(jx, jy, jz),
|
||||||
|
new Vector(kx, ky, kz),
|
||||||
|
];
|
||||||
|
|
||||||
|
// __DEBUG__.AddCSys(shell.csys);
|
||||||
|
// __DEBUG__.AddCSys(targetCsys);
|
||||||
|
|
||||||
|
const tr = shell.csys.inTransformation3x3;
|
||||||
|
basis.forEach(r => tr._apply(r));
|
||||||
|
|
||||||
|
shell.location$.update(csys => {
|
||||||
|
return targetCsys;
|
||||||
|
});
|
||||||
|
// shell.location$.mutate(csys => {
|
||||||
|
// csys.x = basis[0];
|
||||||
|
// csys.y = basis[1];
|
||||||
|
// csys.z = basis[2];
|
||||||
|
// csys.origin = new Vector(ox, oy, oz)._minus(shell.csys.origin);
|
||||||
|
// });
|
||||||
|
|
||||||
|
}
|
||||||
248
web/app/cad/assembly/constraints3d.ts
Normal file
248
web/app/cad/assembly/constraints3d.ts
Normal file
|
|
@ -0,0 +1,248 @@
|
||||||
|
import {Polynomial, POW_1_FN, POW_2_FN} from "../../sketcher/constr/polynomial";
|
||||||
|
import {NoIcon} from "../../sketcher/icons/NoIcon";
|
||||||
|
import {AlgNumConstraint, ConstantsDefinitions, ConstraintSchema} from "../../sketcher/constr/ANConstraints";
|
||||||
|
import {MObject} from "../model/mobject";
|
||||||
|
import {SolvableObject} from "../../sketcher/constr/solvableObject";
|
||||||
|
|
||||||
|
export const Constraints3D = {
|
||||||
|
|
||||||
|
FaceParallel: {
|
||||||
|
id: 'FaceParallel',
|
||||||
|
name: 'Face Parallel',
|
||||||
|
icon: NoIcon,
|
||||||
|
|
||||||
|
defineAssemblyScope: ([face1, face2]) => {
|
||||||
|
return [
|
||||||
|
face1.assemblyNodes.normal,
|
||||||
|
face2.assemblyNodes.normal
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
defineParamsScope: ([n1, n2], cb) => {
|
||||||
|
n1.visitParams(cb);
|
||||||
|
n2.visitParams(cb);
|
||||||
|
},
|
||||||
|
|
||||||
|
collectPolynomials: (polynomials, params) => {
|
||||||
|
|
||||||
|
const [
|
||||||
|
nx1, ny1, nz1, nx2, ny2, nz2,
|
||||||
|
] = params;
|
||||||
|
|
||||||
|
polynomials.push(
|
||||||
|
new Polynomial(1)
|
||||||
|
.monomial()
|
||||||
|
.term(nx1, POW_1_FN)
|
||||||
|
.term(nx2, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(ny1, POW_1_FN)
|
||||||
|
.term(ny2, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(nz1, POW_1_FN)
|
||||||
|
.term(nz2, POW_1_FN)
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
UnitVectorConsistency: {
|
||||||
|
id: 'UnitVectorConsistency',
|
||||||
|
name: 'UnitVectorConsistency',
|
||||||
|
icon: NoIcon,
|
||||||
|
|
||||||
|
defineParamsScope: ([vec], cb) => {
|
||||||
|
vec.visitParams(cb);
|
||||||
|
},
|
||||||
|
|
||||||
|
collectPolynomials: (polynomials, params) => {
|
||||||
|
|
||||||
|
const [x, y, z] = params;
|
||||||
|
|
||||||
|
polynomials.push(
|
||||||
|
new Polynomial(-1)
|
||||||
|
.monomial()
|
||||||
|
.term(x, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(y, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(z, POW_2_FN)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
CSysConsistency: {
|
||||||
|
id: 'CSysConsistency',
|
||||||
|
name: 'CSysConsistency',
|
||||||
|
icon: NoIcon,
|
||||||
|
|
||||||
|
defineParamsScope: ([csys], cb) => {
|
||||||
|
cb(csys.ix);
|
||||||
|
cb(csys.iy);
|
||||||
|
cb(csys.iz);
|
||||||
|
cb(csys.jx);
|
||||||
|
cb(csys.jy);
|
||||||
|
cb(csys.jz);
|
||||||
|
cb(csys.kx);
|
||||||
|
cb(csys.ky);
|
||||||
|
cb(csys.kz);
|
||||||
|
},
|
||||||
|
|
||||||
|
collectPolynomials: (polynomials, params) => {
|
||||||
|
|
||||||
|
const [
|
||||||
|
ix,
|
||||||
|
iy,
|
||||||
|
iz,
|
||||||
|
jx,
|
||||||
|
jy,
|
||||||
|
jz,
|
||||||
|
kx,
|
||||||
|
ky,
|
||||||
|
kz] = params;
|
||||||
|
|
||||||
|
//let's keep matrix orthogonal and unit basis
|
||||||
|
polynomials.push(new Polynomial(0)
|
||||||
|
.monomial()
|
||||||
|
.term(ix, POW_1_FN)
|
||||||
|
.term(jx, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(iy, POW_1_FN)
|
||||||
|
.term(jy, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(iz, POW_1_FN)
|
||||||
|
.term(jz, POW_1_FN));
|
||||||
|
|
||||||
|
polynomials.push(new Polynomial(0)
|
||||||
|
.monomial()
|
||||||
|
.term(ix, POW_1_FN)
|
||||||
|
.term(kx, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(iy, POW_1_FN)
|
||||||
|
.term(ky, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(iz, POW_1_FN)
|
||||||
|
.term(kz, POW_1_FN));
|
||||||
|
|
||||||
|
polynomials.push(new Polynomial(0)
|
||||||
|
.monomial()
|
||||||
|
.term(jx, POW_1_FN)
|
||||||
|
.term(kx, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(jy, POW_1_FN)
|
||||||
|
.term(ky, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(jz, POW_1_FN)
|
||||||
|
.term(kz, POW_1_FN));
|
||||||
|
|
||||||
|
polynomials.push(new Polynomial(-1)
|
||||||
|
.monomial()
|
||||||
|
.term(ix, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(iy, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(iz, POW_2_FN));
|
||||||
|
|
||||||
|
polynomials.push(new Polynomial(-1)
|
||||||
|
.monomial()
|
||||||
|
.term(jx, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(jy, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(jz, POW_2_FN));
|
||||||
|
|
||||||
|
polynomials.push(new Polynomial(-1)
|
||||||
|
.monomial()
|
||||||
|
.term(kx, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(ky, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(kz, POW_2_FN));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
RigidBodyLink3x3: {
|
||||||
|
id: 'RigidBodyLink3x3',
|
||||||
|
name: 'RigidBodyLink3x3',
|
||||||
|
icon: NoIcon,
|
||||||
|
|
||||||
|
defineParamsScope: ([csys, vec], cb) => {
|
||||||
|
cb(csys.ix);
|
||||||
|
cb(csys.iy);
|
||||||
|
cb(csys.iz);
|
||||||
|
cb(csys.jx);
|
||||||
|
cb(csys.jy);
|
||||||
|
cb(csys.jz);
|
||||||
|
cb(csys.kx);
|
||||||
|
cb(csys.ky);
|
||||||
|
cb(csys.kz);
|
||||||
|
vec.visitParams(cb);
|
||||||
|
},
|
||||||
|
|
||||||
|
collectPolynomials: (polynomials, params, _, objects) => {
|
||||||
|
const [csys, vec] = objects;
|
||||||
|
|
||||||
|
const {x: nStarX, y: nStarY, z: nStarZ} = vec.getVector();
|
||||||
|
|
||||||
|
const [ix, iy, iz, jx, jy, jz, kx, ky, kz, x, y, z] = params;
|
||||||
|
|
||||||
|
// out.x = this.mxx * x + this.mxy * y + this.mxz * z + this.tx;
|
||||||
|
// out.y = this.myx * x + this.myy * y + this.myz * z + this.ty;
|
||||||
|
// out.z = this.mzx * x + this.mzy * y + this.mzz * z + this.tz;
|
||||||
|
|
||||||
|
polynomials.push(
|
||||||
|
new Polynomial(0)
|
||||||
|
.monomial(-1)
|
||||||
|
.term(x, POW_1_FN)
|
||||||
|
.monomial(nStarX)
|
||||||
|
.term(ix, POW_1_FN)
|
||||||
|
.monomial(nStarY)
|
||||||
|
.term(jx, POW_1_FN)
|
||||||
|
.monomial(nStarZ)
|
||||||
|
.term(kx, POW_1_FN)
|
||||||
|
);
|
||||||
|
|
||||||
|
polynomials.push(
|
||||||
|
new Polynomial(0)
|
||||||
|
.monomial(-1)
|
||||||
|
.term(y, POW_1_FN)
|
||||||
|
.monomial(nStarX)
|
||||||
|
.term(iy, POW_1_FN)
|
||||||
|
.monomial(nStarY)
|
||||||
|
.term(jy, POW_1_FN)
|
||||||
|
.monomial(nStarZ)
|
||||||
|
.term(ky, POW_1_FN),
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
polynomials.push(
|
||||||
|
new Polynomial(0)
|
||||||
|
.monomial(-1)
|
||||||
|
.term(z, POW_1_FN)
|
||||||
|
.monomial(nStarX)
|
||||||
|
.term(iz, POW_1_FN)
|
||||||
|
.monomial(nStarY)
|
||||||
|
.term(jz, POW_1_FN)
|
||||||
|
.monomial(nStarZ)
|
||||||
|
.term(kz, POW_1_FN)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export interface AssemblyConstraintSchema extends ConstraintSchema {
|
||||||
|
defineAssemblyScope: (objects: MObject[]) => SolvableObject[],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function createAssemblyConstraint(schema: AssemblyConstraintSchema,
|
||||||
|
objects: MObject[],
|
||||||
|
constants?: ConstantsDefinitions,
|
||||||
|
internal?: boolean = false) {
|
||||||
|
|
||||||
|
return new AlgNumConstraint(schema, schema.defineAssemblyScope(objects), constants, internal);
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@ import BBox from '../math/bbox'
|
||||||
import {HashTable} from '../utils/hashmap'
|
import {HashTable} from '../utils/hashmap'
|
||||||
import {Graph} from '../math/graph'
|
import {Graph} from '../math/graph'
|
||||||
import * as math from '../math/math'
|
import * as math from '../math/math'
|
||||||
import {Matrix3, AXIS, ORIGIN} from '../math/l3space'
|
import {Matrix3, AXIS, ORIGIN} from '../../../modules/math/l3space'
|
||||||
import {MeshSceneSolid} from './scene/wrappers/meshSceneObject'
|
import {MeshSceneSolid} from './scene/wrappers/meshSceneObject'
|
||||||
|
|
||||||
export const FACE_COLOR = 0xB0C4DE;
|
export const FACE_COLOR = 0xB0C4DE;
|
||||||
|
|
|
||||||
|
|
@ -56,9 +56,13 @@ export function activate(ctx: ApplicationContext) {
|
||||||
function findEntity(entity, id) {
|
function findEntity(entity, id) {
|
||||||
return index().get(id);
|
return index().get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function find(id) {
|
||||||
|
return index().get(id);
|
||||||
|
}
|
||||||
|
|
||||||
services.cadRegistry = {
|
services.cadRegistry = {
|
||||||
getAllShells, findShell, findFace, findEdge, findSketchObject, findEntity, findDatum, findDatumAxis, findLoop,
|
getAllShells, findShell, findFace, findEdge, findSketchObject, findEntity, findDatum, findDatumAxis, findLoop, find,
|
||||||
get modelIndex() {
|
get modelIndex() {
|
||||||
return streams.cadRegistry.modelIndex.value;
|
return streams.cadRegistry.modelIndex.value;
|
||||||
},
|
},
|
||||||
|
|
@ -85,6 +89,7 @@ export interface CadRegistry {
|
||||||
findDatum(id: string): MObject;
|
findDatum(id: string): MObject;
|
||||||
findDatumAxis(id: string): MObject;
|
findDatumAxis(id: string): MObject;
|
||||||
findLoop(id: string): MObject;
|
findLoop(id: string): MObject;
|
||||||
|
find(id: string): MObject;
|
||||||
modelIndex: Map<String, MObject>;
|
modelIndex: Map<String, MObject>;
|
||||||
models: MObject[];
|
models: MObject[];
|
||||||
shells: MObject[];
|
shells: MObject[];
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import {Matrix3} from '../../../math/l3space'
|
import {Matrix3} from '../../../../../modules/math/l3space'
|
||||||
import * as math from '../../../math/math'
|
import * as math from '../../../math/math'
|
||||||
import {enclose} from '../../../brep/brep-enclose'
|
import {enclose} from '../../../brep/brep-enclose'
|
||||||
import {BooleanOperation, combineShells} from '../booleanOperation'
|
import {BooleanOperation, combineShells} from '../booleanOperation'
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import DatumWizard from './CreateDatumWizard';
|
||||||
import schema from './createDatumOpSchema';
|
import schema from './createDatumOpSchema';
|
||||||
import DatumObject3D from '../datumObject';
|
import DatumObject3D from '../datumObject';
|
||||||
import * as SceneGraph from 'scene/sceneGraph';
|
import * as SceneGraph from 'scene/sceneGraph';
|
||||||
import CSys from '../../../../math/csys';
|
import CSys from '../../../../../../modules/math/csys';
|
||||||
import {MDatum} from '../../../model/mdatum';
|
import {MDatum} from '../../../model/mdatum';
|
||||||
import {roundInteractiveInput} from '../../wizard/roundUtils';
|
import {roundInteractiveInput} from '../../wizard/roundUtils';
|
||||||
import {DatumParamsRenderer} from '../DatumParamsRenderer';
|
import {DatumParamsRenderer} from '../DatumParamsRenderer';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import {MeshLambertMaterial, Object3D} from 'three';
|
import {MeshLambertMaterial, Object3D} from 'three';
|
||||||
import {AXIS} from '../../../math/l3space';
|
import {AXIS} from '../../../../../modules/math/l3space';
|
||||||
import {MeshArrow} from 'scene/objects/auxiliary';
|
import {MeshArrow} from 'scene/objects/auxiliary';
|
||||||
import {viewScaleFactor} from '../../../../../modules/scene/scaleHelper';
|
import {viewScaleFactor} from '../../../../../modules/scene/scaleHelper';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import schema from './rotateDatumOpSchema';
|
import schema from './rotateDatumOpSchema';
|
||||||
import {MDatum} from '../../../model/mdatum';
|
import {MDatum} from '../../../model/mdatum';
|
||||||
import RotateDatumWizard from './RotateDatumWizard';
|
import RotateDatumWizard from './RotateDatumWizard';
|
||||||
import {Matrix3, ORIGIN} from '../../../../math/l3space';
|
import {Matrix3, ORIGIN} from '../../../../../../modules/math/l3space';
|
||||||
import {DEG_RAD} from '../../../../math/math';
|
import {DEG_RAD} from '../../../../math/math';
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import {Mesh, ConeGeometry, Matrix4, CylinderGeometry} from 'three';
|
||||||
import schema from './coneOpSchema';
|
import schema from './coneOpSchema';
|
||||||
import ConeWizard from './ConeWizard';
|
import ConeWizard from './ConeWizard';
|
||||||
import {IMAGINARY_SURFACE_MATERIAL} from '../../../preview/scenePreviewer';
|
import {IMAGINARY_SURFACE_MATERIAL} from '../../../preview/scenePreviewer';
|
||||||
import CSys from '../../../../math/csys';
|
import CSys from '../../../../../../modules/math/csys';
|
||||||
import * as SceneGraph from '../../../../../../modules/scene/sceneGraph';
|
import * as SceneGraph from '../../../../../../modules/scene/sceneGraph';
|
||||||
import datumConsumingOperation from '../datumConsumingOperation';
|
import datumConsumingOperation from '../datumConsumingOperation';
|
||||||
import {assignBooleanParams} from '../booleanOptionHelper';
|
import {assignBooleanParams} from '../booleanOptionHelper';
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import CSys from '../../../math/csys';
|
import CSys from '../../../../../modules/math/csys';
|
||||||
|
|
||||||
export default function datumConsumingOperation(params, services, run) {
|
export default function datumConsumingOperation(params, services, run) {
|
||||||
let mDatum = params.datum && services.cadRegistry.findDatum(params.datum);
|
let mDatum = params.datum && services.cadRegistry.findDatum(params.datum);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {BoxGeometry, Matrix4, Mesh} from 'three';
|
import {BoxGeometry, Matrix4, Mesh} from 'three';
|
||||||
import {IMAGINARY_SURFACE_MATERIAL} from '../../preview/scenePreviewer';
|
import {IMAGINARY_SURFACE_MATERIAL} from '../../preview/scenePreviewer';
|
||||||
import CSys from '../../../math/csys';
|
import CSys from '../../../../../modules/math/csys';
|
||||||
import * as SceneGraph from '../../../../../modules/scene/sceneGraph';
|
import * as SceneGraph from '../../../../../modules/scene/sceneGraph';
|
||||||
|
|
||||||
export default function primitivePreviewer(createThreePrimitiveGeometry, paramsToScales, shift) {
|
export default function primitivePreviewer(createThreePrimitiveGeometry, paramsToScales, shift) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import {createMeshGeometry} from 'scene/geoms';
|
import {createMeshGeometry} from 'scene/geoms';
|
||||||
import {STANDARD_BASES} from '../../../../math/l3space';
|
import {STANDARD_BASES} from '../../../../../../modules/math/l3space';
|
||||||
import {Plane} from '../../../../brep/geom/impl/plane';
|
import {Plane} from '../../../../brep/geom/impl/plane';
|
||||||
import Vector from 'math/vector';
|
import Vector from 'math/vector';
|
||||||
import PlaneWizard from './SimplePlaneWizard';
|
import PlaneWizard from './SimplePlaneWizard';
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import {Mesh, TorusGeometry} from 'three';
|
||||||
import schema from './torusOpSchema';
|
import schema from './torusOpSchema';
|
||||||
import TorusWizard from './TorusWizard';
|
import TorusWizard from './TorusWizard';
|
||||||
import {IMAGINARY_SURFACE_MATERIAL} from '../../../preview/scenePreviewer';
|
import {IMAGINARY_SURFACE_MATERIAL} from '../../../preview/scenePreviewer';
|
||||||
import CSys from '../../../../math/csys';
|
import CSys from '../../../../../../modules/math/csys';
|
||||||
import * as SceneGraph from '../../../../../../modules/scene/sceneGraph';
|
import * as SceneGraph from '../../../../../../modules/scene/sceneGraph';
|
||||||
import datumConsumingOperation from '../datumConsumingOperation';
|
import datumConsumingOperation from '../datumConsumingOperation';
|
||||||
import {assignBooleanParams} from '../booleanOptionHelper';
|
import {assignBooleanParams} from '../booleanOptionHelper';
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import CSys from '../../../math/csys';
|
import CSys from '../../../../../modules/math/csys';
|
||||||
import {MDatum} from '../../model/mdatum';
|
import {MDatum} from '../../model/mdatum';
|
||||||
|
|
||||||
import spatialCurveOpSchema from './spatialCurveOpSchema';
|
import spatialCurveOpSchema from './spatialCurveOpSchema';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Window, {WindowControlButton} from 'ui/components/Window';
|
|
||||||
import Stack from 'ui/components/Stack';
|
import Stack from 'ui/components/Stack';
|
||||||
import Button from 'ui/components/controls/Button';
|
import Button from 'ui/components/controls/Button';
|
||||||
import ButtonGroup from 'ui/components/controls/ButtonGroup';
|
import ButtonGroup from 'ui/components/controls/ButtonGroup';
|
||||||
|
|
@ -9,8 +8,7 @@ import CadError from '../../../../utils/errors';
|
||||||
import {FormContext} from './form/Form';
|
import {FormContext} from './form/Form';
|
||||||
import connect from 'ui/connect';
|
import connect from 'ui/connect';
|
||||||
import {combine} from 'lstream';
|
import {combine} from 'lstream';
|
||||||
import {DocumentationTopic$} from "../../../../../../modules/doc/DocumentationWindow";
|
import {GenericWizard} from "ui/components/GenericWizard";
|
||||||
import {IoMdHelp} from "react-icons/io";
|
|
||||||
|
|
||||||
@connect((streams, props) => combine(props.context.workingRequest$, props.context.state$)
|
@connect((streams, props) => combine(props.context.workingRequest$, props.context.state$)
|
||||||
.map(([workingRequest, state]) => ({
|
.map(([workingRequest, state]) => ({
|
||||||
|
|
@ -56,42 +54,31 @@ export default class Wizard extends React.Component {
|
||||||
let Form = operation.form;
|
let Form = operation.form;
|
||||||
|
|
||||||
const error = this.props.error;
|
const error = this.props.error;
|
||||||
return <Window initWidth={250}
|
return <GenericWizard
|
||||||
initLeft={left || 15}
|
left={left}
|
||||||
title={title}
|
title={title}
|
||||||
onClose={this.cancel}
|
onClose={this.cancel}
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
setFocus={this.focusFirstInput}
|
setFocus={this.focusFirstInput}
|
||||||
className='Wizard mid-typography'
|
className='Wizard'
|
||||||
data-operation-id={operation.id}
|
data-operation-id={operation.id}
|
||||||
controlButtons={<>
|
topicId={operation.id}
|
||||||
<WindowControlButton title='help' onClick={(e) => DocumentationTopic$.next({
|
onCancel={this.cancel}
|
||||||
topic: operation.id,
|
onOK={this.onOK}
|
||||||
x: e.pageX + 40,
|
infoText={error && <div className={ls.errorMessage}>
|
||||||
y: e.pageY
|
{CadError.ALGORITHM_ERROR_KINDS.includes(error.kind) && <span>
|
||||||
})}>
|
performing operation with current parameters leads to an invalid object
|
||||||
<IoMdHelp />
|
(self-intersecting / zero-thickness / complete degeneration or unsupported cases)
|
||||||
</WindowControlButton>
|
</span>}
|
||||||
</>}>
|
{error.code && <div className={ls.errorCode}>{error.code}</div>}
|
||||||
|
{error.userMessage && <div className={ls.userErrorMessage}>{error.userMessage}</div>}
|
||||||
|
{!error.userMessage && <div>internal error processing operation, check the log</div>}
|
||||||
|
</div>}
|
||||||
|
>
|
||||||
<FormContext.Provider value={formContext}>
|
<FormContext.Provider value={formContext}>
|
||||||
<Form/>
|
<Form/>
|
||||||
</FormContext.Provider>
|
</FormContext.Provider>
|
||||||
<Stack>
|
</GenericWizard>;
|
||||||
<ButtonGroup>
|
|
||||||
<Button className='dialog-cancel' onClick={this.cancel}>Cancel</Button>
|
|
||||||
<Button className='dialog-ok' type='accent' onClick={this.onOK}>OK</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
{error && <div className={ls.errorMessage}>
|
|
||||||
{CadError.ALGORITMTHM_ERROR_KINDS.includes(error.kind) && <span>
|
|
||||||
performing operation with current parameters leads to an invalid object
|
|
||||||
(self-intersecting / zero-thickness / complete degeneration or unsupported cases)
|
|
||||||
</span>}
|
|
||||||
{error.code && <div className={ls.errorCode}>{error.code}</div>}
|
|
||||||
{error.userMessage && <div className={ls.userErrorMessage}>{error.userMessage}</div>}
|
|
||||||
{!error.userMessage && <div>internal error processing operation, check the log</div>}
|
|
||||||
</div>}
|
|
||||||
</Stack>
|
|
||||||
</Window>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = e => {
|
onKeyDown = e => {
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,12 @@ function addGlobalDebugActions({viewer, cadScene, cadRegistry}) {
|
||||||
AddSurfaceNormal: (surface) => {
|
AddSurfaceNormal: (surface) => {
|
||||||
__DEBUG__.AddNormal(surface.pointInMiddle(), surface.normalInMiddle());
|
__DEBUG__.AddNormal(surface.pointInMiddle(), surface.normalInMiddle());
|
||||||
},
|
},
|
||||||
|
AddCSys: (csys, scale) => {
|
||||||
|
scale = scale || 100;
|
||||||
|
__DEBUG__.AddNormal(csys.origin, csys.x, 0xff0000, scale)
|
||||||
|
__DEBUG__.AddNormal(csys.origin, csys.y, 0x00ff00, scale)
|
||||||
|
__DEBUG__.AddNormal(csys.origin, csys.z, 0x0000ff, scale)
|
||||||
|
},
|
||||||
AddTessDump: (triangles, color) => {
|
AddTessDump: (triangles, color) => {
|
||||||
const vec = arr => new THREE.Vector3().fromArray(arr);
|
const vec = arr => new THREE.Vector3().fromArray(arr);
|
||||||
color = color || 0xffffff;
|
color = color || 0xffffff;
|
||||||
|
|
|
||||||
377
web/app/cad/dom/components/ModellerContextualActions.tsx
Normal file
377
web/app/cad/dom/components/ModellerContextualActions.tsx
Normal file
|
|
@ -0,0 +1,377 @@
|
||||||
|
import React, {useContext} from 'react';
|
||||||
|
import {AppContext} from "./AppContext";
|
||||||
|
import {useStream} from "ui/effects";
|
||||||
|
import {ApplicationContext} from "context";
|
||||||
|
import {AlgNumSubSystem} from "../../../sketcher/constr/AlgNumSystem";
|
||||||
|
import {ParallelConstraintIcon} from "../../../sketcher/icons/constraints/ConstraintIcons";
|
||||||
|
import {DEG_RAD, makeAngle0_360} from "../../../math/math";
|
||||||
|
import {AlgNumConstraint} from "../../../sketcher/constr/ANConstraints";
|
||||||
|
import {Param} from "../../../sketcher/shapes/param";
|
||||||
|
import {COS_FN, Polynomial, POW_1_FN, POW_2_FN, SIN_FN} from "../../../sketcher/constr/polynomial";
|
||||||
|
import {Matrix3} from "math/l3space";
|
||||||
|
import CSys from "math/csys";
|
||||||
|
import Vector from "math/vector";
|
||||||
|
import {Dialog} from "ui/components/Dialog";
|
||||||
|
import {MObject} from "../../model/mobject";
|
||||||
|
import {MBrepFace} from "../../model/mface";
|
||||||
|
import {solveAssembly} from "../../assembly/assemblySolver";
|
||||||
|
import {Constraints3D, createAssemblyConstraint} from "../../assembly/constraints3d";
|
||||||
|
|
||||||
|
export function ModellerContextualActions({}) {
|
||||||
|
|
||||||
|
const ctx = useContext(AppContext);
|
||||||
|
|
||||||
|
const faceSelection: string[] = useStream(ctx => ctx.streams.selection.face);
|
||||||
|
|
||||||
|
if (faceSelection.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const actions = [];
|
||||||
|
|
||||||
|
if (faceSelection.length === 2) {
|
||||||
|
|
||||||
|
actions.push(<button key='faceParallel' onClick={() => faceParallel(ctx, faceSelection)}>Face Parallel</button>);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Dialog initRight={50} title='AVAILABLE ACTIONS' onClose={() => {}}>
|
||||||
|
{actions}
|
||||||
|
</Dialog>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XConstraints3D = {
|
||||||
|
FaceParallel: {
|
||||||
|
id: 'FaceParallel',
|
||||||
|
name: 'FaceParallel',
|
||||||
|
icon: ParallelConstraintIcon,
|
||||||
|
|
||||||
|
defineAssemblyScope: ([face1, face2], cb) => {
|
||||||
|
cb(face1.assemblyNodes.normal);
|
||||||
|
cb(face2.assemblyNodes.normal);
|
||||||
|
},
|
||||||
|
|
||||||
|
defineParamsScope: (objects, cb) => {
|
||||||
|
|
||||||
|
const [face1W, face2W, csys1W, csys2W] = objects;
|
||||||
|
|
||||||
|
const n1 = face1W.normal;
|
||||||
|
const n2 = face2W.normal;
|
||||||
|
|
||||||
|
|
||||||
|
const [nx1, ny1, nz1] = n1;
|
||||||
|
const [nx2, ny2, nz2] = n2;
|
||||||
|
|
||||||
|
const csysParams1 = csys1W.params;
|
||||||
|
const [
|
||||||
|
ox1, oy1, oz1, ix1, iy1, iz1, jx1, jy1, jz1, kx1, ky1, kz1
|
||||||
|
] = csysParams1;
|
||||||
|
|
||||||
|
const csysParams2 = csys2W.params;
|
||||||
|
const [
|
||||||
|
ox2, oy2, oz2, ix2, iy2, iz2, jx2, jy2, jz2, kx2, ky2, kz2
|
||||||
|
] = csysParams2;
|
||||||
|
|
||||||
|
[
|
||||||
|
nx1, ny1, nz1, nx2, ny2, nz2,
|
||||||
|
ox1, oy1, oz1, ix1, iy1, iz1, jx1, jy1, jz1, kx1, ky1, kz1,
|
||||||
|
ox2, oy2, oz2, ix2, iy2, iz2, jx2, jy2, jz2, kx2, ky2, kz2
|
||||||
|
].forEach(cb);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
collectPolynomials: (polynomials, params, constants, [face1, face2, csys1, csys2]) => {
|
||||||
|
|
||||||
|
const [
|
||||||
|
nx1, ny1, nz1, nx2, ny2, nz2,
|
||||||
|
ox1, oy1, oz1, ix1, iy1, iz1, jx1, jy1, jz1, kx1, ky1, kz1,
|
||||||
|
ox2, oy2, oz2, ix2, iy2, iz2, jx2, jy2, jz2, kx2, ky2, kz2
|
||||||
|
] = params;
|
||||||
|
|
||||||
|
polynomials.push(
|
||||||
|
new Polynomial(1)
|
||||||
|
.monomial()
|
||||||
|
.term(nx1, POW_1_FN)
|
||||||
|
.term(nx2, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(ny1, POW_1_FN)
|
||||||
|
.term(ny2, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(nz1, POW_1_FN)
|
||||||
|
.term(nz2, POW_1_FN)
|
||||||
|
);
|
||||||
|
|
||||||
|
rigidBodyLink3x3(
|
||||||
|
[ix1, iy1, iz1, jx1, jy1, jz1, kx1, ky1, kz1],
|
||||||
|
csys1.csys,
|
||||||
|
face1.normal
|
||||||
|
).forEach(p => polynomials.push(p));
|
||||||
|
|
||||||
|
rigidBodyLink3x3(
|
||||||
|
[ix2, iy2, iz2, jx2, jy2, jz2, kx2, ky2, kz2],
|
||||||
|
csys2.csys,
|
||||||
|
face2.normal
|
||||||
|
).forEach(p => polynomials.push(p));
|
||||||
|
|
||||||
|
polynomials.push(
|
||||||
|
new Polynomial(-1)
|
||||||
|
.monomial()
|
||||||
|
.term(nx1, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(ny1, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(nz1, POW_2_FN)
|
||||||
|
);
|
||||||
|
|
||||||
|
polynomials.push(
|
||||||
|
new Polynomial(-1)
|
||||||
|
.monomial()
|
||||||
|
.term(nx2, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(ny2, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(nz2, POW_2_FN)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
function vectorParams(vec) {
|
||||||
|
const {x, y, z} = vec;
|
||||||
|
return [new Param(x, 'X'), new Param(y, 'Y'), new Param(z, 'Z')];
|
||||||
|
}
|
||||||
|
|
||||||
|
function csysParams(csys) {
|
||||||
|
const {x, y, z} = csys.origin;
|
||||||
|
return [
|
||||||
|
new Param(x, 'X'),
|
||||||
|
new Param(y, 'Y'),
|
||||||
|
new Param(z, 'Z'),
|
||||||
|
new Param(csys.x.x, 'X'),
|
||||||
|
new Param(csys.x.y, 'Y'),
|
||||||
|
new Param(csys.x.z, 'Z'),
|
||||||
|
new Param(csys.y.x, 'X'),
|
||||||
|
new Param(csys.y.y, 'Y'),
|
||||||
|
new Param(csys.y.z, 'Z'),
|
||||||
|
new Param(csys.z.x, 'X'),
|
||||||
|
new Param(csys.z.y, 'Y'),
|
||||||
|
new Param(csys.z.z, 'Z')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function faceWrapper(face: MBrepFace) {
|
||||||
|
|
||||||
|
return {
|
||||||
|
constraints: new Set(),
|
||||||
|
normal: vectorParams(face.normal()),
|
||||||
|
face,
|
||||||
|
visitParams(cb) {
|
||||||
|
this.normal.forEach(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function csysWrapper(csys: CSys) {
|
||||||
|
|
||||||
|
return {
|
||||||
|
constraints: new Set(),
|
||||||
|
params: csysParams(csys),
|
||||||
|
csys,
|
||||||
|
visitParams(cb) {
|
||||||
|
this.params.forEach(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
function faceParallel(ctx: ApplicationContext, faceSelection: string[]) {
|
||||||
|
|
||||||
|
const [face1, face2] = faceSelection.map(id => ctx.cadRegistry.find(id));
|
||||||
|
|
||||||
|
const constraints = [
|
||||||
|
createAssemblyConstraint(Constraints3D.FaceParallel, [face1, face2])
|
||||||
|
];
|
||||||
|
|
||||||
|
solveAssembly(constraints);
|
||||||
|
}
|
||||||
|
|
||||||
|
function faceParallelLegacy(ctx: ApplicationContext, faceSelection: string[]) {
|
||||||
|
|
||||||
|
const [face1, face2] = faceSelection.map(id => ctx.cadRegistry.find(id));
|
||||||
|
|
||||||
|
const stage = {};
|
||||||
|
const objects = [
|
||||||
|
faceWrapper(face1),
|
||||||
|
faceWrapper(face2),
|
||||||
|
csysWrapper(face1.shell.csys),
|
||||||
|
csysWrapper(face2.shell.csys),
|
||||||
|
];
|
||||||
|
objects.forEach(o => o.stage = stage);
|
||||||
|
stage.objects = objects;
|
||||||
|
const algNumConstraint = new AlgNumConstraint(XConstraints3D.FaceParallel, objects);
|
||||||
|
|
||||||
|
const system = new AlgNumSubSystem(() => 0.001, val => val, stage);
|
||||||
|
// __DEBUG__.AddNormal(face1.csys.origin, new Vector().set3(objects[0].normal.map(p => p.get())))
|
||||||
|
// __DEBUG__.AddNormal(face2.csys.origin, new Vector().set3(objects[1].normal.map(p => p.get())))
|
||||||
|
|
||||||
|
system.startTransaction();
|
||||||
|
system.addConstraint(algNumConstraint);
|
||||||
|
system.prepare();
|
||||||
|
system.solveFine();
|
||||||
|
system.finishTransaction();
|
||||||
|
|
||||||
|
__DEBUG__.AddNormal(face1.csys.origin, new Vector().set3(objects[0].normal.map(p => p.get())))
|
||||||
|
__DEBUG__.AddNormal(face2.csys.origin, new Vector().set3(objects[1].normal.map(p => p.get())))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function applyResults(shell, targetCsysParams, normal) {
|
||||||
|
const [
|
||||||
|
ox, oy, oz, ix, iy, iz, jx, jy, jz, kx, ky, kz
|
||||||
|
] = targetCsysParams.map(p => p.get());
|
||||||
|
|
||||||
|
const targetCsys = new CSys(
|
||||||
|
new Vector(ox, oy, oz),
|
||||||
|
new Vector(ix, iy, iz),
|
||||||
|
new Vector(jx, jy, jz),
|
||||||
|
new Vector(kx, ky, kz),
|
||||||
|
);
|
||||||
|
|
||||||
|
const basis = [
|
||||||
|
new Vector(ix, iy, iz),
|
||||||
|
new Vector(jx, jy, jz),
|
||||||
|
new Vector(kx, ky, kz),
|
||||||
|
];
|
||||||
|
|
||||||
|
// __DEBUG__.AddCSys(shell.csys);
|
||||||
|
__DEBUG__.AddCSys(targetCsys);
|
||||||
|
|
||||||
|
const tr = shell.csys.inTransformation3x3;
|
||||||
|
basis.forEach(r => tr._apply(r));
|
||||||
|
|
||||||
|
shell.location$.update(csys => {
|
||||||
|
return targetCsys;
|
||||||
|
});
|
||||||
|
// shell.location$.mutate(csys => {
|
||||||
|
// csys.x = basis[0];
|
||||||
|
// csys.y = basis[1];
|
||||||
|
// csys.z = basis[2];
|
||||||
|
// csys.origin = new Vector(ox, oy, oz)._minus(shell.csys.origin);
|
||||||
|
// });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
applyResults(face1.shell, objects[2].params, new Vector().set3(objects[0].normal.map(p => p.get())));
|
||||||
|
applyResults(face2.shell, objects[3].params, new Vector().set3(objects[1].normal.map(p => p.get())));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function rigidBodyLink3x3(csysParams, csys, vector) {
|
||||||
|
const [ix, iy, iz, jx, jy, jz, kx, ky, kz] = csysParams;
|
||||||
|
const [x, y, z] = vector;
|
||||||
|
|
||||||
|
// const [nStarX, nStarY, nStarZ] = csys.inTransformation3x3.apply3(vector.map(p => p.get()));
|
||||||
|
const [nStarX, nStarY, nStarZ] = vector.map(p => p.get());
|
||||||
|
// out.x = this.mxx * x + this.mxy * y + this.mxz * z + this.tx;
|
||||||
|
// out.y = this.myx * x + this.myy * y + this.myz * z + this.ty;
|
||||||
|
// out.z = this.mzx * x + this.mzy * y + this.mzz * z + this.tz;
|
||||||
|
|
||||||
|
return [
|
||||||
|
new Polynomial(0)
|
||||||
|
.monomial(-1)
|
||||||
|
.term(x, POW_1_FN)
|
||||||
|
.monomial(nStarX)
|
||||||
|
.term(ix, POW_1_FN)
|
||||||
|
.monomial(nStarY)
|
||||||
|
.term(jx, POW_1_FN)
|
||||||
|
.monomial(nStarZ)
|
||||||
|
.term(kx, POW_1_FN),
|
||||||
|
|
||||||
|
new Polynomial(0)
|
||||||
|
.monomial(-1)
|
||||||
|
.term(y, POW_1_FN)
|
||||||
|
.monomial(nStarX)
|
||||||
|
.term(iy, POW_1_FN)
|
||||||
|
.monomial(nStarY)
|
||||||
|
.term(jy, POW_1_FN)
|
||||||
|
.monomial(nStarZ)
|
||||||
|
.term(ky, POW_1_FN),
|
||||||
|
|
||||||
|
new Polynomial(0)
|
||||||
|
.monomial(-1)
|
||||||
|
.term(z, POW_1_FN)
|
||||||
|
.monomial(nStarX)
|
||||||
|
.term(iz, POW_1_FN)
|
||||||
|
.monomial(nStarY)
|
||||||
|
.term(jz, POW_1_FN)
|
||||||
|
.monomial(nStarZ)
|
||||||
|
.term(kz, POW_1_FN),
|
||||||
|
|
||||||
|
|
||||||
|
new Polynomial(0)
|
||||||
|
.monomial()
|
||||||
|
.term(ix, POW_1_FN)
|
||||||
|
.term(jx, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(iy, POW_1_FN)
|
||||||
|
.term(jy, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(iz, POW_1_FN)
|
||||||
|
.term(jz, POW_1_FN),
|
||||||
|
|
||||||
|
new Polynomial(0)
|
||||||
|
.monomial()
|
||||||
|
.term(ix, POW_1_FN)
|
||||||
|
.term(kx, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(iy, POW_1_FN)
|
||||||
|
.term(ky, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(iz, POW_1_FN)
|
||||||
|
.term(kz, POW_1_FN),
|
||||||
|
|
||||||
|
new Polynomial(0)
|
||||||
|
.monomial()
|
||||||
|
.term(jx, POW_1_FN)
|
||||||
|
.term(kx, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(jy, POW_1_FN)
|
||||||
|
.term(ky, POW_1_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(jz, POW_1_FN)
|
||||||
|
.term(kz, POW_1_FN),
|
||||||
|
|
||||||
|
new Polynomial(-1)
|
||||||
|
.monomial()
|
||||||
|
.term(ix, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(iy, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(iz, POW_2_FN),
|
||||||
|
|
||||||
|
new Polynomial(-1)
|
||||||
|
.monomial()
|
||||||
|
.term(jx, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(jy, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(jz, POW_2_FN),
|
||||||
|
|
||||||
|
new Polynomial(-1)
|
||||||
|
.monomial()
|
||||||
|
.term(kx, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(ky, POW_2_FN)
|
||||||
|
.monomial()
|
||||||
|
.term(kz, POW_2_FN),
|
||||||
|
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,6 @@ import connect from 'ui/connect';
|
||||||
import Fa from 'ui/components/Fa';
|
import Fa from 'ui/components/Fa';
|
||||||
import {toIdAndOverrides} from '../../actions/actionRef';
|
import {toIdAndOverrides} from '../../actions/actionRef';
|
||||||
import {isMenuAction} from '../menu/menuPlugin';
|
import {isMenuAction} from '../menu/menuPlugin';
|
||||||
import {combine} from 'lstream';
|
|
||||||
import {menuAboveElementHint} from '../menu/menuUtils';
|
import {menuAboveElementHint} from '../menu/menuUtils';
|
||||||
import {useStream} from "../../../../../modules/ui/effects";
|
import {useStream} from "../../../../../modules/ui/effects";
|
||||||
import {ActionButtonBehavior} from "../../actions/ActionButtonBehavior";
|
import {ActionButtonBehavior} from "../../actions/ActionButtonBehavior";
|
||||||
|
|
@ -44,11 +43,13 @@ const RightGroup = connect(streams => streams.ui.controlBars.right.map(actions =
|
||||||
function ConnectedActionButton(props) {
|
function ConnectedActionButton(props) {
|
||||||
|
|
||||||
const actionId = props.actionId;
|
const actionId = props.actionId;
|
||||||
const stream = useStream(ctx => combine(ctx.streams.action.appearance[actionId], ctx.streams.action.state[actionId]));
|
|
||||||
if (!stream) {
|
const actionAppearance = useStream(ctx => ctx.streams.action.appearance[actionId]);
|
||||||
|
const actionState = useStream(ctx => ctx.streams.action.state[actionId]);
|
||||||
|
|
||||||
|
if (!actionAppearance || !actionState) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const [actionAppearance, actionState] = stream;
|
|
||||||
|
|
||||||
return <ActionButtonBehavior actionId={actionId}>
|
return <ActionButtonBehavior actionId={actionId}>
|
||||||
{behaviourProps => <ActionButton {...behaviourProps} {...actionAppearance} {...actionState} {...props} />}
|
{behaviourProps => <ActionButton {...behaviourProps} {...actionAppearance} {...actionState} {...props} />}
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,11 @@ function ActionButton({label, icon, icon96, icon32, cssIcons, symbol, size, noLa
|
||||||
export function ConnectedActionButton(props) {
|
export function ConnectedActionButton(props) {
|
||||||
|
|
||||||
const actionId = props.actionId;
|
const actionId = props.actionId;
|
||||||
const stream = useStream(ctx => combine(ctx.streams.action.appearance[actionId], ctx.streams.action.state[actionId]));
|
const actionAppearance = useStream(ctx => ctx.streams.action.appearance[actionId]);
|
||||||
if (!stream) {
|
const actionState = useStream(ctx => ctx.streams.action.state[actionId]);
|
||||||
|
if (!actionAppearance || !actionState) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const [actionAppearance, actionState] = stream;
|
|
||||||
|
|
||||||
return<ActionButtonBehavior actionId={actionId}>
|
return<ActionButtonBehavior actionId={actionId}>
|
||||||
{behaviourProps => <ActionButton {...behaviourProps} {...actionAppearance} {...actionState} {...props} />}
|
{behaviourProps => <ActionButton {...behaviourProps} {...actionAppearance} {...actionState} {...props} />}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ export default function UISystem({children, ...props}) {
|
||||||
<MenuHolder/>
|
<MenuHolder/>
|
||||||
<ActionInfo/>
|
<ActionInfo/>
|
||||||
{children}
|
{children}
|
||||||
<ContributedComponents/>
|
|
||||||
<Scope><DocumentationWindow/></Scope>
|
<Scope><DocumentationWindow/></Scope>
|
||||||
</div>
|
</div>
|
||||||
</UISystemContext.Provider>;
|
</UISystemContext.Provider>;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ import {ConstraintEditor} from "../../../sketcher/components/ConstraintEditor";
|
||||||
import SketcherOperationWizard from "../../../sketcher/components/SketcherOperationWizard";
|
import SketcherOperationWizard from "../../../sketcher/components/SketcherOperationWizard";
|
||||||
import {ToastContainer} from "react-toastify";
|
import {ToastContainer} from "react-toastify";
|
||||||
import 'react-toastify/dist/ReactToastify.css';
|
import 'react-toastify/dist/ReactToastify.css';
|
||||||
|
import {ContributedComponents} from "./ContributedComponents";
|
||||||
|
import {ModellerContextualActions} from "./ModellerContextualActions";
|
||||||
|
|
||||||
export default class View3d extends React.Component {
|
export default class View3d extends React.Component {
|
||||||
|
|
||||||
|
|
@ -56,6 +58,8 @@ export default class View3d extends React.Component {
|
||||||
<div className={ls.wizardArea} >
|
<div className={ls.wizardArea} >
|
||||||
<WizardManager/>
|
<WizardManager/>
|
||||||
</div>
|
</div>
|
||||||
|
<ContributedComponents/>
|
||||||
|
<Scope><ModellerContextualActions /></Scope>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={ls.bottomStack}>
|
<div className={ls.bottomStack}>
|
||||||
|
|
|
||||||
|
|
@ -57,11 +57,14 @@ const ConnectedActionMenu = connect((streams, props) =>
|
||||||
export function ConnectedMenuItem(props) {
|
export function ConnectedMenuItem(props) {
|
||||||
|
|
||||||
const actionId = props.actionId;
|
const actionId = props.actionId;
|
||||||
const stream = useStream(ctx => combine(ctx.streams.action.appearance[actionId], ctx.streams.action.state[actionId]));
|
|
||||||
if (!stream) {
|
const actionAppearance = useStream(ctx => ctx.streams.action.appearance[actionId]);
|
||||||
|
const actionState = useStream(ctx => ctx.streams.action.state[actionId]);
|
||||||
|
|
||||||
|
|
||||||
|
if (!actionAppearance || !actionState) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const [actionAppearance, actionState] = stream;
|
|
||||||
|
|
||||||
return <ActionButtonBehavior actionId={actionId}>
|
return <ActionButtonBehavior actionId={actionId}>
|
||||||
{behaviourProps => <ActionMenuItem {...behaviourProps} {...actionAppearance} {...actionState} {...props} />}
|
{behaviourProps => <ActionMenuItem {...behaviourProps} {...actionAppearance} {...actionState} {...props} />}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ import * as UIConfigPlugin from "../part/uiConfigPlugin";
|
||||||
import * as DebugPlugin from "../debugPlugin";
|
import * as DebugPlugin from "../debugPlugin";
|
||||||
import * as ExpressionsPlugin from "../expressions/expressionsPlugin";
|
import * as ExpressionsPlugin from "../expressions/expressionsPlugin";
|
||||||
import * as PartOperationsPlugin from "../part/partOperationsPlugin";
|
import * as PartOperationsPlugin from "../part/partOperationsPlugin";
|
||||||
|
import * as LocationPlugin from "../location/locationPlugin";
|
||||||
|
|
||||||
export default function startApplication(callback) {
|
export default function startApplication(callback) {
|
||||||
|
|
||||||
|
|
@ -75,6 +75,7 @@ export default function startApplication(callback) {
|
||||||
UIConfigPlugin,
|
UIConfigPlugin,
|
||||||
DebugPlugin,
|
DebugPlugin,
|
||||||
PartOperationsPlugin,
|
PartOperationsPlugin,
|
||||||
|
LocationPlugin,
|
||||||
RemotePartsPlugin,
|
RemotePartsPlugin,
|
||||||
ViewSyncPlugin,
|
ViewSyncPlugin,
|
||||||
WizardSelectionPlugin
|
WizardSelectionPlugin
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import {Matrix3} from '../../../math/l3space'
|
import {Matrix3} from '../../../../../modules/math/l3space'
|
||||||
import Vector from 'math/vector';
|
import Vector from 'math/vector';
|
||||||
import * as math from '../../../math/math'
|
import * as math from '../../../math/math'
|
||||||
import {createShared} from '../../cad-utils'
|
import {createShared} from '../../cad-utils'
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import {AXIS, IDENTITY_BASIS} from '../../../../math/l3space'
|
import {AXIS, IDENTITY_BASIS} from '../../../../../../modules/math/l3space'
|
||||||
import * as tk from '../../../../ui/toolkit.js'
|
import * as tk from '../../../../ui/toolkit.js'
|
||||||
import {FACE_COLOR} from '../../../cad-utils'
|
import {FACE_COLOR} from '../../../cad-utils'
|
||||||
import {Wizard} from './wizard-commons'
|
import {Wizard} from './wizard-commons'
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import * as tk from '../../../../ui/toolkit.js'
|
||||||
import * as workbench from '../workbench'
|
import * as workbench from '../workbench'
|
||||||
import * as cad_utils from '../../../cad-utils'
|
import * as cad_utils from '../../../cad-utils'
|
||||||
import Vector from 'math/vector';
|
import Vector from 'math/vector';
|
||||||
import {Matrix3, ORIGIN} from '../../../../math/l3space'
|
import {Matrix3, ORIGIN} from '../../../../../../modules/math/l3space'
|
||||||
import {OpWizard, IMAGINE_MATERIAL, BASE_MATERIAL} from './wizard-commons'
|
import {OpWizard, IMAGINE_MATERIAL, BASE_MATERIAL} from './wizard-commons'
|
||||||
|
|
||||||
export function ExtrudeWizard(app, face, invert, initParams) {
|
export function ExtrudeWizard(app, face, invert, initParams) {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import {AXIS, IDENTITY_BASIS} from '../../../../math/l3space'
|
import {AXIS, IDENTITY_BASIS} from '../../../../../../modules/math/l3space'
|
||||||
import * as tk from '../../../../ui/toolkit.js'
|
import * as tk from '../../../../ui/toolkit.js'
|
||||||
import {FACE_COLOR} from '../../../cad-utils'
|
import {FACE_COLOR} from '../../../cad-utils'
|
||||||
import {Wizard} from './wizard-commons'
|
import {Wizard} from './wizard-commons'
|
||||||
import {Matrix3} from '../../../../math/l3space'
|
import {Matrix3} from '../../../../../../modules/math/l3space'
|
||||||
|
|
||||||
export function PlaneWizard(app, initParams) {
|
export function PlaneWizard(app, initParams) {
|
||||||
Wizard.call(this, app.viewer, initParams);
|
Wizard.call(this, app.viewer, initParams);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import * as tk from '../../../../ui/toolkit.js'
|
||||||
import * as workbench from '../workbench'
|
import * as workbench from '../workbench'
|
||||||
import * as cad_utils from '../../../cad-utils'
|
import * as cad_utils from '../../../cad-utils'
|
||||||
import Vector from 'math/vector';
|
import Vector from 'math/vector';
|
||||||
import {Matrix3, ORIGIN} from '../../../../math/l3space'
|
import {Matrix3, ORIGIN} from '../../../../../../modules/math/l3space'
|
||||||
import {revolveToTriangles} from '../revolve'
|
import {revolveToTriangles} from '../revolve'
|
||||||
import {OpWizard, IMAGINARY_SURFACE_MATERIAL, } from './wizard-commons'
|
import {OpWizard, IMAGINARY_SURFACE_MATERIAL, } from './wizard-commons'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import {AXIS, IDENTITY_BASIS} from '../../../../math/l3space'
|
import {AXIS, IDENTITY_BASIS} from '../../../../../../modules/math/l3space'
|
||||||
import * as tk from '../../../../ui/toolkit.js'
|
import * as tk from '../../../../ui/toolkit.js'
|
||||||
import {FACE_COLOR} from '../../../cad-utils'
|
import {FACE_COLOR} from '../../../cad-utils'
|
||||||
import {Wizard} from './wizard-commons'
|
import {Wizard} from './wizard-commons'
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import {AXIS, IDENTITY_BASIS} from '../../../../math/l3space'
|
import {AXIS, IDENTITY_BASIS} from '../../../../../../modules/math/l3space'
|
||||||
import * as tk from '../../../../ui/toolkit.js'
|
import * as tk from '../../../../ui/toolkit.js'
|
||||||
import {FACE_COLOR} from '../../../cad-utils'
|
import {FACE_COLOR} from '../../../cad-utils'
|
||||||
import {Wizard} from './wizard-commons'
|
import {Wizard} from './wizard-commons'
|
||||||
|
|
|
||||||
116
web/app/cad/location/LocationDialog.tsx
Normal file
116
web/app/cad/location/LocationDialog.tsx
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
import React, {useCallback, useContext} from 'react';
|
||||||
|
import {useStreamWithUpdater} from "ui/effects";
|
||||||
|
import {AppContext} from "../dom/components/AppContext";
|
||||||
|
import {GenericWizard} from "ui/components/GenericWizard";
|
||||||
|
import Field from "ui/components/controls/Field";
|
||||||
|
import {Group} from "../craft/wizard/components/form/Form";
|
||||||
|
import Label from "ui/components/controls/Label";
|
||||||
|
import Folder from "ui/components/Folder";
|
||||||
|
import {never} from "lstream";
|
||||||
|
import NumberControl from "ui/components/controls/NumberControl";
|
||||||
|
import {Location} from "../model/location";
|
||||||
|
import {DEG_RAD} from "../../math/math";
|
||||||
|
import CSys from "math/csys";
|
||||||
|
|
||||||
|
export function LocationDialog() {
|
||||||
|
|
||||||
|
const [req, setReq] = useStreamWithUpdater(ctx => ctx.locationService.editLocationRequest$);
|
||||||
|
|
||||||
|
|
||||||
|
const [location, setLocation] = useStreamWithUpdater(() => req ? req.shell.location$ : never<CSys>());
|
||||||
|
|
||||||
|
const setX = useCallback(x => {
|
||||||
|
location.origin.x = parseFloat(x);
|
||||||
|
setLocation(location);
|
||||||
|
}, [setLocation]);
|
||||||
|
|
||||||
|
const setY = useCallback(y => {
|
||||||
|
location.origin.y = parseFloat(y);
|
||||||
|
setLocation(location);
|
||||||
|
}, [setLocation]);
|
||||||
|
|
||||||
|
const setZ = useCallback(z => {
|
||||||
|
location.origin.z = parseFloat(z);
|
||||||
|
setLocation(location);
|
||||||
|
}, [setLocation]);
|
||||||
|
//
|
||||||
|
// const setAzimuth = useCallback(angle => {
|
||||||
|
// location.rotationAxisAzimuth = parseFloat(angle) * DEG_RAD;
|
||||||
|
// setLocation(location);
|
||||||
|
// }, [setLocation]);
|
||||||
|
//
|
||||||
|
// const setInclination = useCallback(angle => {
|
||||||
|
// location.rotationAxisInclination = parseFloat(angle) * DEG_RAD;
|
||||||
|
// setLocation(location);
|
||||||
|
// }, [setLocation]);
|
||||||
|
//
|
||||||
|
// const setAngle = useCallback(angle => {
|
||||||
|
// location.rotationAxisAngle = parseFloat(angle) * DEG_RAD;
|
||||||
|
// setLocation(location);
|
||||||
|
// }, [setLocation]);
|
||||||
|
|
||||||
|
const ctx = useContext(AppContext);
|
||||||
|
|
||||||
|
if (!req) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const revert = () => {
|
||||||
|
// close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
setReq(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const revertAndClose = () => {
|
||||||
|
close();
|
||||||
|
};
|
||||||
|
|
||||||
|
return <GenericWizard
|
||||||
|
left={15}
|
||||||
|
title='PART LOCATION'
|
||||||
|
onClose={close}
|
||||||
|
className='location-dialog'
|
||||||
|
topicId='entity-location'
|
||||||
|
infoText={null}
|
||||||
|
onCancel={revertAndClose}
|
||||||
|
onOK={close} >
|
||||||
|
|
||||||
|
<Folder title='Position'>
|
||||||
|
<Group>
|
||||||
|
<Field active={false} name='X'>
|
||||||
|
<Label>X:</Label>
|
||||||
|
<NumberControl onChange={setX} value={location.origin.x} />
|
||||||
|
</Field>
|
||||||
|
<Field active={false} name='Y'>
|
||||||
|
<Label>Y:</Label>
|
||||||
|
<NumberControl onChange={setY} value={location.origin.y} />
|
||||||
|
</Field>
|
||||||
|
<Field active={false} name='Z'>
|
||||||
|
<Label>Z:</Label>
|
||||||
|
<NumberControl onChange={setZ} value={location.origin.z} />
|
||||||
|
</Field>
|
||||||
|
</Group>
|
||||||
|
</Folder>
|
||||||
|
<Folder title='Rotation'>
|
||||||
|
<Group>
|
||||||
|
{/*<Field active={false} name='Azimuth'>*/}
|
||||||
|
{/* <Label>Axis Azimuth:</Label>*/}
|
||||||
|
{/* <NumberControl onChange={setAzimuth} value={location.rotationAxisAzimuth / DEG_RAD} />*/}
|
||||||
|
{/*</Field>*/}
|
||||||
|
{/*<Field active={false} name='Inclination'>*/}
|
||||||
|
{/* <Label>Axis Inclination:</Label>*/}
|
||||||
|
{/* <NumberControl onChange={setInclination} value={location.rotationAxisInclination / DEG_RAD} />*/}
|
||||||
|
{/*</Field>*/}
|
||||||
|
{/*<Field active={false} name='Angle'>*/}
|
||||||
|
{/* <Label>Angle:</Label>*/}
|
||||||
|
{/* <NumberControl onChange={setAngle} value={location.rotationAxisAngle / DEG_RAD} />*/}
|
||||||
|
{/*</Field>*/}
|
||||||
|
</Group>
|
||||||
|
</Folder>
|
||||||
|
|
||||||
|
|
||||||
|
</GenericWizard>
|
||||||
|
|
||||||
|
}
|
||||||
44
web/app/cad/location/LocationPlugin.ts
Normal file
44
web/app/cad/location/LocationPlugin.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import {state, StateStream} from "lstream";
|
||||||
|
import {ApplicationContext} from "context";
|
||||||
|
import {MShell} from "../model/mshell";
|
||||||
|
import {LocationDialog} from "./LocationDialog";
|
||||||
|
|
||||||
|
export function activate(ctx: ApplicationContext) {
|
||||||
|
|
||||||
|
ctx.domService.contributeComponent(LocationDialog);
|
||||||
|
|
||||||
|
const editLocationRequest$ = state(null);
|
||||||
|
|
||||||
|
ctx.locationService = {
|
||||||
|
editLocationRequest$,
|
||||||
|
|
||||||
|
edit: shell => {
|
||||||
|
editLocationRequest$.next({
|
||||||
|
shell
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface EditLocationRequest {
|
||||||
|
|
||||||
|
shell: MShell;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LocationService {
|
||||||
|
|
||||||
|
editLocationRequest$: StateStream<EditLocationRequest>;
|
||||||
|
|
||||||
|
edit(shell);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'context' {
|
||||||
|
interface ApplicationContext {
|
||||||
|
|
||||||
|
locationService: LocationService;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
24
web/app/cad/model/location.ts
Normal file
24
web/app/cad/model/location.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import Vector from "math/vector";
|
||||||
|
import {Matrix3} from "math/l3space";
|
||||||
|
|
||||||
|
export class Location {
|
||||||
|
|
||||||
|
rotationAxisAzimuth: number = 0;
|
||||||
|
rotationAxisInclination: number = 0;
|
||||||
|
rotationAxisAngle: number = 0;
|
||||||
|
|
||||||
|
translation: Vector = new Vector();
|
||||||
|
|
||||||
|
__mx = new Matrix3();
|
||||||
|
|
||||||
|
toTransformationMatrix() {
|
||||||
|
this.__mx.rotateWithSphericalAxis(
|
||||||
|
this.rotationAxisAzimuth,
|
||||||
|
this.rotationAxisInclination,
|
||||||
|
this.rotationAxisAngle,
|
||||||
|
this.translation
|
||||||
|
);
|
||||||
|
return this.__mx;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import {MObject, MObjectIdGenerator} from './mobject';
|
import {MObject, MObjectIdGenerator} from './mobject';
|
||||||
import CSys from "../../math/csys";
|
import CSys from "math/csys";
|
||||||
import Vector from "math/vector";
|
import Vector from "math/vector";
|
||||||
|
|
||||||
export class MDatum extends MObject {
|
export class MDatum extends MObject {
|
||||||
|
|
@ -13,9 +13,9 @@ export class MDatum extends MObject {
|
||||||
constructor(csys) {
|
constructor(csys) {
|
||||||
super(MDatum.TYPE, MObjectIdGenerator.next(MDatum.TYPE, 'D'));
|
super(MDatum.TYPE, MObjectIdGenerator.next(MDatum.TYPE, 'D'));
|
||||||
this.csys = csys;
|
this.csys = csys;
|
||||||
this.xAxis = new MDatumAxis(this.id + '/X', this.csys.origin, this.csys.x);
|
this.xAxis = new MDatumAxis(this.id + '/X', this.csys.origin, this.csys.x, this);
|
||||||
this.yAxis = new MDatumAxis(this.id + '/Y', this.csys.origin, this.csys.y);
|
this.yAxis = new MDatumAxis(this.id + '/Y', this.csys.origin, this.csys.y, this);
|
||||||
this.zAxis = new MDatumAxis(this.id + '/Z', this.csys.origin, this.csys.z);
|
this.zAxis = new MDatumAxis(this.id + '/Z', this.csys.origin, this.csys.z, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAxisByLiteral(literal) {
|
getAxisByLiteral(literal) {
|
||||||
|
|
@ -33,6 +33,10 @@ export class MDatum extends MObject {
|
||||||
this.yAxis.traverse(callback);
|
this.yAxis.traverse(callback);
|
||||||
this.zAxis.traverse(callback);
|
this.zAxis.traverse(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get parent() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MDatumAxis extends MObject {
|
export class MDatumAxis extends MObject {
|
||||||
|
|
@ -40,10 +44,16 @@ export class MDatumAxis extends MObject {
|
||||||
static TYPE = 'datumAxis';
|
static TYPE = 'datumAxis';
|
||||||
origin: Vector;
|
origin: Vector;
|
||||||
dir: Vector;
|
dir: Vector;
|
||||||
|
holder: MObject;
|
||||||
|
|
||||||
constructor(id, origin, dir) {
|
constructor(id, origin, dir, holder) {
|
||||||
super(MDatumAxis.TYPE, id);
|
super(MDatumAxis.TYPE, id);
|
||||||
this.origin = origin;
|
this.origin = origin;
|
||||||
this.dir = dir;
|
this.dir = dir;
|
||||||
|
this.holder = holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
get parent() {
|
||||||
|
return this.holder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import {MObject} from './mobject';
|
import {MObject} from './mobject';
|
||||||
import {MBrepShell, MShell} from "./mshell";
|
import {MBrepShell} from "./mshell";
|
||||||
|
|
||||||
export class MEdge extends MObject {
|
export class MEdge extends MObject {
|
||||||
|
|
||||||
|
|
@ -25,4 +25,8 @@ export class MEdge extends MObject {
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get parent() {
|
||||||
|
return this.shell;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
import {MObject} from './mobject';
|
import {MObject} from './mobject';
|
||||||
import Vector from 'math/vector';
|
import Vector from 'math/vector';
|
||||||
import {BasisForPlane} from '../../math/l3space';
|
import {BasisForPlane} from 'math/l3space';
|
||||||
import {MSketchObject} from './msketchObject';
|
import {MSketchObject} from './msketchObject';
|
||||||
import {EMPTY_ARRAY} from 'gems/iterables';
|
import {EMPTY_ARRAY} from 'gems/iterables';
|
||||||
import CSys from '../../math/csys';
|
import CSys from 'math/csys';
|
||||||
import {MSketchLoop} from './mloop';
|
import {MSketchLoop} from './mloop';
|
||||||
import {ProductionInfo} from './productionInfo';
|
import {ProductionInfo} from './productionInfo';
|
||||||
import {MBrepShell, MShell} from "./mshell";
|
import {MBrepShell, MShell} from "./mshell";
|
||||||
|
import {AssemblyUnitVectorNode} from "../assembly/assembly";
|
||||||
|
|
||||||
export class MFace extends MObject {
|
export class MFace extends MObject {
|
||||||
|
|
||||||
|
|
@ -18,6 +19,10 @@ export class MFace extends MObject {
|
||||||
sketch: any;
|
sketch: any;
|
||||||
brepFace: any;
|
brepFace: any;
|
||||||
|
|
||||||
|
assemblyNodes: {
|
||||||
|
normal: AssemblyUnitVectorNode
|
||||||
|
};
|
||||||
|
|
||||||
private _csys: any;
|
private _csys: any;
|
||||||
private w: number;
|
private w: number;
|
||||||
private _basis: [Vector, Vector, Vector];
|
private _basis: [Vector, Vector, Vector];
|
||||||
|
|
@ -31,7 +36,10 @@ export class MFace extends MObject {
|
||||||
this.surface = surface;
|
this.surface = surface;
|
||||||
this.sketchObjects = [];
|
this.sketchObjects = [];
|
||||||
this.sketchLoops = [];
|
this.sketchLoops = [];
|
||||||
this._csys = csys
|
this._csys = csys;
|
||||||
|
this.assemblyNodes = {
|
||||||
|
normal: new AssemblyUnitVectorNode(this, () => this.normal())
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
normal() {
|
normal() {
|
||||||
|
|
@ -166,6 +174,10 @@ export class MFace extends MObject {
|
||||||
this.sketchLoops.forEach(i => i.traverse(callback));
|
this.sketchLoops.forEach(i => i.traverse(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get parent() {
|
||||||
|
return this.shell;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MBrepFace extends MFace {
|
export class MBrepFace extends MFace {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ export class MLoop extends MObject {
|
||||||
super(MLoop.TYPE, id);
|
super(MLoop.TYPE, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get parent() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MSketchLoop extends MLoop {
|
export class MSketchLoop extends MLoop {
|
||||||
|
|
@ -24,5 +27,9 @@ export class MSketchLoop extends MLoop {
|
||||||
this.contour = contour;
|
this.contour = contour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get parent() {
|
||||||
|
return this.face;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
|
|
||||||
export abstract class MObject {
|
export abstract class MObject {
|
||||||
|
|
||||||
TYPE: string;
|
TYPE: string;
|
||||||
|
|
||||||
id: string;
|
id: string;
|
||||||
ext: any = {};
|
ext: any = {};
|
||||||
|
|
||||||
constructor(TYPE, id) {
|
constructor(TYPE, id) {
|
||||||
this.TYPE = TYPE;
|
this.TYPE = TYPE;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
@ -14,6 +13,16 @@ export abstract class MObject {
|
||||||
traverse(callback: (obj: MObject) => void): void {
|
traverse(callback: (obj: MObject) => void): void {
|
||||||
callback(this);
|
callback(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract get parent();
|
||||||
|
|
||||||
|
get root(): MObject {
|
||||||
|
let obj = this;
|
||||||
|
while (obj.parent) {
|
||||||
|
obj = obj.parent;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MObjectIdGenerator = {
|
export const MObjectIdGenerator = {
|
||||||
|
|
@ -50,3 +59,4 @@ export const MObjectIdGenerator = {
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,5 +16,8 @@ export class MOpenFaceShell extends MShell {
|
||||||
get face() {
|
get face() {
|
||||||
return this.faces[0];
|
return this.faces[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get parent() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
import {MObject, MObjectIdGenerator} from './mobject';
|
import {MObject, MObjectIdGenerator} from './mobject';
|
||||||
import {MBrepFace, MFace} from './mface';
|
import {MBrepFace} from './mface';
|
||||||
import {MEdge} from './medge';
|
import {MEdge} from './medge';
|
||||||
import {MVertex} from './mvertex';
|
import {MVertex} from './mvertex';
|
||||||
import CSys from '../../math/csys';
|
import CSys from 'math/csys';
|
||||||
|
import {Matrix3} from "math/l3space";
|
||||||
|
import {state, StateStream} from "lstream";
|
||||||
|
import {AssemblyCSysNode} from "../assembly/assembly";
|
||||||
|
|
||||||
export class MShell extends MObject {
|
export class MShell extends MObject {
|
||||||
|
|
||||||
|
|
@ -15,8 +18,20 @@ export class MShell extends MObject {
|
||||||
edges = [];
|
edges = [];
|
||||||
vertices = [];
|
vertices = [];
|
||||||
|
|
||||||
|
location$: StateStream<CSys> = state(CSys.origin());
|
||||||
|
locationMatrix$ = this.location$.map((csys: CSys) => csys.outTransformation).remember();
|
||||||
|
|
||||||
|
assemblyNodes: {
|
||||||
|
location: AssemblyCSysNode
|
||||||
|
};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(MShell.TYPE, MObjectIdGenerator.next(MShell.TYPE, 'S'))
|
super(MShell.TYPE, MObjectIdGenerator.next(MShell.TYPE, 'S'));
|
||||||
|
// @ts-ignore
|
||||||
|
this.assemblyNodes = {
|
||||||
|
location: new AssemblyCSysNode( this, () => new Matrix3() )
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
traverse(callback: (obj: MObject) => void): void {
|
traverse(callback: (obj: MObject) => void): void {
|
||||||
|
|
@ -25,6 +40,10 @@ export class MShell extends MObject {
|
||||||
this.edges.forEach(i => i.traverse(callback));
|
this.edges.forEach(i => i.traverse(callback));
|
||||||
this.vertices.forEach(i => i.traverse(callback));
|
this.vertices.forEach(i => i.traverse(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get parent() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MBrepShell extends MShell {
|
export class MBrepShell extends MShell {
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,8 @@ export class MSketchObject extends MObject {
|
||||||
this.construction = false;
|
this.construction = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get parent() {
|
||||||
|
return this.face;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -13,4 +13,8 @@ export class MVertex extends MObject {
|
||||||
this.brepVertex = brepVertex;
|
this.brepVertex = brepVertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get parent() {
|
||||||
|
return this.shell;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -11,7 +11,7 @@ import {SelectionView} from "../dom/components/SelectionView";
|
||||||
import {GrSelect} from "react-icons/gr";
|
import {GrSelect} from "react-icons/gr";
|
||||||
|
|
||||||
export const STANDARD_MODE_HEADS_UP_TOOLBAR = ['DATUM_CREATE', 'PLANE', 'EditFace', 'EXTRUDE', 'CUT', 'REVOLVE', 'LOFT',
|
export const STANDARD_MODE_HEADS_UP_TOOLBAR = ['DATUM_CREATE', 'PLANE', 'EditFace', 'EXTRUDE', 'CUT', 'REVOLVE', 'LOFT',
|
||||||
'-', 'FILLET', '-', 'INTERSECTION', 'SUBTRACT', 'UNION', '-', 'IMPORT_PART'];
|
'-', 'FILLET', '-', 'INTERSECTION', 'SUBTRACT', 'UNION', '-', 'IMPORT_PART', "IMPORT_STEP_FILE"];
|
||||||
|
|
||||||
export function activate({services, streams}) {
|
export function activate({services, streams}) {
|
||||||
streams.ui.controlBars.left.value = ['menu.file', 'menu.craft', 'menu.boolean', 'menu.primitives', 'menu.views', 'Donate', 'GitHub'];
|
streams.ui.controlBars.left.value = ['menu.file', 'menu.craft', 'menu.boolean', 'menu.primitives', 'menu.views', 'Donate', 'GitHub'];
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import {AXIS, Matrix3, ORIGIN} from '../math/l3space'
|
import {AXIS, Matrix3, ORIGIN} from '../../../modules/math/l3space'
|
||||||
import * as vec from 'math/vec'
|
import * as vec from 'math/vec'
|
||||||
import Vector from 'math/vector';
|
import Vector from 'math/vector';
|
||||||
import BrepBuilder from '../brep/brep-builder'
|
import BrepBuilder from '../brep/brep-builder'
|
||||||
|
|
@ -9,7 +9,7 @@ import {surfaceIntersect} from '../brep/geom/intersection/surfaceSurface';
|
||||||
import {closestToCurveParam} from '../brep/geom/curves/closestPoint';
|
import {closestToCurveParam} from '../brep/geom/curves/closestPoint';
|
||||||
import NurbsSurface from '../brep/geom/surfaces/nurbsSurface';
|
import NurbsSurface from '../brep/geom/surfaces/nurbsSurface';
|
||||||
import DatumObject3D from './craft/datum/datumObject';
|
import DatumObject3D from './craft/datum/datumObject';
|
||||||
import CSys from '../math/csys';
|
import CSys from '../../../modules/math/csys';
|
||||||
import {createOctreeFromSurface, sphereOctree, traverseOctree} from "../../../modules/voxels/octree";
|
import {createOctreeFromSurface, sphereOctree, traverseOctree} from "../../../modules/voxels/octree";
|
||||||
|
|
||||||
export function runSandbox({bus, services, services: { viewer, cadScene, cadRegistry, exposure, exposure: {addShellOnScene} }}) {
|
export function runSandbox({bus, services, services: { viewer, cadScene, cadRegistry, exposure, exposure: {addShellOnScene} }}) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import {AXIS} from '../../math/l3space'
|
import {AXIS} from '../../../../modules/math/l3space'
|
||||||
import {createArrow} from 'scene/objects/auxiliary';
|
import {createArrow} from 'scene/objects/auxiliary';
|
||||||
import Vector from 'math/vector';
|
import Vector from 'math/vector';
|
||||||
import {OnTopOfAll} from 'scene/materialMixins';
|
import {OnTopOfAll} from 'scene/materialMixins';
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ export function activate(context) {
|
||||||
|
|
||||||
domElement.addEventListener('mousedown', mousedown, false);
|
domElement.addEventListener('mousedown', mousedown, false);
|
||||||
domElement.addEventListener('mouseup', mouseup, false);
|
domElement.addEventListener('mouseup', mouseup, false);
|
||||||
|
domElement.addEventListener('dblclick', mousedblclick, false);
|
||||||
|
|
||||||
let mouseState = {
|
let mouseState = {
|
||||||
startX: 0,
|
startX: 0,
|
||||||
|
|
@ -93,6 +94,10 @@ export function activate(context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mousedblclick(e) {
|
||||||
|
handleSolidPick(e);
|
||||||
|
}
|
||||||
|
|
||||||
function setPickHandler(handler) {
|
function setPickHandler(handler) {
|
||||||
pickHandler = handler || defaultHandler;
|
pickHandler = handler || defaultHandler;
|
||||||
services.marker.clear();
|
services.marker.clear();
|
||||||
|
|
@ -136,8 +141,7 @@ export function activate(context) {
|
||||||
function handleSolidPick(e) {
|
function handleSolidPick(e) {
|
||||||
let pickResults = services.viewer.raycast(e, services.cadScene.workGroup.children);
|
let pickResults = services.viewer.raycast(e, services.cadScene.workGroup.children);
|
||||||
traversePickResults(e, pickResults, PICK_KIND.FACE, (sketchFace) => {
|
traversePickResults(e, pickResults, PICK_KIND.FACE, (sketchFace) => {
|
||||||
streams.selection.solid.next([sketchFace.solid]);
|
context.locationService.edit(sketchFace.shell);
|
||||||
services.viewer.render();
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ function sceneSynchronizer({services: {cadScene, cadRegistry, viewer, wizard, ac
|
||||||
if (model instanceof MOpenFaceShell) {
|
if (model instanceof MOpenFaceShell) {
|
||||||
modelView = new OpenFaceShellView(model);
|
modelView = new OpenFaceShellView(model);
|
||||||
} else if (model instanceof MShell) {
|
} else if (model instanceof MShell) {
|
||||||
modelView = new ShellView(model);
|
modelView = new ShellView(model, undefined, viewer);
|
||||||
} else if (model instanceof MDatum) {
|
} else if (model instanceof MDatum) {
|
||||||
modelView = new DatumView(model, viewer,
|
modelView = new DatumView(model, viewer,
|
||||||
wizard.open,
|
wizard.open,
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {Mesh} from 'three';
|
||||||
|
|
||||||
export class ShellView extends View {
|
export class ShellView extends View {
|
||||||
|
|
||||||
constructor(shell, skin) {
|
constructor(shell, skin, viewer) {
|
||||||
super(shell);
|
super(shell);
|
||||||
|
|
||||||
this.material = createSolidMaterial(skin);
|
this.material = createSolidMaterial(skin);
|
||||||
|
|
@ -45,6 +45,15 @@ export class ShellView extends View {
|
||||||
SceneGraph.addToGroup(this.edgeGroup, edgeView.rootGroup);
|
SceneGraph.addToGroup(this.edgeGroup, edgeView.rootGroup);
|
||||||
this.edgeViews.push(edgeView);
|
this.edgeViews.push(edgeView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.rootGroup.matrixAutoUpdate = false;
|
||||||
|
|
||||||
|
this.model.locationMatrix$.attach(loc => {
|
||||||
|
loc.setToMatrix(this.rootGroup.matrix);
|
||||||
|
this.rootGroup.matrixWorldNeedsUpdate = true;
|
||||||
|
viewer.requestRender();
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mark(color) {
|
mark(color) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {readBrep} from '../../../brep/io/brepIO';
|
import {readBrep} from '../../../brep/io/brepIO';
|
||||||
import {MBrepShell} from '../../model/mshell';
|
import {MBrepShell} from '../../model/mshell';
|
||||||
import CSys from '../../../math/csys';
|
import CSys from '../../../../../modules/math/csys';
|
||||||
|
|
||||||
export function readShellEntityFromJson(data, consumed, csys) {
|
export function readShellEntityFromJson(data, consumed, csys) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import Vector from 'math/vector';
|
import Vector from 'math/vector';
|
||||||
import {BasisForPlane} from '../../../math/l3space'
|
import {BasisForPlane} from '../../../../../modules/math/l3space'
|
||||||
import DPR from 'dpr'
|
import DPR from 'dpr'
|
||||||
import {setAttribute} from "scene/objectData";
|
import {setAttribute} from "scene/objectData";
|
||||||
import {genSolidId} from "../../craft/cadRegistryPlugin";
|
import {genSolidId} from "../../craft/cadRegistryPlugin";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {DelegatingPanTool} from '../../sketcher/tools/pan';
|
import {DelegatingPanTool} from '../../sketcher/tools/pan';
|
||||||
import {Matrix4} from 'three/src/math/Matrix4';
|
import {Matrix4} from 'three/src/math/Matrix4';
|
||||||
import {ORIGIN} from '../../math/l3space';
|
import {ORIGIN} from '../../../../modules/math/l3space';
|
||||||
import {CAMERA_MODE} from '../scene/viewer';
|
import {CAMERA_MODE} from '../scene/viewer';
|
||||||
import DPR from 'dpr';
|
import DPR from 'dpr';
|
||||||
import {SKETCHER_MODE_HEADS_UP_ACTIONS} from "./sketcherUIContrib";
|
import {SKETCHER_MODE_HEADS_UP_ACTIONS} from "./sketcherUIContrib";
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import {LUT} from '../../math/bezier-cubic'
|
||||||
import {distanceAB, isCCW, makeAngle0_360} from '../../math/math'
|
import {distanceAB, isCCW, makeAngle0_360} from '../../math/math'
|
||||||
import {normalizeCurveEnds} from '../../brep/geom/impl/nurbs-ext';
|
import {normalizeCurveEnds} from '../../brep/geom/impl/nurbs-ext';
|
||||||
import Vector from '../../../../modules/math/vector';
|
import Vector from '../../../../modules/math/vector';
|
||||||
import {AXIS, ORIGIN} from '../../math/l3space';
|
import {AXIS, ORIGIN} from '../../../../modules/math/l3space';
|
||||||
|
|
||||||
const RESOLUTION = 20;
|
const RESOLUTION = 20;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import * as sm from './sketchModel'
|
import * as sm from './sketchModel'
|
||||||
import {Matrix3, AXIS, ORIGIN} from '../../math/l3space'
|
import {Matrix3, AXIS, ORIGIN} from '../../../../modules/math/l3space'
|
||||||
import Vector from 'math/vector';
|
import Vector from 'math/vector';
|
||||||
import {Graph} from '../../math/graph'
|
import {Graph} from '../../math/graph'
|
||||||
import * as math from '../../math/math'
|
import * as math from '../../math/math'
|
||||||
|
|
|
||||||
|
|
@ -1,277 +0,0 @@
|
||||||
import Vector from 'math/vector';
|
|
||||||
|
|
||||||
const freeze = Object.freeze;
|
|
||||||
|
|
||||||
const ORIGIN = freeze(new Vector(0, 0, 0));
|
|
||||||
|
|
||||||
const AXIS = freeze({
|
|
||||||
X : freeze(new Vector(1, 0, 0)),
|
|
||||||
Y : freeze(new Vector(0, 1, 0)),
|
|
||||||
Z : freeze(new Vector(0, 0, 1))
|
|
||||||
});
|
|
||||||
|
|
||||||
const IDENTITY_BASIS = Object.freeze([AXIS.X, AXIS.Y, AXIS.Z]);
|
|
||||||
|
|
||||||
export const STANDARD_BASES = freeze({
|
|
||||||
'XY': IDENTITY_BASIS,
|
|
||||||
'XZ': [AXIS.X, AXIS.Z, AXIS.Y],
|
|
||||||
'ZY': [AXIS.Z, AXIS.Y, AXIS.X]
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
class Matrix3 {
|
|
||||||
constructor() {
|
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
apply = vector => this.__apply(vector, new Vector());
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix3.prototype.reset = function() {
|
|
||||||
this.mxx = 1; this.mxy = 0; this.mxz = 0; this.tx = 0;
|
|
||||||
this.myx = 0; this.myy = 1; this.myz = 0; this.ty = 0;
|
|
||||||
this.mzx = 0; this.mzy = 0; this.mzz = 1; this.tz = 0;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.setBasis = function(basis) {
|
|
||||||
var b = basis;
|
|
||||||
this.mxx = b[0].x; this.mxy = b[1].x; this.mxz = b[2].x; this.tx = 0;
|
|
||||||
this.myx = b[0].y; this.myy = b[1].y; this.myz = b[2].y; this.ty = 0;
|
|
||||||
this.mzx = b[0].z; this.mzy = b[1].z; this.mzz = b[2].z; this.tz = 0;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.setBasisAxises = function(x, y, z) {
|
|
||||||
this.mxx = x.x; this.mxy = y.x; this.mxz = z.x; this.tx = 0;
|
|
||||||
this.myx = x.y; this.myy = y.y; this.myz = z.y; this.ty = 0;
|
|
||||||
this.mzx = x.z; this.mzy = y.z; this.mzz = z.z; this.tz = 0;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.scale = function(dx, dy, dz) {
|
|
||||||
this.mxx *= dx;
|
|
||||||
this.myy *= dy;
|
|
||||||
this.mzz *= dz;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.translate = function(dx, dy, dz) {
|
|
||||||
this.tx += dx;
|
|
||||||
this.ty += dy;
|
|
||||||
this.tz += dz;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.set3 = function(
|
|
||||||
mxx, mxy, mxz,
|
|
||||||
myx, myy, myz,
|
|
||||||
mzx, mzy, mzz
|
|
||||||
) {
|
|
||||||
this.mxx = mxx; this.mxy = mxy; this.mxz = mxz;
|
|
||||||
this.myx = myx; this.myy = myy; this.myz = myz;
|
|
||||||
this.mzx = mzx; this.mzy = mzy; this.mzz = mzz;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.set34 = function(
|
|
||||||
mxx, mxy, mxz, tx,
|
|
||||||
myx, myy, myz, ty,
|
|
||||||
mzx, mzy, mzz, tz
|
|
||||||
) {
|
|
||||||
this.mxx = mxx; this.mxy = mxy; this.mxz = mxz; this.tx = tx;
|
|
||||||
this.myx = myx; this.myy = myy; this.myz = myz; this.ty = ty;
|
|
||||||
this.mzx = mzx; this.mzy = mzy; this.mzz = mzz; this.tz = tz;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.setMatrix = function(m) {
|
|
||||||
this.mxx = m.mxx; this.mxy = m.mxy; this.mxz = m.mxz; this.tx = m.tx;
|
|
||||||
this.myx = m.myx; this.myy = m.myy; this.myz = m.myz; this.ty = m.ty;
|
|
||||||
this.mzx = m.mzx; this.mzy = m.mzy; this.mzz = m.mzz; this.tz = m.tz;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.toArray = function() {
|
|
||||||
return [
|
|
||||||
[this.mxx, this.mxy, this.mxz, this.tx],
|
|
||||||
[this.myx, this.myy, this.myz, this.ty],
|
|
||||||
[this.mzx, this.mzy, this.mzz, this.tz]
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.invert = function() {
|
|
||||||
return this.__invert(new Matrix3());
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype._invert = function() {
|
|
||||||
return this.__invert(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.__invert = function(out) {
|
|
||||||
|
|
||||||
var det =
|
|
||||||
this.mxx * (this.myy * this.mzz - this.mzy * this.myz) +
|
|
||||||
this.mxy * (this.myz * this.mzx - this.mzz * this.myx) +
|
|
||||||
this.mxz * (this.myx * this.mzy - this.mzx * this.myy);
|
|
||||||
|
|
||||||
if (det == 0.0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var cxx = this.myy * this.mzz - this.myz * this.mzy;
|
|
||||||
var cyx = - this.myx * this.mzz + this.myz * this.mzx;
|
|
||||||
var czx = this.myx * this.mzy - this.myy * this.mzx;
|
|
||||||
var cxt = - this.mxy * (this.myz * this.tz - this.mzz * this.ty)
|
|
||||||
- this.mxz * (this.ty * this.mzy - this.tz * this.myy)
|
|
||||||
- this.tx * (this.myy * this.mzz - this.mzy * this.myz);
|
|
||||||
var cxy = - this.mxy * this.mzz + this.mxz * this.mzy;
|
|
||||||
var cyy = this.mxx * this.mzz - this.mxz * this.mzx;
|
|
||||||
var czy = - this.mxx * this.mzy + this.mxy * this.mzx;
|
|
||||||
var cyt = this.mxx * (this.myz * this.tz - this.mzz * this.ty)
|
|
||||||
+ this.mxz * (this.ty * this.mzx - this.tz * this.myx)
|
|
||||||
+ this.tx * (this.myx * this.mzz - this.mzx * this.myz);
|
|
||||||
var cxz = this.mxy * this.myz - this.mxz * this.myy;
|
|
||||||
var cyz = - this.mxx * this.myz + this.mxz * this.myx;
|
|
||||||
var czz = this.mxx * this.myy - this.mxy * this.myx;
|
|
||||||
var czt = - this.mxx * (this.myy * this.tz - this.mzy * this.ty)
|
|
||||||
- this.mxy * (this.ty * this.mzx - this.tz * this.myx)
|
|
||||||
- this.tx * (this.myx * this.mzy - this.mzx * this.myy);
|
|
||||||
|
|
||||||
out.mxx = cxx / det;
|
|
||||||
out.mxy = cxy / det;
|
|
||||||
out.mxz = cxz / det;
|
|
||||||
out.tx = cxt / det;
|
|
||||||
out.myx = cyx / det;
|
|
||||||
out.myy = cyy / det;
|
|
||||||
out.myz = cyz / det;
|
|
||||||
out.ty = cyt / det;
|
|
||||||
out.mzx = czx / det;
|
|
||||||
out.mzy = czy / det;
|
|
||||||
out.mzz = czz / det;
|
|
||||||
out.tz = czt / det;
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.combine = function(transform, out) {
|
|
||||||
var txx = transform.mxx;
|
|
||||||
var txy = transform.mxy;
|
|
||||||
var txz = transform.mxz;
|
|
||||||
var ttx = transform.tx;
|
|
||||||
var tyx = transform.myx;
|
|
||||||
var tyy = transform.myy;
|
|
||||||
var tyz = transform.myz;
|
|
||||||
var tty = transform.ty;
|
|
||||||
var tzx = transform.mzx;
|
|
||||||
var tzy = transform.mzy;
|
|
||||||
var tzz = transform.mzz;
|
|
||||||
var ttz = transform.tz;
|
|
||||||
|
|
||||||
var m = out || new Matrix3();
|
|
||||||
m.mxx = (this.mxx * txx + this.mxy * tyx + this.mxz * tzx);
|
|
||||||
m.mxy = (this.mxx * txy + this.mxy * tyy + this.mxz * tzy);
|
|
||||||
m.mxz = (this.mxx * txz + this.mxy * tyz + this.mxz * tzz);
|
|
||||||
m.tx = (this.mxx * ttx + this.mxy * tty + this.mxz * ttz + this.tx);
|
|
||||||
m.myx = (this.myx * txx + this.myy * tyx + this.myz * tzx);
|
|
||||||
m.myy = (this.myx * txy + this.myy * tyy + this.myz * tzy);
|
|
||||||
m.myz = (this.myx * txz + this.myy * tyz + this.myz * tzz);
|
|
||||||
m.ty = (this.myx * ttx + this.myy * tty + this.myz * ttz + this.ty);
|
|
||||||
m.mzx = (this.mzx * txx + this.mzy * tyx + this.mzz * tzx);
|
|
||||||
m.mzy = (this.mzx * txy + this.mzy * tyy + this.mzz * tzy);
|
|
||||||
m.mzz = (this.mzx * txz + this.mzy * tyz + this.mzz * tzz);
|
|
||||||
m.tz = (this.mzx * ttx + this.mzy * tty + this.mzz * ttz + this.tz);
|
|
||||||
|
|
||||||
return m;
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype._apply = function(vector) {
|
|
||||||
return this.__apply(vector, vector);
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.__apply = function(vector, out) {
|
|
||||||
let x = vector.x;
|
|
||||||
let y = vector.y;
|
|
||||||
let z = vector.z;
|
|
||||||
out.x = this.mxx * x + this.mxy * y + this.mxz * z + this.tx;
|
|
||||||
out.y = this.myx * x + this.myy * y + this.myz * z + this.ty;
|
|
||||||
out.z = this.mzx * x + this.mzy * y + this.mzz * z + this.tz;
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.apply3 = function(data) {
|
|
||||||
return this.__apply3(data, [])
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype._apply3 = function(data) {
|
|
||||||
return this.__apply3(data, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.__apply3 = function([x, y, z], out) {
|
|
||||||
out[0] = this.mxx * x + this.mxy * y + this.mxz * z + this.tx;
|
|
||||||
out[1] = this.myx * x + this.myy * y + this.myz * z + this.ty;
|
|
||||||
out[2] = this.mzx * x + this.mzy * y + this.mzz * z + this.tz;
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.prototype.rotate = function(angle, axis, pivot) {
|
|
||||||
return Matrix3.rotateMatrix(angle, axis, pivot, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
Matrix3.rotateMatrix = function(angle, axis, pivot, matrix) {
|
|
||||||
var sin = Math.sin(angle);
|
|
||||||
var cos = Math.cos(angle);
|
|
||||||
var axisX, axisY, axisZ;
|
|
||||||
var m = matrix || new Matrix3();
|
|
||||||
|
|
||||||
if (axis === AXIS.X || axis === AXIS.Y || axis === AXIS.Z) {
|
|
||||||
axisX = axis.x;
|
|
||||||
axisY = axis.y;
|
|
||||||
axisZ = axis.z;
|
|
||||||
} else {
|
|
||||||
// normalize
|
|
||||||
var mag = axis.length();
|
|
||||||
|
|
||||||
if (mag == 0.0) {
|
|
||||||
return m;
|
|
||||||
} else {
|
|
||||||
axisX = axis.x / mag;
|
|
||||||
axisY = axis.y / mag;
|
|
||||||
axisZ = axis.z / mag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var px = pivot.x;
|
|
||||||
var py = pivot.y;
|
|
||||||
var pz = pivot.z;
|
|
||||||
|
|
||||||
m.mxx = cos + axisX * axisX * (1 - cos);
|
|
||||||
m.mxy = axisX * axisY * (1 - cos) - axisZ * sin;
|
|
||||||
m.mxz = axisX * axisZ * (1 - cos) + axisY * sin;
|
|
||||||
|
|
||||||
m.tx = px * (1 - m.mxx) - py * m.mxy - pz * m.mxz;
|
|
||||||
|
|
||||||
m.myx = axisY * axisX * (1 - cos) + axisZ * sin;
|
|
||||||
m.myy = cos + axisY * axisY * (1 - cos);
|
|
||||||
m.myz = axisY * axisZ * (1 - cos) - axisX * sin;
|
|
||||||
m.ty = py * (1 - m.myy) - px * m.myx - pz * m.myz;
|
|
||||||
|
|
||||||
m.mzx = axisZ * axisX * (1 - cos) - axisY * sin;
|
|
||||||
m.mzy = axisZ * axisY * (1 - cos) + axisX * sin;
|
|
||||||
m.mzz = cos + axisZ * axisZ * (1 - cos);
|
|
||||||
m.tz = pz * (1 - m.mzz) - px * m.mzx - py * m.mzy;
|
|
||||||
return m;
|
|
||||||
};
|
|
||||||
|
|
||||||
function BasisForPlane(normal, alignY = AXIS.Y, alignZ = AXIS.Z) {
|
|
||||||
let alignPlane, x, y;
|
|
||||||
if (Math.abs(normal.dot(alignY)) < 0.5) {
|
|
||||||
alignPlane = normal.cross(alignY);
|
|
||||||
} else {
|
|
||||||
alignPlane = normal.cross(alignZ);
|
|
||||||
}
|
|
||||||
y = alignPlane.cross(normal);
|
|
||||||
x = y.cross(normal);
|
|
||||||
return [x, y, normal];
|
|
||||||
}
|
|
||||||
|
|
||||||
export {Matrix3, ORIGIN, IDENTITY_BASIS, AXIS, BasisForPlane};
|
|
||||||
|
|
@ -9,12 +9,13 @@ import {SketcherAppContext} from "./SketcherAppContext";
|
||||||
export function SketchObjectExplorer() {
|
export function SketchObjectExplorer() {
|
||||||
|
|
||||||
const [modification, setModification] = useState(0);
|
const [modification, setModification] = useState(0);
|
||||||
const stream = useStream(ctx => combine(ctx.viewer.streams.objects, ctx.viewer.streams.selection));
|
const objects = useStream(ctx => ctx.viewer.streams.objects);
|
||||||
|
const selection = useStream(ctx.viewer.streams.selection);
|
||||||
const ctx = useContext(SketcherAppContext);
|
const ctx = useContext(SketcherAppContext);
|
||||||
if (!stream) {
|
|
||||||
|
if (!objects || !selection) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const [objects, selection] = stream;
|
|
||||||
|
|
||||||
const select = (obj, exclusive) => {
|
const select = (obj, exclusive) => {
|
||||||
let viewer = ctx.viewer;
|
let viewer = ctx.viewer;
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,15 @@ import {
|
||||||
LengthAnnotation,
|
LengthAnnotation,
|
||||||
RadiusLengthAnnotation
|
RadiusLengthAnnotation
|
||||||
} from "../shapes/annotations/angleAnnotation";
|
} from "../shapes/annotations/angleAnnotation";
|
||||||
|
import {ISolveStage, SolvableObject} from "./solvableObject";
|
||||||
|
import {SketchObject} from "../shapes/sketch-object";
|
||||||
|
import {IconType} from "react-icons";
|
||||||
|
|
||||||
export const ConstraintDefinitions = {
|
export const ConstraintDefinitions
|
||||||
|
// : {
|
||||||
|
// [key: string]: ConstraintSchema
|
||||||
|
// }
|
||||||
|
= {
|
||||||
|
|
||||||
PCoincident : {
|
PCoincident : {
|
||||||
id: 'PCoincident',
|
id: 'PCoincident',
|
||||||
|
|
@ -338,8 +345,8 @@ export const ConstraintDefinitions = {
|
||||||
.monomial(-1);
|
.monomial(-1);
|
||||||
|
|
||||||
|
|
||||||
polynomials.push(ellipsePoly());
|
// polynomials.push(ellipsePoly());
|
||||||
polynomials.push(ellipsePoly());
|
// polynomials.push(ellipsePoly());
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
@ -814,12 +821,12 @@ export const ConstraintDefinitions = {
|
||||||
pt.visitParams(callback);
|
pt.visitParams(callback);
|
||||||
},
|
},
|
||||||
|
|
||||||
collectPolynomials: (polynomials, [px, py], {x, y}) => {
|
collectPolynomials: (polynomials, [px, py], {x, y}: ResolvedConstants) => {
|
||||||
polynomials.push(new Polynomial(-x).monomial().term(px, POW_1_FN));
|
polynomials.push(new Polynomial(-x).monomial().term(px, POW_1_FN));
|
||||||
polynomials.push(new Polynomial(-y).monomial().term(py, POW_1_FN));
|
polynomials.push(new Polynomial(-y).monomial().term(py, POW_1_FN));
|
||||||
},
|
},
|
||||||
|
|
||||||
setConstantsFromGeometry: ([pt], constants) => {
|
setConstantsFromGeometry: ([pt], constants: ConstantsDefinitions) => {
|
||||||
constants.x = pt.x + '';
|
constants.x = pt.x + '';
|
||||||
constants.y = pt.y + '';
|
constants.y = pt.y + '';
|
||||||
}
|
}
|
||||||
|
|
@ -940,11 +947,51 @@ const bezier3Polynomial = (p, t, p0, p1, p2, p3) => new Polynomial()
|
||||||
.monomial(-1)
|
.monomial(-1)
|
||||||
.term(p, POW_1_FN);
|
.term(p, POW_1_FN);
|
||||||
|
|
||||||
|
|
||||||
|
export type ResolvedConstants = { [p: string]: any };
|
||||||
|
export type ConstantsDefinitions = { [p: string]: string };
|
||||||
|
|
||||||
|
export interface ConstraintSchema {
|
||||||
|
|
||||||
|
id: string;
|
||||||
|
name: string,
|
||||||
|
icon: IconType,
|
||||||
|
constants?: {
|
||||||
|
[name: string]: {
|
||||||
|
readOnly?: boolean;
|
||||||
|
type: string,
|
||||||
|
description?: string,
|
||||||
|
transform?: (string) => any,
|
||||||
|
initialValue(objects: SolvableObject[]): any;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
createAnnotations?: (objects: SolvableObject[], constraintInstance: AlgNumConstraint) => SketchObject[];
|
||||||
|
|
||||||
|
defineParamsScope: (object: SolvableObject[], cb: (param: Param) => void) => void;
|
||||||
|
|
||||||
|
collectPolynomials(polynomials: Polynomial[], params: Param[], resolvedConstants: ResolvedConstants, objects: SolvableObject[]): void;
|
||||||
|
|
||||||
|
setConstantsFromGeometry?: (object: SolvableObject[], resolvedConstants: ConstantsDefinitions) => void;
|
||||||
|
|
||||||
|
initialGuess?(params: Param[], resolvedConstants: ResolvedConstants): void;
|
||||||
|
}
|
||||||
|
|
||||||
export class AlgNumConstraint {
|
export class AlgNumConstraint {
|
||||||
|
|
||||||
static Counter = 0;
|
static Counter = 0;
|
||||||
|
|
||||||
constructor(schema, objects, constants, internal = false) {
|
id: string;
|
||||||
|
objects: SolvableObject[];
|
||||||
|
constants: ConstantsDefinitions;
|
||||||
|
resolvedConstants: ResolvedConstants;
|
||||||
|
internal: boolean;
|
||||||
|
schema: ConstraintSchema;
|
||||||
|
params: Param[];
|
||||||
|
stage: ISolveStage;
|
||||||
|
private annotations: SketchObject[];
|
||||||
|
|
||||||
|
constructor(schema: ConstraintSchema, objects: SolvableObject[], constants?: ConstantsDefinitions, internal?: boolean = false) {
|
||||||
this.id = schema.id + ':' + (AlgNumConstraint.Counter ++); // only for debug purposes - not persisted
|
this.id = schema.id + ':' + (AlgNumConstraint.Counter ++); // only for debug purposes - not persisted
|
||||||
this.objects = objects;
|
this.objects = objects;
|
||||||
this.constants = constants;
|
this.constants = constants;
|
||||||
|
|
@ -958,18 +1005,6 @@ export class AlgNumConstraint {
|
||||||
this.schema.defineParamsScope(this.objects, p => this.params.push(p));
|
this.schema.defineParamsScope(this.objects, p => this.params.push(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.modifier = this.schema.modify !== undefined;
|
|
||||||
if (this.modifier) {
|
|
||||||
this.referenceObjects = this.schema.referenceObjects(this.objects);
|
|
||||||
this.managedObjects = this.schema.managedObjects(this.objects);
|
|
||||||
this.managedObjects.forEach(o => {
|
|
||||||
if (o.managedBy) {
|
|
||||||
throw 'there can be only one managing modifier for an object';
|
|
||||||
}
|
|
||||||
o.managedBy = this;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.internal && this.schema.createAnnotations) {
|
if (!this.internal && this.schema.createAnnotations) {
|
||||||
this.annotations = this.schema.createAnnotations(this.objects, this);
|
this.annotations = this.schema.createAnnotations(this.objects, this);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -977,8 +1012,8 @@ export class AlgNumConstraint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collectPolynomials(polynomials) {
|
collectPolynomials(polynomials: Polynomial[]) {
|
||||||
this.schema.collectPolynomials(polynomials, this.params, this.resolvedConstants);
|
this.schema.collectPolynomials(polynomials, this.params, this.resolvedConstants, this.objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveConstants(expressionResolver) {
|
resolveConstants(expressionResolver) {
|
||||||
|
|
@ -988,7 +1023,7 @@ export class AlgNumConstraint {
|
||||||
}
|
}
|
||||||
Object.keys(this.constants).map(name => {
|
Object.keys(this.constants).map(name => {
|
||||||
let def = this.schema.constants[name];
|
let def = this.schema.constants[name];
|
||||||
let val = this.constants[name];
|
let val: any = this.constants[name];
|
||||||
val = expressionResolver(val);
|
val = expressionResolver(val);
|
||||||
if (def.type === 'number') {
|
if (def.type === 'number') {
|
||||||
val = parseFloat(val);
|
val = parseFloat(val);
|
||||||
|
|
@ -1071,4 +1106,3 @@ export class AlgNumConstraint {
|
||||||
this.constants[key] = value + ''; // only string are allowed here
|
this.constants[key] = value + ''; // only string are allowed here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2,8 +2,10 @@ import {prepare} from "./solver";
|
||||||
import {eqEps} from "../../brep/geom/tolerance";
|
import {eqEps} from "../../brep/geom/tolerance";
|
||||||
import {Polynomial, POW_1_FN} from "./polynomial";
|
import {Polynomial, POW_1_FN} from "./polynomial";
|
||||||
import {compositeFn} from "gems/func";
|
import {compositeFn} from "gems/func";
|
||||||
|
import {AlgNumConstraint} from "./ANConstraints";
|
||||||
|
import {SolverParam} from "./solverParam";
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = true;
|
||||||
|
|
||||||
export class AlgNumSubSystem {
|
export class AlgNumSubSystem {
|
||||||
|
|
||||||
|
|
@ -34,6 +36,18 @@ export class AlgNumSubSystem {
|
||||||
|
|
||||||
stage = null;
|
stage = null;
|
||||||
|
|
||||||
|
dof: number = 0;
|
||||||
|
|
||||||
|
requiresHardSolve: boolean = false;
|
||||||
|
|
||||||
|
polynomialIsolations: Isolation[];
|
||||||
|
|
||||||
|
calcVisualLimit: () => number;
|
||||||
|
|
||||||
|
expressionResolver: (string) => any;
|
||||||
|
|
||||||
|
solveStatus: SolveStatus;
|
||||||
|
|
||||||
constructor(calcVisualLimit, expressionResolver, stage) {
|
constructor(calcVisualLimit, expressionResolver, stage) {
|
||||||
|
|
||||||
this.calcVisualLimit = calcVisualLimit;
|
this.calcVisualLimit = calcVisualLimit;
|
||||||
|
|
@ -182,7 +196,7 @@ export class AlgNumSubSystem {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
console.log('reducing system:');
|
console.log('reducing system(of', this.polynomials.length, '):');
|
||||||
this.polynomials.forEach(p => console.log(p.toString()));
|
this.polynomials.forEach(p => console.log(p.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -502,6 +516,13 @@ export class AlgNumSubSystem {
|
||||||
|
|
||||||
|
|
||||||
class Isolation {
|
class Isolation {
|
||||||
|
polynomials: Polynomial[];
|
||||||
|
system: AlgNumSubSystem;
|
||||||
|
beingSolvedParams: Set<SolverParam>;
|
||||||
|
beingSolvedConstraints: Set<AlgNumConstraint>;
|
||||||
|
dof: number;
|
||||||
|
solveStatus: SolveStatus;
|
||||||
|
numericalSolver: { system; diagnose; solveSystem; error; updateLock };
|
||||||
|
|
||||||
constructor(polynomials, system) {
|
constructor(polynomials, system) {
|
||||||
this.system = system;
|
this.system = system;
|
||||||
|
|
@ -605,3 +626,7 @@ class PolynomialResidual {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SolveStatus {
|
||||||
|
success: boolean;
|
||||||
|
error: number
|
||||||
|
}
|
||||||
12
web/app/sketcher/constr/solvableObject.ts
Normal file
12
web/app/sketcher/constr/solvableObject.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import {Param} from "../shapes/param";
|
||||||
|
|
||||||
|
export interface SolvableObject {
|
||||||
|
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISolveStage {
|
||||||
|
objects: Set<SolvableObject>;
|
||||||
|
index: number;
|
||||||
|
}
|
||||||
|
|
@ -6,28 +6,6 @@ import {ConstantWrapper, EqualsTo} from './solverConstraints'
|
||||||
import {dog_leg} from '../../math/optim'
|
import {dog_leg} from '../../math/optim'
|
||||||
import {newVector} from 'math/vec';
|
import {newVector} from 'math/vec';
|
||||||
|
|
||||||
/** @constructor */
|
|
||||||
function Param(value, objectParam) {
|
|
||||||
this.reset(value);
|
|
||||||
this.objectParam = objectParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
Param.prototype.reset = function(value) {
|
|
||||||
this.set(value);
|
|
||||||
this.constant = false;
|
|
||||||
this.j = -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
Param.prototype.set = function(value) {
|
|
||||||
if (this.constant) return;
|
|
||||||
this.value = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Param.prototype.get = function() {
|
|
||||||
return this.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Param.prototype.nop = function() {};
|
|
||||||
|
|
||||||
/** @constructor */
|
/** @constructor */
|
||||||
function System(constraints) {
|
function System(constraints) {
|
||||||
|
|
@ -313,4 +291,4 @@ var solve_lm = function(sys, model, jacobian, rough) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export {Param, prepare}
|
export {prepare}
|
||||||
35
web/app/sketcher/constr/solverParam.ts
Normal file
35
web/app/sketcher/constr/solverParam.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import {Param} from "../shapes/param";
|
||||||
|
|
||||||
|
export class SolverParam {
|
||||||
|
|
||||||
|
value: number;
|
||||||
|
objectParam: Param;
|
||||||
|
constant: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jacobian position
|
||||||
|
*/
|
||||||
|
j: number;
|
||||||
|
|
||||||
|
constructor(value, objectParam) {
|
||||||
|
this.reset(value);
|
||||||
|
this.objectParam = objectParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(value) {
|
||||||
|
this.set(value);
|
||||||
|
this.constant = false;
|
||||||
|
this.j = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
set(value) {
|
||||||
|
if (this.constant) return;
|
||||||
|
this.value = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
get() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -3,6 +3,8 @@ import {AlgNumConstraint, ConstraintDefinitions} from "./constr/ANConstraints";
|
||||||
import {AlgNumSubSystem} from "./constr/AlgNumSystem";
|
import {AlgNumSubSystem} from "./constr/AlgNumSystem";
|
||||||
import {state, stream} from 'lstream';
|
import {state, stream} from 'lstream';
|
||||||
import {toast} from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
|
import {ISolveStage, SolvableObject} from "./constr/solvableObject";
|
||||||
|
import {Viewer} from "./viewer2d";
|
||||||
|
|
||||||
export {Constraints, ParametricManager}
|
export {Constraints, ParametricManager}
|
||||||
|
|
||||||
|
|
@ -31,6 +33,8 @@ class ParametricManager {
|
||||||
$constantDefinition = state('');
|
$constantDefinition = state('');
|
||||||
|
|
||||||
groundStage = new SolveStage(this);
|
groundStage = new SolveStage(this);
|
||||||
|
viewer: Viewer;
|
||||||
|
messageSink: (msg) => void;
|
||||||
|
|
||||||
constructor(viewer) {
|
constructor(viewer) {
|
||||||
this.viewer = viewer;
|
this.viewer = viewer;
|
||||||
|
|
@ -240,7 +244,7 @@ class ParametricManager {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_removeObject = (obj, force) => {
|
_removeObject = (obj, force?) => {
|
||||||
if (obj.__disposed) {
|
if (obj.__disposed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -398,10 +402,12 @@ class ParametricManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SolveStage {
|
class SolveStage implements ISolveStage{
|
||||||
|
|
||||||
generators = new Set();
|
generators = new Set();
|
||||||
objects = new Set();
|
objects = new Set<SolvableObject>();
|
||||||
|
private parametricManager: ParametricManager;
|
||||||
|
private algNumSystem: AlgNumSubSystem;
|
||||||
|
|
||||||
constructor(parametricManager) {
|
constructor(parametricManager) {
|
||||||
this.parametricManager = parametricManager;
|
this.parametricManager = parametricManager;
|
||||||
|
|
@ -460,6 +466,7 @@ class SolveStage {
|
||||||
solve(rough) {
|
solve(rough) {
|
||||||
this.algNumSystem.solve(rough);
|
this.algNumSystem.solve(rough);
|
||||||
this.generators.forEach(gen => {
|
this.generators.forEach(gen => {
|
||||||
|
// @ts-ignore
|
||||||
gen.regenerate(this.viewer);
|
gen.regenerate(this.viewer);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -1,15 +1,18 @@
|
||||||
import {Generator} from "../id-generator";
|
import {Generator} from "../id-generator";
|
||||||
import {Param as SolverParam} from '../constr/solver';
|
import {SolverParam} from "../constr/solverParam";
|
||||||
|
|
||||||
export class Param {
|
export class Param {
|
||||||
|
|
||||||
id: number;
|
id: number;
|
||||||
value: number;
|
value: number;
|
||||||
solverParam: any;
|
solverParam: SolverParam;
|
||||||
private readonly debugSymbol: string;
|
private readonly debugSymbol: string;
|
||||||
normalizer: (number) => any;
|
normalizer: (number) => any;
|
||||||
enforceVisualLimit: boolean = false;
|
enforceVisualLimit: boolean = false;
|
||||||
|
|
||||||
|
//penalty function constraints
|
||||||
|
constraints?: any[];
|
||||||
|
|
||||||
constructor(value, debugSymbol) {
|
constructor(value, debugSymbol) {
|
||||||
this.id = Generator.genID();
|
this.id = Generator.genID();
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,9 @@ import {Styles} from "../styles";
|
||||||
import {NoIcon} from "../icons/NoIcon";
|
import {NoIcon} from "../icons/NoIcon";
|
||||||
import {Layer, Viewer} from "../viewer2d";
|
import {Layer, Viewer} from "../viewer2d";
|
||||||
import {NOOP} from "gems/func";
|
import {NOOP} from "gems/func";
|
||||||
|
import {SolvableObject} from "../constr/solveObject";
|
||||||
|
|
||||||
export abstract class SketchObject extends Shape {
|
export abstract class SketchObject extends Shape implements SolvableObject {
|
||||||
|
|
||||||
ref: string;
|
ref: string;
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {BasisOrigin} from './shapes/basis-origin';
|
||||||
import Vector from 'math/vector';
|
import Vector from 'math/vector';
|
||||||
|
|
||||||
import * as draw_utils from './shapes/draw-utils';
|
import * as draw_utils from './shapes/draw-utils';
|
||||||
import {Matrix3} from '../math/l3space';
|
import {Matrix3} from 'math/l3space';
|
||||||
import sketcherStreams, {SketcherStreams} from './sketcherStreams';
|
import sketcherStreams, {SketcherStreams} from './sketcherStreams';
|
||||||
import {BBox, IO} from "./io";
|
import {BBox, IO} from "./io";
|
||||||
import {NOOP} from "../../../modules/gems/func";
|
import {NOOP} from "../../../modules/gems/func";
|
||||||
|
|
@ -358,13 +358,14 @@ export class Viewer {
|
||||||
};
|
};
|
||||||
|
|
||||||
fit() {
|
fit() {
|
||||||
|
let count = 0;
|
||||||
const bbox = new BBox();
|
const bbox = new BBox();
|
||||||
this.accept(obj => {
|
this.accept(obj => {
|
||||||
|
count ++;
|
||||||
bbox.check(obj);
|
bbox.check(obj);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (!bbox.isValid()) {
|
if (count < 2 || !bbox.isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,5 +22,5 @@ CadError.KIND = {
|
||||||
INVALID_PARAMS: 'INVALID_PARAMS'
|
INVALID_PARAMS: 'INVALID_PARAMS'
|
||||||
};
|
};
|
||||||
|
|
||||||
CadError.ALGORITMTHM_ERROR_KINDS = ['INTERNAL_ERROR', 'UNSUPPORTED_CASE', 'INVALID_INPUT'];
|
CadError.ALGORITHM_ERROR_KINDS = ['INTERNAL_ERROR', 'UNSUPPORTED_CASE', 'INVALID_INPUT'];
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue