+//=======================================================================
+//function : FillGroups
+//purpose : auxilary for DoGroups()
+//=======================================================================
+bool FillGroups(const TopTools_SequenceOfShape *theGroups,
+ const TopTools_IndexedMapOfShape &theIndices,
+ Handle(TColStd_HArray1OfInteger) *theGroupIds)
+{
+ Standard_Integer i;
+
+ for (i = 0; i < 5; ++i) {
+ if (!theGroups[i].IsEmpty()) {
+ const Standard_Integer aNbShapes = theGroups[i].Length();
+ Standard_Integer j;
+
+ theGroupIds[i] = new TColStd_HArray1OfInteger(1, aNbShapes);
+
+ for (j = 1; j <= aNbShapes; ++j) {
+ const TopoDS_Shape &aShape = theGroups[i].Value(j);
+ const Standard_Integer anIndex = theIndices.FindIndex(aShape);
+
+ if (anIndex == 0) {
+ return false;
+ }
+
+ theGroupIds[i]->SetValue(j, anIndex);
+ }
+ }
+ }
+
+ return true;
+}
+
+//=======================================================================
+//function : StoreGroups
+//purpose : auxilary for CreateGroups()
+//=======================================================================
+void StoreGroups(GEOMImpl_IPipe *theCI,
+ Handle(TColStd_HArray1OfInteger) *theGroups)
+{
+ if (theGroups[GROUP_DOWN].IsNull() == Standard_False) {
+ theCI->SetGroupDown(theGroups[GROUP_DOWN]);
+ }
+
+ if (theGroups[GROUP_UP].IsNull() == Standard_False) {
+ theCI->SetGroupUp(theGroups[GROUP_UP]);
+ }
+
+ if (theGroups[GROUP_SIDE1].IsNull() == Standard_False) {
+ theCI->SetGroupSide1(theGroups[GROUP_SIDE1]);
+ }
+
+ if (theGroups[GROUP_SIDE2].IsNull() == Standard_False) {
+ theCI->SetGroupSide2(theGroups[GROUP_SIDE2]);
+ }
+
+ if (theGroups[GROUP_OTHER].IsNull() == Standard_False) {
+ theCI->SetGroupOther(theGroups[GROUP_OTHER]);
+ }
+}
+
+//=======================================================================
+//function : CreateDownUpGroups
+//purpose : auxilary for DoGroups()
+//=======================================================================
+static bool CreateDownUpGroups(BRepPrimAPI_MakeSweep *theSweep,
+ TopTools_SequenceOfShape *theGroups,
+ Standard_Boolean &IsDoSides)
+{
+ const TopoDS_Shape aDownShape = theSweep->FirstShape();
+ const TopAbs_ShapeEnum aType = aDownShape.ShapeType();
+ TopAbs_ShapeEnum anUpDownType = TopAbs_SHAPE;
+
+ IsDoSides = Standard_False;
+
+ switch (aType) {
+ case TopAbs_EDGE:
+ case TopAbs_WIRE:
+ anUpDownType = TopAbs_EDGE;
+
+ if (GEOMUtils::IsOpenPath(aDownShape)) {
+ IsDoSides = Standard_True;
+ }
+ break;
+ case TopAbs_FACE:
+ case TopAbs_SHELL:
+ anUpDownType = TopAbs_FACE;
+ break;
+ default:
+ break;
+ }
+
+ if (anUpDownType == TopAbs_SHAPE) {
+ // Invalid Up and Down group type.
+ return false;
+ }
+
+ TopExp_Explorer anExp(aDownShape, anUpDownType);
+ TopTools_MapOfShape aMapFence;
+
+ // Create Down group.
+ for (; anExp.More(); anExp.Next()) {
+ const TopoDS_Shape &aShape = anExp.Current();
+
+ if (aMapFence.Add(aShape)) {
+ theGroups[GROUP_DOWN].Append(aShape);
+ }
+ }
+
+ // Create Up group
+ const TopoDS_Shape anUpShape = theSweep->LastShape();
+
+ aMapFence.Clear();
+ anExp.Init(anUpShape, anUpDownType);
+
+ for (; anExp.More(); anExp.Next()) {
+ const TopoDS_Shape &aShape = anExp.Current();
+
+ if (aMapFence.Add(aShape)) {
+ theGroups[GROUP_UP].Append(aShape);
+ }
+ }
+
+ return true;
+}
+
+//=======================================================================
+//function : DoGroups
+//purpose : auxilary for CreateGroups()
+//=======================================================================
+bool DoGroups(BRepOffsetAPI_MakePipeShell &theSweep,
+ TopTools_SequenceOfShape *theGroups)
+{
+ Standard_Boolean isDoSides = Standard_False;
+
+ if (!CreateDownUpGroups(&theSweep, theGroups, isDoSides)) {
+ // Up and Down groups creation failure
+ return false;
+ }
+
+ const TopoDS_Shape aDownShape = theSweep.FirstShape();
+
+ if (isDoSides) {
+ // Create Side1 and Side2 groups.
+ const TopAbs_ShapeEnum aType = aDownShape.ShapeType();
+ TopoDS_Vertex aV[2];
+ Standard_Integer i;
+
+ if (aType == TopAbs_EDGE) {
+ TopExp::Vertices(TopoDS::Edge(aDownShape), aV[0], aV[1], Standard_True);
+ } else { // aType == TopAbs_WIRE
+ TopExp::Vertices(TopoDS::Wire(aDownShape), aV[0], aV[1]);
+ }
+
+ for (i = 0; i < 2; ++i) {
+ if (aV[i].IsNull() == Standard_False) {
+ const TopTools_ListOfShape &aLstSide = theSweep.Generated(aV[i]);
+
+ if (!aLstSide.IsEmpty()) {
+ TopTools_ListIteratorOfListOfShape aSideIt(aLstSide);
+ TopTools_MapOfShape aMapFence;
+ const Standard_Integer anIdSide =
+ (i == 0 ? GROUP_SIDE1 : GROUP_SIDE2);
+
+ for (; aSideIt.More(); aSideIt.Next()) {
+ const TopoDS_Shape &aSideShape = aSideIt.Value();
+
+ if (aSideShape.ShapeType() == TopAbs_EDGE) {
+ if (aMapFence.Add(aSideShape)) {
+ theGroups[anIdSide].Append(aSideShape);
+ }
+ } else {
+ // Only edges can be is Side1 and Side2 groups.
+ return false;
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // Create Other group. Get boudnary edges of the profile.
+ TopTools_MapOfShape aMapBndEdges;
+ TopExp_Explorer anExp(aDownShape, TopAbs_EDGE);
+
+ for (; anExp.More(); anExp.Next()) {
+ const TopoDS_Shape &anEdge = anExp.Current();
+
+ if (!aMapBndEdges.Add(anEdge)) {
+ aMapBndEdges.Remove(anEdge);
+ }
+ }
+
+ // Fill the map of faces generated from profile's boundary edges.
+ TopTools_MapIteratorOfMapOfShape anIter(aMapBndEdges);
+ TopTools_MapOfShape aMapFence;
+
+ for (; anIter.More(); anIter.Next()) {
+ const TopTools_ListOfShape &aLstOther = theSweep.Generated(anIter.Key());
+
+ if (!aLstOther.IsEmpty()) {
+ TopTools_ListIteratorOfListOfShape anOtherIt(aLstOther);
+
+ for (; anOtherIt.More(); anOtherIt.Next()) {
+ const TopoDS_Shape &anOtherShape = anOtherIt.Value();
+
+ if (anOtherShape.ShapeType() == TopAbs_FACE) {
+ if (aMapFence.Add(anOtherShape)) {
+ theGroups[GROUP_OTHER].Append(anOtherShape);
+ }
+ } else {
+ // Only faces can be in Other group.
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+//=======================================================================
+//function : CreateGroups
+//purpose : auxilary for Execute()
+//=======================================================================
+bool CreateGroups(BRepOffsetAPI_MakePipeShell &theSweep,
+ GEOMImpl_IPipe *theCI)
+{
+ if (!theCI->GetGenerateGroups()) {
+ // Nothing to do.
+ return true;
+ }
+
+ // Make groups.
+ TopTools_SequenceOfShape aGroups[5];
+
+ if (!DoGroups(theSweep, aGroups)) {
+ return false;
+ }
+
+ // Fill the groups.
+ Handle(TColStd_HArray1OfInteger) aGroupIds[5];
+ TopTools_IndexedMapOfShape anIndices;
+ const TopoDS_Shape aResult = theSweep.Shape();
+
+ TopExp::MapShapes(aResult, anIndices);
+
+ if (!FillGroups(aGroups, anIndices, aGroupIds)) {
+ return false;
+ }
+
+ // Store groups.
+ StoreGroups(theCI, aGroupIds);
+
+ return true;
+}
+
+//=======================================================================
+//function : DoGroups
+//purpose : auxilary for CreateGroups()
+//=======================================================================
+static bool DoGroups(const TopoDS_Shape &theProfile,
+ const TopoDS_Shape &thePath,
+ BRepOffsetAPI_MakePipe &theSweep,
+ TopTools_SequenceOfShape *theGroups)
+{
+ Standard_Boolean isDoSides = Standard_False;
+
+ if (!CreateDownUpGroups(&theSweep, theGroups, isDoSides)) {
+ // Up and Down groups creation failure
+ return false;
+ }
+
+ if (isDoSides) {
+ // Create Side1 and Side2 groups.
+ const TopAbs_ShapeEnum aType = theProfile.ShapeType();
+ TopoDS_Vertex aV[2];
+ Standard_Integer i;
+
+ if (aType == TopAbs_EDGE) {
+ TopExp::Vertices(TopoDS::Edge(theProfile), aV[0], aV[1], Standard_True);
+ } else { // aType == TopAbs_WIRE
+ TopExp::Vertices(TopoDS::Wire(theProfile), aV[0], aV[1]);
+ }
+
+ for (i = 0; i < 2; ++i) {
+ if (aV[i].IsNull() == Standard_False) {
+ TopExp_Explorer anExpP(thePath, TopAbs_EDGE);
+ TopTools_MapOfShape aMapFence;
+ const Standard_Integer anIdSide =
+ (i == 0 ? GROUP_SIDE1 : GROUP_SIDE2);
+
+ for (; anExpP.More(); anExpP.Next()) {
+ const TopoDS_Shape aSideShape =
+ theSweep.Generated(anExpP.Current(), aV[i]);
+
+ if (aSideShape.ShapeType() == TopAbs_EDGE) {
+ if (aMapFence.Add(aSideShape)) {
+ theGroups[anIdSide].Append(aSideShape);
+ }
+ } else {
+ // Only edges can be is Side1 and Side2 groups.
+ return false;
+ }
+ }
+ }
+ }
+ } else {
+ // Create Other group. Get boudnary edges of the profile.
+ TopTools_MapOfShape aMapBndEdges;
+ TopExp_Explorer anExp(theProfile, TopAbs_EDGE);
+
+ for (; anExp.More(); anExp.Next()) {
+ const TopoDS_Shape &anEdge = anExp.Current();
+
+ if (!aMapBndEdges.Add(anEdge)) {
+ aMapBndEdges.Remove(anEdge);
+ }
+ }
+
+ TopExp_Explorer anExpP(thePath, TopAbs_EDGE);
+ TopTools_MapOfShape aMapFence;
+
+ for (; anExpP.More(); anExpP.Next()) {
+ TopTools_MapIteratorOfMapOfShape anIter(aMapBndEdges);
+
+ for (; anIter.More(); anIter.Next()) {
+ const TopoDS_Shape anOtherShape =
+ theSweep.Generated(anExpP.Current(), anIter.Key());
+
+ if (anOtherShape.ShapeType() == TopAbs_FACE) {
+ if (aMapFence.Add(anOtherShape)) {
+ theGroups[GROUP_OTHER].Append(anOtherShape);
+ }
+ } else {
+ // Only faces can be in Other group.
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+//=======================================================================
+//function : CreateGroups
+//purpose : auxilary for Execute()
+//=======================================================================
+static bool CreateGroups(const TopoDS_Shape &theProfile,
+ const TopoDS_Shape &thePath,
+ BRepOffsetAPI_MakePipe &theSweep,
+ GEOMImpl_IPipe *theCI)
+{
+ if (!theCI->GetGenerateGroups()) {
+ // Nothing to do.
+ return true;
+ }
+
+ // Make groups.
+ TopTools_SequenceOfShape aGroups[5];
+
+ if (!DoGroups(theProfile, thePath, theSweep, aGroups)) {
+ return false;
+ }
+
+ // Fill the groups.
+ Handle(TColStd_HArray1OfInteger) aGroupIds[5];
+ TopTools_IndexedMapOfShape anIndices;
+ const TopoDS_Shape aResult = theSweep.Shape();
+
+ TopExp::MapShapes(aResult, anIndices);
+
+ if (!FillGroups(aGroups, anIndices, aGroupIds)) {
+ return false;
+ }
+
+ // Store groups.
+ StoreGroups(theCI, aGroupIds);
+
+ return true;
+}
+