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.
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.
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
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #include "HYDROData_Region.h"
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"
30 #include <TopoDS_Shape.hxx>
31 #include <TopoDS_Shell.hxx>
32 #include <TopoDS_Face.hxx>
36 #include <TopTools_ListOfShape.hxx>
37 #include <TopTools_SequenceOfShape.hxx>
38 #include <TopTools_ListIteratorOfListOfShape.hxx>
39 #include <TopTools_IndexedMapOfShape.hxx>
42 #include <BRep_Builder.hxx>
43 #include <BRepAlgoAPI_Fuse.hxx>
45 #include <ShapeUpgrade_UnifySameDomain.hxx>
47 #include <QStringList>
50 #include "Geom_Plane.hxx"
52 #include "BRepTools_ReShape.hxx"
55 #include "HYDRO_trace.hxx"
57 //#define DEB_GET_REGION_SHAPE
59 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Entity)
62 HYDROData_Region::HYDROData_Region()
63 : HYDROData_Entity( Geom_2d )
67 HYDROData_Region::~HYDROData_Region()
71 bool HYDROData_Region::CanBeUpdated() const
76 void HYDROData_Region::Remove()
78 Handle(HYDROData_CalculationCase) aFatherCalc =
79 Handle(HYDROData_CalculationCase)::DownCast( GetFatherObject() );
81 HYDROData_Entity::Remove();
83 if ( !aFatherCalc.IsNull() )
84 aFatherCalc->UpdateRegionsOrder();
87 bool HYDROData_Region::CanRemove()
92 HYDROData_SequenceOfObjects HYDROData_Region::GetAllReferenceObjects() const
94 HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
96 HYDROData_SequenceOfObjects aSeqOfZones = GetZones();
97 aResSeq.Append( aSeqOfZones );
102 bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone )
104 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
106 if ( theZone.IsNull() )
109 if ( HasReference( theZone, DataTag_Zone ) )
110 return false; // Object is already in reference list
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 )
117 Handle(HYDROData_Zone) aNewZone = addNewZone( aDocument, "", TopoDS_Face(), QStringList() );
118 theZone->CopyTo( aNewZone, false );
120 // To prevent changing of stored shape
121 aNewZone->SetShape( theZone->GetShape() );
123 aFatherRegion->RemoveZone( theZone );
125 theZone->SetLabel( aNewZone->Label() );
129 AddReferenceObject( theZone, DataTag_Zone );
135 HYDROData_SequenceOfObjects HYDROData_Region::GetZones() const
137 return GetReferenceObjects( DataTag_Zone );
140 void HYDROData_Region::RemoveZone( const Handle(HYDROData_Zone)& theZone )
142 if ( theZone.IsNull() )
145 RemoveReferenceObject( theZone->Label(), DataTag_Zone );
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 )
153 // If the last zone has been removed from region we remove this region
154 HYDROData_SequenceOfObjects aRefZones = GetZones();
155 if ( aRefZones.IsEmpty() )
159 void HYDROData_Region::RemoveZones()
161 ClearReferenceObjects( DataTag_Zone );
162 myLab.FindChild( DataTag_ChildZone ).ForgetAllAttributes( true );
165 Handle(HYDROData_Zone) HYDROData_Region::addNewZone( const Handle(HYDROData_Document)& theDoc,
166 const QString& thePrefix,
167 const TopoDS_Face& theFace,
168 const QStringList& theRefObjects )
170 TDF_Label aNewLab = myLab.FindChild( DataTag_ChildZone ).NewChild();
172 Handle(HYDROData_Zone) aNewZone =
173 Handle(HYDROData_Zone)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_ZONE ) );
176 QString aZoneName = HYDROData_Tool::GenerateObjectName( theDoc, thePrefix );
177 aNewZone->SetName( aZoneName );
179 aNewZone->SetShape( theFace );
181 // Add the reference object for zone
182 for ( int i = 0, n = theRefObjects.length(); i < n; ++i )
184 const QString& anObjName = theRefObjects.at( i );
185 Handle(HYDROData_Entity) aRefObject = theDoc->FindObjectByName( anObjName );
186 if ( aRefObject.IsNull() )
189 aNewZone->AddObject( aRefObject );
195 void getUsedGroups( const TopoDS_Shape& theShape,
196 HYDROData_ShapesGroup::SeqOfGroupsDefs& theOriGroups,
197 HYDROData_ShapesGroup::SeqOfGroupsDefs& theUsedGroups )
199 #ifdef DEB_GET_REGION_SHAPE
200 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Zone face edges:", theShape, TopAbs_EDGE );
203 TopTools_IndexedMapOfShape aMapOfSubShapes;
204 TopExp::MapShapes( theShape, TopAbs_EDGE, aMapOfSubShapes );
206 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anIter( theOriGroups );
207 for ( ; anIter.More(); anIter.Next() )
209 HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anIter.ChangeValue();
210 if ( anOriGroupDef.Shapes.IsEmpty() )
213 for ( int i = 1; i <= anOriGroupDef.Shapes.Length(); ++i )
215 TopoDS_Shape aGroupEdge = anOriGroupDef.Shapes.Value( i );
217 int aShapeIndex = aMapOfSubShapes.FindIndex( aGroupEdge );
218 if ( aShapeIndex <= 0 )
221 anOriGroupDef.Shapes.Remove( i );
224 bool anIsAdded = false;
226 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( theUsedGroups );
227 for ( ; aUsedIter.More(); aUsedIter.Next() )
229 HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.ChangeValue();
230 if ( aUsedGroupDef.Name != anOriGroupDef.Name )
233 aUsedGroupDef.Shapes.Append( aGroupEdge );
240 HYDROData_ShapesGroup::GroupDefinition aUsedGroupDef;
241 aUsedGroupDef.Name = anOriGroupDef.Name;
242 aUsedGroupDef.Shapes.Append( aGroupEdge );
243 theUsedGroups.Append( aUsedGroupDef );
250 TopoDS_Shape HYDROData_Region::GetShape( HYDROData_ShapesGroup::SeqOfGroupsDefs* theSeqOfGroups, const TopTools_SequenceOfShape* IntSh ) const
252 DEBTRACE("GetShape");
253 HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfGroups;
254 HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfUsedGroups;
255 if ( theSeqOfGroups )
256 aSeqOfGroups = *theSeqOfGroups;
258 #ifdef DEB_GET_REGION_SHAPE
259 HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfGroups );
262 TopoDS_Shape aResShape;
264 // Unite the region zones (each zone is a face) into one face (united face)
265 // If the zones can't be united into the single face - unite them into shell
267 // Collect the list of region faces
268 TopTools_ListOfShape aRegionFacesList;
270 HYDROData_SequenceOfObjects aZones = GetZones();
271 HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones );
272 TopTools_IndexedMapOfShape AllE;
273 TopTools_IndexedMapOfShape IE; //int edges
275 for ( ; aZoneIter.More(); aZoneIter.Next() )
277 Handle(HYDROData_Zone) aZone =
278 Handle(HYDROData_Zone)::DownCast( aZoneIter.Value() );
279 if ( aZone.IsNull() )
282 TopoDS_Shape aZoneShape = aZone->GetShape();
283 if ( aZoneShape.IsNull() || aZoneShape.ShapeType() != TopAbs_FACE )
286 TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape );
287 aRegionFacesList.Append( aZoneFace );
288 TopExp::MapShapes(aZoneFace, TopAbs_EDGE, AllE); // collect all edges
289 getUsedGroups( aZoneFace, aSeqOfGroups, aSeqOfUsedGroups );
292 DEBTRACE("--- IntSh->Length():" << IntSh->Length());
293 for (int i = 1; i <= IntSh->Length(); i++)
295 const TopoDS_Shape& CS = (*IntSh)(i);
296 if (AllE.Contains(CS))
300 if ( aRegionFacesList.IsEmpty() )
303 TopoDS_Face aRegionFace;
305 if ( aRegionFacesList.Extent() == 1 )
307 DEBTRACE("--- aRegionFacesList.Extent() == 1 ");
308 aResShape = TopoDS::Face( aRegionFacesList.First() );
312 #ifdef DEB_GET_REGION_SHAPE
313 HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfUsedGroups );
316 // Try to fuse all region faces into one common face
317 TopoDS_Shape aFuseShape;
318 TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
319 for ( ; aFaceIter.More(); aFaceIter.Next() )
321 if ( aFuseShape.IsNull() )
323 aFuseShape = aFaceIter.Value();
327 BRepAlgoAPI_Fuse aFuse( aFuseShape, aFaceIter.Value() );
328 if ( !aFuse.IsDone() )
330 aFuseShape.Nullify();
334 aFuseShape = aFuse.Shape();
336 //update history of internal edges
337 TopTools_IndexedMapOfShape DIE;
338 TopTools_ListOfShape newSh1, newSh2;
339 DEBTRACE("IE.Extent():" << IE.Extent());
340 for (int i = 1; i <= IE.Extent(); i++)
342 const TopoDS_Shape& CSH = IE(i);
345 newSh1 = aFuse.Modified(CSH);
346 if (newSh1.IsEmpty())
348 newSh2 = aFuse.Generated(CSH);
349 if (newSh2.IsEmpty())
352 for (TopTools_ListIteratorOfListOfShape lt(newSh2); lt.More(); lt.Next())
353 if (!lt.Value().IsNull())
358 for (TopTools_ListIteratorOfListOfShape lt(newSh1); lt.More(); lt.Next())
359 if (!lt.Value().IsNull())
365 HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &aFuse );
368 #ifdef DEB_GET_REGION_SHAPE
369 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Fused face edges:", aFuseShape, TopAbs_EDGE );
372 aFuseShape = HYDROData_Tool::RebuildCmp(aFuseShape);
378 DEBTRACE("---!IE.IsEmpty() ");
379 //add dummy face to existing shell
380 //this face contains all internal edges
381 //USD algo will skip such edges and will not perform unifying through them
382 //(more than 2 faces are connected to one edge + non same domain surfaces)
384 Handle(Geom_Plane) DPl = new Geom_Plane(gp_Pln (gp_Pnt(0,0,0), gp_Dir(0,1,0))); //non same domain with the main surf
385 BB.MakeFace(DF, DPl, Precision::Confusion());
387 for (int i = 1; i <= IE.Extent(); i++)
390 BB.Add(aFuseShape, DF);
393 ShapeUpgrade_UnifySameDomain unif( aFuseShape, Standard_False, Standard_True, Standard_False );
395 TopoDS_Shape anUnitedShape;
396 const TopoDS_Shape& out = unif.Shape();
398 HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &unif );
402 //remove dummy face from shell; shell becomes valid
403 const TopoDS_Shape& NDF = unif.History()->Modified(DF).First();
404 BRepTools_ReShape ReShaper;
405 ReShaper.Remove(NDF);
406 anUnitedShape = ReShaper.Apply(out);
407 HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &ReShaper );
412 TopTools_SequenceOfShape aShapeFaces;
413 HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_FACE, aShapeFaces );
414 if ( aShapeFaces.Length() == 1 ) //it should be either face or compound of faces (?)
416 const TopoDS_Face& CF = TopoDS::Face( aShapeFaces.Value( 1 ));
421 TopTools_SequenceOfShape aShapeShells;
422 HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_SHELL, aShapeShells );
423 if (aShapeShells.Length() == 1)
424 aResShape = TopoDS::Shell(aShapeShells(1));
426 aResShape = anUnitedShape;
429 // Update the sequence of groups
430 if ( theSeqOfGroups )
432 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( aSeqOfUsedGroups );
433 for ( ; aUsedIter.More(); aUsedIter.Next() )
435 const HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.Value();
436 if ( aUsedGroupDef.Shapes.IsEmpty() )
439 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anOriIter( aSeqOfGroups );
440 for ( ; anOriIter.More(); anOriIter.Next() )
442 HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anOriIter.ChangeValue();
443 if ( anOriGroupDef.Name != aUsedGroupDef.Name )
446 HYDROData_ShapesTool::AddShapes( anOriGroupDef.Shapes, aUsedGroupDef.Shapes );
451 *theSeqOfGroups = aSeqOfGroups;
458 QStringList HYDROData_Region::DumpToPython( const QString& thePyScriptPath,
459 MapOfTreatedObjects& theTreatedObjects,
460 QString defRegName ) const
462 QStringList aResList;
465 findPythonReferenceObject( aResList, defRegName );
468 HYDROData_SequenceOfObjects aZones = GetZones();
469 HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
470 for ( ; aZonesIter.More(); aZonesIter.Next() ) {
471 Handle(HYDROData_Zone) aZone =
472 Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
473 if ( aZone.IsNull() ) {
478 aZone->findPythonReferenceObject( aResList );
479 theTreatedObjects.insert( aZone->GetName(), aZone );
481 // set zone merge type
482 QString aMergeTypeStr;
483 HYDROData_Zone::MergeType aMergeType = aZone->GetMergeType();
484 if ( aMergeType == HYDROData_Zone::Merge_ZMIN ) {
485 aMergeTypeStr = "HYDROData_Zone.Merge_ZMIN";
486 } else if ( aMergeType == HYDROData_Zone::Merge_ZMAX ) {
487 aMergeTypeStr = "HYDROData_Zone.Merge_ZMAX";
488 } else if ( aMergeType == HYDROData_Zone::Merge_Object ) {
489 aMergeTypeStr = "HYDROData_Zone.Merge_Object";
492 if ( !aMergeTypeStr.isEmpty() ) {
493 aResList << QString( "%1.SetMergeType( %2 )" ).arg( aZone->GetObjPyName() ).arg( aMergeTypeStr );
495 if ( aMergeType == HYDROData_Zone::Merge_Object ) {
496 Handle(HYDROData_Entity) aMergeObject = aZone->GetMergeObject();
497 if ( !aMergeObject.IsNull() ) {
498 aMergeObject->findPythonReferenceObject( aResList );
499 aResList << QString( "%1.SetMergeObject( %2 )" ).arg( aZone->GetObjPyName() )
500 .arg( aMergeObject->GetObjPyName() );
504 QColor zoneColor = aZone->GetColor(Qt::darkBlue);
505 aResList << QString( "%1.SetColor( QColor( %2, %3, %4 ))" )
506 .arg( aZone->GetObjPyName() ).arg( zoneColor.red() ).arg( zoneColor.green() ).arg( zoneColor.blue() );
508 setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aZone, "AddZone" );
515 bool HYDROData_Region::IsSubmersible() const
517 HYDROData_SequenceOfObjects aZones = GetZones();
518 HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
519 for ( ; aZonesIter.More(); aZonesIter.Next() )
521 Handle(HYDROData_Zone) aZone =
522 Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
523 if ( !aZone->IsSubmersible() )
524 return false; //if one of zones is not submersible the region is considered as not submersible