Salome HOME
Create goups for stream.
[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     TopTools_ListOfShape aList;
144         TopTools_ListIteratorOfListOfShape it1(aListOfNew);
145         for(;it1.More();it1.Next())       
146           aList.Append(it1.Value());
147     const TopTools_ListOfShape& aListOfGen = aBuilder->Generated(anIt.Value());
148         TopTools_ListIteratorOfListOfShape it2(aListOfGen);    
149         for(;it2.More();it2.Next())     
150           aList.Append(it2.Value());
151
152         aDM1.Bind(anIt.Value(), aList);
153         //cout << "NB_Face = " << aList.Extent() <<endl;
154         //TopExp_Explorer exp (anIt.Value(), TopAbs_EDGE);
155         //for (;exp.More();exp.Next()) {
156           //const TopTools_ListOfShape& aList2 = aBuilder->Modified(exp.Current());
157          // cout << "NB_EDGE = " << aList2.Extent() <<endl;
158         //}
159   }
160
161   // aDM2: NewShape ==> ListOfOldShapes
162   HYDROData_DataMapOfShapeListOfShape aDM2;
163   HYDROData_DataMapIteratorOfDataMapOfShapeListOfShape aMIt(aDM1);
164   for(;aMIt.More();aMIt.Next()) {
165         const TopoDS_Shape& aKey = aMIt.Key();
166         TopTools_ListOfShape aList;
167         aList.Append(aKey);
168         const TopTools_ListOfShape& aListOfNew = aMIt.Value();
169         TopTools_ListIteratorOfListOfShape it(aListOfNew);
170         for(;it.More();it.Next()) {
171           if(!aDM2.IsBound(it.Value()))
172             aDM2.Bind(it.Value(), aList);
173           else {
174                 TopTools_ListOfShape& aList = aDM2.ChangeFind(it.Value());
175                 aList.Prepend(aKey);
176           }
177         }
178   }
179   //cout << "DM2 Ext = " <<aDM2.Extent() <<endl;
180   // Step 4. Fill output structure.
181   aMIt.Initialize(aDM2);
182   for(;aMIt.More();aMIt.Next()) {
183         const TopoDS_Shape& aKey = aMIt.Key(); //new
184     const TopTools_ListOfShape& aListOfOld = aMIt.Value();
185         SplitData aDestSplitData;
186         QStringList aListOfNames;
187     TopTools_ListIteratorOfListOfShape it(aListOfOld);
188         for(;it.More();it.Next()) {     
189           const TopoDS_Shape& aSh = it.Value(); //old
190           if(aDM3.IsBound(aSh)) {
191             const QStringList& ObjectNames = aDM3.Find(aSh);
192                 aListOfNames.append(ObjectNames);
193           }      
194         }
195         aDestSplitData.Shape = aKey;
196         aDestSplitData.ObjectNames = aListOfNames;
197   aDestSplitData.Type = SplitData::Data_Zone;
198         anOutputSplitDataList.append(aDestSplitData);
199   }
200   return anOutputSplitDataList;
201   /*
202   SplitDataListIterator anInputIter( anInputSplitDataList );
203   while( anInputIter.hasNext() )
204   {
205     const SplitData& anInputSplitData = anInputIter.next();
206     if( anOutputSplitDataList.isEmpty() )
207       anOutputSplitDataList.append( anInputSplitData );
208     else
209     {
210       SplitDataList aSplitDataList;
211
212       SplitDataList aSrcSplitDataList;
213       aSrcSplitDataList.append( anInputSplitData );
214
215       SplitDataList aDestSplitDataList = anOutputSplitDataList;
216       anOutputSplitDataList.clear();
217
218       while( !aDestSplitDataList.isEmpty() )
219       {
220         SplitData aSrcSplitData = aSrcSplitDataList.last();
221
222         SplitData aDestSplitData = aDestSplitDataList.first();
223         aDestSplitDataList.pop_front();
224
225         SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
226         if( SplitTwoData( aSrcSplitData, aDestSplitData,
227                           aData1Subtracted, aData2Subtracted, aDataIntersected ) )
228           anOutputSplitDataList.append( aDataIntersected );
229         anOutputSplitDataList.append( aData2Subtracted );
230         aSrcSplitDataList.append( aData1Subtracted );
231       }
232
233       if( !aSrcSplitDataList.isEmpty() )
234         anOutputSplitDataList.append( aSrcSplitDataList.last() );
235     }
236   }
237
238   // Step 2. Take into account the boundary polyline.
239   if( !thePolyline.IsNull() )
240   {
241     TopoDS_Wire aWire = TopoDS::Wire( thePolyline->GetShape() );
242     if( !aWire.IsNull() )
243     {
244       BRepBuilderAPI_MakeFace aMakeFace( aWire, Standard_True );
245       aMakeFace.Build();
246       if( aMakeFace.IsDone() )
247       {
248         SplitData aBoundarySplitData( SplitData::Data_Zone, aMakeFace.Face(), "" );
249
250         SplitDataList aCutSplitDataList;
251         SplitDataListIterator anOutputIter( anOutputSplitDataList );
252         while( anOutputIter.hasNext() )
253         {
254           const SplitData& anOutputSplitData = anOutputIter.next();
255
256           SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
257           if( SplitTwoData( anOutputSplitData, aBoundarySplitData,
258                             aData1Subtracted, aData2Subtracted, aDataIntersected ) )
259             aCutSplitDataList.append( aDataIntersected );
260         }
261         anOutputSplitDataList = aCutSplitDataList;
262       }
263     }
264   }
265
266   // Step 3. Extract the separate regions.
267   SplitDataList anExtractedSplitDataList;
268   SplitDataListIterator anOutputIter( anOutputSplitDataList );
269   while( anOutputIter.hasNext() )
270   {
271     const SplitData& anOutputSplitData = anOutputIter.next();
272     anExtractedSplitDataList.append( ExtractSeparateData( anOutputSplitData ) );
273   }
274 */
275  // return anExtractedSplitDataList;
276 }
277
278 bool HYDROData_SplitToZonesTool::SplitTwoData( const SplitData& theData1,
279                                                const SplitData& theData2,
280                                                SplitData& theData1Subtracted,
281                                                SplitData& theData2Subtracted,
282                                                SplitData& theDataIntersected )
283 {
284   const TopoDS_Shape& aShape1 = theData1.Shape;
285   const TopoDS_Shape& aShape2 = theData2.Shape;
286
287   const QStringList& anObjectNames1 = theData1.ObjectNames;
288   const QStringList& anObjectNames2 = theData2.ObjectNames;
289
290   BRepAlgoAPI_Common aCommon( aShape1, aShape2 );
291   TopoDS_Shape aCommonShape = aCommon.Shape();
292   if( aCommonShape.IsNull() )
293   {
294     theData1Subtracted = theData1;
295     theData2Subtracted = theData2;
296     return false;
297   }
298
299   BRepAlgoAPI_Cut aCut1( aShape1, aShape2 );
300   TopoDS_Shape aCut1Shape = aCut1.Shape();
301
302   BRepAlgoAPI_Cut aCut2( aShape2, aShape1 );
303   TopoDS_Shape aCut2Shape = aCut2.Shape();
304
305   theData1Subtracted = SplitData( SplitData::Data_Zone, aCut1Shape, anObjectNames1 );
306   theData2Subtracted = SplitData( SplitData::Data_Zone, aCut2Shape, anObjectNames2 );
307   theDataIntersected = SplitData( SplitData::Data_Zone, aCommonShape, anObjectNames1 + anObjectNames2 );
308
309   return true;
310 }
311
312 HYDROData_SplitToZonesTool::SplitDataList
313 HYDROData_SplitToZonesTool::ExtractSeparateData( const SplitData& theData )
314 {
315   SplitDataList aSplitDataList;
316   TopExp_Explorer anExp( theData.Shape, TopAbs_FACE );
317   for( ; anExp.More(); anExp.Next() )
318   {
319     TopoDS_Shape aShape = anExp.Current();
320     if( aShape.ShapeType() == TopAbs_FACE )
321     {
322       TopoDS_Face aFace = TopoDS::Face( aShape );
323       if( !aFace.IsNull() )
324       {
325         SplitData aSplitData( SplitData::Data_Zone, aFace, theData.ObjectNames );
326         aSplitDataList.append( aSplitData );
327       }
328     }
329   }
330   return aSplitDataList;
331 }