]> SALOME platform Git repositories - modules/hydro.git/blob - src/HYDROData/HYDROData_Region.cxx
Salome HOME
LOT 15
[modules/hydro.git] / src / HYDROData / HYDROData_Region.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include "HYDROData_Region.h"
20
21 #include "HYDROData_CalculationCase.h"
22 #include "HYDROData_Document.h"
23 #include "HYDROData_Iterator.h"
24 #include "HYDROData_Object.h"
25 #include "HYDROData_ShapesTool.h"
26 #include "HYDROData_Zone.h"
27 #include "HYDROData_Tool.h"
28
29 #include <TopoDS.hxx>
30 #include <TopoDS_Shape.hxx>
31 #include <TopoDS_Shell.hxx>
32 #include <TopoDS_Face.hxx>
33
34 #include <TopExp.hxx>
35
36 #include <TopTools_ListOfShape.hxx>
37 #include <TopTools_SequenceOfShape.hxx>
38 #include <TopTools_ListIteratorOfListOfShape.hxx>
39 #include <TopTools_IndexedMapOfShape.hxx>
40
41
42 #include <BRep_Builder.hxx>
43 #include <BRepAlgoAPI_Fuse.hxx>
44
45 #include <ShapeUpgrade_UnifySameDomain.hxx>
46
47 #include <QStringList>
48 #include <QColor>
49
50 #include "Geom_Plane.hxx"
51 #include "gp_Pln.hxx"
52 #include "BRepTools_ReShape.hxx"
53
54 //#define _DEVDEBUG_
55 #include "HYDRO_trace.hxx"
56
57 //#define DEB_GET_REGION_SHAPE
58
59 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Entity)
60
61
62 HYDROData_Region::HYDROData_Region()
63  : HYDROData_Entity( Geom_2d )
64 {
65 }
66
67 HYDROData_Region::~HYDROData_Region()
68 {
69 }
70
71 bool HYDROData_Region::CanBeUpdated() const
72 {
73   return false;
74 }
75
76 void HYDROData_Region::Remove()
77 {
78   Handle(HYDROData_CalculationCase) aFatherCalc = 
79     Handle(HYDROData_CalculationCase)::DownCast( GetFatherObject() );
80
81   HYDROData_Entity::Remove();
82
83   if ( !aFatherCalc.IsNull() )
84     aFatherCalc->UpdateRegionsOrder();
85 }
86
87 bool HYDROData_Region::CanRemove()
88 {
89   return false;
90 }
91
92 HYDROData_SequenceOfObjects HYDROData_Region::GetAllReferenceObjects() const
93 {
94   HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
95
96   HYDROData_SequenceOfObjects aSeqOfZones = GetZones();
97   aResSeq.Append( aSeqOfZones );
98
99   return aResSeq;
100 }
101
102 bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone )
103 {
104   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
105
106   if ( theZone.IsNull() )
107     return false;
108   
109   if ( HasReference( theZone, DataTag_Zone ) )
110     return false; // Object is already in reference list
111
112   // Move the zone from other region
113   Handle(HYDROData_Region) aFatherRegion = 
114     Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
115   if ( !aFatherRegion.IsNull() && aFatherRegion->Label() != myLab )
116   {
117     Handle(HYDROData_Zone) aNewZone = addNewZone( aDocument, "", TopoDS_Face(), QStringList() );
118     theZone->CopyTo( aNewZone, false );
119
120     // To prevent changing of stored shape
121     aNewZone->SetShape( theZone->GetShape() );
122
123     aFatherRegion->RemoveZone( theZone );
124
125     theZone->SetLabel( aNewZone->Label() );
126   }
127   else
128   {
129     AddReferenceObject( theZone, DataTag_Zone );
130   }
131
132   return true;
133 }
134
135 HYDROData_SequenceOfObjects HYDROData_Region::GetZones() const
136 {
137   return GetReferenceObjects( DataTag_Zone );
138 }
139
140 void HYDROData_Region::RemoveZone( const Handle(HYDROData_Zone)& theZone,  bool removeRegion )
141 {
142   if ( theZone.IsNull() )
143     return;
144
145   RemoveReferenceObject( theZone->Label(), DataTag_Zone );
146
147   // Remove zone from data model
148   Handle(HYDROData_Region) aFatherRegion = 
149     Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
150   if ( !aFatherRegion.IsNull() && aFatherRegion->Label() == myLab )
151     theZone->Remove();
152
153   if (removeRegion)
154   {
155     // If the last zone has been removed from region we remove this region
156     HYDROData_SequenceOfObjects aRefZones = GetZones();
157     if ( aRefZones.IsEmpty() )
158       Remove();
159   }
160 }
161
162 void HYDROData_Region::RemoveZones()
163 {
164   ClearReferenceObjects( DataTag_Zone );
165   myLab.FindChild( DataTag_ChildZone ).ForgetAllAttributes( true );
166 }
167
168 Handle(HYDROData_Zone) HYDROData_Region::addNewZone( const Handle(HYDROData_Document)& theDoc,
169                                                      const QString& thePrefix,
170                                                      const TopoDS_Face& theFace,
171                                                      const QStringList& theRefObjects )
172 {
173   TDF_Label aNewLab = myLab.FindChild( DataTag_ChildZone ).NewChild();
174
175   Handle(HYDROData_Zone) aNewZone =
176     Handle(HYDROData_Zone)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_ZONE ) );
177   AddZone( aNewZone );
178
179   QString aZoneName = HYDROData_Tool::GenerateObjectName( theDoc, thePrefix );
180   aNewZone->SetName( aZoneName );
181
182   aNewZone->SetShape( theFace );
183
184   // Add the reference object for zone
185   for ( int i = 0, n = theRefObjects.length(); i < n; ++i )
186   {
187     const QString& anObjName = theRefObjects.at( i );
188     Handle(HYDROData_Entity) aRefObject = theDoc->FindObjectByName( anObjName );
189     if ( aRefObject.IsNull() )
190       continue;
191
192     aNewZone->AddObject( aRefObject );
193   }
194
195   return aNewZone;
196 }
197
198 void getUsedGroups( const TopoDS_Shape&                     theShape,
199                     HYDROData_ShapesGroup::SeqOfGroupsDefs& theOriGroups,
200                     HYDROData_ShapesGroup::SeqOfGroupsDefs& theUsedGroups )
201 {
202 #ifdef DEB_GET_REGION_SHAPE
203   HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Zone face edges:", theShape, TopAbs_EDGE );
204 #endif
205
206   TopTools_IndexedMapOfShape aMapOfSubShapes;
207   TopExp::MapShapes( theShape, TopAbs_EDGE, aMapOfSubShapes );
208
209   HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anIter( theOriGroups );
210   for ( ; anIter.More(); anIter.Next() )
211   {
212     HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anIter.ChangeValue();
213     if ( anOriGroupDef.Shapes.IsEmpty() )
214       continue;
215
216     for ( int i = 1; i <= anOriGroupDef.Shapes.Length(); ++i )
217     {
218       TopoDS_Shape aGroupEdge = anOriGroupDef.Shapes.Value( i );
219       
220       int aShapeIndex = aMapOfSubShapes.FindIndex( aGroupEdge );
221       if ( aShapeIndex <= 0 )
222         continue;
223
224       anOriGroupDef.Shapes.Remove( i );
225       --i;
226
227       bool anIsAdded = false;
228
229       HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( theUsedGroups );
230       for ( ; aUsedIter.More(); aUsedIter.Next() )
231       {
232         HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.ChangeValue();
233         if ( aUsedGroupDef.Name != anOriGroupDef.Name )
234           continue;
235
236         aUsedGroupDef.Shapes.Append( aGroupEdge );
237         anIsAdded = true;
238         break;
239       }
240
241       if ( !anIsAdded )
242       {
243         HYDROData_ShapesGroup::GroupDefinition aUsedGroupDef;
244         aUsedGroupDef.Name = anOriGroupDef.Name;
245         aUsedGroupDef.Shapes.Append( aGroupEdge );
246         theUsedGroups.Append( aUsedGroupDef );
247       }
248     }
249   }
250 }
251
252
253 TopoDS_Shape HYDROData_Region::GetShape( HYDROData_ShapesGroup::SeqOfGroupsDefs* theSeqOfGroups, const TopTools_SequenceOfShape* IntSh ) const
254 {
255   DEBTRACE("GetShape");
256   HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfGroups;
257   HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfUsedGroups;
258   if ( theSeqOfGroups )
259     aSeqOfGroups = *theSeqOfGroups;
260
261 #ifdef DEB_GET_REGION_SHAPE
262   HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfGroups );
263 #endif
264
265   TopoDS_Shape aResShape;
266
267   // Unite the region zones (each zone is a face) into one face (united face)
268   // If the zones can't be united into the single face - unite them into shell
269
270   // Collect the list of region faces
271   TopTools_ListOfShape aRegionFacesList;
272
273   HYDROData_SequenceOfObjects aZones = GetZones();
274   HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones );
275   TopTools_IndexedMapOfShape AllE;
276   TopTools_IndexedMapOfShape IE; //int edges
277
278   for ( ; aZoneIter.More(); aZoneIter.Next() )
279   {
280     Handle(HYDROData_Zone) aZone =
281       Handle(HYDROData_Zone)::DownCast( aZoneIter.Value() );
282     if ( aZone.IsNull() )
283       continue;
284
285     TopoDS_Shape aZoneShape = aZone->GetShape();
286     if ( aZoneShape.IsNull() || aZoneShape.ShapeType() != TopAbs_FACE )
287       continue;
288
289     TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape );
290     aRegionFacesList.Append( aZoneFace );
291     TopExp::MapShapes(aZoneFace, TopAbs_EDGE, AllE); // collect all edges
292     getUsedGroups( aZoneFace, aSeqOfGroups, aSeqOfUsedGroups );
293   } // zones iterator
294
295   DEBTRACE("--- IntSh->Length():" << IntSh->Length());
296   for (int i = 1; i <= IntSh->Length(); i++)
297   {
298     const TopoDS_Shape& CS = (*IntSh)(i);
299     if (AllE.Contains(CS))
300       IE.Add(CS);
301   }
302   
303   if ( aRegionFacesList.IsEmpty() )
304     return aResShape;
305
306   TopoDS_Face aRegionFace;
307
308   if ( aRegionFacesList.Extent() == 1 )
309   {
310     DEBTRACE("--- aRegionFacesList.Extent() == 1 ");
311     aResShape = TopoDS::Face( aRegionFacesList.First() );
312   }
313   else
314   {
315 #ifdef DEB_GET_REGION_SHAPE
316     HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfUsedGroups );
317 #endif
318
319     // Try to fuse all region faces into one common face
320     TopoDS_Shape aFuseShape;
321     TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
322     for ( ; aFaceIter.More(); aFaceIter.Next() )
323     {
324       if ( aFuseShape.IsNull() )
325       {
326         aFuseShape = aFaceIter.Value();
327         continue;
328       }
329
330       BRepAlgoAPI_Fuse aFuse( aFuseShape, aFaceIter.Value() );
331       if ( !aFuse.IsDone() )
332       {
333         aFuseShape.Nullify();
334         break;
335       }
336
337       aFuseShape = aFuse.Shape();
338
339       //update history of internal edges
340       TopTools_IndexedMapOfShape DIE;
341       TopTools_ListOfShape newSh1, newSh2;
342       DEBTRACE("IE.Extent():" << IE.Extent());
343       for (int i = 1; i <= IE.Extent(); i++)
344       {
345         const TopoDS_Shape& CSH = IE(i);
346         newSh1.Clear();
347         newSh2.Clear();
348         newSh1 = aFuse.Modified(CSH);
349         if (newSh1.IsEmpty())
350         {
351           newSh2 = aFuse.Generated(CSH);
352           if (newSh2.IsEmpty())
353             DIE.Add(CSH);
354           else
355             for (TopTools_ListIteratorOfListOfShape lt(newSh2); lt.More(); lt.Next())
356               if (!lt.Value().IsNull())
357                  DIE.Add(lt.Value());
358         }
359         else
360         {
361           for (TopTools_ListIteratorOfListOfShape lt(newSh1); lt.More(); lt.Next())
362             if (!lt.Value().IsNull())
363               DIE.Add(lt.Value());
364         }
365       }
366       IE = DIE;
367       //update groups
368       HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &aFuse );
369     } // faces iterator
370
371 #ifdef DEB_GET_REGION_SHAPE
372     HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Fused face edges:", aFuseShape, TopAbs_EDGE );
373 #endif
374
375     aFuseShape = HYDROData_Tool::RebuildCmp(aFuseShape);
376
377     ShapeUpgrade_UnifySameDomain unif( aFuseShape, Standard_False, Standard_True, Standard_False );
378     if (!IE.IsEmpty())
379     {
380       TopTools_MapOfShape IEM;
381       for (int i = 1; i <= IE.Extent(); i++)
382         IEM.Add(IE(i));
383       unif.KeepShapes(IEM);
384     }
385
386     unif.Build();
387     TopoDS_Shape anUnitedShape;
388     anUnitedShape = unif.Shape();
389
390     HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &unif );
391
392     //cout << "inif:   fuseshape: " << aFuseShape.TShape().get() << "unifS " << anUnitedShape.TShape().get() << endl;
393 #ifdef DEB_GET_REGION_SHAPE
394     HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfUsedGroups );
395 #endif
396
397     TopTools_SequenceOfShape aShapeFaces;
398     HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_FACE, aShapeFaces );
399     if ( aShapeFaces.Length() == 1 ) //it should be either face or compound of faces (?)
400     {
401       const TopoDS_Face& CF = TopoDS::Face( aShapeFaces.Value( 1 ));
402       aResShape = CF;
403     }
404     else
405     {
406       TopTools_SequenceOfShape aShapeShells;
407       HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_SHELL, aShapeShells );
408       if (aShapeShells.Length() == 1)
409         aResShape = TopoDS::Shell(aShapeShells(1));
410       else
411         aResShape = anUnitedShape;
412     }
413
414     // Update the sequence of groups
415     if ( theSeqOfGroups )
416     {
417       HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( aSeqOfUsedGroups );
418       for ( ; aUsedIter.More(); aUsedIter.Next() )
419       {
420         const HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.Value();
421         if ( aUsedGroupDef.Shapes.IsEmpty() )
422           continue;
423
424         HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anOriIter( aSeqOfGroups );
425         for ( ; anOriIter.More(); anOriIter.Next() )
426         {
427           HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anOriIter.ChangeValue();
428           if ( anOriGroupDef.Name != aUsedGroupDef.Name )
429             continue;
430
431           HYDROData_ShapesTool::AddShapes( anOriGroupDef.Shapes, aUsedGroupDef.Shapes );
432           break;
433         }
434       }
435
436       *theSeqOfGroups = aSeqOfGroups;
437     }
438   }
439                                                      
440   return aResShape;
441 }
442
443 QStringList HYDROData_Region::DumpToPython( const QString&       thePyScriptPath,
444                                             MapOfTreatedObjects& theTreatedObjects,
445                                             QString              defRegName ) const
446 {
447   QStringList aResList;
448
449   // Find region
450   findPythonReferenceObject( aResList, defRegName );
451
452   // Add zones
453   HYDROData_SequenceOfObjects aZones = GetZones();
454   HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
455   for ( ; aZonesIter.More(); aZonesIter.Next() ) {
456     Handle(HYDROData_Zone) aZone =
457       Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
458     if ( aZone.IsNull() ) {
459       continue;
460     }
461     
462     // find zone
463     aZone->findPythonReferenceObject( aResList );
464     theTreatedObjects.insert( aZone->GetName(), aZone );
465     
466     // set zone merge type
467     QString aMergeTypeStr;
468     HYDROData_Zone::MergeType aMergeType = aZone->GetMergeType();
469     if ( aMergeType == HYDROData_Zone::Merge_ZMIN ) {
470       aMergeTypeStr = "HYDROData_Zone.Merge_ZMIN";
471     } else if ( aMergeType == HYDROData_Zone::Merge_ZMAX ) {
472       aMergeTypeStr = "HYDROData_Zone.Merge_ZMAX";
473     } else if ( aMergeType == HYDROData_Zone::Merge_Object ) {
474       aMergeTypeStr = "HYDROData_Zone.Merge_Object";
475     }
476
477     if ( !aMergeTypeStr.isEmpty() ) {
478       aResList << QString( "%1.SetMergeType( %2 )" ).arg( aZone->GetObjPyName() ).arg( aMergeTypeStr );
479     }
480     if ( aMergeType == HYDROData_Zone::Merge_Object ) {
481       Handle(HYDROData_Entity) aMergeObject = aZone->GetMergeObject();
482       if ( !aMergeObject.IsNull() ) {
483         aMergeObject->findPythonReferenceObject( aResList );
484         aResList << QString( "%1.SetMergeObject( %2 )" ).arg( aZone->GetObjPyName() )
485                                                         .arg( aMergeObject->GetObjPyName() );
486       }
487     }
488     // set color
489     QColor zoneColor = aZone->GetColor(Qt::darkBlue);
490     aResList << QString( "%1.SetColor( QColor( %2, %3, %4 ))" )
491                  .arg( aZone->GetObjPyName() ).arg( zoneColor.red() ).arg( zoneColor.green() ).arg( zoneColor.blue() );
492     // add zone
493     setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aZone, "AddZone" );
494
495   }
496
497   return aResList;
498 }
499
500 bool HYDROData_Region::IsSubmersible() const
501 {
502   HYDROData_SequenceOfObjects aZones = GetZones();
503   HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
504   for ( ; aZonesIter.More(); aZonesIter.Next() )
505   {
506     Handle(HYDROData_Zone) aZone =
507       Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
508     if ( !aZone->IsSubmersible() )
509       return false; //if one of zones is not submersible the region is considered as not submersible
510   }
511   return true;
512 }