Salome HOME
Update the names of Regions and Zones if case name changed (Bug #110).
[modules/hydro.git] / src / HYDROData / HYDROData_SplitToZonesTool.cxx
1
2 #include "HYDROData_SplitToZonesTool.h"
3
4 #include "HYDROData_Polyline.h"
5
6 #include <BRepAlgoAPI_Common.hxx>
7 #include <BRepAlgoAPI_Cut.hxx>
8 #include <BRepBuilderAPI_MakeFace.hxx>
9
10 #include <TopExp_Explorer.hxx>
11 #include <TopoDS.hxx>
12 #include <TopoDS_Iterator.hxx>
13 #include <TopoDS_Wire.hxx>
14
15 TopoDS_Face HYDROData_SplitToZonesTool::SplitData::Face() const
16 {
17   TopoDS_Face aResFace;
18
19   if( !Shape.IsNull() )
20   {
21     if ( Shape.ShapeType() == TopAbs_FACE )
22     {
23       aResFace = TopoDS::Face( Shape );
24     }
25     else if ( Shape.ShapeType() == TopAbs_WIRE )
26     {
27       BRepBuilderAPI_MakeFace aMakeFace( TopoDS::Wire( Shape ), Standard_True );
28       aMakeFace.Build();
29       if( aMakeFace.IsDone() )
30         aResFace = aMakeFace.Face();
31     }
32   }
33
34   return aResFace;
35 }
36
37 HYDROData_SplitToZonesTool::SplitDataList
38 HYDROData_SplitToZonesTool::SplitToZones( const HYDROData_SequenceOfObjects& theObjectList,
39                                           const Handle(HYDROData_Polyline)&  thePolyline )
40 {
41   SplitDataList anOutputSplitDataList;
42
43   // Preparation. Collect the object shapes to split.
44   SplitDataList anInputSplitDataList;
45   for( int anIndex = 1, aLength = theObjectList.Length(); anIndex <= aLength; anIndex++ )
46   {
47     Handle(HYDROData_Object) aGeomObj = 
48       Handle(HYDROData_Object)::DownCast( theObjectList.Value( anIndex ) );
49     if( !aGeomObj.IsNull() )
50     {
51       SplitData aSplitData( aGeomObj->GetTopShape(), aGeomObj->GetName() );
52       anInputSplitDataList.append( aSplitData );
53     }
54   }
55
56   // Step 1. Split the paths.
57   SplitDataListIterator anInputIter( anInputSplitDataList );
58   while( anInputIter.hasNext() )
59   {
60     const SplitData& anInputSplitData = anInputIter.next();
61     if( anOutputSplitDataList.isEmpty() )
62       anOutputSplitDataList.append( anInputSplitData );
63     else
64     {
65       SplitDataList aSplitDataList;
66
67       SplitDataList aSrcSplitDataList;
68       aSrcSplitDataList.append( anInputSplitData );
69
70       SplitDataList aDestSplitDataList = anOutputSplitDataList;
71       anOutputSplitDataList.clear();
72
73       while( !aDestSplitDataList.isEmpty() )
74       {
75         SplitData aSrcSplitData = aSrcSplitDataList.last();
76
77         SplitData aDestSplitData = aDestSplitDataList.first();
78         aDestSplitDataList.pop_front();
79
80         SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
81         if( SplitTwoData( aSrcSplitData, aDestSplitData,
82                           aData1Subtracted, aData2Subtracted, aDataIntersected ) )
83           anOutputSplitDataList.append( aDataIntersected );
84         anOutputSplitDataList.append( aData2Subtracted );
85         aSrcSplitDataList.append( aData1Subtracted );
86       }
87
88       if( !aSrcSplitDataList.isEmpty() )
89         anOutputSplitDataList.append( aSrcSplitDataList.last() );
90     }
91   }
92
93   // Step 2. Take into account the boundary polyline.
94   if( !thePolyline.IsNull() )
95   {
96     TopoDS_Wire aWire = TopoDS::Wire( thePolyline->GetTopShape() );
97     if( !aWire.IsNull() )
98     {
99       BRepBuilderAPI_MakeFace aMakeFace( aWire, Standard_True );
100       aMakeFace.Build();
101       if( aMakeFace.IsDone() )
102       {
103         SplitData aBoundarySplitData( aMakeFace.Face(), "" );
104
105         SplitDataList aCutSplitDataList;
106         SplitDataListIterator anOutputIter( anOutputSplitDataList );
107         while( anOutputIter.hasNext() )
108         {
109           const SplitData& anOutputSplitData = anOutputIter.next();
110
111           SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
112           if( SplitTwoData( anOutputSplitData, aBoundarySplitData,
113                             aData1Subtracted, aData2Subtracted, aDataIntersected ) )
114             aCutSplitDataList.append( aDataIntersected );
115         }
116         anOutputSplitDataList = aCutSplitDataList;
117       }
118     }
119   }
120
121   // Step 3. Extract the separate regions.
122   SplitDataList anExtractedSplitDataList;
123   SplitDataListIterator anOutputIter( anOutputSplitDataList );
124   while( anOutputIter.hasNext() )
125   {
126     const SplitData& anOutputSplitData = anOutputIter.next();
127     anExtractedSplitDataList.append( ExtractSeparateData( anOutputSplitData ) );
128   }
129
130   return anExtractedSplitDataList;
131 }
132
133 bool HYDROData_SplitToZonesTool::SplitTwoData( const SplitData& theData1,
134                                                const SplitData& theData2,
135                                                SplitData& theData1Subtracted,
136                                                SplitData& theData2Subtracted,
137                                                SplitData& theDataIntersected )
138 {
139   const TopoDS_Shape& aShape1 = theData1.Shape;
140   const TopoDS_Shape& aShape2 = theData2.Shape;
141
142   const QStringList& anObjectNames1 = theData1.ObjectNames;
143   const QStringList& anObjectNames2 = theData2.ObjectNames;
144
145   BRepAlgoAPI_Common aCommon( aShape1, aShape2 );
146   TopoDS_Shape aCommonShape = aCommon.Shape();
147   if( aCommonShape.IsNull() )
148   {
149     theData1Subtracted = theData1;
150     theData2Subtracted = theData2;
151     return false;
152   }
153
154   BRepAlgoAPI_Cut aCut1( aShape1, aShape2 );
155   TopoDS_Shape aCut1Shape = aCut1.Shape();
156
157   BRepAlgoAPI_Cut aCut2( aShape2, aShape1 );
158   TopoDS_Shape aCut2Shape = aCut2.Shape();
159
160   theData1Subtracted = SplitData( aCut1Shape, anObjectNames1 );
161   theData2Subtracted = SplitData( aCut2Shape, anObjectNames2 );
162   theDataIntersected = SplitData( aCommonShape, anObjectNames1 + anObjectNames2 );
163
164   return true;
165 }
166
167 HYDROData_SplitToZonesTool::SplitDataList
168 HYDROData_SplitToZonesTool::ExtractSeparateData( const SplitData& theData )
169 {
170   SplitDataList aSplitDataList;
171   TopExp_Explorer anExp( theData.Shape, TopAbs_FACE );
172   for( ; anExp.More(); anExp.Next() )
173   {
174     TopoDS_Shape aShape = anExp.Current();
175     if( aShape.ShapeType() == TopAbs_FACE )
176     {
177       TopoDS_Face aFace = TopoDS::Face( aShape );
178       if( !aFace.IsNull() )
179       {
180         SplitData aSplitData( aFace, theData.ObjectNames );
181         aSplitDataList.append( aSplitData );
182       }
183     }
184   }
185   return aSplitDataList;
186 }