+ }
+ }
+
+ // 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], anExtVec);
+ 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(anExtVec * -aPrismLength);
+ BRepBuilderAPI_Transform* aTransformBuilder = new BRepBuilderAPI_Transform(aBaseShape, aTrsf);
+ if(!aTransformBuilder || !aTransformBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ new GeomAlgoAPI_MakeShape(aTransformBuilder)));
+ TopoDS_Shape aMovedBase = aTransformBuilder->Shape();
+
+ // Making prism.
+ BRepPrimAPI_MakePrism* aPrismBuilder =
+ new BRepPrimAPI_MakePrism(aMovedBase, anExtVec * 2 * aPrismLength);
+ if(!aPrismBuilder || !aPrismBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ new GeomAlgoAPI_MakeShape(aPrismBuilder)));
+ TopoDS_Shape aResult = aPrismBuilder->Shape();
+
+ BRepBndLib::Add(aResult, aBndBox);
+ aBndBox.Add(aFromPnt->impl<gp_Pnt>());
+ aBndBox.Add(aToPnt->impl<gp_Pnt>());
+ Standard_Real aBndBoxSize = aBndBox.CornerMin().Distance(aBndBox.CornerMax());
+
+ // 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, anExtVec);
+ 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 * anExtVec) > 0)
+ aToDir->setImpl(new gp_Dir(aVec.Reversed()));
+ aVec = aFromDir->impl<gp_Dir>();
+ if((aVec * anExtVec) < 0)
+ aFromDir->setImpl(new gp_Dir(aVec.Reversed()));
+ } else {
+ gp_Vec aVec = aToDir->impl<gp_Dir>();
+ if((aVec * anExtVec) < 0)
+ aToDir->setImpl(new gp_Dir(aVec.Reversed()));
+ aVec = aFromDir->impl<gp_Dir>();
+ if((aVec * anExtVec) > 0)
+ aFromDir->setImpl(new gp_Dir(aVec.Reversed()));
+ }
+
+ static const double THE_FACE_SIZE_COEFF = 10.0;
+ GeomShapePtr aBoundingFromShape =
+ GeomAlgoAPI_FaceBuilder::squareFace(aFromPnt, aFromDir, THE_FACE_SIZE_COEFF * aBndBoxSize);
+ GeomShapePtr aBoundingToShape =
+ GeomAlgoAPI_FaceBuilder::squareFace(aToPnt, aToDir, THE_FACE_SIZE_COEFF * aBndBoxSize);
+
+ // bounding planes
+ 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);
+
+ // Solid based on "To" bounding plane
+ gp_Vec aNormal = aToDir->impl<gp_Dir>();
+ BRepPrimAPI_MakePrism* aToPrismBuilder =
+ new BRepPrimAPI_MakePrism(aToShape, aNormal * (-2.0 * aBndBoxSize));
+ if (!aToPrismBuilder || !aToPrismBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ new GeomAlgoAPI_MakeShape(aToPrismBuilder)));
+ TopoDS_Shape aToSolid = aToPrismBuilder->Shape();
+
+ // 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 (theTypeToExp == GeomAPI_Shape::FACE || theTypeToExp == GeomAPI_Shape::COMPOUND) {
+ TopTools_ListOfShape aPrismShapes = aToPrismBuilder->Modified(aToShape);
+ if (aPrismShapes.IsEmpty())
+ aPrismShapes.Append(aToShape);
+ for (TopTools_ListIteratorOfListOfShape anIt1(aPrismShapes); anIt1.More(); anIt1.Next()) {
+ const TopTools_ListOfShape& aToShapes = aToCutBuilder->Modified(anIt1.Value());
+ for (TopTools_ListIteratorOfListOfShape anIt2(aToShapes); anIt2.More(); anIt2.Next()) {
+ GeomShapePtr aGeomSh = toShape(anIt2.Value());
+ fixOrientation(aGeomSh);
+ this->addToShape(aGeomSh);