1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "HYDROData_Region.h"
25 #include "HYDROData_CalculationCase.h"
26 #include "HYDROData_Document.h"
27 #include "HYDROData_Iterator.h"
28 #include "HYDROData_Object.h"
29 #include "HYDROData_ShapesTool.h"
30 #include "HYDROData_Zone.h"
31 #include "HYDROData_Tool.h"
34 #include <TopoDS_Shape.hxx>
35 #include <TopoDS_Shell.hxx>
36 #include <TopoDS_Face.hxx>
40 #include <TopTools_ListOfShape.hxx>
41 #include <TopTools_SequenceOfShape.hxx>
42 #include <TopTools_ListIteratorOfListOfShape.hxx>
43 #include <TopTools_IndexedMapOfShape.hxx>
45 #include <BRep_Builder.hxx>
46 #include <BRepAlgoAPI_Fuse.hxx>
48 #include <ShapeUpgrade_UnifySameDomain.hxx>
50 #include <QStringList>
52 //#define DEB_GET_REGION_SHAPE
54 IMPLEMENT_STANDARD_HANDLE(HYDROData_Region, HYDROData_Entity)
55 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Entity)
58 HYDROData_Region::HYDROData_Region()
63 HYDROData_Region::~HYDROData_Region()
67 bool HYDROData_Region::CanBeUpdated() const
72 void HYDROData_Region::Remove()
74 Handle(HYDROData_CalculationCase) aFatherCalc =
75 Handle(HYDROData_CalculationCase)::DownCast( GetFatherObject() );
77 HYDROData_Entity::Remove();
79 if ( !aFatherCalc.IsNull() )
80 aFatherCalc->UpdateRegionsOrder();
83 bool HYDROData_Region::CanRemove()
88 HYDROData_SequenceOfObjects HYDROData_Region::GetAllReferenceObjects() const
90 HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
92 HYDROData_SequenceOfObjects aSeqOfZones = GetZones();
93 aResSeq.Append( aSeqOfZones );
98 bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone )
100 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
102 if ( theZone.IsNull() )
105 if ( HasReference( theZone, DataTag_Zone ) )
106 return false; // Object is already in reference list
108 // Move the zone from other region
109 Handle(HYDROData_Region) aFatherRegion =
110 Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
111 if ( !aFatherRegion.IsNull() && aFatherRegion->Label() != myLab )
113 Handle(HYDROData_Zone) aNewZone = addNewZone( aDocument, "", TopoDS_Face(), QStringList() );
114 theZone->CopyTo( aNewZone );
116 // To prevent changing of stored shape
117 aNewZone->SetShape( theZone->GetShape() );
119 aFatherRegion->RemoveZone( theZone );
121 theZone->SetLabel( aNewZone->Label() );
125 AddReferenceObject( theZone, DataTag_Zone );
131 HYDROData_SequenceOfObjects HYDROData_Region::GetZones() const
133 return GetReferenceObjects( DataTag_Zone );
136 void HYDROData_Region::RemoveZone( const Handle(HYDROData_Zone)& theZone )
138 if ( theZone.IsNull() )
141 RemoveReferenceObject( theZone->Label(), DataTag_Zone );
143 // Remove zone from data model
144 Handle(HYDROData_Region) aFatherRegion =
145 Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
146 if ( !aFatherRegion.IsNull() && aFatherRegion->Label() == myLab )
149 // If the last zone has been removed from region we remove this region
150 HYDROData_SequenceOfObjects aRefZones = GetZones();
151 if ( aRefZones.IsEmpty() )
155 void HYDROData_Region::RemoveZones()
157 ClearReferenceObjects( DataTag_Zone );
158 myLab.FindChild( DataTag_ChildZone ).ForgetAllAttributes( true );
161 Handle(HYDROData_Zone) HYDROData_Region::addNewZone( const Handle(HYDROData_Document)& theDoc,
162 const QString& thePrefix,
163 const TopoDS_Face& theFace,
164 const QStringList& theRefObjects )
166 TDF_Label aNewLab = myLab.FindChild( DataTag_ChildZone ).NewChild();
168 Handle(HYDROData_Zone) aNewZone =
169 Handle(HYDROData_Zone)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_ZONE ) );
172 QString aZoneName = HYDROData_Tool::GenerateObjectName( theDoc, thePrefix );
173 aNewZone->SetName( aZoneName );
175 aNewZone->SetShape( theFace );
177 // Add the reference object for zone
178 for ( int i = 0, n = theRefObjects.length(); i < n; ++i )
180 const QString& anObjName = theRefObjects.at( i );
181 Handle(HYDROData_Object) aRefObject =
182 Handle(HYDROData_Object)::DownCast( theDoc->FindObjectByName( anObjName ) );
183 if ( aRefObject.IsNull() )
186 aNewZone->AddGeometryObject( aRefObject );
192 void getUsedGroups( const TopoDS_Shape& theShape,
193 HYDROData_ShapesGroup::SeqOfGroupsDefs& theOriGroups,
194 HYDROData_ShapesGroup::SeqOfGroupsDefs& theUsedGroups )
196 #ifdef DEB_GET_REGION_SHAPE
197 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Zone face edges:", theShape, TopAbs_EDGE );
200 TopTools_IndexedMapOfShape aMapOfSubShapes;
201 TopExp::MapShapes( theShape, TopAbs_EDGE, aMapOfSubShapes );
203 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anIter( theOriGroups );
204 for ( ; anIter.More(); anIter.Next() )
206 HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anIter.ChangeValue();
207 if ( anOriGroupDef.Shapes.IsEmpty() )
210 for ( int i = 1; i <= anOriGroupDef.Shapes.Length(); ++i )
212 TopoDS_Shape aGroupEdge = anOriGroupDef.Shapes.Value( i );
214 int aShapeIndex = aMapOfSubShapes.FindIndex( aGroupEdge );
215 if ( aShapeIndex <= 0 )
218 anOriGroupDef.Shapes.Remove( i );
221 bool anIsAdded = false;
223 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( theUsedGroups );
224 for ( ; aUsedIter.More(); aUsedIter.Next() )
226 HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.ChangeValue();
227 if ( aUsedGroupDef.Name != anOriGroupDef.Name )
230 aUsedGroupDef.Shapes.Append( aGroupEdge );
237 HYDROData_ShapesGroup::GroupDefinition aUsedGroupDef;
238 aUsedGroupDef.Name = anOriGroupDef.Name;
239 aUsedGroupDef.Shapes.Append( aGroupEdge );
240 theUsedGroups.Append( aUsedGroupDef );
246 TopoDS_Shape HYDROData_Region::GetShape( HYDROData_ShapesGroup::SeqOfGroupsDefs* theSeqOfGroups ) const
248 HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfGroups;
249 HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfUsedGroups;
250 if ( theSeqOfGroups )
251 aSeqOfGroups = *theSeqOfGroups;
253 #ifdef DEB_GET_REGION_SHAPE
254 HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfGroups );
257 TopoDS_Shape aResShape;
259 // Unite the region zones (each zone is a face) into one face (united face)
260 // If the zones can't be united into the single face - unite them into shell
262 // Collect the list of region faces
263 TopTools_ListOfShape aRegionFacesList;
265 HYDROData_SequenceOfObjects aZones = GetZones();
266 HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones );
267 for ( ; aZoneIter.More(); aZoneIter.Next() )
269 Handle(HYDROData_Zone) aZone =
270 Handle(HYDROData_Zone)::DownCast( aZoneIter.Value() );
271 if ( aZone.IsNull() )
274 TopoDS_Shape aZoneShape = aZone->GetShape();
275 if ( aZoneShape.IsNull() || aZoneShape.ShapeType() != TopAbs_FACE )
278 TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape );
279 aRegionFacesList.Append( aZoneFace );
281 getUsedGroups( aZoneFace, aSeqOfGroups, aSeqOfUsedGroups );
284 if ( aRegionFacesList.IsEmpty() )
287 // The unite region face
288 TopoDS_Face aRegionFace;
290 if ( aRegionFacesList.Extent() == 1 )
292 aRegionFace = TopoDS::Face( aRegionFacesList.First() );
296 #ifdef DEB_GET_REGION_SHAPE
297 HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfUsedGroups );
300 // Try to fuse all region faces into one common face
301 TopoDS_Shape aFuseShape;
302 TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
303 for ( ; aFaceIter.More(); aFaceIter.Next() )
305 if ( aFuseShape.IsNull() )
307 aFuseShape = aFaceIter.Value();
311 BRepAlgoAPI_Fuse aFuse( aFuseShape, aFaceIter.Value() );
312 if ( !aFuse.IsDone() )
314 aFuseShape.Nullify();
318 aFuseShape = aFuse.Shape();
319 HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &aFuse );
322 #ifdef DEB_GET_REGION_SHAPE
323 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Fused face edges:", aFuseShape, TopAbs_EDGE );
326 // Check the result of fuse operation
327 if ( !aFuseShape.IsNull() )
329 ShapeUpgrade_UnifySameDomain anUnifier( aFuseShape );
332 const TopoDS_Shape& anUnitedShape = anUnifier.Shape();
334 TopTools_SequenceOfShape aShapeFaces;
335 HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_FACE, aShapeFaces );
336 if ( aShapeFaces.Length() == 1 )
338 aRegionFace = TopoDS::Face( aShapeFaces.Value( 1 ) );
340 #ifdef DEB_GET_REGION_SHAPE
341 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Result face edges:", aRegionFace, TopAbs_EDGE );
344 HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &anUnifier );
346 // Update the sequence of groups
347 if ( theSeqOfGroups )
349 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( aSeqOfUsedGroups );
350 for ( ; aUsedIter.More(); aUsedIter.Next() )
352 const HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.Value();
353 if ( aUsedGroupDef.Shapes.IsEmpty() )
356 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anOriIter( aSeqOfGroups );
357 for ( ; anOriIter.More(); anOriIter.Next() )
359 HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anOriIter.ChangeValue();
360 if ( anOriGroupDef.Name != aUsedGroupDef.Name )
363 HYDROData_ShapesTool::AddShapes( anOriGroupDef.Shapes, aUsedGroupDef.Shapes );
368 *theSeqOfGroups = aSeqOfGroups;
374 if ( !aRegionFace.IsNull() )
376 // result shape is a face
377 aResShape = aRegionFace;
381 // result shape is a shell
383 BRep_Builder aBuilder;
384 aBuilder.MakeShell( aShell );
386 TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
387 for ( ; aFaceIter.More(); aFaceIter.Next() )
388 aBuilder.Add( aShell, aFaceIter.Value() );
396 QStringList HYDROData_Region::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
398 QStringList aResList;
401 findPythonReferenceObject( theTreatedObjects, aResList );
404 HYDROData_SequenceOfObjects aZones = GetZones();
405 HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
406 for ( ; aZonesIter.More(); aZonesIter.Next() ) {
407 Handle(HYDROData_Zone) aZone =
408 Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
409 if ( aZone.IsNull() ) {
414 aZone->findPythonReferenceObject( theTreatedObjects, aResList );
415 theTreatedObjects.insert( aZone->GetName(), aZone );
417 // set zone merge type
418 QString aMergeTypeStr;
419 HYDROData_Zone::MergeAltitudesType aMergeType = aZone->GetMergeType();
420 if ( aMergeType == HYDROData_Zone::Merge_ZMIN ) {
421 aMergeTypeStr = "HYDROData_Zone.Merge_ZMIN";
422 } else if ( aMergeType == HYDROData_Zone::Merge_ZMAX ) {
423 aMergeTypeStr = "HYDROData_Zone.Merge_ZMAX";
424 } else if ( aMergeType == HYDROData_Zone::Merge_Object ) {
425 aMergeTypeStr = "HYDROData_Zone.Merge_Object";
428 if ( !aMergeTypeStr.isEmpty() ) {
429 aResList << QString( "%1.SetMergeType( %2 )" ).arg( aZone->GetObjPyName() ).arg( aMergeTypeStr );
431 if ( aMergeType == HYDROData_Zone::Merge_Object ) {
432 Handle(HYDROData_IAltitudeObject) aMergeAltitude = aZone->GetMergeAltitude();
433 if ( !aMergeAltitude.IsNull() ) {
434 aMergeAltitude->findPythonReferenceObject( theTreatedObjects, aResList );
435 aResList << QString( "%1.SetMergeAltitude( %2 )" ).arg( aZone->GetObjPyName() )
436 .arg( aMergeAltitude->GetObjPyName() );
441 setPythonReferenceObject( theTreatedObjects, aResList, aZone, "AddZone" );