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 "Handle_Geom_Plane.hxx"
51 #include "Geom_Plane.hxx"
53 #include "BRepTools_ReShape.hxx"
55 //#define DEB_GET_REGION_SHAPE
57 IMPLEMENT_STANDARD_HANDLE(HYDROData_Region, HYDROData_Entity)
58 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Entity)
61 HYDROData_Region::HYDROData_Region()
62 : HYDROData_Entity( Geom_2d )
66 HYDROData_Region::~HYDROData_Region()
70 bool HYDROData_Region::CanBeUpdated() const
75 void HYDROData_Region::Remove()
77 Handle(HYDROData_CalculationCase) aFatherCalc =
78 Handle(HYDROData_CalculationCase)::DownCast( GetFatherObject() );
80 HYDROData_Entity::Remove();
82 if ( !aFatherCalc.IsNull() )
83 aFatherCalc->UpdateRegionsOrder();
86 bool HYDROData_Region::CanRemove()
91 HYDROData_SequenceOfObjects HYDROData_Region::GetAllReferenceObjects() const
93 HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
95 HYDROData_SequenceOfObjects aSeqOfZones = GetZones();
96 aResSeq.Append( aSeqOfZones );
101 bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone )
103 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
105 if ( theZone.IsNull() )
108 if ( HasReference( theZone, DataTag_Zone ) )
109 return false; // Object is already in reference list
111 // Move the zone from other region
112 Handle(HYDROData_Region) aFatherRegion =
113 Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
114 if ( !aFatherRegion.IsNull() && aFatherRegion->Label() != myLab )
116 Handle(HYDROData_Zone) aNewZone = addNewZone( aDocument, "", TopoDS_Face(), QStringList() );
117 theZone->CopyTo( aNewZone, false );
119 // To prevent changing of stored shape
120 aNewZone->SetShape( theZone->GetShape() );
122 aFatherRegion->RemoveZone( theZone );
124 theZone->SetLabel( aNewZone->Label() );
128 AddReferenceObject( theZone, DataTag_Zone );
134 HYDROData_SequenceOfObjects HYDROData_Region::GetZones() const
136 return GetReferenceObjects( DataTag_Zone );
139 void HYDROData_Region::RemoveZone( const Handle(HYDROData_Zone)& theZone )
141 if ( theZone.IsNull() )
144 RemoveReferenceObject( theZone->Label(), DataTag_Zone );
146 // Remove zone from data model
147 Handle(HYDROData_Region) aFatherRegion =
148 Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
149 if ( !aFatherRegion.IsNull() && aFatherRegion->Label() == myLab )
152 // If the last zone has been removed from region we remove this region
153 HYDROData_SequenceOfObjects aRefZones = GetZones();
154 if ( aRefZones.IsEmpty() )
158 void HYDROData_Region::RemoveZones()
160 ClearReferenceObjects( DataTag_Zone );
161 myLab.FindChild( DataTag_ChildZone ).ForgetAllAttributes( true );
164 Handle(HYDROData_Zone) HYDROData_Region::addNewZone( const Handle(HYDROData_Document)& theDoc,
165 const QString& thePrefix,
166 const TopoDS_Face& theFace,
167 const QStringList& theRefObjects )
169 TDF_Label aNewLab = myLab.FindChild( DataTag_ChildZone ).NewChild();
171 Handle(HYDROData_Zone) aNewZone =
172 Handle(HYDROData_Zone)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_ZONE ) );
175 QString aZoneName = HYDROData_Tool::GenerateObjectName( theDoc, thePrefix );
176 aNewZone->SetName( aZoneName );
178 aNewZone->SetShape( theFace );
180 // Add the reference object for zone
181 for ( int i = 0, n = theRefObjects.length(); i < n; ++i )
183 const QString& anObjName = theRefObjects.at( i );
184 Handle(HYDROData_Entity) aRefObject = theDoc->FindObjectByName( anObjName );
185 if ( aRefObject.IsNull() )
188 aNewZone->AddObject( aRefObject );
194 void getUsedGroups( const TopoDS_Shape& theShape,
195 HYDROData_ShapesGroup::SeqOfGroupsDefs& theOriGroups,
196 HYDROData_ShapesGroup::SeqOfGroupsDefs& theUsedGroups )
198 #ifdef DEB_GET_REGION_SHAPE
199 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Zone face edges:", theShape, TopAbs_EDGE );
202 TopTools_IndexedMapOfShape aMapOfSubShapes;
203 TopExp::MapShapes( theShape, TopAbs_EDGE, aMapOfSubShapes );
205 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anIter( theOriGroups );
206 for ( ; anIter.More(); anIter.Next() )
208 HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anIter.ChangeValue();
209 if ( anOriGroupDef.Shapes.IsEmpty() )
212 for ( int i = 1; i <= anOriGroupDef.Shapes.Length(); ++i )
214 TopoDS_Shape aGroupEdge = anOriGroupDef.Shapes.Value( i );
216 int aShapeIndex = aMapOfSubShapes.FindIndex( aGroupEdge );
217 if ( aShapeIndex <= 0 )
220 anOriGroupDef.Shapes.Remove( i );
223 bool anIsAdded = false;
225 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( theUsedGroups );
226 for ( ; aUsedIter.More(); aUsedIter.Next() )
228 HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.ChangeValue();
229 if ( aUsedGroupDef.Name != anOriGroupDef.Name )
232 aUsedGroupDef.Shapes.Append( aGroupEdge );
239 HYDROData_ShapesGroup::GroupDefinition aUsedGroupDef;
240 aUsedGroupDef.Name = anOriGroupDef.Name;
241 aUsedGroupDef.Shapes.Append( aGroupEdge );
242 theUsedGroups.Append( aUsedGroupDef );
250 TopoDS_Shape HYDROData_Region::GetShape( HYDROData_ShapesGroup::SeqOfGroupsDefs* theSeqOfGroups, const TopTools_SequenceOfShape* IntSh ) const
252 HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfGroups;
253 HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfUsedGroups;
254 if ( theSeqOfGroups )
255 aSeqOfGroups = *theSeqOfGroups;
257 #ifdef DEB_GET_REGION_SHAPE
258 HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfGroups );
261 TopoDS_Shape aResShape;
263 // Unite the region zones (each zone is a face) into one face (united face)
264 // If the zones can't be united into the single face - unite them into shell
266 // Collect the list of region faces
267 TopTools_ListOfShape aRegionFacesList;
269 HYDROData_SequenceOfObjects aZones = GetZones();
270 HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones );
271 TopTools_IndexedMapOfShape AllE;
272 TopTools_IndexedMapOfShape IE; //int edges
274 for ( ; aZoneIter.More(); aZoneIter.Next() )
276 Handle(HYDROData_Zone) aZone =
277 Handle(HYDROData_Zone)::DownCast( aZoneIter.Value() );
278 if ( aZone.IsNull() )
281 TopoDS_Shape aZoneShape = aZone->GetShape();
282 if ( aZoneShape.IsNull() || aZoneShape.ShapeType() != TopAbs_FACE )
285 TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape );
286 aRegionFacesList.Append( aZoneFace );
287 TopExp::MapShapes(aZoneFace, TopAbs_EDGE, AllE); // collect all edges
288 getUsedGroups( aZoneFace, aSeqOfGroups, aSeqOfUsedGroups );
291 for (int i = 1; i <= IntSh->Length(); i++)
293 const TopoDS_Shape& CS = (*IntSh)(i);
294 if (AllE.Contains(CS))
298 if ( aRegionFacesList.IsEmpty() )
301 TopoDS_Face aRegionFace;
303 if ( aRegionFacesList.Extent() == 1 )
305 aResShape = TopoDS::Face( aRegionFacesList.First() );
309 #ifdef DEB_GET_REGION_SHAPE
310 HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfUsedGroups );
313 // Try to fuse all region faces into one common face
314 TopoDS_Shape aFuseShape;
315 TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
316 for ( ; aFaceIter.More(); aFaceIter.Next() )
318 if ( aFuseShape.IsNull() )
320 aFuseShape = aFaceIter.Value();
324 BRepAlgoAPI_Fuse aFuse( aFuseShape, aFaceIter.Value() );
325 if ( !aFuse.IsDone() )
327 aFuseShape.Nullify();
331 aFuseShape = aFuse.Shape();
333 //update history of internal edges
334 TopTools_IndexedMapOfShape DIE;
335 TopTools_ListOfShape newSh1, newSh2;
336 for (int i = 1; i <= IE.Extent(); i++)
338 const TopoDS_Shape& CSH = IE(i);
341 newSh1 = aFuse.Modified(CSH);
342 if (newSh1.IsEmpty())
344 newSh2 = aFuse.Generated(CSH);
345 if (newSh2.IsEmpty())
348 for (TopTools_ListIteratorOfListOfShape lt(newSh2); lt.More(); lt.Next())
349 if (!lt.Value().IsNull())
354 for (TopTools_ListIteratorOfListOfShape lt(newSh1); lt.More(); lt.Next())
355 if (!lt.Value().IsNull())
361 HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &aFuse );
364 #ifdef DEB_GET_REGION_SHAPE
365 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Fused face edges:", aFuseShape, TopAbs_EDGE );
372 //add dummy face to existing shell
373 //this face contains all internal edges
374 //USD algo will skip such edges and will not perform unifying through them
375 //(more than 2 faces are connected to one edge + non same domain surfaces)
377 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
378 BB.MakeFace(DF, DPl, Precision::Confusion());
380 for (int i = 1; i <= IE.Extent(); i++)
383 BB.Add(aFuseShape, DF);
386 ShapeUpgrade_UnifySameDomain unif( aFuseShape );
388 TopoDS_Shape anUnitedShape;
389 const TopoDS_Shape& out = unif.Shape();
391 HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &unif );
395 //remove dummy face from shell; shell becomes valid
396 const TopoDS_Shape& NDF = unif.Generated(DF);
397 BRepTools_ReShape ReShaper;
398 ReShaper.Remove(NDF);
399 anUnitedShape = ReShaper.Apply(out);
400 HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &ReShaper );
405 TopTools_SequenceOfShape aShapeFaces;
406 HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_FACE, aShapeFaces );
407 if ( aShapeFaces.Length() == 1 ) //it should be either face or compound of faces (?)
409 const TopoDS_Face& CF = TopoDS::Face( aShapeFaces.Value( 1 ));
414 TopTools_SequenceOfShape aShapeShells;
415 HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_SHELL, aShapeShells );
416 if (aShapeShells.Length() == 1)
417 aResShape = TopoDS::Shell(aShapeShells(1));
419 aResShape = anUnitedShape;
422 // Update the sequence of groups
423 if ( theSeqOfGroups )
425 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( aSeqOfUsedGroups );
426 for ( ; aUsedIter.More(); aUsedIter.Next() )
428 const HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.Value();
429 if ( aUsedGroupDef.Shapes.IsEmpty() )
432 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anOriIter( aSeqOfGroups );
433 for ( ; anOriIter.More(); anOriIter.Next() )
435 HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anOriIter.ChangeValue();
436 if ( anOriGroupDef.Name != aUsedGroupDef.Name )
439 HYDROData_ShapesTool::AddShapes( anOriGroupDef.Shapes, aUsedGroupDef.Shapes );
444 *theSeqOfGroups = aSeqOfGroups;
451 QStringList HYDROData_Region::DumpToPython( const QString& thePyScriptPath,
452 MapOfTreatedObjects& theTreatedObjects,
453 QString defRegName ) const
455 QStringList aResList;
458 findPythonReferenceObject( aResList, defRegName );
461 HYDROData_SequenceOfObjects aZones = GetZones();
462 HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
463 for ( ; aZonesIter.More(); aZonesIter.Next() ) {
464 Handle(HYDROData_Zone) aZone =
465 Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
466 if ( aZone.IsNull() ) {
471 aZone->findPythonReferenceObject( aResList );
472 theTreatedObjects.insert( aZone->GetName(), aZone );
474 // set zone merge type
475 QString aMergeTypeStr;
476 HYDROData_Zone::MergeType aMergeType = aZone->GetMergeType();
477 if ( aMergeType == HYDROData_Zone::Merge_ZMIN ) {
478 aMergeTypeStr = "HYDROData_Zone.Merge_ZMIN";
479 } else if ( aMergeType == HYDROData_Zone::Merge_ZMAX ) {
480 aMergeTypeStr = "HYDROData_Zone.Merge_ZMAX";
481 } else if ( aMergeType == HYDROData_Zone::Merge_Object ) {
482 aMergeTypeStr = "HYDROData_Zone.Merge_Object";
485 if ( !aMergeTypeStr.isEmpty() ) {
486 aResList << QString( "%1.SetMergeType( %2 )" ).arg( aZone->GetObjPyName() ).arg( aMergeTypeStr );
488 if ( aMergeType == HYDROData_Zone::Merge_Object ) {
489 Handle(HYDROData_Entity) aMergeObject = aZone->GetMergeObject();
490 if ( !aMergeObject.IsNull() ) {
491 aMergeObject->findPythonReferenceObject( aResList );
492 aResList << QString( "%1.SetMergeObject( %2 )" ).arg( aZone->GetObjPyName() )
493 .arg( aMergeObject->GetObjPyName() );
497 QColor zoneColor = aZone->GetColor(Qt::darkBlue);
498 aResList << QString( "%1.SetColor( QColor( %2, %3, %4 ))" )
499 .arg( aZone->GetObjPyName() ).arg( zoneColor.red() ).arg( zoneColor.green() ).arg( zoneColor.blue() );
501 setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aZone, "AddZone" );
508 bool HYDROData_Region::IsSubmersible() const
510 HYDROData_SequenceOfObjects aZones = GetZones();
511 HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
512 for ( ; aZonesIter.More(); aZonesIter.Next() )
514 Handle(HYDROData_Zone) aZone =
515 Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
516 if ( !aZone->IsSubmersible() )
517 return false; //if one of zones is not submersible the region is considered as not submersible