diff --git a/modules/math/functions.ts b/modules/math/functions.ts new file mode 100644 index 00000000..ab6d3f1f --- /dev/null +++ b/modules/math/functions.ts @@ -0,0 +1,3 @@ +import Vector from "math/vector"; + +export type VectorTransformer = (Vector) => Vector; \ No newline at end of file diff --git a/modules/math/matrix.ts b/modules/math/matrix.ts index d7b82109..4c41a920 100644 --- a/modules/math/matrix.ts +++ b/modules/math/matrix.ts @@ -1,5 +1,6 @@ import Vector, {AXIS} from "math/vector"; import {Vec3} from "math/vec"; +import {VectorTransformer} from "math/functions"; export type Matrix3x4Data = [[number, number, number, number], [number, number, number, number], [number, number, number, number]]; export type Matrix3x4FlatData = [number, number, number, number, number, number, number, number, number, number, number, number]; @@ -410,7 +411,7 @@ export class Matrix3x4 { return m; }; - apply = vector => this.__apply(vector, new Vector()); + apply: VectorTransformer = vector => this.__apply(vector, new Vector()); setTranslation(tx, ty, tz) { this.tx = tx; diff --git a/modules/workbenches/modeler/features/extrude/extrude.operation.ts b/modules/workbenches/modeler/features/extrude/extrude.operation.ts index 59b7d76f..14ca7367 100644 --- a/modules/workbenches/modeler/features/extrude/extrude.operation.ts +++ b/modules/workbenches/modeler/features/extrude/extrude.operation.ts @@ -1,6 +1,6 @@ import {roundValueForPresentation as r} from 'cad/craft/operationHelper'; -import {ProductionInfo} from "cad/model/productionInfo"; import {MFace} from "cad/model/mface"; +import {ApplicationContext} from "context"; interface ExtrudeParams { length: number; @@ -14,7 +14,7 @@ export default { info: 'extrudes 2D sketch', paramsInfo: ({value}) => `(${r(value)})`, mutualExclusiveFields: ['datumAxisVector', 'edgeVector', 'sketchSegmentVector'], - run: (params: ExtrudeParams, ctx) => { + run: (params: ExtrudeParams, ctx: ApplicationContext) => { let occ = ctx.occService; const oci = occ.commandInterface; @@ -24,7 +24,7 @@ export default { let sketch = ctx.sketchStorageService.readSketch(face.id); if (!sketch) throw 'sketch not found for the face ' + face.id; - const occFaces = occ.utils.sketchToFaces(sketch); + const occFaces = occ.utils.sketchToFaces(sketch, face.csys); const shapeNames = occ.utils.prism(occFaces, [0, 0, params.length]); diff --git a/web/app/cad/craft/e0/OCCUtils.ts b/web/app/cad/craft/e0/OCCUtils.ts index 793d67e2..5367e6c7 100644 --- a/web/app/cad/craft/e0/OCCUtils.ts +++ b/web/app/cad/craft/e0/OCCUtils.ts @@ -3,12 +3,13 @@ import {Vec3} from "math/vec"; import {SketchGeom} from "cad/sketch/sketchReader"; import {OCCService} from "cad/craft/e0/occService"; import {CoreContext} from "context"; +import CSys from "math/csys"; export interface OCCUtils { wiresToFaces(wires: string[]): string[]; - sketchToFaces(sketch: SketchGeom): string[]; + sketchToFaces(sketch: SketchGeom, csys: CSys): string[]; prism(faces: string[], dir: Vec3): string[]; @@ -16,9 +17,9 @@ export interface OCCUtils { export function createOCCUtils(ctx: CoreContext): OCCUtils { - function sketchToFaces(sketch: SketchGeom): string[] { + function sketchToFaces(sketch: SketchGeom, csys: CSys): string[] { const occ = ctx.occService; - const wires = occ.io.sketchLoader.pushSketchAsWires(sketch.contours); + const wires = occ.io.sketchLoader.pushSketchAsWires(sketch.contours, csys); return wiresToFaces(wires); } diff --git a/web/app/cad/craft/e0/occSketchLoader.ts b/web/app/cad/craft/e0/occSketchLoader.ts index 6a094ec4..a470cbb4 100644 --- a/web/app/cad/craft/e0/occSketchLoader.ts +++ b/web/app/cad/craft/e0/occSketchLoader.ts @@ -1,21 +1,22 @@ import {Contour} from "cad/sketch/sketchModel"; import {OCCCommandInterface} from "cad/craft/e0/occCommandInterface"; +import CSys from "math/csys"; export interface OCCSketchLoader { - pushSketchAsWires(sketch: Contour[]): string[]; + pushSketchAsWires(sketch: Contour[], csys: CSys): string[]; - pushContourAsWire(contour: Contour, id: string|number): string; + pushContourAsWire(contour: Contour, id: string|number, csys: CSys): string; } export function createOCCSketchLoader(oci: OCCCommandInterface): OCCSketchLoader { - function pushContourAsWire(contour: Contour, id: string|number): string { + function pushContourAsWire(contour: Contour, id: string|number, csys: CSys): string { const boundCurves = contour.segments.map(s => { const geomId = "SketchGeom:" + s.id; - s.toOCCGeometry(oci, geomId); + s.toOCCGeometry(oci, geomId, csys); return geomId; }); @@ -33,7 +34,7 @@ export function createOCCSketchLoader(oci: OCCCommandInterface): OCCSketchLoader } - const pushSketchAsWires = (sketch: Contour[]): string[] => sketch.map(pushContourAsWire); + const pushSketchAsWires = (sketch: Contour[], csys: CSys): string[] => sketch.map((c, i) => pushContourAsWire(c, i, csys)); return { pushSketchAsWires, pushContourAsWire diff --git a/web/app/cad/sketch/sketchModel.ts b/web/app/cad/sketch/sketchModel.ts index fb91bce3..f9b0e130 100644 --- a/web/app/cad/sketch/sketchModel.ts +++ b/web/app/cad/sketch/sketchModel.ts @@ -7,7 +7,6 @@ import Vector from 'math/vector'; import CSys from "math/csys"; import {distanceAB} from "math/distance"; import {isCCW} from "geom/euclidean"; -import {OCCService} from "cad/craft/e0/occService"; import {OCCCommandInterface} from "cad/craft/e0/occCommandInterface"; @@ -46,7 +45,7 @@ class SketchPrimitive { return !this.isCurve; } - toNurbs(csys) { + toNurbs(csys: CSys) { let verbNurbs = this.toVerbNurbs(csys.outTransformation.apply, csys); if (this.inverted) { verbNurbs = verbNurbs.reverse(); @@ -66,12 +65,12 @@ class SketchPrimitive { throw 'not implemented' } - toOCCGeometry(oci: OCCCommandInterface, underName: string) { + toOCCGeometry(oci: OCCCommandInterface, underName: string, csys: CSys) { throw 'not implemented' } } -export class Segment extends SketchPrimitive { +export class Segment extends SketchPrimitive { a: Vector; b: Vector; @@ -90,14 +89,31 @@ export class Segment extends SketchPrimitive { return new verb.geom.Line(tr(this.a).data(), tr(this.b).data()); } - toOCCGeometry(oci: OCCCommandInterface, underName: string) { - oci.point(underName + "_A", this.a.x, this.a.y, this.a.z); - oci.point(underName + "_B", this.b.x, this.b.y, this.b.z); - oci.gcarc(underName, "seg", underName + "_A", underName + "_B") + toGenericForm() { + const endpoints = [ + this.a, //from endpoint + this.b, //to endpoint + ]; + if (this.inverted) { + endpoints.reverse(); + } + return endpoints } + + toOCCGeometry(oci: OCCCommandInterface, underName: string, csys: CSys) { + const genForm = this.toGenericForm().map(csys.outTransformation.apply); + const [A, B] = genForm; + oci.point(underName + "_A", A.x, A.y, A.z); + oci.point(underName + "_B", B.x, B.y, B.z); + oci.gcarc(underName, "seg", underName + "_A", underName + "_B")} } export class Arc extends SketchPrimitive { + + a: Vector; + b: Vector; + c: Vector; + constructor(id, a, b, c) { super(id); this.a = a; @@ -130,11 +146,42 @@ export class Arc extends SketchPrimitive { return adjustEnds(arc, tr(this.a), tr(this.b)) } - toOCCGeometry(oci: OCCCommandInterface, underName: string) { - oci.point(underName + "_A", this.a.x, this.a.y, this.a.z); - oci.point(underName + "_B", this.b.x, this.b.y, this.b.z); - oci.point(underName + "_C", this.b.x, this.b.y, this.b.z); - oci.gcarc(underName, "cir", underName + "_A", underName + "_B", underName + "_C") + toGenericForm() { + const endpoints = [this.a, this.b]; + if (this.inverted) { + endpoints.reverse(); + } + const [a, b] = endpoints; + const tangent = a.minus(this.c)._perpXY() //tangent vector + if (this.inverted) { + tangent._negate(); + } + return [ + a, //from endpoint + b, //to endpoint + tangent //tangent vector + ] + } + + toOCCGeometry(oci: OCCCommandInterface, underName: string, csys: CSys) { + + const tr = csys.outTransformation.apply; + const s = this; + const a = tr(s.inverted ? s.b : s.a); + const b = tr(s.inverted ? s.a : s.b); + const c = tr(s.c); + const tangent = c.minus(a)._cross(csys.z);//._normalize(); + + if (s.inverted) { + tangent._negate(); + } + + const A_TAN = a.plus(tangent); + oci.point(underName + "_A", a.x, a.y, a.z); + oci.point(underName + "_B", b.x, b.y, b.z); + oci.point(underName + "_T1", a.x, a.y, a.z); + oci.point(underName + "_T2", A_TAN.x, A_TAN.y, A_TAN.z); + oci.gcarc(underName, "cir", underName + "_A", underName + "_T1", underName + "_T2", underName + "_B") } } @@ -187,6 +234,9 @@ export class EllipticalArc extends SketchPrimitive { } export class Circle extends SketchPrimitive { + c: Vector; + r: number + constructor(id, c, r) { super(id); this.c = c; @@ -198,6 +248,12 @@ export class Circle extends SketchPrimitive { const basisY = csys.y; return new verb.geom.Circle(tr(this.c).data(), basisX.data(), basisY.data(), this.r); } + + toOCCGeometry(oci: OCCCommandInterface, underName: string, csys: CSys) { + const C = csys.outTransformation.apply(this.c); + const DIR = csys.z; + oci.circle(underName, ...C.data(), ...DIR.data(), this.r); + } } export class Ellipse extends SketchPrimitive {