Salome HOME
Splitting data for calculation case edges (Feature #242).
[modules/hydro.git] / src / HYDROData / HYDROData_SplitToZonesTool.cxx
1
2 #include "HYDROData_SplitToZonesTool.h"
3
4 #include "HYDROData_PolylineXY.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::Split( const HYDROData_SequenceOfObjects&  theObjectList,
39                                      const HYDROData_SequenceOfObjects&  theGroupsList,
40                                      const Handle(HYDROData_PolylineXY)& thePolyline )
41 {
42   SplitDataList anOutputSplitDataList;
43
44   // Preparation. Collect the object shapes to split.
45   SplitDataList anInputSplitDataList;
46   for( int anIndex = 1, aLength = theObjectList.Length(); anIndex <= aLength; anIndex++ )
47   {
48     Handle(HYDROData_Object) aGeomObj = 
49       Handle(HYDROData_Object)::DownCast( theObjectList.Value( anIndex ) );
50     if( aGeomObj.IsNull() )
51       continue;
52
53     TopoDS_Shape aShape = aGeomObj->GetTopShape();
54     if ( aShape.IsNull() )
55       continue;
56         
57     if ( aShape.ShapeType() == TopAbs_COMPOUND ) {
58       // Create split data for each face contained in the compound
59       TopExp_Explorer anExp( aShape, TopAbs_FACE );
60       for ( ; anExp.More(); anExp.Next() ) {
61         TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
62         if ( !aFace.IsNull() ) {
63           SplitData aSplitData( SplitData::Data_Zone, aFace, aGeomObj->GetName() );
64           anInputSplitDataList.append( aSplitData );
65         }
66       }
67     } else {
68       SplitData aSplitData( SplitData::Data_Zone, aShape, aGeomObj->GetName() );
69       anInputSplitDataList.append( aSplitData );
70     }
71   }
72
73   // Step 1. Split the paths.
74   SplitDataListIterator anInputIter( anInputSplitDataList );
75   while( anInputIter.hasNext() )
76   {
77     const SplitData& anInputSplitData = anInputIter.next();
78     if( anOutputSplitDataList.isEmpty() )
79       anOutputSplitDataList.append( anInputSplitData );
80     else
81     {
82       SplitDataList aSplitDataList;
83
84       SplitDataList aSrcSplitDataList;
85       aSrcSplitDataList.append( anInputSplitData );
86
87       SplitDataList aDestSplitDataList = anOutputSplitDataList;
88       anOutputSplitDataList.clear();
89
90       while( !aDestSplitDataList.isEmpty() )
91       {
92         SplitData aSrcSplitData = aSrcSplitDataList.last();
93
94         SplitData aDestSplitData = aDestSplitDataList.first();
95         aDestSplitDataList.pop_front();
96
97         SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
98         if( SplitTwoData( aSrcSplitData, aDestSplitData,
99                           aData1Subtracted, aData2Subtracted, aDataIntersected ) )
100           anOutputSplitDataList.append( aDataIntersected );
101         anOutputSplitDataList.append( aData2Subtracted );
102         aSrcSplitDataList.append( aData1Subtracted );
103       }
104
105       if( !aSrcSplitDataList.isEmpty() )
106         anOutputSplitDataList.append( aSrcSplitDataList.last() );
107     }
108   }
109
110   // Step 2. Take into account the boundary polyline.
111   if( !thePolyline.IsNull() )
112   {
113     TopoDS_Wire aWire = TopoDS::Wire( thePolyline->GetShape() );
114     if( !aWire.IsNull() )
115     {
116       BRepBuilderAPI_MakeFace aMakeFace( aWire, Standard_True );
117       aMakeFace.Build();
118       if( aMakeFace.IsDone() )
119       {
120         SplitData aBoundarySplitData( SplitData::Data_Zone, aMakeFace.Face(), "" );
121
122         SplitDataList aCutSplitDataList;
123         SplitDataListIterator anOutputIter( anOutputSplitDataList );
124         while( anOutputIter.hasNext() )
125         {
126           const SplitData& anOutputSplitData = anOutputIter.next();
127
128           SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
129           if( SplitTwoData( anOutputSplitData, aBoundarySplitData,
130                             aData1Subtracted, aData2Subtracted, aDataIntersected ) )
131             aCutSplitDataList.append( aDataIntersected );
132         }
133         anOutputSplitDataList = aCutSplitDataList;
134       }
135     }
136   }
137
138   // Step 3. Extract the separate regions.
139   SplitDataList anExtractedSplitDataList;
140   SplitDataListIterator anOutputIter( anOutputSplitDataList );
141   while( anOutputIter.hasNext() )
142   {
143     const SplitData& anOutputSplitData = anOutputIter.next();
144     anExtractedSplitDataList.append( ExtractSeparateData( anOutputSplitData ) );
145   }
146
147   return anExtractedSplitDataList;
148 }
149
150 bool HYDROData_SplitToZonesTool::SplitTwoData( const SplitData& theData1,
151                                                const SplitData& theData2,
152                                                SplitData& theData1Subtracted,
153                                                SplitData& theData2Subtracted,
154                                                SplitData& theDataIntersected )
155 {
156   const TopoDS_Shape& aShape1 = theData1.Shape;
157   const TopoDS_Shape& aShape2 = theData2.Shape;
158
159   const QStringList& anObjectNames1 = theData1.ObjectNames;
160   const QStringList& anObjectNames2 = theData2.ObjectNames;
161
162   BRepAlgoAPI_Common aCommon( aShape1, aShape2 );
163   TopoDS_Shape aCommonShape = aCommon.Shape();
164   if( aCommonShape.IsNull() )
165   {
166     theData1Subtracted = theData1;
167     theData2Subtracted = theData2;
168     return false;
169   }
170
171   BRepAlgoAPI_Cut aCut1( aShape1, aShape2 );
172   TopoDS_Shape aCut1Shape = aCut1.Shape();
173
174   BRepAlgoAPI_Cut aCut2( aShape2, aShape1 );
175   TopoDS_Shape aCut2Shape = aCut2.Shape();
176
177   theData1Subtracted = SplitData( SplitData::Data_Zone, aCut1Shape, anObjectNames1 );
178   theData2Subtracted = SplitData( SplitData::Data_Zone, aCut2Shape, anObjectNames2 );
179   theDataIntersected = SplitData( SplitData::Data_Zone, aCommonShape, anObjectNames1 + anObjectNames2 );
180
181   return true;
182 }
183
184 HYDROData_SplitToZonesTool::SplitDataList
185 HYDROData_SplitToZonesTool::ExtractSeparateData( const SplitData& theData )
186 {
187   SplitDataList aSplitDataList;
188   TopExp_Explorer anExp( theData.Shape, TopAbs_FACE );
189   for( ; anExp.More(); anExp.Next() )
190   {
191     TopoDS_Shape aShape = anExp.Current();
192     if( aShape.ShapeType() == TopAbs_FACE )
193     {
194       TopoDS_Face aFace = TopoDS::Face( aShape );
195       if( !aFace.IsNull() )
196       {
197         SplitData aSplitData( SplitData::Data_Zone, aFace, theData.ObjectNames );
198         aSplitDataList.append( aSplitData );
199       }
200     }
201   }
202   return aSplitDataList;
203 }