-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: GeomAlgoAPI_Prism.cpp
-// Created: 5 May 2015
-// Author: Dmitry Bobylev
-
-#include <GeomAlgoAPI_Prism.h>
-
+// Copyright (C) 2014-2022 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "GeomAlgoAPI_Prism.h"
+
+#include <GeomAPI_Ax1.h>
+#include <GeomAPI_Dir.h>
#include <GeomAPI_Face.h>
#include <GeomAPI_Pln.h>
#include <GeomAPI_Pnt.h>
#include <GeomAPI_ShapeExplorer.h>
#include <GeomAPI_XYZ.h>
+
+#include <GeomAlgoAPI_CompoundBuilder.h>
#include <GeomAlgoAPI_DFLoader.h>
#include <GeomAlgoAPI_FaceBuilder.h>
-#include <GeomAlgoAPI_MakeShapeList.h>
+#include <GeomAlgoAPI_Offset.h>
+#include <GeomAlgoAPI_Partition.h>
#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAlgoAPI_Translation.h>
#include <Bnd_Box.hxx>
#include <BRep_Builder.hxx>
-#include <BRep_Tool.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepBndLib.hxx>
-#include <BRepBuilderAPI_MakeEdge.hxx>
-#include <BRepBuilderAPI_MakeShape.hxx>
-#include <BRepBuilderAPI_MakeWire.hxx>
-#include <BRepCheck_Analyzer.hxx>
-#include <BRepExtrema_ExtCF.hxx>
-#include <BRepGProp.hxx>
-#include <BRepOffsetAPI_MakePipe.hxx>
+#include <BRepBuilderAPI_FindPlane.hxx>
+#include <BRepBuilderAPI_Transform.hxx>
#include <BRepTools.hxx>
+#include <Geom_Curve.hxx>
+#include <Geom2d_Curve.hxx>
+#include <BRepLib_CheckCurveOnSurface.hxx>
+#include <BRepPrimAPI_MakePrism.hxx>
#include <Geom_Plane.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
#include <gp_Pln.hxx>
-#include <GProp_GProps.hxx>
-#include <TCollection_AsciiString.hxx>
+#include <IntAna_IntConicQuad.hxx>
+#include <IntAna_Quadric.hxx>
+#include <IntTools_Context.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Shell.hxx>
#include <TopoDS_Solid.hxx>
-#include <TopoDS_Wire.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
-//=================================================================================================
-GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(std::shared_ptr<GeomAPI_Shape> theBasis,
- double theToSize,
- double theFromSize)
-: myDone(false)
+
+/// Expand planar face to cover the bounding box if theOriginalShape is planar.
+/// Otherwise, return the same shape;
+static GeomShapePtr buildPlanarFace(const GeomShapePtr& theOriginalShape,
+ const Bnd_Box& theBaseShapeBB);
+
+/// Build offset for the given shape.
+/// If the offset algorithm failed, translate the shape along the direction.
+static GeomShapePtr buildOffset(const GeomShapePtr& theShape,
+ const double theOffset,
+ const GeomDirPtr theDirection,
+ GeomAlgoAPI_MakeShapeList& theMakeShapeList);
+
+/// Collect base faces of the prism.
+static void collectPrismBases(const TopoDS_Shape& theBaseShape,
+ BRepPrimAPI_MakePrism& thePrismAlgo,
+ ListOfShape& theBoundaries,
+ const GeomAPI_Shape::ShapeType theTypeToExp);
+
+/// Collect all solids which contain boundaries but do not contain bases of prism.
+static GeomShapePtr collectResults(const GeomMakeShapePtr& theOperation,
+ const ListOfShape& theBoundaries,
+ const ListOfShape& theShapesToExclude,
+ const GeomAPI_Shape::ShapeType theTypeToExp);
+
+static void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+ const TopoDS_Shape& theBase,
+ const TopAbs_ShapeEnum theType,
+ BRepPrimAPI_MakePrism* thePrismBuilder);
+
+static void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+ const TopoDS_Shape& theResult,
+ const TopAbs_ShapeEnum theType,
+ const TopoDS_Face& theToFace,
+ const TopoDS_Face& theFromFace);
+
+static GeomShapePtr toShape(const TopoDS_Shape& theShape)
{
- build(theBasis, std::shared_ptr<GeomAPI_Shape>(), theToSize, std::shared_ptr<GeomAPI_Shape>(), theFromSize);
+ GeomShapePtr aShape(new GeomAPI_Shape());
+ aShape->setImpl(new TopoDS_Shape(theShape));
+ return aShape;
}
-//=================================================================================================
-GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(std::shared_ptr<GeomAPI_Shape> theBasis,
- std::shared_ptr<GeomAPI_Shape> theToShape,
- double theToSize,
- std::shared_ptr<GeomAPI_Shape> theFromShape,
- double theFromSize)
-: myDone(false)
+static void changeOrientationIfNeeded(const TopoDS_Shape& theShape, gp_Vec& theNormal)
{
- build(theBasis, theToShape, theToSize, theFromShape, theFromSize);
+ TopExp_Explorer anExp(theShape, TopAbs_VERTEX);
+ gp_Pnt aPnt0 = BRep_Tool::Pnt(TopoDS::Vertex(anExp.Current()));
+ gp_Dir aDir01;
+ for (anExp.Next(); anExp.More(); anExp.Next()) {
+ gp_Pnt aPnt1 = BRep_Tool::Pnt(TopoDS::Vertex(anExp.Current()));
+ if (aPnt1.SquareDistance(aPnt0) > Precision::SquareConfusion()) {
+ aDir01 = gp_Dir(gp_Vec(aPnt0, aPnt1));
+ break;
+ }
+ }
+ gp_Vec aNormal;
+ for (; anExp.More(); anExp.Next()) {
+ gp_Pnt aPnt2 = BRep_Tool::Pnt(TopoDS::Vertex(anExp.Current()));
+ if (aPnt2.SquareDistance(aPnt0) > Precision::SquareConfusion()) {
+ aNormal = gp_Vec(aDir01) ^ gp_Vec(aPnt0, aPnt2);
+ if (aNormal.SquareMagnitude() > Precision::SquareConfusion())
+ break;
+ }
+ }
+ if (anExp.More() && aNormal.XYZ().Dot(theNormal.XYZ()) < -Precision::Confusion()) {
+ // directions differ, reverse the normal
+ theNormal.Reverse();
+ }
}
-//=================================================================================================
-void GeomAlgoAPI_Prism::build(const std::shared_ptr<GeomAPI_Shape>& theBasis,
- const std::shared_ptr<GeomAPI_Shape>& theToShape,
- double theToSize,
- const std::shared_ptr<GeomAPI_Shape>& theFromShape,
- double theFromSize)
+//==================================================================================================
+GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr theBaseShape,
+ const GeomDirPtr theDirection,
+ const GeomShapePtr theToShape,
+ const double theToSize,
+ const GeomShapePtr theFromShape,
+ const double theFromSize)
{
- if(!theBasis ||
- (((!theFromShape && !theToShape) || (theFromShape && theToShape && theFromShape->isEqual(theToShape)))
+ if(!theBaseShape.get() ||
+ (((!theFromShape.get() && !theToShape.get()) ||
+ (theFromShape.get() && theToShape.get() && theFromShape->isEqual(theToShape)))
&& (theFromSize == -theToSize))) {
return;
}
- // If bounding faces was not set creating them.
- std::shared_ptr<GeomAPI_Face> aBaseFace;
- if(theBasis->shapeType() == GeomAPI_Shape::SHELL) {
- GeomAPI_ShapeExplorer anExp(theBasis, GeomAPI_Shape::FACE);
- if(anExp.more()) {
- std::shared_ptr<GeomAPI_Shape> aFaceOnShell = anExp.current();
- aBaseFace = std::shared_ptr<GeomAPI_Face>(new GeomAPI_Face(aFaceOnShell));
+ // Getting base shape.
+ const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
+ GeomAPI_Shape::ShapeType aShapeTypeToExp;
+ switch(aBaseShape.ShapeType()) {
+ case TopAbs_VERTEX:
+ aShapeTypeToExp = GeomAPI_Shape::VERTEX;
+ break;
+ case TopAbs_EDGE:
+ case TopAbs_WIRE:
+ aShapeTypeToExp = GeomAPI_Shape::EDGE;
+ break;
+ case TopAbs_FACE:
+ case TopAbs_SHELL:
+ aShapeTypeToExp = GeomAPI_Shape::FACE;
+ break;
+ case TopAbs_COMPOUND:
+ aShapeTypeToExp = GeomAPI_Shape::COMPOUND;
+ break;
+ default:
+ return;
+ }
+
+ // Getting direction.
+ gp_Vec aBaseVec;
+ std::shared_ptr<GeomAPI_Pnt> aBaseLoc;
+ std::shared_ptr<GeomAPI_Dir> aBaseDir;
+ BRepBuilderAPI_FindPlane aFindPlane(aBaseShape);
+ if(aFindPlane.Found() == Standard_True)
+ {
+ bool checkOrientation = false;
+ Handle(Geom_Plane) aPlane;
+ if(aBaseShape.ShapeType() == TopAbs_FACE || aBaseShape.ShapeType() == TopAbs_SHELL) {
+ TopExp_Explorer anExp(aBaseShape, TopAbs_FACE);
+ const TopoDS_Shape& aFace = anExp.Current();
+ Handle(Geom_Surface) aSurface = BRep_Tool::Surface(TopoDS::Face(aFace));
+ if(aSurface->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
+ Handle(Geom_RectangularTrimmedSurface) aTrimSurface =
+ Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
+ aSurface = aTrimSurface->BasisSurface();
+ }
+ if (aSurface->DynamicType() == STANDARD_TYPE(Geom_Plane))
+ aPlane = Handle(Geom_Plane)::DownCast(aSurface);
+ }
+
+ if (aPlane.IsNull()) {
+ aPlane = aFindPlane.Plane();
+ checkOrientation = true;
}
+ gp_Pnt aLoc = aPlane->Axis().Location();
+ aBaseVec = aPlane->Axis().Direction();
+
+ if (checkOrientation) {
+ // to stabilize the result of algorithm, if base shape is a wire, compare the orientation
+ // of calculated plane with the normal vector got iterating on vertices
+ changeOrientationIfNeeded(aBaseShape, aBaseVec);
+ }
+
+ aBaseLoc.reset(new GeomAPI_Pnt(aLoc.X(), aLoc.Y(), aLoc.Z()));
+ aBaseDir.reset(new GeomAPI_Dir(aBaseVec.X(), aBaseVec.Y(), aBaseVec.Z()));
+ }
+ else if (theDirection.get())
+ {
+ aBaseDir = theDirection;
+ aBaseVec = theDirection->impl<gp_Dir>();
+ }
+ else
+ {
+ return;
+ }
+
+ if(!aBaseLoc.get()) {
+ gp_Pnt aLoc;
+ gp_XYZ aDirXYZ = aBaseVec.XYZ();
+ Standard_Real aMinParam = Precision::Infinite();
+ for(TopExp_Explorer anExp(aBaseShape, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
+ const TopoDS_Shape& aVertex = anExp.Current();
+ gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex));
+ double aParam = aDirXYZ.Dot(aPnt.XYZ());
+ if(aParam < aMinParam) {
+ aMinParam = aParam;
+ aLoc = aPnt;
+ }
+ }
+ aBaseLoc.reset(new GeomAPI_Pnt(aLoc.X(), aLoc.Y(), aLoc.Z()));
+ }
+
+ gp_Vec anExtVec;
+ std::shared_ptr<GeomAPI_Dir> anExtDir;
+ if (theDirection.get())
+ {
+ anExtDir = theDirection;
+ anExtVec = theDirection->impl<gp_Dir>();
+ }
+ else
+ {
+ anExtDir = aBaseDir;
+ anExtVec = aBaseDir->impl<gp_Dir>();
+ }
+
+
+ TopoDS_Shape aResult;
+ const bool isBoundingShapesSet = theFromShape.get() || theToShape.get();
+ if(!isBoundingShapesSet) {
+ buildBySizes(theBaseShape, anExtDir, theToSize, theFromSize, aShapeTypeToExp);
} else {
- aBaseFace = std::shared_ptr<GeomAPI_Face>(new GeomAPI_Face(theBasis));
+ GeomShapePtr aBasePlane = GeomAlgoAPI_FaceBuilder::squareFace(aBaseLoc, aBaseDir, 100.0);
+
+ GeomShapePtr aBoundingFromShape = theFromShape ? theFromShape : aBasePlane;
+ GeomShapePtr aBoundingToShape = theToShape ? theToShape : aBasePlane;
+
+ bool isFromShapePlanar = aBoundingFromShape->isPlanar();
+ bool isToShapePlanar = aBoundingToShape->isPlanar();
+
+ // Set signs of offsets if both bounding shapes are planar
+ if (isFromShapePlanar && isToShapePlanar) {
+ std::shared_ptr<GeomAPI_Pln> aFromPln = GeomAPI_Face(aBoundingFromShape).getPlane();
+ std::shared_ptr<GeomAPI_Pln> aToPln = GeomAPI_Face(aBoundingToShape).getPlane();
+ buildByPlanes(theBaseShape, anExtDir,
+ aToPln, theToSize,
+ aFromPln, theFromSize,
+ aShapeTypeToExp);
+ }
+ else {
+ buildByFaces(theBaseShape, anExtDir,
+ aBoundingToShape, theToSize, isToShapePlanar,
+ aBoundingFromShape, theFromSize, isFromShapePlanar,
+ aShapeTypeToExp);
+ }
+ }
+}
+
+//==================================================================================================
+void GeomAlgoAPI_Prism::buildBySizes(const GeomShapePtr theBaseShape,
+ const GeomDirPtr theDirection,
+ const double theToSize,
+ const double theFromSize,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
+{
+ const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
+ gp_Vec anExtVec = theDirection->impl<gp_Dir>();
+
+ // Moving base shape.
+ gp_Trsf aTrsf;
+ aTrsf.SetTranslation(anExtVec * -theFromSize);
+ BRepBuilderAPI_Transform* aTransformBuilder =
+ new BRepBuilderAPI_Transform(aBaseShape, aTrsf);
+ if (!aTransformBuilder || !aTransformBuilder->IsDone()) {
+ return;
}
- if(!aBaseFace.get()) {
+ 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 * (theFromSize + theToSize));
+ if (!aPrismBuilder || !aPrismBuilder->IsDone()) {
return;
}
- std::shared_ptr<GeomAPI_Pln> aBasePln = aBaseFace->getPlane();
- std::shared_ptr<GeomAPI_Dir> aBaseDir = aBasePln->direction();
- std::shared_ptr<GeomAPI_Pnt> aBaseLoc = aBasePln->location();
- std::shared_ptr<GeomAPI_Shape> aBasePlane = GeomAlgoAPI_FaceBuilder::planarFace(aBaseLoc, aBaseDir);
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ new GeomAlgoAPI_MakeShape(aPrismBuilder)));
+ TopoDS_Shape aResult = aPrismBuilder->Shape();
+
+ // Setting naming.
+ if(theTypeToExp == GeomAPI_Shape::COMPOUND) {
+ storeGenerationHistory(this, aMovedBase, TopAbs_EDGE, aPrismBuilder);
+ storeGenerationHistory(this, aMovedBase, TopAbs_FACE, aPrismBuilder);
+ } else {
+ storeGenerationHistory(this, aMovedBase, (TopAbs_ShapeEnum)theTypeToExp, aPrismBuilder);
+ }
- std::shared_ptr<GeomAPI_Shape> aBoundingFromShape = theFromShape ? theFromShape : aBasePlane;
- std::shared_ptr<GeomAPI_Shape> aBoundingToShape = theToShape ? theToShape : aBasePlane;
+ // Setting result.
+ if (!aResult.IsNull()) {
+ aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+ this->setShape(toShape(aResult));
+ this->setDone(true);
+ }
+}
+
+//==================================================================================================
+void GeomAlgoAPI_Prism::buildByPlanes(const GeomShapePtr theBaseShape,
+ const GeomDirPtr theDirection,
+ const GeomPlanePtr theToPlane,
+ const double theToSize,
+ const GeomPlanePtr theFromPlane,
+ const double theFromSize,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
+{
+ const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
+ gp_Vec anExtVec = theDirection->impl<gp_Dir>();
- // Moving bounding faces according to "from" and "to" sizes.
- std::shared_ptr<GeomAPI_Face> aFromFace(new GeomAPI_Face(aBoundingFromShape));
- std::shared_ptr<GeomAPI_Pln> aFromPln = aFromFace->getPlane();
- std::shared_ptr<GeomAPI_Pnt> aFromLoc = aFromPln->location();
- std::shared_ptr<GeomAPI_Dir> aFromDir = aFromPln->direction();
+ // Moving prism bounding faces according to "from" and "to" sizes.
+ std::shared_ptr<GeomAPI_Pnt> aFromLoc = theFromPlane->location();
+ std::shared_ptr<GeomAPI_Dir> aFromDir = theFromPlane->direction();
- std::shared_ptr<GeomAPI_Face> aToFace(new GeomAPI_Face(aBoundingToShape));
- std::shared_ptr<GeomAPI_Pln> aToPln = aToFace->getPlane();
- std::shared_ptr<GeomAPI_Pnt> aToLoc = aToPln->location();
- std::shared_ptr<GeomAPI_Dir> aToDir = aToPln->direction();
+ std::shared_ptr<GeomAPI_Pnt> aToLoc = theToPlane->location();
+ std::shared_ptr<GeomAPI_Dir> aToDir = theToPlane->direction();
- bool aSign = aFromLoc->xyz()->dot(aBaseDir->xyz()) > aToLoc->xyz()->dot(aBaseDir->xyz());
+ std::shared_ptr<GeomAPI_XYZ> anExtDir = theDirection->xyz();
+ bool aSign = aFromLoc->xyz()->dot(anExtDir) > aToLoc->xyz()->dot(anExtDir);
- 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> aFromPnt(
+ new GeomAPI_Pnt(aFromLoc->xyz()->added(anExtDir->multiplied(
+ aSign ? theFromSize : -theFromSize))));
- std::shared_ptr<GeomAPI_Pnt> aToPnt(new GeomAPI_Pnt(aToLoc->xyz()->added(aBaseDir->xyz()->multiplied(
- aSign ? -theToSize : theToSize))));
- aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
+ std::shared_ptr<GeomAPI_Pnt> aToPnt(
+ new GeomAPI_Pnt(aToLoc->xyz()->added(anExtDir->multiplied(
+ aSign ? -theToSize : theToSize))));
// Getting bounding box for base shape.
- const TopoDS_Shape& aBasisShape = theBasis->impl<TopoDS_Shape>();
Bnd_Box aBndBox;
- BRepBndLib::Add(aBasisShape, 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()};
}
// Project points to bounding planes. Search max distance to them.
- const TopoDS_Shape& aBndToShape = aBoundingToShape->impl<TopoDS_Shape>();
- const TopoDS_Shape& aBndFromShape = aBoundingFromShape->impl<TopoDS_Shape>();
+ 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;
- gp_Vec aNormal(aBaseDir->impl<gp_Dir>());
for(int i = 0; i < 8; i++) {
- gp_Lin aLine(aPoints[i], aNormal);
- TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(aLine).Edge();
- BRepExtrema_ExtCF aToExt(anEdge, TopoDS::Face(aBndToShape));
- BRepExtrema_ExtCF aFromExt(anEdge, TopoDS::Face(aBndFromShape));
- if(aToExt.NbExt() == 0 || aFromExt.NbExt() == 0) {
+ 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 = aToExt.PointOnFace(1);
- const gp_Pnt& aPntOnFromFace = aFromExt.PointOnFace(1);
+ 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);
}
aMaxFromDist = aPoints[i].Distance(aPntOnFromFace);
}
}
- Standard_Real aPipeLength = aMaxToDist + aMaxFromDist;
-
- // Making wire for pipe.
- std::shared_ptr<GeomAPI_Pnt> aCentreOfMass = GeomAlgoAPI_ShapeTools::centreOfMass(theBasis);
- const gp_Pnt aCentrePnt = aCentreOfMass->impl<gp_Pnt>();
- TopoDS_Face aFace = TopoDS::Face(aBaseFace->impl<TopoDS_Shape>());
- gp_Pnt aPipeStartPnt = aCentrePnt.Translated(aNormal.Scaled(aPipeLength));
- gp_Pnt aPipeEndPnt = aCentrePnt.Translated(aNormal.Scaled(-aPipeLength));
- TopoDS_Edge aPipeEdge = BRepBuilderAPI_MakeEdge(aPipeStartPnt, aPipeEndPnt);
- TopoDS_Wire aPipeWire = BRepBuilderAPI_MakeWire(aPipeEdge).Wire();
-
- // Making pipe.
- ListOfMakeShape aListOfMakeShape;
- BRepOffsetAPI_MakePipe* aPipeBuilder = new BRepOffsetAPI_MakePipe(aPipeWire, aBasisShape);
- if(!aPipeBuilder) {
+
+ // 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;
}
- std::shared_ptr<GeomAPI_Shape> aWire(new GeomAPI_Shape);
- aWire->setImpl(new TopoDS_Shape(aPipeWire));
- aListOfMakeShape.push_back(std::make_shared<GeomAlgoAPI_MakeShape>(aPipeBuilder, aWire));
- TopoDS_Shape aResult = aPipeBuilder->Shape();
+ 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.
- gp_Lin aLine(aCentrePnt, aNormal);
- TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(aLine).Edge();
- BRepExtrema_ExtCF aToExt(anEdge, TopoDS::Face(aBndToShape));
- BRepExtrema_ExtCF aFromExt(anEdge, TopoDS::Face(aBndFromShape));
- Standard_Real aToParameter = aToExt.ParameterOnEdge(1);
- Standard_Real aFromParameter = aFromExt.ParameterOnEdge(1);
+ 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 * aNormal) > 0) {
+ if((aVec * anExtVec) > 0)
aToDir->setImpl(new gp_Dir(aVec.Reversed()));
- aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
- }
aVec = aFromDir->impl<gp_Dir>();
- if((aVec * aNormal) < 0) {
+ if((aVec * anExtVec) < 0)
aFromDir->setImpl(new gp_Dir(aVec.Reversed()));
- aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
- }
} else {
gp_Vec aVec = aToDir->impl<gp_Dir>();
- if((aVec * aNormal) < 0) {
+ if((aVec * anExtVec) < 0)
aToDir->setImpl(new gp_Dir(aVec.Reversed()));
- aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
- }
aVec = aFromDir->impl<gp_Dir>();
- if((aVec * aNormal) > 0) {
+ if((aVec * anExtVec) > 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;
+ 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>();
- BRep_Builder aBoundingBuilder;
- aBoundingBuilder.MakeShell(aToShell);
- aBoundingBuilder.MakeShell(aFromShell);
- aBoundingBuilder.Add(aToShell, aToShape);
- aBoundingBuilder.Add(aFromShell, aFromShape);
- aBoundingBuilder.MakeSolid(aToSolid);
- aBoundingBuilder.MakeSolid(aFromSolid);
- aBoundingBuilder.Add(aToSolid, aToShell);
- aBoundingBuilder.Add(aFromSolid, aFromShell);
+ 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);
if(!aToCutBuilder->IsDone()) {
return;
}
- aListOfMakeShape.push_back(std::make_shared<GeomAlgoAPI_MakeShape>(aToCutBuilder));
- const TopTools_ListOfShape& aToShapes = aToCutBuilder->Modified(aToShape);
- for(TopTools_ListIteratorOfListOfShape anIt(aToShapes); anIt.More(); anIt.Next()) {
- std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
- aShape->setImpl(new TopoDS_Shape(anIt.Value()));
- myToFaces.push_back(aShape);
- }
+ 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);
+ }
+ }
+ }
+
+ // Solid based on "From" bounding plane
+ aNormal = aFromDir->impl<gp_Dir>();
+ BRepPrimAPI_MakePrism* aFromPrismBuilder =
+ new BRepPrimAPI_MakePrism(aFromShape, aNormal * (-2.0 * aBndBoxSize));
+ if (!aFromPrismBuilder || !aFromPrismBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ new GeomAlgoAPI_MakeShape(aFromPrismBuilder)));
+ TopoDS_Shape aFromSolid = aFromPrismBuilder->Shape();
// Cutting with from plane.
BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aResult, aFromSolid);
if(!aFromCutBuilder->IsDone()) {
return;
}
- aListOfMakeShape.push_back(std::make_shared<GeomAlgoAPI_MakeShape>(aFromCutBuilder));
- const TopTools_ListOfShape& aFromShapes = aFromCutBuilder->Modified(aFromShape);
- for(TopTools_ListIteratorOfListOfShape anIt(aFromShapes); anIt.More(); anIt.Next()) {
- std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
- aShape->setImpl(new TopoDS_Shape(anIt.Value()));
- myFromFaces.push_back(aShape);
- }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ new GeomAlgoAPI_MakeShape(aFromCutBuilder)));
aResult = aFromCutBuilder->Shape();
-
- TopExp_Explorer anExp(aResult, TopAbs_SOLID);
- if(!anExp.More()) {
+ TopoDS_Iterator aCheckIt(aResult);
+ if(!aCheckIt.More()) {
return;
}
if(aResult.ShapeType() == TopAbs_COMPOUND) {
aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
}
+ if (theTypeToExp == GeomAPI_Shape::FACE || theTypeToExp == GeomAPI_Shape::COMPOUND) {
+ TopTools_ListOfShape aPrismShapes = aFromPrismBuilder->Modified(aFromShape);
+ if (aPrismShapes.IsEmpty())
+ aPrismShapes.Append(aFromShape);
+ for (TopTools_ListIteratorOfListOfShape anIt1(aPrismShapes); anIt1.More(); anIt1.Next()) {
+ const TopTools_ListOfShape& aFromShapes = aFromCutBuilder->Modified(anIt1.Value());
+ for (TopTools_ListIteratorOfListOfShape anIt2(aFromShapes); anIt2.More(); anIt2.Next()) {
+ GeomShapePtr aGeomSh = toShape(anIt2.Value());
+ fixOrientation(aGeomSh);
+ this->addFromShape(aGeomSh);
+ }
+ }
+ }
+
+ // Naming for extrusion from vertex, edge.
+ if(theTypeToExp == GeomAPI_Shape::COMPOUND) {
+ storeGenerationHistory(this, aResult, TopAbs_EDGE, aToFace, aFromFace);
+ storeGenerationHistory(this, aResult, TopAbs_FACE, aToFace, aFromFace);
+ } else {
+ storeGenerationHistory(this, aResult, (TopAbs_ShapeEnum)theTypeToExp, aToFace, aFromFace);
+ }
+
+ if(aResult.ShapeType() == TopAbs_COMPOUND) {
+ GeomShapePtr aGeomShape = toShape(aResult);
+ ListOfShape aResults;
+ aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
+ GeomAPI_Shape::COMPSOLID,
+ aResults);
+ aResult = aGeomShape->impl<TopoDS_Shape>();
+ }
+
+ // Setting result.
+ if (!aResult.IsNull()) {
+ aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+ this->setShape(toShape(aResult));
+ this->setDone(true);
+ }
+}
+
+//==================================================================================================
+void GeomAlgoAPI_Prism::buildByFaces(const GeomShapePtr theBaseShape,
+ const GeomDirPtr theDirection,
+ const GeomShapePtr theToShape,
+ const double theToSize,
+ const bool theToIsPlanar,
+ const GeomShapePtr theFromShape,
+ const double theFromSize,
+ const bool theFromIsPlanar,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
+{
+ const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
+ gp_Vec anExtVec = theDirection->impl<gp_Dir>();
+
+ // Moving prism bounding faces according to "from" and "to" sizes.
+ GeomShapePtr aBoundingFromShape = buildOffset(theFromShape, -theFromSize, theDirection, *this);
+ GeomShapePtr aBoundingToShape = buildOffset(theToShape, theToSize, theDirection, *this);
+
+ // Bounding box for shapes used in prism building.
+ Bnd_Box aBndBox;
+ BRepBndLib::Add(aBaseShape, aBndBox);
+ BRepBndLib::Add(aBoundingFromShape->impl<TopoDS_Shape>(), aBndBox);
+ BRepBndLib::Add(aBoundingToShape->impl<TopoDS_Shape>(), aBndBox);
+ double aPrismLength = 2.0 * aBndBox.CornerMin().Distance(aBndBox.CornerMax());
+
+ // Prism building.
+ 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)));
+
+ GeomShapePtr aResult = toShape(aPrismBuilder->Shape());
+
+ // Prism generatrix
+ ListOfShape aPrismBaseFaces;
+ collectPrismBases(aMovedBase, *aPrismBuilder, aPrismBaseFaces, theTypeToExp);
+
+ // Build planar faces intersecting the prism fully.
+ BRepBndLib::Add(aResult->impl<TopoDS_Shape>(), aBndBox);
+ aBoundingFromShape = buildPlanarFace(aBoundingFromShape, aBndBox);
+ aBoundingToShape = buildPlanarFace(aBoundingToShape, aBndBox);
+
+ // Perform partition.
+ ListOfShape anObjects, aTools;
+ anObjects.push_back(aResult);
+ aTools.push_back(aBoundingFromShape);
+ aTools.push_back(aBoundingToShape);
+
+ GeomMakeShapePtr aPartition(new GeomAlgoAPI_Partition(anObjects, aTools));
+ if (!aPartition->isDone())
+ return;
+
+ this->appendAlgo(aPartition);
+
+ // Collect pieces of boundary shapes, split by Partition.
+ if (theFromIsPlanar) {
+ ListOfShape anImagesFrom;
+ aPartition->modified(aBoundingFromShape, anImagesFrom);
+ for (ListOfShape::iterator anIt = anImagesFrom.begin(); anIt != anImagesFrom.end(); ++anIt)
+ addFromShape(*anIt);
+ }
- myShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
- myShape->setImpl(new TopoDS_Shape(aResult));
+ if (theToIsPlanar) {
+ ListOfShape anImagesTo;
+ aPartition->modified(aBoundingToShape, anImagesTo);
+ for (ListOfShape::iterator anIt = anImagesTo.begin(); anIt != anImagesTo.end(); ++anIt)
+ addToShape(*anIt);
+ }
- // Fill data map to keep correct orientation of sub-shapes.
- myMap = std::shared_ptr<GeomAPI_DataMapOfShapeShape>(new GeomAPI_DataMapOfShapeShape);
- for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) {
- std::shared_ptr<GeomAPI_Shape> aCurrentShape(new GeomAPI_Shape());
- aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current()));
- myMap->bind(aCurrentShape, aCurrentShape);
+ // Collect results which have both boundaries, selected for extrusion,
+ // but which do not contain top and bottom faces of the prism
+ // (these faces are treated as infinitely distant).
+ aResult = collectResults(aPartition, aTools, aPrismBaseFaces, theTypeToExp);
+ if (aResult && aResult->shapeType() == GeomAPI_Shape::COMPOUND) {
+ ListOfShape aResults;
+ aResult = GeomAlgoAPI_ShapeTools::combineShapes(aResult,
+ theTypeToExp == GeomAPI_Shape::EDGE ? GeomAPI_Shape::SHELL : GeomAPI_Shape::COMPSOLID,
+ aResults);
+
+ if (aResults.size() > 1 &&
+ (GeomAlgoAPI_ShapeTools::hasSharedTopology(aResults, GeomAPI_Shape::EDGE) ||
+ GeomAlgoAPI_ShapeTools::hasSharedTopology(aResults, GeomAPI_Shape::VERTEX))) {
+ // results shuold not have shared topology
+ aResult = GeomShapePtr();
+ }
}
- myMkShape = std::shared_ptr<GeomAlgoAPI_MakeShapeList>(new GeomAlgoAPI_MakeShapeList(aListOfMakeShape));
- myDone = true;
+ if (aResult) {
+ this->setShape(aResult);
+ this->setDone(true);
+ }
}
-//=================================================================================================
-bool GeomAlgoAPI_Prism::isDone() const
+
+// Auxilary functions:
+//==================================================================================================
+GeomShapePtr buildPlanarFace(const GeomShapePtr& theOriginalShape,
+ const Bnd_Box& theBaseShapeBB)
{
- return myDone;
+ GeomPlanePtr aPlane = GeomAPI_Face(theOriginalShape).getPlane();
+ if (!aPlane)
+ return theOriginalShape;
+
+ gp_Pnt aCornerMin = theBaseShapeBB.CornerMin();
+ gp_Pnt aCornerMax = theBaseShapeBB.CornerMax();
+ double aSize = aCornerMin.SquareDistance(aCornerMax);
+
+ gp_Pnt aLocation = aPlane->location()->impl<gp_Pnt>();
+
+ gp_Pnt aCurPnt;
+ for (int x = 0; x < 2; ++x) {
+ aCurPnt.SetX(x == 0 ? aCornerMin.X() : aCornerMax.X());
+ for (int y = 0; y < 2; ++y) {
+ aCurPnt.SetY(y == 0 ? aCornerMin.Y() : aCornerMax.Y());
+ for (int z = 0; z < 2; ++z) {
+ aCurPnt.SetZ(z == 0 ? aCornerMin.Z() : aCornerMax.Z());
+ double aDist = aCurPnt.SquareDistance(aLocation);
+ if (aDist > aSize)
+ aSize = aDist;
+ }
+ }
+ }
+
+ aSize = Sqrt(aSize);
+ return GeomAlgoAPI_FaceBuilder::squareFace(aPlane, 2.0 * aSize);
}
-//=================================================================================================
-bool GeomAlgoAPI_Prism::isValid() const
+//==================================================================================================
+GeomShapePtr buildOffset(const GeomShapePtr& theShape,
+ const double theOffset,
+ const GeomDirPtr theDirection,
+ GeomAlgoAPI_MakeShapeList& theMakeShapeList)
{
- BRepCheck_Analyzer aChecker(myShape->impl<TopoDS_Shape>());
- return (aChecker.IsValid() == Standard_True);
+ if (Abs(theOffset) < Precision::Confusion())
+ return theShape; // no need zero offset
+
+ GeomMakeShapePtr anAlgo(new GeomAlgoAPI_Offset(theShape, theOffset));
+ if (!anAlgo->isDone()) {
+ // offset not done, perform translation
+ std::shared_ptr<GeomAPI_Ax1> anAxis(new GeomAPI_Ax1());
+ anAxis->setDir(theDirection);
+ anAlgo.reset(new GeomAlgoAPI_Translation(theShape, anAxis, theOffset));
+ }
+
+ GeomShapePtr aResult = theShape;
+ if (anAlgo->isDone()) {
+ theMakeShapeList.appendAlgo(anAlgo);
+ aResult = anAlgo->shape();
+ }
+ return aResult;
}
-//=================================================================================================
-bool GeomAlgoAPI_Prism::hasVolume() const
+//==================================================================================================
+void collectPrismBases(const TopoDS_Shape& theBaseShape,
+ BRepPrimAPI_MakePrism& thePrismAlgo,
+ ListOfShape& theBoundaries,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
{
- bool hasVolume(false);
- if(isValid()) {
- const TopoDS_Shape& aRShape = myShape->impl<TopoDS_Shape>();
- GProp_GProps aGProp;
- BRepGProp::VolumeProperties(aRShape, aGProp);
- if(aGProp.Mass() > Precision::Confusion())
- hasVolume = true;
- }
- return hasVolume;
+ for (TopExp_Explorer anExp(theBaseShape, (TopAbs_ShapeEnum)theTypeToExp);
+ anExp.More(); anExp.Next()) {
+ theBoundaries.push_back(toShape(thePrismAlgo.FirstShape(anExp.Current())));
+ theBoundaries.push_back(toShape(thePrismAlgo.LastShape(anExp.Current())));
+ }
}
-//=================================================================================================
-std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_Prism::shape() const
+//==================================================================================================
+typedef std::set<GeomShapePtr, GeomAPI_Shape::Comparator> SetOfShape;
+
+bool isShapeApplicable(const GeomShapePtr& theSolid,
+ const std::list<ListOfShape>& theShapesToExist,
+ const SetOfShape& theShapesToExclude,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
{
- return myShape;
+ SetOfShape aFaces;
+ for (GeomAPI_ShapeExplorer aFExp(theSolid, theTypeToExp);
+ aFExp.more(); aFExp.next()) {
+ GeomShapePtr aCurrent = aFExp.current();
+ if (theShapesToExclude.find(aCurrent) != theShapesToExclude.end())
+ return false;
+ aFaces.insert(aCurrent);
+ }
+
+ // check all faces are in solid
+ bool isApplicable = true;
+ for (std::list<ListOfShape>::const_iterator it1 = theShapesToExist.begin();
+ it1 != theShapesToExist.end() && isApplicable; ++it1) {
+ ListOfShape::const_iterator it2 = it1->begin();
+ for (; it2 != it1->end(); ++it2)
+ if (aFaces.find(*it2) != aFaces.end())
+ break;
+ isApplicable = it2 != it1->end();
+ }
+ return isApplicable;
}
-//=================================================================================================
-const ListOfShape& GeomAlgoAPI_Prism::fromFaces() const
+void collectModified(const GeomMakeShapePtr& theOperation,
+ const ListOfShape& theShapes,
+ std::list<ListOfShape>& theModified)
{
- return myFromFaces;
+ for (ListOfShape::const_iterator anIt = theShapes.begin();
+ anIt != theShapes.end(); ++anIt) {
+ theModified.push_back(ListOfShape());
+ theOperation->modified(*anIt, theModified.back());
+ theOperation->generated(*anIt, theModified.back());
+ theModified.back().push_back(*anIt);
+ }
}
-//=================================================================================================
-const ListOfShape& GeomAlgoAPI_Prism::toFaces() const
+GeomShapePtr collectResults(const GeomMakeShapePtr& theOperation,
+ const ListOfShape& theBoundaries,
+ const ListOfShape& theShapesToExclude,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
{
- return myToFaces;
+ ListOfShape aResults;
+
+ // collect modified shapes
+ std::list<ListOfShape> aModifiedBoundaries;
+ collectModified(theOperation, theBoundaries, aModifiedBoundaries);
+
+ std::list<ListOfShape> aModifiedExclude;
+ collectModified(theOperation, theShapesToExclude, aModifiedExclude);
+ SetOfShape aTabooShapes;
+ for (std::list<ListOfShape>::iterator anIt = aModifiedExclude.begin();
+ anIt != aModifiedExclude.end(); ++anIt)
+ aTabooShapes.insert(anIt->begin(), anIt->end());
+
+ // type of sub-shapes to explode
+ GeomAPI_Shape::ShapeType aSubshapeType;
+ switch (theTypeToExp) {
+ case GeomAPI_Shape::VERTEX:
+ aSubshapeType = GeomAPI_Shape::EDGE;
+ break;
+ case GeomAPI_Shape::EDGE:
+ aSubshapeType = GeomAPI_Shape::FACE;
+ break;
+ case GeomAPI_Shape::FACE:
+ aSubshapeType = GeomAPI_Shape::SOLID;
+ break;
+ default:
+ aSubshapeType = GeomAPI_Shape::COMPOUND;
+ }
+
+ // search applicable solids
+ GeomShapePtr anOperationResult = theOperation->shape();
+ for (GeomAPI_ShapeExplorer anExp(anOperationResult, aSubshapeType);
+ anExp.more(); anExp.next()) {
+ if (isShapeApplicable(anExp.current(), aModifiedBoundaries, aTabooShapes, theTypeToExp))
+ aResults.push_back(anExp.current());
+ }
+
+ GeomShapePtr aResult;
+ if (aResults.size() == 1)
+ aResult = aResults.front();
+ else if (!aResults.empty())
+ aResult = GeomAlgoAPI_CompoundBuilder::compound(aResults);
+ return aResult;
}
-//=================================================================================================
-std::shared_ptr<GeomAPI_DataMapOfShapeShape> GeomAlgoAPI_Prism::mapOfShapes() const
+//==================================================================================================
+void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+ const TopoDS_Shape& theBase,
+ const TopAbs_ShapeEnum theType,
+ BRepPrimAPI_MakePrism* thePrismBuilder)
{
- return myMap;
+ for(TopExp_Explorer anExp(theBase, theType); anExp.More(); anExp.Next()) {
+ const TopoDS_Shape& aShape = anExp.Current();
+ GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
+ aFromShape->setImpl(new TopoDS_Shape(thePrismBuilder->FirstShape(aShape)));
+ aToShape->setImpl(new TopoDS_Shape(thePrismBuilder->LastShape(aShape)));
+ thePrismAlgo->fixOrientation(aFromShape);
+ thePrismAlgo->fixOrientation(aToShape);
+ thePrismAlgo->addFromShape(aFromShape);
+ thePrismAlgo->addToShape(aToShape);
+ }
}
-//=================================================================================================
-std::shared_ptr<GeomAlgoAPI_MakeShape> GeomAlgoAPI_Prism::makeShape() const
+//==================================================================================================
+void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+ const TopoDS_Shape& theResult,
+ const TopAbs_ShapeEnum theType,
+ const TopoDS_Face& theToFace,
+ const TopoDS_Face& theFromFace)
{
- return myMkShape;
+ for(TopExp_Explorer anExp(theResult, theType); anExp.More(); anExp.Next()) {
+ const TopoDS_Shape& aShape = anExp.Current();
+ GeomShapePtr aGeomSh(new GeomAPI_Shape());
+ if(theType == TopAbs_VERTEX) {
+ gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
+ IntTools_Context anIntTools;
+ if(anIntTools.IsValidPointForFace(aPnt,
+ theToFace, Precision::Confusion()) == Standard_True) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ thePrismAlgo->fixOrientation(aGeomSh);
+ thePrismAlgo->addToShape(aGeomSh);
+ }
+ if(anIntTools.IsValidPointForFace(aPnt,
+ theFromFace, Precision::Confusion()) == Standard_True) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ thePrismAlgo->fixOrientation(aGeomSh);
+ thePrismAlgo->addFromShape(aGeomSh);
+ }
+ } else if(theType == TopAbs_EDGE) {
+ TopoDS_Edge anEdge = TopoDS::Edge(aShape);
+ BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, theToFace);
+ anEdgeCheck.Perform();
+ if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ thePrismAlgo->fixOrientation(aGeomSh);
+ thePrismAlgo->addToShape(aGeomSh);
+ }
+ anEdgeCheck.Init(anEdge, theFromFace);
+ anEdgeCheck.Perform();
+ if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ thePrismAlgo->fixOrientation(aGeomSh);
+ thePrismAlgo->addFromShape(aGeomSh);
+ }
+ } else {
+ break;
+ }
+ }
}