Salome HOME
SIP: HYDROData_ObstacleAltitude is included.
[modules/hydro.git] / src / HYDROData / HYDROData_SplitToZonesTool.cxx
1
2 #include "HYDROData_SplitToZonesTool.h"
3
4 #include "HYDROData_PolylineXY.h"
5 #include "HYDROData_ShapesGroup.h"
6 #include <HYDROData_Transform.h>
7 #include <BRepAlgoAPI_Cut.hxx>
8 #include <BRepAlgoAPI_Common.hxx>
9 #include <BRepBuilderAPI_MakeFace.hxx>
10 #include <BRep_Builder.hxx>
11 #include <TopExp_Explorer.hxx>
12 #include <TopoDS.hxx>
13 #include <TopoDS_Shape.hxx>
14 #include <TopoDS_Compound.hxx>
15 #include <TopoDS_Wire.hxx>
16 #include <TopoDS_Edge.hxx>
17 #include <BRepCheck_Analyzer.hxx>
18 #include <TopTools_ListOfShape.hxx>
19 #include <TopTools_ListIteratorOfListOfShape.hxx>
20 #include <gp_Pln.hxx>
21 #include <BRepGProp.hxx>
22 #include <GProp_GProps.hxx>
23 #include <Geom_Plane.hxx>
24 #include <BRepBuilderAPI_FindPlane.hxx>
25
26 //#define DEB_SPLIT_TO_ZONES 1
27 #ifdef DEB_SPLIT_TO_ZONES
28 #include <BRepTools.hxx>
29 #endif
30 TopoDS_Face HYDROData_SplitToZonesTool::SplitData::Face() const
31 {
32   TopoDS_Face aResFace;
33
34   if( !Shape.IsNull() )
35   {
36     if ( Shape.ShapeType() == TopAbs_FACE )
37     {
38       aResFace = TopoDS::Face( Shape );
39     }
40     else if ( Shape.ShapeType() == TopAbs_WIRE )
41     {
42       BRepBuilderAPI_MakeFace aMakeFace( TopoDS::Wire( Shape ), Standard_True );
43       aMakeFace.Build();
44       if( aMakeFace.IsDone() )
45         aResFace = aMakeFace.Face();
46     }
47   }
48
49   return aResFace;
50 }
51
52 Standard_Boolean buildLimFace(const TopoDS_Wire& theBndWire, TopoDS_Face& outFace) 
53 {
54   GProp_GProps G;
55   BRepGProp::LinearProperties(theBndWire,G);
56   const gp_Pnt& aCPnt = G.CentreOfMass();
57   gp_Pln aPln;
58   BRepBuilderAPI_FindPlane fndPlane (theBndWire, Precision::Confusion());  
59   if(fndPlane.Found())
60     aPln = fndPlane.Plane()->Pln();
61   else
62     aPln = gp_Pln(aCPnt, gp::OZ().Direction());
63   BRepBuilderAPI_MakeFace  aMkFace(aPln, theBndWire);
64   if(aMkFace.IsDone()) {
65     outFace = aMkFace.Face();     
66     if(!outFace.IsNull()) {
67 #ifdef DEB_SPLIT_TO_ZONES
68 //        BRepTools::Write(limFace,"FL.brep");
69 #endif
70       return Standard_True;
71         }
72   }
73   return Standard_False;
74 }
75 //======================================================================================
76 Standard_Integer HYDROData_SplitToZonesTool::SplitFaces(const TopoDS_Compound& theComp, 
77                                                                                                                 HYDROData_Transform& theTool)
78 {
79   theTool.Clear();
80   theTool.SetArgument(theComp);
81   theTool.Detect();
82   const Standard_Boolean bToTransform = theTool.ToTransform();  
83   theTool.SetToTransform(bToTransform);  
84   theTool.Perform();
85   Standard_Integer anErr = theTool.ErrorStatus();
86   return anErr;
87 }
88
89 //======================================================================================
90 HYDROData_SplitToZonesTool::SplitDataList
91   HYDROData_SplitToZonesTool::Split( const HYDROData_SequenceOfObjects&  theObjectList,
92                                      const HYDROData_SequenceOfObjects&  theGroupsList,
93                                      const Handle(HYDROData_PolylineXY)& thePolyline )
94 {
95   SplitDataList anOutputSplitDataList;
96   if(theObjectList.IsEmpty()) return anOutputSplitDataList;
97   // Preparation. 
98   // Collect the object shapes to split. InputDataList will contain elements which will hold shape & name_of_shape.
99   SplitDataList anInputSplitDataList;
100   TCollection_AsciiString aNam("Faces_");
101   for( int anIndex = 1, aLength = theObjectList.Length(); anIndex <= aLength; anIndex++ )
102   {
103     Handle(HYDROData_Object) aGeomObj = 
104       Handle(HYDROData_Object)::DownCast( theObjectList.Value( anIndex ) );
105     if( aGeomObj.IsNull() )
106       continue;
107
108     TopoDS_Shape aShape = aGeomObj->GetTopShape();
109     if ( aShape.IsNull() )
110       continue;  
111    //TCollection_AsciiString aName = aNam + anIndex + ".brep";
112    //BRepTools::Write(aShape, aName.ToCString());
113
114     if ( aShape.ShapeType() == TopAbs_COMPOUND ) {
115       // Create split data for each face contained in the compound
116       TopExp_Explorer anExp( aShape, TopAbs_FACE );
117       for ( ; anExp.More(); anExp.Next() ) {
118         const TopoDS_Face& aFace = TopoDS::Face( anExp.Current() );
119         if ( !aFace.IsNull() ) {
120           SplitData aSplitData( SplitData::Data_Zone, aFace, aGeomObj->GetName() );
121           anInputSplitDataList.append( aSplitData );
122         }
123       }
124     } else {
125       SplitData aSplitData( SplitData::Data_Zone, aShape, aGeomObj->GetName() );
126       anInputSplitDataList.append( aSplitData );
127     }
128   }
129   //
130   SplitDataList anInputGroupList;
131   for( int anIndex = 1; anIndex <= theGroupsList.Length(); anIndex++ )
132   {
133     Handle(HYDROData_ShapesGroup) aGeomGroup = 
134       Handle(HYDROData_ShapesGroup)::DownCast( theGroupsList.Value( anIndex ) );
135     if( aGeomGroup.IsNull() )
136       continue;
137       
138     TopTools_SequenceOfShape aGroupShapes;
139     aGeomGroup->GetShapes( aGroupShapes );
140     for( int i = 1, aNbShapes = aGroupShapes.Length(); i <= aNbShapes; i++ ) {
141       const TopoDS_Shape& aGroupShape = aGroupShapes.Value( i );
142       if ( aGroupShape.IsNull() )
143         continue;  
144
145       if ( aGroupShape.ShapeType() == TopAbs_COMPOUND ) {    
146         TopExp_Explorer anExp( aGroupShape, TopAbs_EDGE );
147         for ( ; anExp.More(); anExp.Next() ) {
148           const TopoDS_Edge& anEdge = TopoDS::Edge( anExp.Current() );
149           if ( !anEdge.IsNull() ) {
150             SplitData aSplitData( SplitData::Data_Edge, anEdge, aGeomGroup->GetName() );
151             anInputGroupList.append( aSplitData );
152           }
153           }
154       } else {
155         SplitData aSplitData( SplitData::Data_Edge, aGroupShape, aGeomGroup->GetName() );
156         anInputGroupList.append( aSplitData );
157       }
158     }
159   }
160   // If only one shape is given we don't split it 
161   // algorithm just returns the unpacked input data
162   if(theObjectList.Size() == 1)  {
163         anOutputSplitDataList.append(anInputSplitDataList); 
164         if(!theGroupsList.IsEmpty() ) 
165           anOutputSplitDataList.append(anInputGroupList);       
166     return anOutputSplitDataList;
167   }
168   HYDROData_DataMapOfShapeListOfString aDM3;
169   if(!anInputGroupList.isEmpty()) {// Old edge ==> List_Of_Names
170     QStringList aListOfNames;
171     for (int i=0;i < anInputGroupList.size() ;i++) {
172       const TopoDS_Shape& aSh = anInputGroupList.at(i).Shape;
173       aDM3.Bind(aSh, anInputGroupList.at(i).ObjectNames);
174     }
175   }
176   // Step 1. Prepare Partition structures. 
177   BOPCol_ListOfShape aLS;  
178   QStringList aListOfNames;
179   TopoDS_Compound aCmp;
180   BRep_Builder aBB;
181   aBB.MakeCompound(aCmp);
182   for (int i=0;i < anInputSplitDataList.size() ;i++) {
183     const TopoDS_Shape& aSh = anInputSplitDataList.at(i).Shape;
184     aDM3.Bind(aSh, anInputSplitDataList.at(i).ObjectNames);
185     aLS.Append(aSh);
186         aBB.Add(aCmp,aSh);
187     //TCollection_AsciiString aName = aNam + i + ".brep";
188     //BRepTools::Write(aSh, aName.ToCString());
189   }
190   HYDROData_Transform splitTool; 
191   const Standard_Integer anErr = SplitFaces(aCmp, splitTool);    
192   if(anErr)
193     return anOutputSplitDataList;
194   const TopoDS_Shape& aResult = splitTool.Shape();
195   if (aResult.IsNull()) 
196     return anOutputSplitDataList;
197   BRepCheck_Analyzer aCheck (aResult);
198   if(!aCheck.IsValid()) {
199 #ifdef DEB_SPLIT_TO_ZONES
200     cout << "result is not valid" <<endl;
201     BRepTools::Write(aResult, "SplitFacesNV.brep");  
202 #endif
203     return anOutputSplitDataList;
204   }
205 #ifdef DEB_SPLIT_TO_ZONES
206   BRepTools::Write(aResult, "SplitFacesV.brep");
207 #endif
208   
209   // Step 3. Collect history  
210   HYDROData_DataMapOfShapeListOfShape aDM1;
211   BOPCol_ListIteratorOfListOfShape anIt(aLS); 
212   //TCollection_AsciiString aNamM ("EdgM_");
213   //TCollection_AsciiString aNamG ("EdgG_");
214   for (int i =1;anIt.More();anIt.Next(),i++) {
215         Standard_Boolean foundF(Standard_False);
216     const TopTools_ListOfShape& aListOfNew = splitTool.Modified(anIt.Value());
217         if(!aListOfNew.IsEmpty())
218           foundF = Standard_True;
219     TopTools_ListOfShape aList;
220     TopTools_ListIteratorOfListOfShape it(aListOfNew);
221     for(;it.More();it.Next())       
222       aList.Append(it.Value());
223     // Bug in History: partition should give only modified entities! => temporary solution is used
224     const TopTools_ListOfShape& aListOfGen = splitTool.Generated(anIt.Value());
225         if(!aListOfGen.IsEmpty())
226           foundF = Standard_True;
227         it.Initialize(aListOfGen);    
228         for(;it.More();it.Next())     
229           aList.Append(it.Value());
230     if(!foundF) // face is not modified
231           aList.Append (anIt.Value());
232         aDM1.Bind(anIt.Value(), aList);
233         //TCollection_AsciiString aName;
234         if(!anInputGroupList.isEmpty() ) { // 1
235       aList.Clear();
236           TopExp_Explorer exp (anIt.Value(), TopAbs_EDGE);
237           for (int j =1;exp.More();exp.Next(),j++) {
238             Standard_Boolean foundE(Standard_False);
239             const TopTools_ListOfShape& aListM = splitTool.Modified(exp.Current());     
240                 //cout << "NB_EDGE_M = " << aListM.Extent() <<endl;
241                 if(aListM.Extent()) foundE = Standard_True;
242                 it.Initialize(aListM);    
243                 for(int k=1;it.More();it.Next(),k++) {    
244               aList.Append(it.Value());
245                   //aName = aNamM + i + j +k +".brep";
246                   //BRepTools::Write(it.Value(),aName.ToCString());
247                 }
248                 const TopTools_ListOfShape& aListG = splitTool.Generated(exp.Current());
249                 if(aListG.Extent()) foundE = Standard_True;
250                 it.Initialize(aListG);    
251                 for(int k=1;it.More();it.Next(),k++)   {  
252               aList.Append(it.Value());
253                   //aName = aNamG + i + j +k +".brep";
254                   //BRepTools::Write(it.Value(),aName.ToCString());
255                 }
256                 //cout << "NB_EDGE = " << aList.Extent() <<endl;
257                 if(!foundE) //{
258                   aList.Append (exp.Current());
259                 //aName = aNamG + i + j +".brep";
260                 //BRepTools::Write(exp.Current(),aName.ToCString());
261                 //}
262                 aDM1.Bind(exp.Current(), aList);
263           }      
264         }
265   }
266
267   // aDM2: NewShape ==> ListOfOldShapes
268   HYDROData_DataMapOfShapeListOfShape aDM2;
269   // make limiting face
270   HYDROData_DataMapOfShapeListOfShape aDM4;
271   Standard_Boolean hasLimits(Standard_False);
272   if (! thePolyline.IsNull()) {  
273     //const TopoDS_Shape aShape = thePolyline->GetShape();      
274     const TopoDS_Wire aBndWire = TopoDS::Wire(thePolyline->GetShape());
275     if(!aBndWire.IsNull()) {
276       TopoDS_Face limFace;        
277           if(buildLimFace(aBndWire, limFace)) {
278                 TopoDS_Shape aComResult;
279             BRepAlgoAPI_Common mkCom(aResult, limFace);
280                 if(mkCom.IsDone()) {
281               aComResult = mkCom.Shape();
282                   BRepCheck_Analyzer aCheck (aComResult);
283           if(aCheck.IsValid()) {
284 #ifdef DEB_SPLIT_TO_ZONES
285                     BRepTools::Write(aComResult,"CommonV.brep");
286 #endif  
287
288                     hasLimits = Standard_True; // DM2 should filled here
289                     HYDROData_MapOfShape aView;
290                     TopExp_Explorer exp (aResult, TopAbs_FACE);
291                     for (int i =1;exp.More();exp.Next(),i++) {
292               const TopoDS_Shape& aFace = exp.Current();
293                       if(!aFace.IsNull()) {
294                         const TopTools_ListOfShape& aListOfNew = mkCom.Modified(aFace);
295                           //cout << "Modified: " << aListOfNew.Extent() <<endl;                 
296                 const TopTools_ListOfShape& aListOfGen = mkCom.Generated(aFace);                        
297                             if(!aListOfNew.IsEmpty()) {
298                       aDM4.Bind(aFace, aListOfNew);
299                               //TCollection_AsciiString aName = aNam + i + ".brep";
300                                   //BRepTools::Write(aListOfNew.Last(), aName.ToCString());                             
301                                 }
302                                 else {
303                               if(!mkCom.IsDeleted(aFace)) {
304                                     if(!aListOfGen.IsEmpty()) {
305                           aDM4.Bind(aFace, aListOfGen);                        
306                                       //TCollection_AsciiString aName = aNam + i + "g.brep";
307                                       //BRepTools::Write(aListOfGen.Last(), aName.ToCString());
308                                         }
309                                          else {
310                                     TopTools_ListOfShape aList; 
311                                         aList.Append(aFace);
312                                         aDM4.Bind(aFace, aList); //the same face - not modified
313                                          }
314                                   }
315                          }
316                          TopExp_Explorer exp2 (aFace, TopAbs_EDGE);
317                          for (int j =1;exp2.More();exp2.Next(),j++) {
318                            const TopoDS_Shape& anEdge = exp2.Current();
319                            if(!anEdge.IsNull()) {
320                                  if(aView.Contains(anEdge)) continue;
321                                  aView.Add(anEdge);
322                                  const TopTools_ListOfShape& aListOfNewEd = mkCom.Modified(anEdge);
323                                  const TopTools_ListOfShape& aListOfGenEd = mkCom.Generated(anEdge);
324                  if(!aListOfNewEd.IsEmpty())
325                        aDM4.Bind(anEdge, aListOfNewEd);
326                                  else {
327                                    if(!mkCom.IsDeleted(anEdge)) {
328                                          if(!aListOfGenEd.IsEmpty()) {
329                                            aDM4.Bind(anEdge, aListOfGenEd);
330                                          } else {
331                                            TopTools_ListOfShape aList; 
332                                        aList.Append(anEdge);
333                                        aDM4.Bind(anEdge, aList);//the same edge - not modified
334                                          }
335                                    }
336                                  }
337                            }
338                          }
339                         }
340                   } //end DM4 filling (phase 1)
341                     //cout << "DM4 Ext = " <<aDM4.Extent() <<endl;
342                  // phase 2 (from tool)
343          TopExp_Explorer expt (limFace, TopAbs_EDGE);
344                  for(;expt.More();expt.Next()) {
345                    const TopoDS_Shape& anEdge = expt.Current();
346                    if(!anEdge.IsNull()) {
347              const TopTools_ListOfShape& aListOfNewEd = mkCom.Modified(anEdge);
348                          const TopTools_ListOfShape& aListOfGenEd = mkCom.Generated(anEdge);
349              if(!aListOfNewEd.IsEmpty())
350                    aDM4.Bind(anEdge, aListOfNewEd);
351                          else {
352                            if(!mkCom.IsDeleted(anEdge)) {
353                                  if(!aListOfGenEd.IsEmpty()) {
354                                    aDM4.Bind(anEdge, aListOfGenEd);
355                                  } else {
356                                    TopTools_ListOfShape aList; 
357                                aList.Append(anEdge);
358                                aDM4.Bind(anEdge, aList);//the same edge - not modified
359                                  }
360                            }
361                          }
362                    }
363                  }
364                  //cout << "DM4 Ext = " <<aDM4.Extent() <<endl;
365          HYDROData_DataMapIteratorOfDataMapOfShapeListOfShape aMIt(aDM1); 
366                  //DM4 contains Old - New after common op. DM1: old - new after Split op.
367          for(;aMIt.More();aMIt.Next()) {
368            const TopoDS_Shape& aKey = aMIt.Key();
369            TopTools_ListOfShape aList;
370            aList.Append(aKey);
371            const TopTools_ListOfShape& aListOfNew = aMIt.Value();
372            TopTools_ListIteratorOfListOfShape it(aListOfNew);
373            for(;it.More();it.Next()) {// iterate new: b1, b2, b3...
374                          if(!aDM4.IsBound(it.Value())) // bi - is deleted
375                continue; // go to the next bi
376                          else {
377                                 const TopTools_ListOfShape& aListOfNew4 = aDM4.Find(it.Value());
378                             TopTools_ListIteratorOfListOfShape it4(aListOfNew4); // {c1, c2, c3,...}
379                 for(;it4.More();it4.Next()) {
380                                   if(!aDM2.IsBound(it4.Value()))
381                     aDM2.Bind(it4.Value(), aList);
382                               else {
383                     TopTools_ListOfShape& aList = aDM2.ChangeFind(it4.Value());
384                     aList.Prepend(aKey);
385                                   }
386                                 }
387                          }
388                    }//
389                   }
390                  } else {
391                          hasLimits = Standard_False;
392 #ifdef DEB_SPLIT_TO_ZONES
393                      BRepTools::Write(aComResult,"CommonNV.brep");
394 #endif  
395                   }
396            }
397           }
398         }
399   }
400   if(!hasLimits) {
401     HYDROData_DataMapIteratorOfDataMapOfShapeListOfShape aMIt(aDM1);
402     for(;aMIt.More();aMIt.Next()) {
403       const TopoDS_Shape& aKey = aMIt.Key();
404       TopTools_ListOfShape aList;
405       aList.Append(aKey);
406       const TopTools_ListOfShape& aListOfNew = aMIt.Value();
407       TopTools_ListIteratorOfListOfShape it(aListOfNew);
408       for(;it.More();it.Next()) {
409         if(!aDM2.IsBound(it.Value()))
410           aDM2.Bind(it.Value(), aList);
411         else {
412           TopTools_ListOfShape& aList = aDM2.ChangeFind(it.Value());
413           aList.Prepend(aKey);
414                 }
415           }
416         }
417   }
418   // Step 4. Fill output structure.
419   //TCollection_AsciiString aNam4 ("SC_");
420   
421   HYDROData_DataMapIteratorOfDataMapOfShapeListOfShape aMIt(aDM2);
422   for(int i =1;aMIt.More();aMIt.Next(),i++) {
423     SplitData aDestSplitData;
424     const TopoDS_Shape& aKey = aMIt.Key(); //new
425     aDestSplitData.Shape = aKey;
426     if(aKey.ShapeType() == TopAbs_FACE)
427       aDestSplitData.Type = SplitData::Data_Zone;
428     else
429       aDestSplitData.Type = SplitData::Data_Edge;
430 #ifdef DEB_SPLIT_TO_ZONES
431           //TCollection_AsciiString aName = aNam4 + i + ".brep";
432           //BRepTools::Write(aKey,aName.ToCString());
433 #endif  
434
435
436     QStringList aListOfNames; // names processing
437     const TopTools_ListOfShape& aListOfOld = aMIt.Value();
438     TopTools_ListIteratorOfListOfShape it(aListOfOld);
439         for(;it.More();it.Next()) {     
440           const TopoDS_Shape& aSh = it.Value(); //old
441           if(aDM3.IsBound(aSh)) {
442             const QStringList& ObjectNames = aDM3.Find(aSh);
443                 aListOfNames.append(ObjectNames);
444           }      
445         }
446
447         aDestSplitData.ObjectNames = aListOfNames;  
448         anOutputSplitDataList.append(aDestSplitData);
449   }
450  
451   return anOutputSplitDataList;
452 }
453
454 bool HYDROData_SplitToZonesTool::SplitTwoData( const SplitData& theData1,
455                                                const SplitData& theData2,
456                                                SplitData& theData1Subtracted,
457                                                SplitData& theData2Subtracted,
458                                                SplitData& theDataIntersected )
459 {
460   const TopoDS_Shape& aShape1 = theData1.Shape;
461   const TopoDS_Shape& aShape2 = theData2.Shape;
462
463   const QStringList& anObjectNames1 = theData1.ObjectNames;
464   const QStringList& anObjectNames2 = theData2.ObjectNames;
465
466   BRepAlgoAPI_Common aCommon( aShape1, aShape2 );
467   TopoDS_Shape aCommonShape = aCommon.Shape();
468   if( aCommonShape.IsNull() )
469   {
470     theData1Subtracted = theData1;
471     theData2Subtracted = theData2;
472     return false;
473   }
474
475   BRepAlgoAPI_Cut aCut1( aShape1, aShape2 );
476   TopoDS_Shape aCut1Shape = aCut1.Shape();
477
478   BRepAlgoAPI_Cut aCut2( aShape2, aShape1 );
479   TopoDS_Shape aCut2Shape = aCut2.Shape();
480
481   theData1Subtracted = SplitData( SplitData::Data_Zone, aCut1Shape, anObjectNames1 );
482   theData2Subtracted = SplitData( SplitData::Data_Zone, aCut2Shape, anObjectNames2 );
483   theDataIntersected = SplitData( SplitData::Data_Zone, aCommonShape, anObjectNames1 + anObjectNames2 );
484
485   return true;
486 }
487
488 HYDROData_SplitToZonesTool::SplitDataList
489 HYDROData_SplitToZonesTool::ExtractSeparateData( const SplitData& theData )
490 {
491   SplitDataList aSplitDataList;
492   TopExp_Explorer anExp( theData.Shape, TopAbs_FACE );
493   for( ; anExp.More(); anExp.Next() )
494   {
495     TopoDS_Shape aShape = anExp.Current();
496     if( aShape.ShapeType() == TopAbs_FACE )
497     {
498       TopoDS_Face aFace = TopoDS::Face( aShape );
499       if( !aFace.IsNull() )
500       {
501         SplitData aSplitData( SplitData::Data_Zone, aFace, theData.ObjectNames );
502         aSplitDataList.append( aSplitData );
503       }
504     }
505   }
506   return aSplitDataList;
507 }