Salome HOME
17.12.2013. Added Partition algorithm (draft version).
[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 #include <TopoDS_Iterator.hxx>
15 #include <BRepCheck_Analyzer.hxx>
16 #include <NCollection_IncAllocator.hxx>
17 #include <BOPAlgo_Builder.hxx>
18 #include <BOPAlgo_PaveFiller.hxx>
19 #include <NCollection_DataMap.hxx>
20 #include <TopTools_ListOfShape.hxx>
21 #include <TopTools_ListIteratorofListOfShape.hxx>
22 #include <TopTools_ShapeMapHasher.hxx>
23 typedef NCollection_DataMap<TopoDS_Shape, TopTools_ListOfShape, TopTools_ShapeMapHasher> HYDROData_DataMapOfShapeListOfShape;
24 typedef HYDROData_DataMapOfShapeListOfShape::Iterator HYDROData_DataMapIteratorOfDataMapOfShapeListOfShape;
25 typedef NCollection_DataMap<TopoDS_Shape,  QStringList, TopTools_ShapeMapHasher> HYDROData_DataMapOfShapeListOfString;
26 typedef HYDROData_DataMapOfShapeListOfString::Iterator HYDROData_DataMapIteratorOfDataMapOfShapeListOfString;
27 #undef _NCollection_MapHasher
28
29 #define DEB_SPLIT_TO_ZONES 1
30 #ifdef DEB_SPLIT_TO_ZONES        
31 #include <BRepTools.hxx>
32 #endif
33 TopoDS_Face HYDROData_SplitToZonesTool::SplitData::Face() const
34 {
35   TopoDS_Face aResFace;
36
37   if( !Shape.IsNull() )
38   {
39     if ( Shape.ShapeType() == TopAbs_FACE )
40     {
41       aResFace = TopoDS::Face( Shape );
42     }
43     else if ( Shape.ShapeType() == TopAbs_WIRE )
44     {
45       BRepBuilderAPI_MakeFace aMakeFace( TopoDS::Wire( Shape ), Standard_True );
46       aMakeFace.Build();
47       if( aMakeFace.IsDone() )
48         aResFace = aMakeFace.Face();
49     }
50   }
51
52   return aResFace;
53 }
54
55 HYDROData_SplitToZonesTool::SplitDataList
56   HYDROData_SplitToZonesTool::Split( const HYDROData_SequenceOfObjects&  theObjectList,
57                                      const HYDROData_SequenceOfObjects&  theGroupsList,
58                                      const Handle(HYDROData_PolylineXY)& thePolyline )
59 {
60   SplitDataList anOutputSplitDataList;
61
62   // Preparation. Collect the object shapes to split. InputDataList will contain elements which will hold shape & name_of_shape.
63   SplitDataList anInputSplitDataList;
64   for( int anIndex = 1, aLength = theObjectList.Length(); anIndex <= aLength; anIndex++ )
65   {
66     Handle(HYDROData_Object) aGeomObj = 
67       Handle(HYDROData_Object)::DownCast( theObjectList.Value( anIndex ) );
68     if( aGeomObj.IsNull() )
69       continue;
70
71     TopoDS_Shape aShape = aGeomObj->GetTopShape();
72     if ( aShape.IsNull() )
73       continue;
74         
75     if ( aShape.ShapeType() == TopAbs_COMPOUND ) {
76       // Create split data for each face contained in the compound
77       TopExp_Explorer anExp( aShape, TopAbs_FACE );
78       for ( ; anExp.More(); anExp.Next() ) {
79         TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
80         if ( !aFace.IsNull() ) {
81           SplitData aSplitData( SplitData::Data_Zone, aFace, aGeomObj->GetName() );
82           anInputSplitDataList.append( aSplitData );
83         }
84       }
85     } else {
86       SplitData aSplitData( SplitData::Data_Zone, aShape, aGeomObj->GetName() );
87       anInputSplitDataList.append( aSplitData );
88     }
89   }
90
91   // Step 1. Prepare Partition structures.
92   Handle(NCollection_BaseAllocator) pA1 = new NCollection_IncAllocator, pA2 = new NCollection_IncAllocator;
93   BOPAlgo_PaveFiller* aPaveFiller      = new BOPAlgo_PaveFiller(pA1);
94   BOPAlgo_Builder* aBuilder            = new BOPAlgo_Builder(pA2);
95   BOPCol_ListOfShape aLS;  
96   HYDROData_DataMapOfShapeListOfString aDM3;
97   QStringList aListOfNames;
98   for (int i=0;i < anInputSplitDataList.size() ;i++) {
99         const TopoDS_Shape& aSh = anInputSplitDataList.at(i).Shape;     
100         aDM3.Bind(aSh, anInputSplitDataList.at(i).ObjectNames);
101     aLS.Append(aSh);    
102   }
103    aPaveFiller->SetArguments(aLS);
104    aPaveFiller->Perform();
105    Standard_Integer anErr = aPaveFiller->ErrorStatus();
106    if(anErr) 
107      return anOutputSplitDataList;
108    BOPDS_PDS pDS = aPaveFiller->PDS();
109    if (!pDS) 
110            return anOutputSplitDataList;
111    aBuilder->Clear();
112
113    // Step 2. Split faces 
114    BOPCol_ListIteratorOfListOfShape anIt(aPaveFiller->Arguments());
115    for (; anIt.More(); anIt.Next()) {
116      const TopoDS_Shape& aS = anIt.Value();
117      aBuilder->AddArgument(aS);
118    }
119     aBuilder->PerformWithFiller(*aPaveFiller);
120         anErr = aBuilder->ErrorStatus();
121     if(anErr) 
122       return anOutputSplitDataList;
123         const TopoDS_Shape& aResult = aBuilder->Shape();
124   if (aResult.IsNull()) 
125     return anOutputSplitDataList;
126   BRepCheck_Analyzer aCheck (aResult);
127   if(!aCheck.IsValid()) {
128 #ifdef DEB_SPLIT_TO_ZONES       
129      cout << "result is not valid" <<endl;       
130          BRepTools::Write(aResult, "SplitFacesNV.brep");  
131 #endif
132      return anOutputSplitDataList;
133   }
134 #ifdef DEB_SPLIT_TO_ZONES       
135   BRepTools::Write(aResult, "SplitFacesV.brep");
136 #endif
137   
138   // Step 3. Collect history  
139   HYDROData_DataMapOfShapeListOfShape aDM1;
140   anIt.Init(aLS);
141   for (;anIt.More();anIt.Next()) {
142         const TopTools_ListOfShape& aListOfNew = aBuilder->Modified(anIt.Value());
143         aDM1.Bind(anIt.Value(), aListOfNew);
144         //cout << "NB_Face = " << aList.Extent() <<endl;
145         //TopExp_Explorer exp (anIt.Value(), TopAbs_EDGE);
146         //for (;exp.More();exp.Next()) {
147           //const TopTools_ListOfShape& aList2 = aBuilder->Modified(exp.Current());
148          // cout << "NB_EDGE = " << aList2.Extent() <<endl;
149         //}
150   }
151   // aDM2: NewShape ==> ListOfOldShapes
152   HYDROData_DataMapOfShapeListOfShape aDM2;
153   HYDROData_DataMapIteratorOfDataMapOfShapeListOfShape aMIt(aDM1);
154   for(;aMIt.More();aMIt.Next()) {
155         const TopoDS_Shape& aKey = aMIt.Key();
156         TopTools_ListOfShape aList;
157         aList.Append(aKey);
158         const TopTools_ListOfShape& aListOfNew = aMIt.Value();
159         TopTools_ListIteratorOfListOfShape it(aListOfNew);
160         for(;it.More();it.Next()) {
161           if(!aDM2.IsBound(it.Value()))
162             aDM2.Bind(it.Value(), aList);
163           else {
164                 TopTools_ListOfShape& aList = aDM2.ChangeFind(it.Value());
165                 aList.Prepend(aKey);
166           }
167         }
168   }
169
170   // Step 4. Fill output structure.
171   aMIt.Initialize(aDM2);
172   for(;aMIt.More();aMIt.Next()) {
173         const TopoDS_Shape& aKey = aMIt.Key(); //new
174     const TopTools_ListOfShape& aListOfOld = aMIt.Value();
175         SplitData aDestSplitData;
176         QStringList aListOfNames;
177     TopTools_ListIteratorOfListOfShape it(aListOfOld);
178         for(;it.More();it.Next()) {     
179           const TopoDS_Shape& aSh = it.Value(); //old
180           if(aDM3.IsBound(aSh)) {
181             const QStringList& ObjectNames = aDM3.Find(aSh);
182                 aListOfNames.append(ObjectNames);
183           }      
184         }
185         aDestSplitData.Shape = aKey;
186         aDestSplitData.ObjectNames = aListOfNames;
187         anOutputSplitDataList.append(aDestSplitData);
188   }
189   return anOutputSplitDataList;
190   /*
191   SplitDataListIterator anInputIter( anInputSplitDataList );
192   while( anInputIter.hasNext() )
193   {
194     const SplitData& anInputSplitData = anInputIter.next();
195     if( anOutputSplitDataList.isEmpty() )
196       anOutputSplitDataList.append( anInputSplitData );
197     else
198     {
199       SplitDataList aSplitDataList;
200
201       SplitDataList aSrcSplitDataList;
202       aSrcSplitDataList.append( anInputSplitData );
203
204       SplitDataList aDestSplitDataList = anOutputSplitDataList;
205       anOutputSplitDataList.clear();
206
207       while( !aDestSplitDataList.isEmpty() )
208       {
209         SplitData aSrcSplitData = aSrcSplitDataList.last();
210
211         SplitData aDestSplitData = aDestSplitDataList.first();
212         aDestSplitDataList.pop_front();
213
214         SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
215         if( SplitTwoData( aSrcSplitData, aDestSplitData,
216                           aData1Subtracted, aData2Subtracted, aDataIntersected ) )
217           anOutputSplitDataList.append( aDataIntersected );
218         anOutputSplitDataList.append( aData2Subtracted );
219         aSrcSplitDataList.append( aData1Subtracted );
220       }
221
222       if( !aSrcSplitDataList.isEmpty() )
223         anOutputSplitDataList.append( aSrcSplitDataList.last() );
224     }
225   }
226
227   // Step 2. Take into account the boundary polyline.
228   if( !thePolyline.IsNull() )
229   {
230     TopoDS_Wire aWire = TopoDS::Wire( thePolyline->GetShape() );
231     if( !aWire.IsNull() )
232     {
233       BRepBuilderAPI_MakeFace aMakeFace( aWire, Standard_True );
234       aMakeFace.Build();
235       if( aMakeFace.IsDone() )
236       {
237         SplitData aBoundarySplitData( SplitData::Data_Zone, aMakeFace.Face(), "" );
238
239         SplitDataList aCutSplitDataList;
240         SplitDataListIterator anOutputIter( anOutputSplitDataList );
241         while( anOutputIter.hasNext() )
242         {
243           const SplitData& anOutputSplitData = anOutputIter.next();
244
245           SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
246           if( SplitTwoData( anOutputSplitData, aBoundarySplitData,
247                             aData1Subtracted, aData2Subtracted, aDataIntersected ) )
248             aCutSplitDataList.append( aDataIntersected );
249         }
250         anOutputSplitDataList = aCutSplitDataList;
251       }
252     }
253   }
254
255   // Step 3. Extract the separate regions.
256   SplitDataList anExtractedSplitDataList;
257   SplitDataListIterator anOutputIter( anOutputSplitDataList );
258   while( anOutputIter.hasNext() )
259   {
260     const SplitData& anOutputSplitData = anOutputIter.next();
261     anExtractedSplitDataList.append( ExtractSeparateData( anOutputSplitData ) );
262   }
263 */
264  // return anExtractedSplitDataList;
265 }
266
267 bool HYDROData_SplitToZonesTool::SplitTwoData( const SplitData& theData1,
268                                                const SplitData& theData2,
269                                                SplitData& theData1Subtracted,
270                                                SplitData& theData2Subtracted,
271                                                SplitData& theDataIntersected )
272 {
273   const TopoDS_Shape& aShape1 = theData1.Shape;
274   const TopoDS_Shape& aShape2 = theData2.Shape;
275
276   const QStringList& anObjectNames1 = theData1.ObjectNames;
277   const QStringList& anObjectNames2 = theData2.ObjectNames;
278
279   BRepAlgoAPI_Common aCommon( aShape1, aShape2 );
280   TopoDS_Shape aCommonShape = aCommon.Shape();
281   if( aCommonShape.IsNull() )
282   {
283     theData1Subtracted = theData1;
284     theData2Subtracted = theData2;
285     return false;
286   }
287
288   BRepAlgoAPI_Cut aCut1( aShape1, aShape2 );
289   TopoDS_Shape aCut1Shape = aCut1.Shape();
290
291   BRepAlgoAPI_Cut aCut2( aShape2, aShape1 );
292   TopoDS_Shape aCut2Shape = aCut2.Shape();
293
294   theData1Subtracted = SplitData( SplitData::Data_Zone, aCut1Shape, anObjectNames1 );
295   theData2Subtracted = SplitData( SplitData::Data_Zone, aCut2Shape, anObjectNames2 );
296   theDataIntersected = SplitData( SplitData::Data_Zone, aCommonShape, anObjectNames1 + anObjectNames2 );
297
298   return true;
299 }
300
301 HYDROData_SplitToZonesTool::SplitDataList
302 HYDROData_SplitToZonesTool::ExtractSeparateData( const SplitData& theData )
303 {
304   SplitDataList aSplitDataList;
305   TopExp_Explorer anExp( theData.Shape, TopAbs_FACE );
306   for( ; anExp.More(); anExp.Next() )
307   {
308     TopoDS_Shape aShape = anExp.Current();
309     if( aShape.ShapeType() == TopAbs_FACE )
310     {
311       TopoDS_Face aFace = TopoDS::Face( aShape );
312       if( !aFace.IsNull() )
313       {
314         SplitData aSplitData( SplitData::Data_Zone, aFace, theData.ObjectNames );
315         aSplitDataList.append( aSplitData );
316       }
317     }
318   }
319   return aSplitDataList;
320 }