+ aSize = Sqrt(aSize);
+ return GeomAlgoAPI_FaceBuilder::squareFace(aPlane, 2.0 * aSize);
+}
+
+//==================================================================================================
+GeomShapePtr buildOffset(const GeomShapePtr& theShape,
+ const double theOffset,
+ const GeomDirPtr theDirection,
+ GeomAlgoAPI_MakeShapeList& theMakeShapeList)
+{
+ 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;
+}
+
+//==================================================================================================
+void collectPrismBases(const TopoDS_Shape& theBaseShape,
+ BRepPrimAPI_MakePrism& thePrismAlgo,
+ ListOfShape& theBoundaries,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
+{
+ 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())));
+ }
+}
+
+//==================================================================================================
+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)
+{
+ 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;
+}
+
+void collectModified(const GeomMakeShapePtr& theOperation,
+ const ListOfShape& theShapes,
+ std::list<ListOfShape>& theModified)
+{
+ 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);
+ }
+}
+
+GeomShapePtr collectResults(const GeomMakeShapePtr& theOperation,
+ const ListOfShape& theBoundaries,
+ const ListOfShape& theShapesToExclude,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
+{
+ 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;
+}
+
+//==================================================================================================
+void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+ const TopoDS_Shape& theBase,
+ const TopAbs_ShapeEnum theType,
+ BRepPrimAPI_MakePrism* thePrismBuilder)
+{
+ 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);
+ }
+}
+
+//==================================================================================================
+void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+ const TopoDS_Shape& theResult,
+ const TopAbs_ShapeEnum theType,
+ const TopoDS_Face& theToFace,
+ const TopoDS_Face& theFromFace)
+{
+ 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;
+ }