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>
41 #include <BRep_Builder.hxx>
42 #include <BRepAlgoAPI_Fuse.hxx>
44 #include <ShapeUpgrade_UnifySameDomain.hxx>
46 #include <QStringList>
49 //#define DEB_GET_REGION_SHAPE
51 IMPLEMENT_STANDARD_HANDLE(HYDROData_Region, HYDROData_Entity)
52 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Entity)
55 HYDROData_Region::HYDROData_Region()
56 : HYDROData_Entity( Geom_2d )
60 HYDROData_Region::~HYDROData_Region()
64 bool HYDROData_Region::CanBeUpdated() const
69 void HYDROData_Region::Remove()
71 Handle(HYDROData_CalculationCase) aFatherCalc =
72 Handle(HYDROData_CalculationCase)::DownCast( GetFatherObject() );
74 HYDROData_Entity::Remove();
76 if ( !aFatherCalc.IsNull() )
77 aFatherCalc->UpdateRegionsOrder();
80 bool HYDROData_Region::CanRemove()
85 HYDROData_SequenceOfObjects HYDROData_Region::GetAllReferenceObjects() const
87 HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
89 HYDROData_SequenceOfObjects aSeqOfZones = GetZones();
90 aResSeq.Append( aSeqOfZones );
95 bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone )
97 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
99 if ( theZone.IsNull() )
102 if ( HasReference( theZone, DataTag_Zone ) )
103 return false; // Object is already in reference list
105 // Move the zone from other region
106 Handle(HYDROData_Region) aFatherRegion =
107 Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
108 if ( !aFatherRegion.IsNull() && aFatherRegion->Label() != myLab )
110 Handle(HYDROData_Zone) aNewZone = addNewZone( aDocument, "", TopoDS_Face(), QStringList() );
111 theZone->CopyTo( aNewZone, false );
113 // To prevent changing of stored shape
114 aNewZone->SetShape( theZone->GetShape() );
116 aFatherRegion->RemoveZone( theZone );
118 theZone->SetLabel( aNewZone->Label() );
122 AddReferenceObject( theZone, DataTag_Zone );
128 HYDROData_SequenceOfObjects HYDROData_Region::GetZones() const
130 return GetReferenceObjects( DataTag_Zone );
133 void HYDROData_Region::RemoveZone( const Handle(HYDROData_Zone)& theZone )
135 if ( theZone.IsNull() )
138 RemoveReferenceObject( theZone->Label(), DataTag_Zone );
140 // Remove zone from data model
141 Handle(HYDROData_Region) aFatherRegion =
142 Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
143 if ( !aFatherRegion.IsNull() && aFatherRegion->Label() == myLab )
146 // If the last zone has been removed from region we remove this region
147 HYDROData_SequenceOfObjects aRefZones = GetZones();
148 if ( aRefZones.IsEmpty() )
152 void HYDROData_Region::RemoveZones()
154 ClearReferenceObjects( DataTag_Zone );
155 myLab.FindChild( DataTag_ChildZone ).ForgetAllAttributes( true );
158 Handle(HYDROData_Zone) HYDROData_Region::addNewZone( const Handle(HYDROData_Document)& theDoc,
159 const QString& thePrefix,
160 const TopoDS_Face& theFace,
161 const QStringList& theRefObjects )
163 TDF_Label aNewLab = myLab.FindChild( DataTag_ChildZone ).NewChild();
165 Handle(HYDROData_Zone) aNewZone =
166 Handle(HYDROData_Zone)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_ZONE ) );
169 QString aZoneName = HYDROData_Tool::GenerateObjectName( theDoc, thePrefix );
170 aNewZone->SetName( aZoneName );
172 aNewZone->SetShape( theFace );
174 // Add the reference object for zone
175 for ( int i = 0, n = theRefObjects.length(); i < n; ++i )
177 const QString& anObjName = theRefObjects.at( i );
178 Handle(HYDROData_Entity) aRefObject = theDoc->FindObjectByName( anObjName );
179 if ( aRefObject.IsNull() )
182 aNewZone->AddObject( aRefObject );
188 void getUsedGroups( const TopoDS_Shape& theShape,
189 HYDROData_ShapesGroup::SeqOfGroupsDefs& theOriGroups,
190 HYDROData_ShapesGroup::SeqOfGroupsDefs& theUsedGroups )
192 #ifdef DEB_GET_REGION_SHAPE
193 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Zone face edges:", theShape, TopAbs_EDGE );
196 TopTools_IndexedMapOfShape aMapOfSubShapes;
197 TopExp::MapShapes( theShape, TopAbs_EDGE, aMapOfSubShapes );
199 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anIter( theOriGroups );
200 for ( ; anIter.More(); anIter.Next() )
202 HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anIter.ChangeValue();
203 if ( anOriGroupDef.Shapes.IsEmpty() )
206 for ( int i = 1; i <= anOriGroupDef.Shapes.Length(); ++i )
208 TopoDS_Shape aGroupEdge = anOriGroupDef.Shapes.Value( i );
210 int aShapeIndex = aMapOfSubShapes.FindIndex( aGroupEdge );
211 if ( aShapeIndex <= 0 )
214 anOriGroupDef.Shapes.Remove( i );
217 bool anIsAdded = false;
219 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( theUsedGroups );
220 for ( ; aUsedIter.More(); aUsedIter.Next() )
222 HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.ChangeValue();
223 if ( aUsedGroupDef.Name != anOriGroupDef.Name )
226 aUsedGroupDef.Shapes.Append( aGroupEdge );
233 HYDROData_ShapesGroup::GroupDefinition aUsedGroupDef;
234 aUsedGroupDef.Name = anOriGroupDef.Name;
235 aUsedGroupDef.Shapes.Append( aGroupEdge );
236 theUsedGroups.Append( aUsedGroupDef );
242 TopoDS_Shape HYDROData_Region::GetShape( HYDROData_ShapesGroup::SeqOfGroupsDefs* theSeqOfGroups ) const
244 HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfGroups;
245 HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfUsedGroups;
246 if ( theSeqOfGroups )
247 aSeqOfGroups = *theSeqOfGroups;
249 #ifdef DEB_GET_REGION_SHAPE
250 HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfGroups );
253 TopoDS_Shape aResShape;
255 // Unite the region zones (each zone is a face) into one face (united face)
256 // If the zones can't be united into the single face - unite them into shell
258 // Collect the list of region faces
259 TopTools_ListOfShape aRegionFacesList;
261 HYDROData_SequenceOfObjects aZones = GetZones();
262 HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones );
263 for ( ; aZoneIter.More(); aZoneIter.Next() )
265 Handle(HYDROData_Zone) aZone =
266 Handle(HYDROData_Zone)::DownCast( aZoneIter.Value() );
267 if ( aZone.IsNull() )
270 TopoDS_Shape aZoneShape = aZone->GetShape();
271 if ( aZoneShape.IsNull() || aZoneShape.ShapeType() != TopAbs_FACE )
274 TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape );
275 aRegionFacesList.Append( aZoneFace );
277 getUsedGroups( aZoneFace, aSeqOfGroups, aSeqOfUsedGroups );
280 if ( aRegionFacesList.IsEmpty() )
283 // The unite region face
284 TopoDS_Face aRegionFace;
286 if ( aRegionFacesList.Extent() == 1 )
288 aRegionFace = TopoDS::Face( aRegionFacesList.First() );
292 #ifdef DEB_GET_REGION_SHAPE
293 HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfUsedGroups );
296 // Try to fuse all region faces into one common face
297 TopoDS_Shape aFuseShape;
298 TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
299 for ( ; aFaceIter.More(); aFaceIter.Next() )
301 if ( aFuseShape.IsNull() )
303 aFuseShape = aFaceIter.Value();
307 BRepAlgoAPI_Fuse aFuse( aFuseShape, aFaceIter.Value() );
308 if ( !aFuse.IsDone() )
310 aFuseShape.Nullify();
314 aFuseShape = aFuse.Shape();
315 HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &aFuse );
318 #ifdef DEB_GET_REGION_SHAPE
319 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Fused face edges:", aFuseShape, TopAbs_EDGE );
322 // Check the result of fuse operation
323 if ( !aFuseShape.IsNull() )
325 ShapeUpgrade_UnifySameDomain anUnifier( aFuseShape );
328 const TopoDS_Shape& anUnitedShape = anUnifier.Shape();
330 TopTools_SequenceOfShape aShapeFaces;
331 HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_FACE, aShapeFaces );
332 if ( aShapeFaces.Length() == 1 )
334 aRegionFace = TopoDS::Face( aShapeFaces.Value( 1 ) );
336 #ifdef DEB_GET_REGION_SHAPE
337 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Result face edges:", aRegionFace, TopAbs_EDGE );
340 HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &anUnifier );
342 // Update the sequence of groups
343 if ( theSeqOfGroups )
345 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( aSeqOfUsedGroups );
346 for ( ; aUsedIter.More(); aUsedIter.Next() )
348 const HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.Value();
349 if ( aUsedGroupDef.Shapes.IsEmpty() )
352 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anOriIter( aSeqOfGroups );
353 for ( ; anOriIter.More(); anOriIter.Next() )
355 HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anOriIter.ChangeValue();
356 if ( anOriGroupDef.Name != aUsedGroupDef.Name )
359 HYDROData_ShapesTool::AddShapes( anOriGroupDef.Shapes, aUsedGroupDef.Shapes );
364 *theSeqOfGroups = aSeqOfGroups;
370 if ( !aRegionFace.IsNull() )
372 // result shape is a face
373 aResShape = aRegionFace;
377 // result shape is a shell
379 BRep_Builder aBuilder;
380 aBuilder.MakeShell( aShell );
382 TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
383 for ( ; aFaceIter.More(); aFaceIter.Next() )
384 aBuilder.Add( aShell, aFaceIter.Value() );
392 QStringList HYDROData_Region::DumpToPython( const QString& thePyScriptPath,
393 MapOfTreatedObjects& theTreatedObjects,
394 QString defRegName ) const
396 QStringList aResList;
399 findPythonReferenceObject( aResList, defRegName );
402 HYDROData_SequenceOfObjects aZones = GetZones();
403 HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
404 for ( ; aZonesIter.More(); aZonesIter.Next() ) {
405 Handle(HYDROData_Zone) aZone =
406 Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
407 if ( aZone.IsNull() ) {
412 aZone->findPythonReferenceObject( aResList );
413 theTreatedObjects.insert( aZone->GetName(), aZone );
415 // set zone merge type
416 QString aMergeTypeStr;
417 HYDROData_Zone::MergeType aMergeType = aZone->GetMergeType();
418 if ( aMergeType == HYDROData_Zone::Merge_ZMIN ) {
419 aMergeTypeStr = "HYDROData_Zone.Merge_ZMIN";
420 } else if ( aMergeType == HYDROData_Zone::Merge_ZMAX ) {
421 aMergeTypeStr = "HYDROData_Zone.Merge_ZMAX";
422 } else if ( aMergeType == HYDROData_Zone::Merge_Object ) {
423 aMergeTypeStr = "HYDROData_Zone.Merge_Object";
426 if ( !aMergeTypeStr.isEmpty() ) {
427 aResList << QString( "%1.SetMergeType( %2 )" ).arg( aZone->GetObjPyName() ).arg( aMergeTypeStr );
429 if ( aMergeType == HYDROData_Zone::Merge_Object ) {
430 Handle(HYDROData_Entity) aMergeObject = aZone->GetMergeObject();
431 if ( !aMergeObject.IsNull() ) {
432 aMergeObject->findPythonReferenceObject( aResList );
433 aResList << QString( "%1.SetMergeObject( %2 )" ).arg( aZone->GetObjPyName() )
434 .arg( aMergeObject->GetObjPyName() );
438 QColor zoneColor = aZone->GetColor(Qt::darkBlue);
439 aResList << QString( "%1.SetColor( QColor( %2, %3, %4 ))" )
440 .arg( aZone->GetObjPyName() ).arg( zoneColor.red() ).arg( zoneColor.green() ).arg( zoneColor.blue() );
442 setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aZone, "AddZone" );
449 bool HYDROData_Region::IsSubmersible() const
451 HYDROData_SequenceOfObjects aZones = GetZones();
452 HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
453 for ( ; aZonesIter.More(); aZonesIter.Next() )
455 Handle(HYDROData_Zone) aZone =
456 Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
457 if ( !aZone->IsSubmersible() )
458 return false; //if one of zones is not submersible the region is considered as not submersible