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