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