@bitbybit-dev/occt
Version:
Bit By Bit Developers CAD algorithms using OpenCascade Technology kernel. Run in Node and in Browser.
660 lines (659 loc) • 28.7 kB
JavaScript
import * as Inputs from "../../api/inputs/inputs";
export class OperationsService {
constructor(occ, enumService, entitiesService, converterService, booleansService, shapeGettersService, edgesService, transformsService, vecHelper, wiresService, facesService, solidsService, shellsService) {
this.occ = occ;
this.enumService = enumService;
this.entitiesService = entitiesService;
this.converterService = converterService;
this.booleansService = booleansService;
this.shapeGettersService = shapeGettersService;
this.edgesService = edgesService;
this.transformsService = transformsService;
this.vecHelper = vecHelper;
this.wiresService = wiresService;
this.facesService = facesService;
this.solidsService = solidsService;
this.shellsService = shellsService;
}
loftAdvanced(inputs) {
if (inputs.periodic && !inputs.closed) {
throw new Error("Cant construct periodic non closed loft.");
}
const pipe = new this.occ.BRepOffsetAPI_ThruSections(inputs.makeSolid, inputs.straight, inputs.tolerance);
const wires = [];
const vertices = [];
if (inputs.startVertex) {
const v = this.entitiesService.makeVertex(inputs.startVertex);
pipe.AddVertex(v);
vertices.push(v);
}
if (inputs.closed && !inputs.periodic) {
inputs.shapes.push(inputs.shapes[0]);
}
else if (inputs.closed && inputs.periodic) {
const pointsOnCrvs = [];
inputs.shapes.forEach((s) => {
if (this.enumService.getShapeTypeEnum(s) === Inputs.OCCT.shapeTypeEnum.edge) {
s = this.entitiesService.bRepBuilderAPIMakeWire(s);
}
const pts = this.wiresService.divideWireByParamsToPoints({ shape: s, nrOfDivisions: inputs.nrPeriodicSections, removeStartPoint: false, removeEndPoint: false });
pointsOnCrvs.push(pts);
});
// <= needed due to start and end points that are added
for (let i = 0; i <= inputs.nrPeriodicSections; i++) {
const ptsForPerpWire = pointsOnCrvs.map(p => p[i]);
const periodicWire = this.wiresService.interpolatePoints({ points: ptsForPerpWire, tolerance: inputs.tolerance, periodic: true });
pipe.AddWire(periodicWire);
wires.push(periodicWire);
}
}
if (!inputs.periodic) {
inputs.shapes.forEach((wire) => {
pipe.AddWire(wire);
});
}
const endVertices = [];
if (inputs.endVertex) {
const v = this.entitiesService.makeVertex(inputs.endVertex);
pipe.AddVertex(v);
endVertices.push(v);
}
if (inputs.useSmoothing) {
pipe.SetSmoothing(inputs.useSmoothing);
}
if (inputs.maxUDegree) {
pipe.SetMaxDegree(inputs.maxUDegree);
}
let parType = undefined;
if (inputs.parType === Inputs.OCCT.approxParametrizationTypeEnum.approxChordLength) {
parType = this.occ.Approx_ParametrizationType.Approx_ChordLength;
}
else if (inputs.parType === Inputs.OCCT.approxParametrizationTypeEnum.approxCentripetal) {
parType = this.occ.Approx_ParametrizationType.Approx_Centripetal;
}
else if (inputs.parType === Inputs.OCCT.approxParametrizationTypeEnum.approxIsoParametric) {
parType = this.occ.Approx_ParametrizationType.Approx_IsoParametric;
}
if (parType) {
pipe.SetParType(parType);
}
pipe.CheckCompatibility(false);
const pipeShape = pipe.Shape();
const res = this.converterService.getActualTypeOfShape(pipeShape);
pipeShape.delete();
pipe.delete();
wires.forEach(w => w.delete());
vertices.forEach(v => v.delete());
endVertices.forEach(v => v.delete());
return res;
}
closestPointsBetweenTwoShapes(shape1, shape2) {
const messageProgress = new this.occ.Message_ProgressRange_1();
const extrema = new this.occ.BRepExtrema_DistShapeShape_2(shape1, shape2, this.occ.Extrema_ExtFlag.Extrema_ExtFlag_MIN, this.occ.Extrema_ExtAlgo.Extrema_ExtAlgo_Grad, messageProgress);
const messageProgress1 = new this.occ.Message_ProgressRange_1();
extrema.Perform(messageProgress1);
if (extrema.IsDone() && extrema.NbSolution() > 0) {
const closestPoint1 = extrema.PointOnShape1(1);
const closestPoint2 = extrema.PointOnShape2(1);
return [[closestPoint1.X(), closestPoint1.Y(), closestPoint1.Z()], [closestPoint2.X(), closestPoint2.Y(), closestPoint2.Z()]];
}
else {
throw new Error("Closest points could not be found.");
}
}
closestPointsOnShapeFromPoints(inputs) {
const vertexes = inputs.points.map(p => this.entitiesService.makeVertex(p));
const pointsOnShape = vertexes.map(v => this.closestPointsBetweenTwoShapes(v, inputs.shape));
return pointsOnShape.map(p => p[1]);
}
closestPointsOnShapesFromPoints(inputs) {
const vertexes = inputs.points.map(p => this.entitiesService.makeVertex(p));
const result = [];
inputs.shapes.forEach((s) => {
const pointsOnShape = vertexes.map(v => this.closestPointsBetweenTwoShapes(v, s));
result.push(...pointsOnShape.map(p => p[1]));
});
return result;
}
distancesToShapeFromPoints(inputs) {
const vertexes = inputs.points.map(p => this.entitiesService.makeVertex(p));
const pointsOnShape = vertexes.map(v => this.closestPointsBetweenTwoShapes(v, inputs.shape));
return pointsOnShape.map(p => {
return this.vecHelper.distanceBetweenPoints(p[0], p[1]);
});
}
boundingBoxOfShape(inputs) {
const bbox = new this.occ.Bnd_Box_1();
this.occ.BRepBndLib.Add(inputs.shape, bbox, false);
const cornerMin = bbox.CornerMin();
const cornerMax = bbox.CornerMax();
const min = [cornerMin.X(), cornerMin.Y(), cornerMin.Z()];
const max = [cornerMax.X(), cornerMax.Y(), cornerMax.Z()];
const center = [
(cornerMin.X() + cornerMax.X()) / 2,
(cornerMin.Y() + cornerMax.Y()) / 2,
(cornerMin.Z() + cornerMax.Z()) / 2
];
const size = [
cornerMax.X() - cornerMin.X(),
cornerMax.Y() - cornerMin.Y(),
cornerMax.Z() - cornerMin.Z()
];
bbox.delete();
const result = {
min,
max,
center,
size
};
return result;
}
boundingBoxShapeOfShape(inputs) {
const bbox = this.boundingBoxOfShape(inputs);
return this.solidsService.createBoxFromCorner({
corner: bbox.min,
width: bbox.size[0],
height: bbox.size[1],
length: bbox.size[2],
});
}
boundingSphereOfShape(inputs) {
const bbox = this.boundingBoxOfShape(inputs);
const center = bbox.center;
const radius = this.vecHelper.distanceBetweenPoints(bbox.min, center);
const result = {
center,
radius
};
return result;
}
boundingSphereShapeOfShape(inputs) {
const bbox = this.boundingSphereOfShape(inputs);
return this.solidsService.createSphere({
center: bbox.center,
radius: bbox.radius,
});
}
loft(inputs) {
const pipe = new this.occ.BRepOffsetAPI_ThruSections(inputs.makeSolid, false, 1.0e-06);
inputs.shapes.forEach((wire) => {
if (this.enumService.getShapeTypeEnum(wire) === Inputs.OCCT.shapeTypeEnum.edge) {
wire = this.entitiesService.bRepBuilderAPIMakeWire(wire);
}
pipe.AddWire(wire);
});
pipe.CheckCompatibility(false);
const pipeShape = pipe.Shape();
const res = this.converterService.getActualTypeOfShape(pipeShape);
pipeShape.delete();
pipe.delete();
return res;
}
offset(inputs) {
return this.offsetAdv({ shape: inputs.shape, face: inputs.face, distance: inputs.distance, tolerance: inputs.tolerance, joinType: Inputs.OCCT.joinTypeEnum.arc, removeIntEdges: false });
}
offsetAdv(inputs) {
if (!inputs.tolerance) {
inputs.tolerance = 0.1;
}
if (inputs.distance === 0.0) {
return inputs.shape;
}
let offset;
const joinType = this.getJoinType(inputs.joinType);
// only this mode is implemented currently, so we cannot expose others...
const brepOffsetMode = this.occ.BRepOffset_Mode.BRepOffset_Skin;
const wires = [];
if ((this.enumService.getShapeTypeEnum(inputs.shape) === Inputs.OCCT.shapeTypeEnum.wire ||
this.enumService.getShapeTypeEnum(inputs.shape) === Inputs.OCCT.shapeTypeEnum.edge)) {
let wire;
if (this.enumService.getShapeTypeEnum(inputs.shape) === Inputs.OCCT.shapeTypeEnum.edge) {
wire = this.entitiesService.bRepBuilderAPIMakeWire(inputs.shape);
wires.push(wire);
}
else {
wire = inputs.shape;
}
try {
offset = new this.occ.BRepOffsetAPI_MakeOffset_1();
if (inputs.face) {
offset.Init_1(inputs.face, joinType, false);
}
else {
offset.Init_2(joinType, false);
}
offset.AddWire(wire);
const messageProgress1 = new this.occ.Message_ProgressRange_1();
offset.Build(messageProgress1);
offset.Perform(inputs.distance, 0.0);
}
catch (ex) {
offset = new this.occ.BRepOffsetAPI_MakeOffsetShape();
offset.PerformByJoin(wire, inputs.distance, inputs.tolerance, brepOffsetMode, false, false, joinType, inputs.removeIntEdges, new this.occ.Message_ProgressRange_1());
}
}
else {
const shapeToOffset = inputs.shape;
offset = new this.occ.BRepOffsetAPI_MakeOffsetShape();
offset.PerformByJoin(shapeToOffset, inputs.distance, inputs.tolerance, brepOffsetMode, false, false, joinType, inputs.removeIntEdges, new this.occ.Message_ProgressRange_1());
}
const offsetShape = offset.Shape();
const result = this.converterService.getActualTypeOfShape(offsetShape);
offsetShape.delete();
if (offset) {
offset.delete();
}
wires.forEach(w => w.delete());
return result;
}
offset3DWire(inputs) {
const extrusion = this.extrude({
shape: inputs.shape,
direction: inputs.direction,
});
const thickSolid = this.makeThickSolidSimple({
shape: extrusion,
offset: inputs.offset,
});
const nrOfEdges = this.shapeGettersService.getEdges({ shape: inputs.shape }).length;
const predictedNrOfFaces = nrOfEdges * 4 + 2;
const lastFaceIndex = predictedNrOfFaces / 2 - 1;
const firstFaceIndex = lastFaceIndex - nrOfEdges + 1;
const faceEdges = [];
this.shapeGettersService.getFaces({ shape: thickSolid }).forEach((f, index) => {
if (index >= firstFaceIndex && index <= lastFaceIndex) {
const firstEdge = this.shapeGettersService.getEdges({ shape: f })[2];
faceEdges.push(firstEdge);
}
});
let result;
try {
result = this.converterService.combineEdgesAndWiresIntoAWire({ shapes: faceEdges });
result = result.Reversed();
result = this.converterService.getActualTypeOfShape(result);
}
catch (_a) {
result = faceEdges;
return result;
}
return result;
}
extrudeShapes(inputs) {
return inputs.shapes.map(shape => {
const extruded = this.extrude({ shape, direction: inputs.direction });
const result = this.converterService.getActualTypeOfShape(extruded);
extruded.delete();
return result;
});
}
extrude(inputs) {
const gpVec = new this.occ.gp_Vec_4(inputs.direction[0], inputs.direction[1], inputs.direction[2]);
const prismMaker = new this.occ.BRepPrimAPI_MakePrism_1(inputs.shape, gpVec, false, true);
const prismShape = prismMaker.Shape();
prismMaker.delete();
gpVec.delete();
return prismShape;
}
splitShapeWithShapes(inputs) {
const bopalgoBuilder = new this.occ.BOPAlgo_Builder_1();
bopalgoBuilder.SetNonDestructive(inputs.nonDestructive);
bopalgoBuilder.SetFuzzyValue(inputs.localFuzzyTolerance);
bopalgoBuilder.AddArgument(inputs.shape);
inputs.shapes.forEach(s => {
bopalgoBuilder.AddArgument(s);
});
bopalgoBuilder.Perform(new this.occ.Message_ProgressRange_1());
let shapes;
if (!inputs.nonDestructive) {
const res = bopalgoBuilder.Modified(inputs.shape);
const shapeCompound = this.occ.BitByBitDev.BitListOfShapesToCompound(res);
shapes = this.shapeGettersService.getShapesOfCompound({ shape: shapeCompound });
}
else {
const res = bopalgoBuilder.Shape();
shapes = this.shapeGettersService.getShapesOfCompound({ shape: res });
}
return shapes;
}
revolve(inputs) {
if (!inputs.angle) {
inputs.angle = 360.0;
}
if (!inputs.direction) {
inputs.direction = [0, 0, 1];
}
let result;
if (inputs.angle >= 360.0) {
const pt1 = new this.occ.gp_Pnt_3(0, 0, 0);
const dir = new this.occ.gp_Dir_4(inputs.direction[0], inputs.direction[1], inputs.direction[2]);
const ax1 = new this.occ.gp_Ax1_2(pt1, dir);
const makeRevol = new this.occ.BRepPrimAPI_MakeRevol_2(inputs.shape, ax1, inputs.copy);
result = makeRevol.Shape();
makeRevol.delete();
pt1.delete();
dir.delete();
ax1.delete();
}
else {
const pt1 = new this.occ.gp_Pnt_3(0, 0, 0);
const dir = new this.occ.gp_Dir_4(inputs.direction[0], inputs.direction[1], inputs.direction[2]);
const ax1 = new this.occ.gp_Ax1_2(pt1, dir);
const makeRevol = new this.occ.BRepPrimAPI_MakeRevol_1(inputs.shape, ax1, inputs.angle * 0.0174533, inputs.copy);
result = makeRevol.Shape();
makeRevol.delete();
pt1.delete();
dir.delete();
ax1.delete();
}
const actual = this.converterService.getActualTypeOfShape(result);
result.delete();
return actual;
}
rotatedExtrude(inputs) {
// Get the bounding box of the input shape to determine its current position
const bbox = this.boundingBoxOfShape({ shape: inputs.shape });
const shapeStartY = bbox.min[1]; // Y coordinate of the bottom of the shape
const shapeEndY = shapeStartY + inputs.height; // Target Y coordinate after extrusion
const translatedShape = this.transformsService.translate({
translation: [0, inputs.height, 0],
shape: inputs.shape,
});
const upperPolygon = this.transformsService.rotate({
axis: [0, 1, 0],
angle: inputs.angle,
shape: translatedShape
});
// Define the straight spine going from the shape's current position
const spineWire = this.wiresService.createBSpline({
points: [
[0, shapeStartY, 0],
[0, shapeEndY, 0]
],
closed: false,
});
// Define the guiding helical auxiliary spine (which controls the rotation)
const steps = 30;
const aspinePoints = [];
for (let i = 0; i <= steps; i++) {
const alpha = i / steps;
aspinePoints.push([
20 * Math.sin(alpha * inputs.angle * 0.0174533),
shapeStartY + (inputs.height * alpha),
20 * Math.cos(alpha * inputs.angle * 0.0174533),
]);
}
const aspineWire = this.wiresService.createBSpline({ points: aspinePoints, closed: false });
// Sweep the face wires along the spine to create the extrusion
const pipe = new this.occ.BRepOffsetAPI_MakePipeShell(spineWire);
pipe.SetMode_5(aspineWire, true, this.occ.BRepFill_TypeOfContact.BRepFill_NoContact);
pipe.Add_1(inputs.shape, false, false);
pipe.Add_1(upperPolygon, false, false);
pipe.Build(new this.occ.Message_ProgressRange_1());
// default should be to make the solid for backwards compatibility
if (inputs.makeSolid || inputs.makeSolid === undefined) {
pipe.MakeSolid();
}
const pipeShape = pipe.Shape();
const result = this.converterService.getActualTypeOfShape(pipeShape);
pipeShape.delete();
pipe.delete();
aspineWire.delete();
spineWire.delete();
upperPolygon.delete();
translatedShape.delete();
return result;
}
pipe(inputs) {
const pipe = new this.occ.BRepOffsetAPI_MakePipeShell(inputs.shape);
inputs.shapes.forEach(sh => {
pipe.Add_1(sh, false, false);
});
pipe.Build(new this.occ.Message_ProgressRange_1());
pipe.MakeSolid();
const pipeShape = pipe.Shape();
const result = this.converterService.getActualTypeOfShape(pipeShape);
pipeShape.delete();
pipe.delete();
return result;
}
pipePolylineWireNGon(inputs) {
// Input wire (the spine)
const wire = inputs.shape;
// Get the edges of the wire
const edge = this.shapeGettersService.getEdge({ shape: wire, index: 1 });
// Get the start point and tangent of the first edge
const startPoint = this.edgesService.pointOnEdgeAtParam({ shape: edge, param: 0 });
const tangent = this.edgesService.tangentOnEdgeAtParam({ shape: edge, param: 0 });
const ngon = this.wiresService.createNGonWire({
radius: inputs.radius,
center: startPoint,
direction: tangent,
nrCorners: inputs.nrCorners
});
const reversedNgon = this.wiresService.reversedWire({
shape: ngon
});
let shape = reversedNgon;
if (inputs.makeSolid) {
shape = this.facesService.createFaceFromWire({
shape: reversedNgon,
planar: true,
});
}
const geomFillTrihedron = this.enumService.getGeomFillTrihedronEnumOCCTValue(inputs.trihedronEnum);
const pipe = new this.occ.BRepOffsetAPI_MakePipe_2(wire, shape, geomFillTrihedron, inputs.forceApproxC1 ? true : false);
pipe.Build(new this.occ.Message_ProgressRange_1());
const pipeShape = pipe.Shape();
// Convert and clean up
const result = this.converterService.getActualTypeOfShape(pipeShape);
pipeShape.delete();
pipe.delete();
ngon.delete();
reversedNgon.delete();
return result;
}
pipeWireCylindrical(inputs) {
// Input wire (the spine)
const wire = inputs.shape;
// Get the edges of the wire
const edges = this.shapeGettersService.getEdges({ shape: wire });
// Get the start point and tangent of the first edge
const firstEdge = edges[0];
const startPoint = this.edgesService.startPointOnEdge({ shape: firstEdge });
const tangent = this.edgesService.tangentOnEdgeAtParam({ shape: firstEdge, param: 0 });
const circle = this.entitiesService.createCircle(inputs.radius, startPoint, tangent, inputs.makeSolid ? Inputs.OCCT.typeSpecificityEnum.face : Inputs.OCCT.typeSpecificityEnum.wire);
// Create the pipe by sweeping the profile along the wire
const geomFillTrihedron = this.enumService.getGeomFillTrihedronEnumOCCTValue(inputs.trihedronEnum);
const pipe = new this.occ.BRepOffsetAPI_MakePipe_2(wire, circle, geomFillTrihedron, inputs.forceApproxC1 ? true : false);
pipe.Build(new this.occ.Message_ProgressRange_1());
const pipeShape = pipe.Shape();
// Convert and clean up
const result = this.converterService.getActualTypeOfShape(pipeShape);
pipeShape.delete();
pipe.delete();
circle.delete();
return result;
}
pipeWiresCylindrical(inputs) {
return inputs.shapes.map(wire => {
return this.pipeWireCylindrical({ shape: wire, radius: inputs.radius, makeSolid: inputs.makeSolid, trihedronEnum: inputs.trihedronEnum, forceApproxC1: inputs.forceApproxC1 });
});
}
makeThickSolidSimple(inputs) {
const maker = new this.occ.BRepOffsetAPI_MakeThickSolid();
maker.MakeThickSolidBySimple(inputs.shape, inputs.offset);
maker.Build(new this.occ.Message_ProgressRange_1());
const makerShape = maker.Shape();
const result = this.converterService.getActualTypeOfShape(makerShape);
let res2 = result;
if (inputs.offset > 0) {
const faces = this.shapeGettersService.getFaces({ shape: result });
const revFaces = faces.map(face => face.Reversed());
res2 = this.shellsService.sewFaces({ shapes: revFaces, tolerance: 1e-7 });
result.delete();
}
maker.delete();
makerShape.delete();
return res2;
}
makeThickSolidByJoin(inputs) {
const facesToRemove = new this.occ.TopTools_ListOfShape_1();
inputs.shapes.forEach(shape => {
facesToRemove.Append_1(shape);
});
const myBody = new this.occ.BRepOffsetAPI_MakeThickSolid();
const jointType = this.getJoinType(inputs.joinType);
myBody.MakeThickSolidByJoin(inputs.shape, facesToRemove, inputs.offset, inputs.tolerance, this.occ.BRepOffset_Mode.BRepOffset_Skin, // currently a single option
inputs.intersection, inputs.selfIntersection, jointType, inputs.removeIntEdges, new this.occ.Message_ProgressRange_1());
const makeThick = myBody.Shape();
const result = this.converterService.getActualTypeOfShape(makeThick);
makeThick.delete();
myBody.delete();
facesToRemove.delete();
return result;
}
getJoinType(jointType) {
let res;
switch (jointType) {
case Inputs.OCCT.joinTypeEnum.arc: {
res = this.occ.GeomAbs_JoinType.GeomAbs_Arc;
break;
}
case Inputs.OCCT.joinTypeEnum.intersection: {
res = this.occ.GeomAbs_JoinType.GeomAbs_Intersection;
break;
}
case Inputs.OCCT.joinTypeEnum.tangent: {
res = this.occ.GeomAbs_JoinType.GeomAbs_Tangent;
break;
}
}
return res;
}
getBRepOffsetMode(offsetMode) {
let res;
switch (offsetMode) {
case Inputs.OCCT.bRepOffsetModeEnum.skin: {
res = this.occ.BRepOffset_Mode.BRepOffset_Skin;
break;
}
case Inputs.OCCT.bRepOffsetModeEnum.pipe: {
res = this.occ.BRepOffset_Mode.BRepOffset_Pipe;
break;
}
case Inputs.OCCT.bRepOffsetModeEnum.rectoVerso: {
res = this.occ.BRepOffset_Mode.BRepOffset_RectoVerso;
break;
}
}
return res;
}
slice(inputs) {
if (inputs.step <= 0) {
throw new Error("Step needs to be positive.");
}
const { bbox, transformedShape } = this.createBBoxAndTransformShape(inputs.shape, inputs.direction);
const intersections = [];
if (!bbox.IsThin(0.0001)) {
const { minY, maxY, maxDist } = this.computeBounds(bbox);
const planes = [];
for (let i = minY; i < maxY; i += inputs.step) {
const pq = this.facesService.createSquareFace({ size: maxDist, center: [0, i, 0], direction: [0, 1, 0] });
planes.push(pq);
}
this.applySlices(transformedShape, planes, inputs.direction, intersections);
}
const res = this.converterService.makeCompound({ shapes: intersections });
return res;
}
sliceInStepPattern(inputs) {
if (!inputs.steps || inputs.steps.length === 0) {
throw new Error("Steps must be provided with at elast one positive value");
}
const { bbox, transformedShape } = this.createBBoxAndTransformShape(inputs.shape, inputs.direction);
const intersections = [];
if (!bbox.IsThin(0.0001)) {
const { minY, maxY, maxDist } = this.computeBounds(bbox);
const planes = [];
let index = 0;
for (let i = minY; i < maxY; i += inputs.steps[index]) {
const pq = this.facesService.createSquareFace({ size: maxDist, center: [0, i, 0], direction: [0, 1, 0] });
planes.push(pq);
if (inputs.steps[index + 1] === undefined) {
index = 0;
}
else {
index++;
}
}
this.applySlices(transformedShape, planes, inputs.direction, intersections);
}
const res = this.converterService.makeCompound({ shapes: intersections });
return res;
}
createBBoxAndTransformShape(shape, direction) {
// we orient the given shape to the reverse direction of sections so that slicing
// would always happen in flat bbox aligned orientation
// after algorithm computes, we turn all intersections to original shape so that it would match a given shape.
// const fromDir
const transformedShape = this.transformsService.align({
shape,
fromOrigin: [0, 0, 0],
fromDirection: direction,
toOrigin: [0, 0, 0],
toDirection: [0, 1, 0],
});
const bbox = new this.occ.Bnd_Box_1();
this.occ.BRepBndLib.Add(transformedShape, bbox, false);
return { bbox, transformedShape };
}
computeBounds(bbox) {
const cornerMin = bbox.CornerMin();
const cornerMax = bbox.CornerMax();
const minY = cornerMin.Y();
const maxY = cornerMax.Y();
const minX = cornerMin.X();
const maxX = cornerMax.X();
const minZ = cornerMin.Z();
const maxZ = cornerMax.Z();
const distX = maxX - minX;
const distZ = maxZ - minZ;
const percentage = 1.2;
let maxDist = distX >= distZ ? distX : distZ;
maxDist *= percentage;
return { minY, maxY, maxDist };
}
applySlices(transformedShape, planes, direction, intersections) {
const shapesToSlice = [];
if (this.enumService.getShapeTypeEnum(transformedShape) === Inputs.OCCT.shapeTypeEnum.solid) {
shapesToSlice.push(transformedShape);
}
else {
const solids = this.shapeGettersService.getSolids({ shape: transformedShape });
shapesToSlice.push(...solids);
}
if (shapesToSlice.length === 0) {
throw new Error("No solids found to slice.");
}
shapesToSlice.forEach(s => {
const intInputs = new Inputs.OCCT.IntersectionDto();
intInputs.keepEdges = true;
intInputs.shapes = [s];
const compound = this.converterService.makeCompound({ shapes: planes });
intInputs.shapes.push(compound);
const ints = this.booleansService.intersection(intInputs);
ints.forEach(int => {
if (int && !int.IsNull()) {
const transformedInt = this.transformsService.align({
shape: int,
fromOrigin: [0, 0, 0],
fromDirection: [0, 1, 0],
toOrigin: [0, 0, 0],
toDirection: direction,
});
intersections.push(transformedInt);
}
});
});
}
}