+ std::shared_ptr<GeomAPI_Pnt> aFromPnt(new GeomAPI_Pnt(aFromLoc->xyz()->added(aBaseDir->xyz()->multiplied(
+ aSign ? theFromSize : -theFromSize))));
+ aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
+
+ std::shared_ptr<GeomAPI_Pnt> aToPnt(new GeomAPI_Pnt(aToLoc->xyz()->added(aBaseDir->xyz()->multiplied(
+ aSign ? -theToSize : theToSize))));
+ aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
+
+ // Getting bounding box for base shape.
+ Bnd_Box aBndBox;
+ BRepBndLib::Add(aBaseShape, aBndBox);
+ Standard_Real aXArr[2] = {aBndBox.CornerMin().X(), aBndBox.CornerMax().X()};
+ Standard_Real aYArr[2] = {aBndBox.CornerMin().Y(), aBndBox.CornerMax().Y()};
+ Standard_Real aZArr[2] = {aBndBox.CornerMin().Z(), aBndBox.CornerMax().Z()};
+ gp_Pnt aPoints[8];
+ int aNum = 0;
+ for(int i = 0; i < 2; i++) {
+ for(int j = 0; j < 2; j++) {
+ for(int k = 0; k < 2; k++) {
+ aPoints[aNum] = gp_Pnt(aXArr[i], aYArr[j], aZArr[k]);
+ aNum++;
+ }
+ }
+ }
+
+ // Project points to bounding planes. Search max distance to them.
+ IntAna_Quadric aBndToQuadric(gp_Pln(aToPnt->impl<gp_Pnt>(), aToDir->impl<gp_Dir>()));
+ IntAna_Quadric aBndFromQuadric(gp_Pln(aFromPnt->impl<gp_Pnt>(), aFromDir->impl<gp_Dir>()));
+ Standard_Real aMaxToDist = 0, aMaxFromDist = 0;
+ for(int i = 0; i < 8; i++) {
+ gp_Lin aLine(aPoints[i], aDirVec);
+ IntAna_IntConicQuad aToIntAna(aLine, aBndToQuadric);
+ IntAna_IntConicQuad aFromIntAna(aLine, aBndFromQuadric);
+ if(aToIntAna.NbPoints() == 0 || aFromIntAna.NbPoints() == 0) {
+ return;
+ }
+ const gp_Pnt& aPntOnToFace = aToIntAna.Point(1);
+ const gp_Pnt& aPntOnFromFace = aFromIntAna.Point(1);
+ if(aPoints[i].Distance(aPntOnToFace) > aMaxToDist) {
+ aMaxToDist = aPoints[i].Distance(aPntOnToFace);
+ }
+ if(aPoints[i].Distance(aPntOnFromFace) > aMaxFromDist) {
+ aMaxFromDist = aPoints[i].Distance(aPntOnFromFace);
+ }
+ }
+
+ // We added 1 just to be sure that prism is long enough for boolean operation.
+ double aPrismLength = aMaxToDist + aMaxFromDist + 1;
+
+ // Moving base shape.
+ gp_Trsf aTrsf;
+ aTrsf.SetTranslation(aDirVec * -aPrismLength);
+ BRepBuilderAPI_Transform* aTransformBuilder = new BRepBuilderAPI_Transform(aBaseShape, aTrsf);
+ if(!aTransformBuilder) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aTransformBuilder)));
+ if(!aTransformBuilder->IsDone()) {
+ return;
+ }
+ TopoDS_Shape aMovedBase = aTransformBuilder->Shape();
+
+ // Making prism.
+ BRepPrimAPI_MakePrism* aPrismBuilder = new BRepPrimAPI_MakePrism(aMovedBase, aDirVec * 2 * aPrismLength);
+ if(!aPrismBuilder) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aPrismBuilder)));
+ if(!aPrismBuilder->IsDone()) {
+ return;
+ }
+ aResult = aPrismBuilder->Shape();
+
+ // Orienting bounding planes.
+ std::shared_ptr<GeomAPI_Pnt> aCentreOfMass = GeomAlgoAPI_ShapeTools::centreOfMass(theBaseShape);
+ const gp_Pnt& aCentrePnt = aCentreOfMass->impl<gp_Pnt>();
+ gp_Lin aLine(aCentrePnt, aDirVec);
+ IntAna_IntConicQuad aToIntAna(aLine, aBndToQuadric);
+ IntAna_IntConicQuad aFromIntAna(aLine, aBndFromQuadric);
+ Standard_Real aToParameter = aToIntAna.ParamOnConic(1);
+ Standard_Real aFromParameter = aFromIntAna.ParamOnConic(1);
+ if(aToParameter > aFromParameter) {
+ gp_Vec aVec = aToDir->impl<gp_Dir>();
+ if((aVec * aDirVec) > 0) {
+ aToDir->setImpl(new gp_Dir(aVec.Reversed()));
+ aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
+ }
+ aVec = aFromDir->impl<gp_Dir>();
+ if((aVec * aDirVec) < 0) {
+ aFromDir->setImpl(new gp_Dir(aVec.Reversed()));
+ aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
+ }
+ } else {
+ gp_Vec aVec = aToDir->impl<gp_Dir>();
+ if((aVec * aDirVec) < 0) {
+ aToDir->setImpl(new gp_Dir(aVec.Reversed()));
+ aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
+ }
+ aVec = aFromDir->impl<gp_Dir>();
+ if((aVec * aDirVec) > 0) {
+ aFromDir->setImpl(new gp_Dir(aVec.Reversed()));
+ aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
+ }
+ }
+
+ // Making solids from bounding planes.
+ TopoDS_Shell aToShell, aFromShell;
+ TopoDS_Solid aToSolid, aFromSolid;
+ const TopoDS_Shape& aToShape = aBoundingToShape->impl<TopoDS_Shape>();
+ const TopoDS_Shape& aFromShape = aBoundingFromShape->impl<TopoDS_Shape>();
+ TopoDS_Face aToFace = TopoDS::Face(aToShape);
+ TopoDS_Face aFromFace = TopoDS::Face(aFromShape);
+ BRep_Builder aBoundingBuilder;
+ aBoundingBuilder.MakeShell(aToShell);
+ aBoundingBuilder.Add(aToShell, aToShape);
+ aBoundingBuilder.MakeShell(aFromShell);
+ aBoundingBuilder.Add(aFromShell, aFromShape);
+ aBoundingBuilder.MakeSolid(aToSolid);
+ aBoundingBuilder.Add(aToSolid, aToShell);
+ aBoundingBuilder.MakeSolid(aFromSolid);
+ aBoundingBuilder.Add(aFromSolid, aFromShell);
+
+ // Cutting with to plane.
+ BRepAlgoAPI_Cut* aToCutBuilder = new BRepAlgoAPI_Cut(aResult, aToSolid);
+ aToCutBuilder->Build();
+ if(!aToCutBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aToCutBuilder)));
+ aResult = aToCutBuilder->Shape();
+ if(aResult.ShapeType() == TopAbs_COMPOUND) {
+ aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+ }
+ if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
+ const TopTools_ListOfShape& aToShapes = aToCutBuilder->Modified(aToShape);
+ for(TopTools_ListIteratorOfListOfShape anIt(aToShapes); anIt.More(); anIt.Next()) {
+ GeomShapePtr aGeomSh(new GeomAPI_Shape());
+ aGeomSh->setImpl(new TopoDS_Shape(anIt.Value()));
+ this->addToShape(aGeomSh);
+ }
+ }
+
+ // Cutting with from plane.
+ BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aResult, aFromSolid);
+ aFromCutBuilder->Build();
+ if(!aFromCutBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aFromCutBuilder)));
+ aResult = aFromCutBuilder->Shape();
+ TopoDS_Iterator aCheckIt(aResult);
+ if(!aCheckIt.More()) {
+ return;
+ }
+ if(aResult.ShapeType() == TopAbs_COMPOUND) {
+ aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+ }
+ if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
+ const TopTools_ListOfShape& aFromShapes = aFromCutBuilder->Modified(aFromShape);
+ for(TopTools_ListIteratorOfListOfShape anIt(aFromShapes); anIt.More(); anIt.Next()) {
+ GeomShapePtr aGeomSh(new GeomAPI_Shape());
+ aGeomSh->setImpl(new TopoDS_Shape(anIt.Value()));
+ this->addFromShape(aGeomSh);
+ }
+ }
+
+ // Naming for extrusion from vertex, edge.
+ if(aShapeTypeToExp == TopAbs_COMPOUND) {
+ storeGenerationHistory(this, aResult, TopAbs_EDGE, aToFace, aFromFace);
+ storeGenerationHistory(this, aResult, TopAbs_FACE, aToFace, aFromFace);
+ } else {
+ storeGenerationHistory(this, aResult, aShapeTypeToExp, aToFace, aFromFace);
+ }
+
+ if(aResult.ShapeType() == TopAbs_COMPOUND) {
+ std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
+ aGeomShape->setImpl(new TopoDS_Shape(aResult));
+ ListOfShape aCompSolids, aFreeSolids;
+ aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
+ GeomAPI_Shape::COMPSOLID,
+ aCompSolids,
+ aFreeSolids);
+ aResult = aGeomShape->impl<TopoDS_Shape>();
+ }
+ }
+
+ // Setting result.
+ if(aResult.IsNull()) {
+ return;
+ }
+ aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+ GeomShapePtr aGeomSh(new GeomAPI_Shape());
+ aGeomSh->setImpl(new TopoDS_Shape(aResult));
+ this->setShape(aGeomSh);
+ this->setDone(true);