UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

261 lines (245 loc) 8.35 kB
/** * extrudes CAD primitives * * */ import {CADSopNode} from './_BaseCAD'; import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig'; import { OpenCascadeInstance, gp_Vec, CadGC, CadGeometryType, cadGeometryTypeFromShape, GCRegisterFunction, cadDowncast, TopoDS_Edge, TopoDS_Wire, TopoDS_Face, TopoDS_Shape, } from '../../../core/geometry/modules/cad/CadCommon'; import {CoreGroup} from '../../../core/geometry/Group'; import {SopType} from '../../poly/registers/nodes/types/Sop'; import {CadLoaderSync} from '../../../core/geometry/modules/cad/CadLoaderSync'; import {CadObject} from '../../../core/geometry/modules/cad/CadObject'; import {isBooleanTrue} from '../../../core/Type'; interface CommonOptions { oc: OpenCascadeInstance; r: GCRegisterFunction; newObjects: CadObject<CadGeometryType>[]; extrudeDir: gp_Vec; } class CADExtrudeSopParamsConfig extends NodeParamsConfig { /** @param direction */ dir = ParamConfig.VECTOR3([0, 1, 0]); /** @param height */ height = ParamConfig.FLOAT(1, { range: [-10, 10], rangeLocked: [false, false], }); /** @param create caps */ cap = ParamConfig.BOOLEAN(1); /** @param convert caps to faces */ capsAsFaces = ParamConfig.BOOLEAN(1); } const ParamsConfig = new CADExtrudeSopParamsConfig(); export class CADExtrudeSopNode extends CADSopNode<CADExtrudeSopParamsConfig> { override paramsConfig = ParamsConfig; static override type() { return SopType.CAD_EXTRUDE; } protected override initializeNode() { this.io.inputs.setCount(1); } override cook(inputCoreGroups: CoreGroup[]) { const inputCoreGroup = inputCoreGroups[0]; const extrudeDir = CadLoaderSync.gp_Vec; extrudeDir.SetCoord_2( this.pv.dir.x * this.pv.height, this.pv.dir.y * this.pv.height, this.pv.dir.z * this.pv.height ); const newObjects: CadObject<CadGeometryType>[] = []; const inputObjects = inputCoreGroup.cadObjects(); if (inputObjects) { const oc = CadLoaderSync.oc(); CadGC.withGC((r) => { const options: CommonOptions = { oc, r, newObjects, extrudeDir, }; for (const object of inputObjects) { this._processObject(object, options); } }); } this.setCADObjects(newObjects); } private _processObject(object: CadObject<CadGeometryType>, options: CommonOptions) { const type = object.type; switch (type) { case CadGeometryType.VERTEX: { return this._processVertexObject(object as CadObject<CadGeometryType.VERTEX>, options); } case CadGeometryType.EDGE: { return this._processEdgeObject(object as CadObject<CadGeometryType.EDGE>, options); } case CadGeometryType.WIRE: { return this._processWireObject(object as CadObject<CadGeometryType.WIRE>, options); } case CadGeometryType.FACE: { return this._processFaceObject(object as CadObject<CadGeometryType.FACE>, options); } case CadGeometryType.SHELL: { return this._processShellObject(object as CadObject<CadGeometryType.SHELL>, options); } default: { return options.newObjects.push(object); } } } private _processVertexObject(object: CadObject<CadGeometryType.VERTEX>, options: CommonOptions) { const {oc, r, newObjects, extrudeDir} = options; const vertex = object.cadGeometry(); const prismApi = r(new oc.BRepPrimAPI_MakePrism_1(vertex, extrudeDir, false, true)); const prism = prismApi.Shape(); const type = cadGeometryTypeFromShape(oc, prism); if (type) { const newObject = new CadObject(prism, type); newObjects.push(newObject); } } private _processEdgeObject(object: CadObject<CadGeometryType.EDGE>, options: CommonOptions) { const {oc, r, extrudeDir, newObjects} = options; const edge = object.cadGeometry() as TopoDS_Edge; const api = r(new oc.BRepPrimAPI_MakePrism_1(edge, extrudeDir, false, true)); const shapes = [api.Shape()]; // if (isBooleanTrue(this.pv.cap)) { // const addCap = (capShape: TopoDS_Shape | undefined, invert: boolean) => { // if (!capShape) { // return; // } // console.log('capShape', capShape, cadGeometryTypeFromShape(oc, capShape)); // if (cadGeometryTypeFromShape(oc, capShape) == CadGeometryType.WIRE) { // const wire = cadDowncast(oc, capShape) as TopoDS_Wire; // if (isBooleanTrue(this.pv.capsAsFaces)) { // const capApi = r(new oc.BRepBuilderAPI_MakeFace_15(wire, true)); // if (capApi.IsDone()) { // const face = capApi.Face(); // shapes.push(invert ? face.Complemented() : face); // } // } else { // shapes.push(capShape); // } // } // }; // addCap(api.FirstShape(), true); // addCap(api.LastShape(), false); // } for (const shape of shapes) { const type = cadGeometryTypeFromShape(oc, shape); if (type) { const newObject = new CadObject(shape, type); newObjects.push(newObject); } } // convert to a wire // const api = new oc.BRepBuilderAPI_MakeWire_1(); // const edge = cadDowncast(oc, object.cadGeometry()) as TopoDS_Edge; // api.Add_1(edge); // const wire = api.Wire(); // api.delete(); // // process as wire // this._processWire(wire, options); } private _processWireObject(object: CadObject<CadGeometryType.WIRE>, options: CommonOptions) { const wire = object.cadGeometry(); this._processWire(wire, options); } private _processWire(wire: TopoDS_Wire, options: CommonOptions) { const {oc, r, extrudeDir, newObjects} = options; const api = r(new oc.BRepPrimAPI_MakePrism_1(wire, extrudeDir, false, true)); const shapes = [api.Shape()]; if (isBooleanTrue(this.pv.cap)) { const addCap = (capShape: TopoDS_Shape | undefined, invert: boolean) => { if (!capShape) { return; } if (cadGeometryTypeFromShape(oc, capShape) == CadGeometryType.WIRE) { const wire = cadDowncast(oc, capShape) as TopoDS_Wire; if (isBooleanTrue(this.pv.capsAsFaces)) { const capApi = r(new oc.BRepBuilderAPI_MakeFace_15(wire, true)); if (capApi.IsDone()) { const face = capApi.Face(); shapes.push(invert ? face.Complemented() : face); } } else { shapes.push(capShape); } } }; addCap(api.FirstShape(), false); addCap(api.LastShape(), true); } for (const shape of shapes) { const type = cadGeometryTypeFromShape(oc, shape); if (type) { const newObject = new CadObject(shape, type); newObjects.push(newObject); } } // TODO: cad/convert or cad/makeFace // const faceApi = r(new oc.BRepBuilderAPI_MakeFace_15(wire, true)); // const face = faceApi.Face(); // this._processFace(face, options); } private _processFaceObject(object: CadObject<CadGeometryType.FACE>, options: CommonOptions) { this._processFace(object.cadGeometry(), options); } private _processFace(face: TopoDS_Face, options: CommonOptions) { const {oc, r, newObjects, extrudeDir} = options; const api = r(new oc.BRepPrimAPI_MakePrism_1(face, extrudeDir, false, true)); const shapes = [api.Shape()]; // if (isBooleanTrue(this.pv.cap)) { // const addCap = (capShape: TopoDS_Shape | undefined, invert: boolean) => { // if (!capShape) { // return; // } // if (cadGeometryTypeFromShape(oc, capShape) == CadGeometryType.WIRE) { // const wire = cadDowncast(oc, capShape) as TopoDS_Wire; // if (isBooleanTrue(this.pv.capsAsFaces)) { // const capApi = r(new oc.BRepBuilderAPI_MakeFace_15(wire, true)); // if (capApi.IsDone()) { // const face = capApi.Face(); // shapes.push(invert ? face.Complemented() : face); // } // } else { // shapes.push(capShape); // } // } // }; // addCap(api.FirstShape(), true); // addCap(api.LastShape(), false); // } for (const shape of shapes) { const type = cadGeometryTypeFromShape(oc, shape); if (type) { const newObject = new CadObject(shape, type); newObjects.push(newObject); } } } private _processShellObject(object: CadObject<CadGeometryType.SHELL>, options: CommonOptions) { const {oc, r, newObjects, extrudeDir} = options; const shell = object.cadGeometry(); const prismApi = r(new oc.BRepPrimAPI_MakePrism_1(shell, extrudeDir, false, true)); const prism = prismApi.Shape(); const type = cadGeometryTypeFromShape(oc, prism); if (type) { const newObject = new CadObject(prism, type); newObjects.push(newObject); } } }