Salome HOME
de99585d7a5fbd3b8e026ec9e0eebf31f6863e39
[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   aDestSplitData.Type = SplitData::Data_Zone;
188         anOutputSplitDataList.append(aDestSplitData);
189   }
190   return anOutputSplitDataList;
191   /*
192   SplitDataListIterator anInputIter( anInputSplitDataList );
193   while( anInputIter.hasNext() )
194   {
195     const SplitData& anInputSplitData = anInputIter.next();
196     if( anOutputSplitDataList.isEmpty() )
197       anOutputSplitDataList.append( anInputSplitData );
198     else
199     {
200       SplitDataList aSplitDataList;
201
202       SplitDataList aSrcSplitDataList;
203       aSrcSplitDataList.append( anInputSplitData );
204
205       SplitDataList aDestSplitDataList = anOutputSplitDataList;
206       anOutputSplitDataList.clear();
207
208       while( !aDestSplitDataList.isEmpty() )
209       {
210         SplitData aSrcSplitData = aSrcSplitDataList.last();
211
212         SplitData aDestSplitData = aDestSplitDataList.first();
213         aDestSplitDataList.pop_front();
214
215         SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
216         if( SplitTwoData( aSrcSplitData, aDestSplitData,
217                           aData1Subtracted, aData2Subtracted, aDataIntersected ) )
218           anOutputSplitDataList.append( aDataIntersected );
219         anOutputSplitDataList.append( aData2Subtracted );
220         aSrcSplitDataList.append( aData1Subtracted );
221       }
222
223       if( !aSrcSplitDataList.isEmpty() )
224         anOutputSplitDataList.append( aSrcSplitDataList.last() );
225     }
226   }
227
228   // Step 2. Take into account the boundary polyline.
229   if( !thePolyline.IsNull() )
230   {
231     TopoDS_Wire aWire = TopoDS::Wire( thePolyline->GetShape() );
232     if( !aWire.IsNull() )
233     {
234       BRepBuilderAPI_MakeFace aMakeFace( aWire, Standard_True );
235       aMakeFace.Build();
236       if( aMakeFace.IsDone() )
237       {
238         SplitData aBoundarySplitData( SplitData::Data_Zone, aMakeFace.Face(), "" );
239
240         SplitDataList aCutSplitDataList;
241         SplitDataListIterator anOutputIter( anOutputSplitDataList );
242         while( anOutputIter.hasNext() )
243         {
244           const SplitData& anOutputSplitData = anOutputIter.next();
245
246           SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
247           if( SplitTwoData( anOutputSplitData, aBoundarySplitData,
248                             aData1Subtracted, aData2Subtracted, aDataIntersected ) )
249             aCutSplitDataList.append( aDataIntersected );
250         }
251         anOutputSplitDataList = aCutSplitDataList;
252       }
253     }
254   }
255
256   // Step 3. Extract the separate regions.
257   SplitDataList anExtractedSplitDataList;
258   SplitDataListIterator anOutputIter( anOutputSplitDataList );
259   while( anOutputIter.hasNext() )
260   {
261     const SplitData& anOutputSplitData = anOutputIter.next();
262     anExtractedSplitDataList.append( ExtractSeparateData( anOutputSplitData ) );
263   }
264 */
265  // return anExtractedSplitDataList;
266 }
267
268 bool HYDROData_SplitToZonesTool::SplitTwoData( const SplitData& theData1,
269                                                const SplitData& theData2,
270                                                SplitData& theData1Subtracted,
271                                                SplitData& theData2Subtracted,
272                                                SplitData& theDataIntersected )
273 {
274   const TopoDS_Shape& aShape1 = theData1.Shape;
275   const TopoDS_Shape& aShape2 = theData2.Shape;
276
277   const QStringList& anObjectNames1 = theData1.ObjectNames;
278   const QStringList& anObjectNames2 = theData2.ObjectNames;
279
280   BRepAlgoAPI_Common aCommon( aShape1, aShape2 );
281   TopoDS_Shape aCommonShape = aCommon.Shape();
282   if( aCommonShape.IsNull() )
283   {
284     theData1Subtracted = theData1;
285     theData2Subtracted = theData2;
286     return false;
287   }
288
289   BRepAlgoAPI_Cut aCut1( aShape1, aShape2 );
290   TopoDS_Shape aCut1Shape = aCut1.Shape();
291
292   BRepAlgoAPI_Cut aCut2( aShape2, aShape1 );
293   TopoDS_Shape aCut2Shape = aCut2.Shape();
294
295   theData1Subtracted = SplitData( SplitData::Data_Zone, aCut1Shape, anObjectNames1 );
296   theData2Subtracted = SplitData( SplitData::Data_Zone, aCut2Shape, anObjectNames2 );
297   theDataIntersected = SplitData( SplitData::Data_Zone, aCommonShape, anObjectNames1 + anObjectNames2 );
298
299   return true;
300 }
301
302 HYDROData_SplitToZonesTool::SplitDataList
303 HYDROData_SplitToZonesTool::ExtractSeparateData( const SplitData& theData )
304 {
305   SplitDataList aSplitDataList;
306   TopExp_Explorer anExp( theData.Shape, TopAbs_FACE );
307   for( ; anExp.More(); anExp.Next() )
308   {
309     TopoDS_Shape aShape = anExp.Current();
310     if( aShape.ShapeType() == TopAbs_FACE )
311     {
312       TopoDS_Face aFace = TopoDS::Face( aShape );
313       if( !aFace.IsNull() )
314       {
315         SplitData aSplitData( SplitData::Data_Zone, aFace, theData.ObjectNames );
316         aSplitDataList.append( aSplitData );
317       }
318     }
319   }
320   return aSplitDataList;
321 }