UNPKG

@polygonjs/polygonjs

Version:

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

126 lines (111 loc) 4.06 kB
/** * Creates a rectangle. * * */ import {CADSopNode} from './_BaseCAD'; import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig'; import {step} from '../../../core/geometry/modules/cad/CadConstant'; import {CadLoader} from '../../../core/geometry/modules/cad/CadLoader'; import type {OpenCascadeInstance, GCRegisterFunction} from '../../../core/geometry/modules/cad/CadCommon'; import {CadGC} 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 {cadShapeTranslate} from '../../../core/geometry/modules/cad/toObject3D/CadShapeCommon'; // TODO: make by default on the same axis as other 3d curve primitives like cad/circle const FILLET_RADIUS_SAFETY_MARGIN = 0.01; const HALF_PI = 0.5 * Math.PI; class CADRectangleSopParamsConfig extends NodeParamsConfig { /** @param size */ size = ParamConfig.VECTOR2([1, 1]); /** @param center */ center = ParamConfig.VECTOR3([0, 0, 0]); /** @param fillet radius */ filletRadius = ParamConfig.FLOAT(0.1, { range: [0, 1], rangeLocked: [true, false], step, }); } const ParamsConfig = new CADRectangleSopParamsConfig(); export class CADRectangleSopNode extends CADSopNode<CADRectangleSopParamsConfig> { override paramsConfig = ParamsConfig; static override type() { return SopType.CAD_RECTANGLE; } override async cook(inputCoreGroups: CoreGroup[]) { const oc = await CadLoader.core(this); CadGC.withGC((r) => { const w = this.pv.size.x; const h = this.pv.size.y; const minDim = Math.min(w, h); const rad = Math.min(this.pv.filletRadius, minDim / 2 - FILLET_RADIUS_SAFETY_MARGIN); const x = w / 2 - rad; const z = h / 2 - rad; // withCadException(oc, () => { const arc0 = _createArc(oc, r, x, z, rad, 3); const arc1 = _createArc(oc, r, x, -z, rad, 0); const arc2 = _createArc(oc, r, -x, -z, rad, 1); const arc3 = _createArc(oc, r, -x, z, rad, 2); const edgesCount = 8; const linesCount = 4; const edges = r(new oc.TopTools_Array1OfShape_2(0, edgesCount - 1)); const vertices = r(new oc.TopTools_Array1OfShape_2(0, 7)); // add edges to list edges.SetValue(0, arc0.edge); edges.SetValue(2, arc1.edge); edges.SetValue(4, arc2.edge); edges.SetValue(6, arc3.edge); // add vertices to list vertices.SetValue(0, arc0.vertex1); vertices.SetValue(1, arc1.vertex0); vertices.SetValue(2, arc1.vertex1); vertices.SetValue(3, arc2.vertex0); vertices.SetValue(4, arc2.vertex1); vertices.SetValue(5, arc3.vertex0); vertices.SetValue(6, arc3.vertex1); vertices.SetValue(7, arc0.vertex0); for (let i = 0; i < linesCount; i += 1) { const startVertex = oc.TopoDS.Vertex_2(vertices.Value(i * 2)); const endVertex = oc.TopoDS.Vertex_2(vertices.Value(i * 2 + 1)); const edgeApi = r(new oc.BRepBuilderAPI_MakeEdge_2(startVertex, endVertex)); const edge = edgeApi.Edge(); edges.SetValue(i * 2 + 1, edge); } // create wire const wireApi = r(new oc.BRepBuilderAPI_MakeWire_1()); for (let i = 0; i < edgesCount; i++) { wireApi.Add_1(oc.TopoDS.Edge_2(edges.Value(i))); } const wire = wireApi.Wire(); const shape = cadShapeTranslate(wire, this.pv.center); this.setCADShape(shape); }); } } function _createArc( oc: OpenCascadeInstance, r: GCRegisterFunction, x: number, z: number, radius: number, angleIncrement: number ) { const dir = CadLoaderSync.gp_Dir; dir.SetCoord_2(0, 1, 0); const axis = r(new oc.gp_Ax2_1()); axis.SetDirection(dir); const offset = r(new oc.gp_Vec_4(x, 0, z)); axis.Translate_1(offset); const circle = new oc.gp_Circ_2(axis, radius); const angleStart = angleIncrement * HALF_PI; const angleEnd = (angleIncrement + 1) * HALF_PI; const api = r(new oc.BRepBuilderAPI_MakeEdge_9(circle, angleStart, angleEnd)); const edge = api.Edge(); return { edge, vertex0: api.Vertex1(), vertex1: api.Vertex2(), }; }