UNPKG

@bitbybit-dev/occt

Version:

Bit By Bit Developers CAD algorithms using OpenCascade Technology kernel. Run in Node and in Browser.

838 lines (837 loc) 39.6 kB
import * as Inputs from "../../api/inputs/inputs"; export class EdgesService { constructor(occ, occRefReturns, shapeGettersService, entitiesService, iteratorService, converterService, enumService, geomService, transformsService, vecHelper) { this.occ = occ; this.occRefReturns = occRefReturns; this.shapeGettersService = shapeGettersService; this.entitiesService = entitiesService; this.iteratorService = iteratorService; this.converterService = converterService; this.enumService = enumService; this.geomService = geomService; this.transformsService = transformsService; this.vecHelper = vecHelper; } getCornerPointsOfEdgesForShape(inputs) { const edges = this.shapeGettersService.getEdges(inputs); let points = []; edges.forEach((edge) => { const param1 = { current: 0 }; const param2 = { current: 0 }; const crvHandle = this.occRefReturns.BRep_Tool_Curve_2(edge, param1, param2); try { const crv = crvHandle.get(); if (crv) { const pt1 = crv.Value(param1.current); const pt2 = crv.Value(param2.current); const pt1g = [pt1.X(), pt1.Y(), pt1.Z()]; const pt2g = [pt2.X(), pt2.Y(), pt2.Z()]; pt1.delete(); pt2.delete(); points.push(pt1g); points.push(pt2g); } } catch (ex) { console.log(ex); } }); if (points.length > 0) { points = this.vecHelper.removeAllDuplicateVectors(points); } return points; } getCircularEdgesAlongWire(inputs) { return this.getEdgesAlongWire(inputs).filter(edge => this.isEdgeCircular({ shape: edge })); } getLinearEdgesAlongWire(inputs) { return this.getEdgesAlongWire(inputs).filter(edge => this.isEdgeLinear({ shape: edge })); } getEdgesAlongWire(inputs) { if (inputs.shape && this.enumService.getShapeTypeEnum(inputs.shape) === Inputs.OCCT.shapeTypeEnum.edge) { return [inputs.shape]; } if (!inputs.shape || inputs.shape.IsNull()) { throw (new Error("Shape is not provided or is of incorrect type")); } const edges = []; const wireWithFixedEdges = this.fixEdgeOrientationsAlongWire(inputs); this.iteratorService.forEachEdgeAlongWire(wireWithFixedEdges, (i, edge) => { edges.push(edge); }); return edges; } fixEdgeOrientationsAlongWire(inputs) { const edges = []; this.iteratorService.forEachEdgeAlongWire(inputs.shape, (i, edge) => { edges.push(edge); }); // rebuilding wire from edges along wire fixes edge directions return this.converterService.combineEdgesAndWiresIntoAWire({ shapes: edges }); } arcThroughThreePoints(inputs) { const gpPnt1 = this.entitiesService.gpPnt(inputs.start); const gpPnt2 = this.entitiesService.gpPnt(inputs.middle); const gpPnt3 = this.entitiesService.gpPnt(inputs.end); const segment = new this.occ.GC_MakeArcOfCircle_4(gpPnt1, gpPnt2, gpPnt3); const hcurve = new this.occ.Handle_Geom_Curve_2(segment.Value().get()); const makeEdge = new this.occ.BRepBuilderAPI_MakeEdge_24(hcurve); const shape = makeEdge.Edge(); gpPnt1.delete(); gpPnt2.delete(); gpPnt3.delete(); segment.delete(); hcurve.delete(); makeEdge.delete(); return shape; } arcThroughTwoPointsAndTangent(inputs) { const gpPnt1 = this.entitiesService.gpPnt(inputs.start); const gpVec = this.entitiesService.gpVec(inputs.tangentVec); const gpPnt2 = this.entitiesService.gpPnt(inputs.end); const segment = new this.occ.GC_MakeArcOfCircle_5(gpPnt1, gpVec, gpPnt2); const hcurve = new this.occ.Handle_Geom_Curve_2(segment.Value().get()); const makeEdge = new this.occ.BRepBuilderAPI_MakeEdge_24(hcurve); const shape = makeEdge.Edge(); gpPnt1.delete(); gpVec.delete(); gpPnt2.delete(); segment.delete(); hcurve.delete(); makeEdge.delete(); return shape; } arcFromCircleAndTwoAngles(inputs) { const circle = this.getGpCircleFromEdge({ shape: inputs.circle }); const radAlpha1 = this.vecHelper.degToRad(inputs.alphaAngle1); const radAlpha2 = this.vecHelper.degToRad(inputs.alphaAngle2); const arc = new this.occ.GC_MakeArcOfCircle_1(circle, radAlpha1, radAlpha2, inputs.sense); const hcurve = new this.occ.Handle_Geom_Curve_2(arc.Value().get()); const makeEdge = new this.occ.BRepBuilderAPI_MakeEdge_24(hcurve); const shape = makeEdge.Edge(); circle.delete(); arc.delete(); hcurve.delete(); makeEdge.delete(); return shape; } arcFromCirclePointAndAngle(inputs) { const circle = this.getGpCircleFromEdge({ shape: inputs.circle }); const radAlpha = this.vecHelper.degToRad(inputs.alphaAngle); const point = this.entitiesService.gpPnt(inputs.point); const arc = new this.occ.GC_MakeArcOfCircle_2(circle, point, radAlpha, inputs.sense); const hcurve = new this.occ.Handle_Geom_Curve_2(arc.Value().get()); const makeEdge = new this.occ.BRepBuilderAPI_MakeEdge_24(hcurve); const shape = makeEdge.Edge(); circle.delete(); arc.delete(); point.delete(); hcurve.delete(); makeEdge.delete(); return shape; } lineEdge(inputs) { const gpPnt1 = this.entitiesService.gpPnt(inputs.start); const gpPnt2 = this.entitiesService.gpPnt(inputs.end); const segment = new this.occ.GC_MakeSegment_1(gpPnt1, gpPnt2); const segVal = segment.Value(); const seg = segVal.get(); const hcurve = new this.occ.Handle_Geom_Curve_2(seg); const edgeMaker = new this.occ.BRepBuilderAPI_MakeEdge_24(hcurve); const edge = edgeMaker.Edge(); edgeMaker.delete(); hcurve.delete(); gpPnt1.delete(); gpPnt2.delete(); segVal.delete(); seg.delete(); return edge; } getEdgeLength(inputs) { const makeWire = new this.occ.BRepBuilderAPI_MakeWire_2(inputs.shape); const wire = makeWire.Wire(); const curve = new this.occ.BRepAdaptor_CompCurve_2(wire, false); const length = this.geomService.curveLength({ shape: curve }); curve.delete(); wire.delete(); makeWire.delete(); return length; } getEdgeLengthsOfShape(inputs) { const edgesOnShape = this.shapeGettersService.getEdges({ shape: inputs.shape }); return edgesOnShape.map(edge => { return this.getEdgeLength({ shape: edge }); }); } getEdgesLengths(inputs) { if (inputs.shapes === undefined) { throw (Error(("Shapes are not defined"))); } return inputs.shapes.map(edge => this.getEdgeLength({ shape: edge })); } getEdgesCentersOfMass(inputs) { if (inputs.shapes === undefined) { throw (Error(("Shapes are not defined"))); } return inputs.shapes.map(edge => this.geomService.getLinearCenterOfMass({ shape: edge })); } edgesToPoints(inputs) { const shapeType = this.enumService.getShapeTypeEnum(inputs.shape); let edges = []; if (shapeType === Inputs.OCCT.shapeTypeEnum.edge) { edges = [inputs.shape]; } else if (shapeType === Inputs.OCCT.shapeTypeEnum.wire) { edges = this.getEdgesAlongWire({ shape: inputs.shape }); } else { edges = this.shapeGettersService.getEdges({ shape: inputs.shape }); } // Reuse edgeToPoints for each edge to ensure consistent direction handling const allEdgePoints = edges.map(edge => { return this.edgeToPoints(Object.assign(Object.assign({}, inputs), { shape: edge })); }); return allEdgePoints; } startPointOnEdge(inputs) { const edge = inputs.shape; const wire = this.converterService.combineEdgesAndWiresIntoAWire({ shapes: [edge] }); const curve = new this.occ.BRepAdaptor_CompCurve_2(wire, false); const pt = this.geomService.pointOnCurveAtParam({ shape: curve, param: 0 }); curve.delete(); return pt; } endPointOnEdge(inputs) { const edge = inputs.shape; const wire = this.converterService.combineEdgesAndWiresIntoAWire({ shapes: [edge] }); const curve = new this.occ.BRepAdaptor_CompCurve_2(wire, false); const pt = this.geomService.pointOnCurveAtParam({ shape: curve, param: 1 }); curve.delete(); return pt; } edgeToPoints(inputs) { const edgePoints = []; const aLocation = new this.occ.TopLoc_Location_1(); const adaptorCurve = new this.occ.BRepAdaptor_Curve_2(inputs.shape); const tangDef = new this.occ.GCPnts_TangentialDeflection_2(adaptorCurve, inputs.angularDeflection, inputs.curvatureDeflection, inputs.minimumOfPoints, inputs.uTolerance, inputs.minimumLength); const nrPoints = tangDef.NbPoints(); const tangDefValues = []; for (let j = 0; j < nrPoints; j++) { const tangDefVal = tangDef.Value(j + 1); edgePoints.push([ tangDefVal.X(), tangDefVal.Y(), tangDefVal.Z() ]); tangDefValues.push(tangDefVal); } tangDefValues.forEach(v => v.delete()); aLocation.delete(); adaptorCurve.delete(); tangDef.delete(); // Ensure tessellation matches edge direction // The tessellation might be in reverse order relative to the edge's start->end direction if (edgePoints.length > 1) { const edgeStart = this.startPointOnEdge({ shape: inputs.shape }); const tessStart = edgePoints[0]; const tessEnd = edgePoints[edgePoints.length - 1]; // Check if first tessellation point is closer to edge start or end const distStartToStart = this.vecHelper.distanceBetweenPoints(tessStart, edgeStart); const distEndToStart = this.vecHelper.distanceBetweenPoints(tessEnd, edgeStart); // If the last tessellation point is closer to the edge start, the array is reversed if (distEndToStart < distStartToStart) { edgePoints.reverse(); } } return edgePoints; } makeEdgeFromGeom2dCurveAndSurfaceBounded(inputs, umin, umax) { const curve2d = new this.occ.Handle_Geom2d_Curve_2(inputs.curve); const surface = new this.occ.Handle_Geom_Surface_2(inputs.surface); const res = new this.occ.BRepBuilderAPI_MakeEdge_31(curve2d, surface, umin, umax); const resShape = res.Shape(); const r = this.converterService.getActualTypeOfShape(resShape); resShape.delete(); res.delete(); return r; } makeEdgeFromGeom2dCurveAndSurface(inputs) { const curve2d = new this.occ.Handle_Geom2d_Curve_2(inputs.curve); const surface = new this.occ.Handle_Geom_Surface_2(inputs.surface); const res = new this.occ.BRepBuilderAPI_MakeEdge_30(curve2d, surface); const resShape = res.Shape(); const r = this.converterService.getActualTypeOfShape(resShape); resShape.delete(); res.delete(); return r; } constraintTanLinesFromTwoPtsToCircle(inputs) { const cirDir = this.getCircularEdgePlaneDirection({ shape: inputs.circle }); const cirPos = this.getCircularEdgeCenterPoint({ shape: inputs.circle }); const alignOpt = new Inputs.OCCT.AlignDto(); alignOpt.fromDirection = cirDir; alignOpt.toDirection = [0, 0, 1]; alignOpt.fromOrigin = cirPos; alignOpt.toOrigin = [0, 0, 0]; alignOpt.shape = inputs.circle; const circleAligned = this.transformsService.align(alignOpt); const ptVertex1 = this.entitiesService.makeVertex(inputs.point1); alignOpt.shape = ptVertex1; const ptVertex1Aligned = this.transformsService.align(alignOpt); ptVertex1.delete(); const pt1Aligned = this.converterService.vertexToPoint({ shape: ptVertex1Aligned }); ptVertex1Aligned.delete(); const pt2d1 = this.entitiesService.gpPnt2d([pt1Aligned[0], pt1Aligned[1]]); const ptVertex2 = this.entitiesService.makeVertex(inputs.point2); alignOpt.shape = ptVertex2; const ptVertex2Aligned = this.transformsService.align(alignOpt); ptVertex2.delete(); const pt2Aligned = this.converterService.vertexToPoint({ shape: ptVertex2Aligned }); ptVertex2Aligned.delete(); const pt2d2 = this.entitiesService.gpPnt2d([pt2Aligned[0], pt2Aligned[1]]); const circle = this.getGpCircle2dFromEdge({ shape: circleAligned }); circleAligned.delete(); const qCircle = new this.occ.GccEnt_QualifiedCirc(circle, this.enumService.getGccEntPositionFromEnum(Inputs.OCCT.gccEntPositionEnum.unqualified)); circle.delete(); const lin1 = new this.occ.GccAna_Lin2d2Tan_2(qCircle, pt2d1, inputs.tolerance); const lin2 = new this.occ.GccAna_Lin2d2Tan_2(qCircle, pt2d2, inputs.tolerance); qCircle.delete(); const solutions1 = []; for (let i = 1; i <= lin1.NbSolutions(); i++) { const sol = lin1.ThisSolution(i); const location = sol.Location(); const edgeLine = this.lineEdge({ start: [location.X(), location.Y(), 0], end: pt1Aligned }); alignOpt.fromDirection = [0, 0, 1]; alignOpt.toDirection = cirDir; alignOpt.fromOrigin = [0, 0, 0]; alignOpt.toOrigin = cirPos; alignOpt.shape = edgeLine; const aligned = this.transformsService.align(alignOpt); solutions1.push(aligned); sol.delete(); location.delete(); edgeLine.delete(); } lin1.delete(); const solutions2 = []; for (let i = 1; i <= lin2.NbSolutions(); i++) { const sol = lin2.ThisSolution(i); const location = sol.Location(); const edgeLine = this.lineEdge({ start: [location.X(), location.Y(), 0], end: pt2Aligned }); alignOpt.fromDirection = [0, 0, 1]; alignOpt.toDirection = cirDir; alignOpt.fromOrigin = [0, 0, 0]; alignOpt.toOrigin = cirPos; alignOpt.shape = edgeLine; const aligned = this.transformsService.align(alignOpt); solutions2.push(aligned); sol.delete(); location.delete(); edgeLine.delete(); } lin2.delete(); let resultingSol = []; if (inputs.positionResult === Inputs.OCCT.positionResultEnum.all) { resultingSol = [...solutions1, ...solutions2]; } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide1) { resultingSol = [solutions1[1], solutions2[0]]; } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide2) { resultingSol = [solutions1[0], solutions2[1]]; } else { resultingSol = [...solutions1, ...solutions2]; } if (resultingSol.length === 2 && inputs.circleRemainder !== Inputs.OCCT.circleInclusionEnum.none) { let startPoint; let endPoint; if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide2) { if (inputs.circleRemainder === Inputs.OCCT.circleInclusionEnum.keepSide1) { startPoint = this.startPointOnEdge({ shape: resultingSol[1] }); endPoint = this.startPointOnEdge({ shape: resultingSol[0] }); } else if (inputs.circleRemainder === Inputs.OCCT.circleInclusionEnum.keepSide2) { startPoint = this.startPointOnEdge({ shape: resultingSol[0] }); endPoint = this.startPointOnEdge({ shape: resultingSol[1] }); } } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide1) { if (inputs.circleRemainder === Inputs.OCCT.circleInclusionEnum.keepSide1) { startPoint = this.startPointOnEdge({ shape: resultingSol[0] }); endPoint = this.startPointOnEdge({ shape: resultingSol[1] }); } else if (inputs.circleRemainder === Inputs.OCCT.circleInclusionEnum.keepSide2) { startPoint = this.startPointOnEdge({ shape: resultingSol[1] }); endPoint = this.startPointOnEdge({ shape: resultingSol[0] }); } } const edge = this.arcFromCircleAndTwoPoints({ circle: inputs.circle, start: startPoint, end: endPoint, sense: true }); resultingSol.splice(1, 0, edge); } return resultingSol; } constraintTanLinesFromPtToCircle(inputs) { const cirDir = this.getCircularEdgePlaneDirection({ shape: inputs.circle }); const cirPos = this.getCircularEdgeCenterPoint({ shape: inputs.circle }); const alignOpt = new Inputs.OCCT.AlignDto(); alignOpt.fromDirection = cirDir; alignOpt.toDirection = [0, 0, 1]; alignOpt.fromOrigin = cirPos; alignOpt.toOrigin = [0, 0, 0]; alignOpt.shape = inputs.circle; const circleAligned = this.transformsService.align(alignOpt); const ptVertex = this.entitiesService.makeVertex(inputs.point); alignOpt.shape = ptVertex; const ptVertexAligned = this.transformsService.align(alignOpt); ptVertex.delete(); const ptAligned = this.converterService.vertexToPoint({ shape: ptVertexAligned }); ptVertexAligned.delete(); const pt2d = this.entitiesService.gpPnt2d([ptAligned[0], ptAligned[1]]); const circle = this.getGpCircle2dFromEdge({ shape: circleAligned }); circleAligned.delete(); const qCircle = new this.occ.GccEnt_QualifiedCirc(circle, this.enumService.getGccEntPositionFromEnum(Inputs.OCCT.gccEntPositionEnum.unqualified)); circle.delete(); const lin = new this.occ.GccAna_Lin2d2Tan_2(qCircle, pt2d, inputs.tolerance); qCircle.delete(); const solutions = []; for (let i = 1; i <= lin.NbSolutions(); i++) { const sol = lin.ThisSolution(i); const location = sol.Location(); const edgeLine = this.lineEdge({ start: [location.X(), location.Y(), 0], end: ptAligned }); alignOpt.fromDirection = [0, 0, 1]; alignOpt.toDirection = cirDir; alignOpt.fromOrigin = [0, 0, 0]; alignOpt.toOrigin = cirPos; alignOpt.shape = edgeLine; const aligned = this.transformsService.align(alignOpt); solutions.push(aligned); sol.delete(); location.delete(); edgeLine.delete(); } lin.delete(); let resultingSol = []; if (inputs.positionResult === Inputs.OCCT.positionResultEnum.all) { resultingSol = [...solutions]; } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide1) { resultingSol = [solutions[0]]; } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide2) { resultingSol = [solutions[1]]; } else { resultingSol = [...solutions]; } if (resultingSol.length === 2 && inputs.circleRemainder !== Inputs.OCCT.circleInclusionEnum.none) { let startPoint; let endPoint; if (inputs.circleRemainder === Inputs.OCCT.circleInclusionEnum.keepSide1) { startPoint = this.startPointOnEdge({ shape: resultingSol[1] }); endPoint = this.startPointOnEdge({ shape: resultingSol[0] }); } else if (inputs.circleRemainder === Inputs.OCCT.circleInclusionEnum.keepSide2) { startPoint = this.startPointOnEdge({ shape: resultingSol[0] }); endPoint = this.startPointOnEdge({ shape: resultingSol[1] }); } const edge = this.arcFromCircleAndTwoPoints({ circle: inputs.circle, start: startPoint, end: endPoint, sense: true }); resultingSol.splice(1, 0, edge); } return resultingSol; } constraintTanLinesOnTwoCircles(inputs) { const cirDir = this.getCircularEdgePlaneDirection({ shape: inputs.circle1 }); const cirPos = this.getCircularEdgeCenterPoint({ shape: inputs.circle1 }); const alignOpt = new Inputs.OCCT.AlignDto(); alignOpt.fromDirection = cirDir; alignOpt.toDirection = [0, 0, 1]; alignOpt.fromOrigin = cirPos; alignOpt.toOrigin = [0, 0, 0]; alignOpt.shape = inputs.circle1; const circle1Aligned = this.transformsService.align(alignOpt); alignOpt.shape = inputs.circle2; const circle2Aligned = this.transformsService.align(alignOpt); const circle1 = this.getGpCircle2dFromEdge({ shape: circle1Aligned }); const circle2 = this.getGpCircle2dFromEdge({ shape: circle2Aligned }); circle1Aligned.delete(); circle2Aligned.delete(); const qCircle1 = new this.occ.GccEnt_QualifiedCirc(circle1, this.enumService.getGccEntPositionFromEnum(Inputs.OCCT.gccEntPositionEnum.unqualified)); const qCircle2 = new this.occ.GccEnt_QualifiedCirc(circle2, this.enumService.getGccEntPositionFromEnum(Inputs.OCCT.gccEntPositionEnum.unqualified)); circle1.delete(); circle2.delete(); const lin1 = new this.occ.GccAna_Lin2d2Tan_3(qCircle1, qCircle2, inputs.tolerance); const lin2 = new this.occ.GccAna_Lin2d2Tan_3(qCircle2, qCircle1, inputs.tolerance); qCircle1.delete(); qCircle2.delete(); const lin1Sols = []; for (let i = 1; i <= lin1.NbSolutions(); i++) { const sol = lin1.ThisSolution(i); lin1Sols.push(sol); } lin1.delete(); const lin2Sols = []; for (let i = 1; i <= lin2.NbSolutions(); i++) { const sol = lin2.ThisSolution(i); lin2Sols.push(sol); } lin2.delete(); let adjustLin2Sol; if (lin2Sols.length === 4) { adjustLin2Sol = [lin2Sols[2], lin2Sols[1], lin2Sols[0], lin2Sols[3]]; } else if (lin2Sols.length === 2) { adjustLin2Sol = [lin2Sols[1], lin2Sols[0]]; } const solutions = []; for (let i = 0; i < lin1Sols.length; i++) { const sol1 = lin1Sols[i]; const sol2 = adjustLin2Sol[i]; const locationStart = sol1.Location(); const startPoint = [locationStart.X(), locationStart.Y(), 0]; const locationEnd = sol2.Location(); const endPoint = [locationEnd.X(), locationEnd.Y(), 0]; const edgeLine = this.lineEdge({ start: startPoint, end: endPoint }); alignOpt.fromDirection = [0, 0, 1]; alignOpt.toDirection = cirDir; alignOpt.fromOrigin = [0, 0, 0]; alignOpt.toOrigin = cirPos; alignOpt.shape = edgeLine; const aligned = this.transformsService.align(alignOpt); solutions.push(aligned); edgeLine.delete(); sol1.delete(); sol2.delete(); locationStart.delete(); locationEnd.delete(); } let resultingSol = []; if (inputs.positionResult === Inputs.OCCT.positionResultEnum.all) { resultingSol = [...solutions]; } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide1 && solutions.length === 4) { resultingSol = [solutions[1], solutions[3]]; } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide2 && solutions.length === 4) { resultingSol = [solutions[0], solutions[2]]; } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide1 && solutions.length === 2) { resultingSol = []; } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide2 && solutions.length === 2) { resultingSol = [solutions[0], solutions[1]]; } else { resultingSol = [...solutions]; } if (resultingSol.length === 2 && inputs.circleRemainders !== Inputs.OCCT.twoCircleInclusionEnum.none) { let startPoint1; let startPoint2; let endPoint1; let endPoint2; if (inputs.circleRemainders === Inputs.OCCT.twoCircleInclusionEnum.outside) { if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide2 || inputs.positionResult === Inputs.OCCT.positionResultEnum.all) { startPoint1 = this.startPointOnEdge({ shape: resultingSol[1] }); startPoint2 = this.startPointOnEdge({ shape: resultingSol[0] }); } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide1) { startPoint1 = this.startPointOnEdge({ shape: resultingSol[0] }); startPoint2 = this.startPointOnEdge({ shape: resultingSol[1] }); } endPoint1 = this.endPointOnEdge({ shape: resultingSol[0] }); endPoint2 = this.endPointOnEdge({ shape: resultingSol[1] }); } else if (inputs.circleRemainders === Inputs.OCCT.twoCircleInclusionEnum.inside) { if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide2 || inputs.positionResult === Inputs.OCCT.positionResultEnum.all) { startPoint1 = this.startPointOnEdge({ shape: resultingSol[0] }); startPoint2 = this.startPointOnEdge({ shape: resultingSol[1] }); } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide1) { startPoint1 = this.startPointOnEdge({ shape: resultingSol[1] }); startPoint2 = this.startPointOnEdge({ shape: resultingSol[0] }); } endPoint1 = this.endPointOnEdge({ shape: resultingSol[1] }); endPoint2 = this.endPointOnEdge({ shape: resultingSol[0] }); } else if (inputs.circleRemainders === Inputs.OCCT.twoCircleInclusionEnum.insideOutside) { if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide2 || inputs.positionResult === Inputs.OCCT.positionResultEnum.all) { startPoint1 = this.startPointOnEdge({ shape: resultingSol[0] }); startPoint2 = this.startPointOnEdge({ shape: resultingSol[1] }); } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide1) { startPoint1 = this.startPointOnEdge({ shape: resultingSol[1] }); startPoint2 = this.startPointOnEdge({ shape: resultingSol[0] }); } endPoint1 = this.endPointOnEdge({ shape: resultingSol[0] }); endPoint2 = this.endPointOnEdge({ shape: resultingSol[1] }); } else if (inputs.circleRemainders === Inputs.OCCT.twoCircleInclusionEnum.outsideInside) { if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide2 || inputs.positionResult === Inputs.OCCT.positionResultEnum.all) { startPoint1 = this.startPointOnEdge({ shape: resultingSol[1] }); startPoint2 = this.startPointOnEdge({ shape: resultingSol[0] }); } else if (inputs.positionResult === Inputs.OCCT.positionResultEnum.keepSide1) { startPoint1 = this.startPointOnEdge({ shape: resultingSol[0] }); startPoint2 = this.startPointOnEdge({ shape: resultingSol[1] }); } endPoint1 = this.endPointOnEdge({ shape: resultingSol[1] }); endPoint2 = this.endPointOnEdge({ shape: resultingSol[0] }); } const edge1 = this.arcFromCircleAndTwoPoints({ circle: inputs.circle1, start: startPoint1, end: startPoint2, sense: true }); const edge2 = this.arcFromCircleAndTwoPoints({ circle: inputs.circle2, start: endPoint1, end: endPoint2, sense: true }); resultingSol.unshift(edge1); resultingSol.push(edge2); } return resultingSol; } constraintTanCirclesOnCircleAndPnt(inputs) { const cirDir = this.getCircularEdgePlaneDirection({ shape: inputs.circle }); const cirPos = this.getCircularEdgeCenterPoint({ shape: inputs.circle }); const { alignOpt, circle1Aligned: circleAligned } = this.alignCircle(cirDir, cirPos, inputs.circle); const ptVertex = this.entitiesService.makeVertex(inputs.point); alignOpt.shape = ptVertex; const ptVertexAligned = this.transformsService.align(alignOpt); ptVertex.delete(); const ptAligned = this.converterService.vertexToPoint({ shape: ptVertexAligned }); ptVertexAligned.delete(); const pt2d = this.entitiesService.gpPnt2d([ptAligned[0], ptAligned[1]]); const circle = this.getGpCircle2dFromEdge({ shape: circleAligned }); circleAligned.delete(); const qCircle = new this.occ.GccEnt_QualifiedCirc(circle, this.enumService.getGccEntPositionFromEnum(Inputs.OCCT.gccEntPositionEnum.unqualified)); circle.delete(); const lin1 = new this.occ.GccAna_Circ2d2TanRad_3(qCircle, pt2d, inputs.radius, inputs.tolerance); qCircle.delete(); const lin1Sols = []; for (let i = 1; i <= lin1.NbSolutions(); i++) { const sol = lin1.ThisSolution(i); lin1Sols.push(sol); } lin1.delete(); const solutions = []; for (let i = 0; i < lin1Sols.length; i++) { const sol = lin1Sols[i]; const res = this.reconstructCircleAndAlignBack(lin1Sols, sol, alignOpt, cirDir, cirPos); solutions.push(res); } return solutions; } alignCircle(cirDir, cirPos, circle) { const alignOpt = new Inputs.OCCT.AlignDto(); alignOpt.fromDirection = cirDir; alignOpt.toDirection = [0, 0, 1]; alignOpt.fromOrigin = cirPos; alignOpt.toOrigin = [0, 0, 0]; alignOpt.shape = circle; const circle1Aligned = this.transformsService.align(alignOpt); return { alignOpt, circle1Aligned }; } constraintTanCirclesOnTwoCircles(inputs) { const cirDir = this.getCircularEdgePlaneDirection({ shape: inputs.circle1 }); const cirPos = this.getCircularEdgeCenterPoint({ shape: inputs.circle1 }); const { alignOpt, circle1Aligned } = this.alignCircle(cirDir, cirPos, inputs.circle1); alignOpt.shape = inputs.circle2; const circle2Aligned = this.transformsService.align(alignOpt); const circle1 = this.getGpCircle2dFromEdge({ shape: circle1Aligned }); const circle2 = this.getGpCircle2dFromEdge({ shape: circle2Aligned }); circle1Aligned.delete(); circle2Aligned.delete(); const qCircle1 = new this.occ.GccEnt_QualifiedCirc(circle1, this.enumService.getGccEntPositionFromEnum(Inputs.OCCT.gccEntPositionEnum.unqualified)); const qCircle2 = new this.occ.GccEnt_QualifiedCirc(circle2, this.enumService.getGccEntPositionFromEnum(Inputs.OCCT.gccEntPositionEnum.unqualified)); circle1.delete(); circle2.delete(); const lin1 = new this.occ.GccAna_Circ2d2TanRad_1(qCircle1, qCircle2, inputs.radius, inputs.tolerance); qCircle1.delete(); qCircle2.delete(); const lin1Sols = []; for (let i = 1; i <= lin1.NbSolutions(); i++) { const sol = lin1.ThisSolution(i); lin1Sols.push(sol); } lin1.delete(); const solutions = []; for (let i = 0; i < lin1Sols.length; i++) { const sol = lin1Sols[i]; const res = this.reconstructCircleAndAlignBack(lin1Sols, sol, alignOpt, cirDir, cirPos); solutions.push(res); } return solutions; } divideEdgeByParamsToPoints(inputs) { const edge = inputs.shape; const wire = this.converterService.combineEdgesAndWiresIntoAWire({ shapes: [edge] }); const curve = new this.occ.BRepAdaptor_CompCurve_2(wire, false); const points = this.geomService.divideCurveToNrSegments(Object.assign(Object.assign({}, inputs), { shape: curve }), curve.FirstParameter(), curve.LastParameter()); curve.delete(); wire.delete(); return points; } divideEdgeByEqualDistanceToPoints(inputs) { const edge = inputs.shape; const wire = this.converterService.combineEdgesAndWiresIntoAWire({ shapes: [edge] }); const curve = new this.occ.BRepAdaptor_CompCurve_2(wire, false); const points = this.geomService.divideCurveByEqualLengthDistance(Object.assign(Object.assign({}, inputs), { shape: curve })); curve.delete(); wire.delete(); return points; } pointOnEdgeAtParam(inputs) { const edge = inputs.shape; const { uMin, uMax } = this.getEdgeBounds(edge); const curve = this.converterService.getGeomCurveFromEdge(edge, uMin, uMax); const gpPnt = this.entitiesService.gpPnt([0, 0, 0]); const param = this.vecHelper.remap(inputs.param, 0, 1, uMin, uMax); if (curve) { curve.D0(param, gpPnt); const pt = [gpPnt.X(), gpPnt.Y(), gpPnt.Z()]; gpPnt.delete(); return pt; } else { return undefined; } } reconstructCircleAndAlignBack(lin1Sols, sol, alignOpt, dir, pos) { const locationStart = sol.Location(); const startPoint = [locationStart.X(), locationStart.Y(), 0]; const circle = this.entitiesService.createCircle(sol.Radius(), startPoint, [0, 0, 1], Inputs.OCCT.typeSpecificityEnum.edge); alignOpt.fromDirection = [0, 0, 1]; alignOpt.toDirection = dir; alignOpt.fromOrigin = [0, 0, 0]; alignOpt.toOrigin = pos; alignOpt.shape = circle; const aligned = this.transformsService.align(alignOpt); circle.delete(); sol.delete(); locationStart.delete(); return aligned; } arcFromCircleAndTwoPoints(inputs) { const circle = this.getGpCircleFromEdge({ shape: inputs.circle }); const gpPnt1 = this.entitiesService.gpPnt(inputs.start); const gpPnt2 = this.entitiesService.gpPnt(inputs.end); const arc = new this.occ.GC_MakeArcOfCircle_3(circle, gpPnt1, gpPnt2, inputs.sense); const hcurve = new this.occ.Handle_Geom_Curve_2(arc.Value().get()); const makeEdge = new this.occ.BRepBuilderAPI_MakeEdge_24(hcurve); const shape = makeEdge.Edge(); circle.delete(); gpPnt1.delete(); gpPnt2.delete(); arc.delete(); hcurve.delete(); makeEdge.delete(); return shape; } getCircularEdgePlaneDirection(inputs) { const circle = this.getGpCircleFromEdge(inputs); const axis = circle.Position(); const dir = axis.Direction(); const result = [dir.X(), dir.Y(), dir.Z()]; dir.delete(); axis.delete(); circle.delete(); return result; } getCircularEdgeCenterPoint(inputs) { const circle = this.getGpCircleFromEdge(inputs); const location = circle.Location(); const result = [location.X(), location.Y(), location.Z()]; location.delete(); circle.delete(); return result; } getCircularEdgeRadius(inputs) { const circle = this.getGpCircleFromEdge(inputs); const radius = circle.Radius(); circle.delete(); return radius; } getGpCircleFromEdge(inputs) { const curve = new this.occ.BRepAdaptor_Curve_2(inputs.shape); try { const circle = curve.Circle(); curve.delete(); return circle; } catch (ex) { curve.delete(); throw new Error("Edge is not a circular edge."); } } getGpCircle2dFromEdge(inputs) { const curve = new this.occ.BRepAdaptor_Curve_2(inputs.shape); try { const circle = curve.Circle(); const ax = circle.Position(); const location = circle.Location(); const ax2d = this.entitiesService.gpAx2d([location.X(), location.Y()], [1, 0]); const radius = circle.Radius(); const circle2d = new this.occ.gp_Circ2d_2(ax2d, radius, true); curve.delete(); circle.delete(); ax.delete(); location.delete(); ax2d.delete(); return circle2d; } catch (ex) { curve.delete(); throw new Error("Edge is not a circular edge."); } } tangentOnEdgeAtParam(inputs) { const edge = inputs.shape; const { uMin, uMax } = this.getEdgeBounds(edge); const curve = this.converterService.getGeomCurveFromEdge(edge, uMin, uMax); const param = this.vecHelper.remap(inputs.param, 0, 1, uMin, uMax); const vec = curve.DN(param, 1); const vector = [vec.X(), vec.Y(), vec.Z()]; vec.delete(); return vector; } pointOnEdgeAtLength(inputs) { const edge = inputs.shape; const wire = this.converterService.combineEdgesAndWiresIntoAWire({ shapes: [edge] }); const curve = new this.occ.BRepAdaptor_CompCurve_2(wire, false); const res = this.geomService.pointOnCurveAtLength(Object.assign(Object.assign({}, inputs), { shape: curve })); curve.delete(); wire.delete(); return res; } tangentOnEdgeAtLength(inputs) { const edge = inputs.shape; const wire = this.converterService.combineEdgesAndWiresIntoAWire({ shapes: [edge] }); const curve = new this.occ.BRepAdaptor_CompCurve_2(wire, false); const res = this.geomService.tangentOnCurveAtLength(Object.assign(Object.assign({}, inputs), { shape: curve })); wire.delete(); curve.delete(); return res; } getEdgeBounds(edge) { const p1 = { current: 0 }; const p2 = { current: 0 }; this.occRefReturns.BRep_Tool_Range_1(edge, p1, p2); return { uMin: p1.current, uMax: p2.current }; } isEdgeCircular(inputs) { const curve = new this.occ.BRepAdaptor_Curve_2(inputs.shape); try { curve.Circle(); curve.delete(); return true; } catch (ex) { return false; } } isEdgeLinear(inputs) { const curve = new this.occ.BRepAdaptor_Curve_2(inputs.shape); try { curve.Line(); curve.delete(); return true; } catch (ex) { return false; } } }