2 #include "HYDROData_Region.h"
4 #include "HYDROData_CalculationCase.h"
5 #include "HYDROData_Document.h"
6 #include "HYDROData_Iterator.h"
7 #include "HYDROData_Object.h"
8 #include "HYDROData_ShapesTool.h"
9 #include "HYDROData_Zone.h"
10 #include "HYDROData_Tool.h"
13 #include <TopoDS_Shape.hxx>
14 #include <TopoDS_Shell.hxx>
15 #include <TopoDS_Face.hxx>
19 #include <TopTools_ListOfShape.hxx>
20 #include <TopTools_SequenceOfShape.hxx>
21 #include <TopTools_ListIteratorOfListOfShape.hxx>
22 #include <TopTools_IndexedMapOfShape.hxx>
24 #include <BRep_Builder.hxx>
25 #include <BRepAlgoAPI_Fuse.hxx>
27 #include <ShapeUpgrade_UnifySameDomain.hxx>
29 #include <QStringList>
31 //#define DEB_GET_REGION_SHAPE
33 IMPLEMENT_STANDARD_HANDLE(HYDROData_Region, HYDROData_Entity)
34 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Entity)
37 HYDROData_Region::HYDROData_Region()
42 HYDROData_Region::~HYDROData_Region()
46 bool HYDROData_Region::CanBeUpdated() const
51 void HYDROData_Region::Remove()
53 Handle(HYDROData_CalculationCase) aFatherCalc =
54 Handle(HYDROData_CalculationCase)::DownCast( GetFatherObject() );
56 HYDROData_Entity::Remove();
58 if ( !aFatherCalc.IsNull() )
59 aFatherCalc->UpdateRegionsOrder();
62 bool HYDROData_Region::CanRemove()
67 HYDROData_SequenceOfObjects HYDROData_Region::GetAllReferenceObjects() const
69 HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
71 HYDROData_SequenceOfObjects aSeqOfZones = GetZones();
72 aResSeq.Append( aSeqOfZones );
77 bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone )
79 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
81 if ( theZone.IsNull() )
84 if ( HasReference( theZone, DataTag_Zone ) )
85 return false; // Object is already in reference list
87 // Move the zone from other region
88 Handle(HYDROData_Region) aFatherRegion =
89 Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
90 if ( !aFatherRegion.IsNull() && aFatherRegion->Label() != myLab )
92 Handle(HYDROData_Zone) aNewZone = addNewZone( aDocument, "", TopoDS_Face(), QStringList() );
93 theZone->CopyTo( aNewZone );
95 // To prevent changing of stored shape
96 aNewZone->SetShape( theZone->GetShape() );
98 aFatherRegion->RemoveZone( theZone );
100 theZone->SetLabel( aNewZone->Label() );
104 AddReferenceObject( theZone, DataTag_Zone );
110 HYDROData_SequenceOfObjects HYDROData_Region::GetZones() const
112 return GetReferenceObjects( DataTag_Zone );
115 void HYDROData_Region::RemoveZone( const Handle(HYDROData_Zone)& theZone )
117 if ( theZone.IsNull() )
120 RemoveReferenceObject( theZone->Label(), DataTag_Zone );
122 // Remove zone from data model
123 Handle(HYDROData_Region) aFatherRegion =
124 Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
125 if ( !aFatherRegion.IsNull() && aFatherRegion->Label() == myLab )
128 // If the last zone has been removed from region we remove this region
129 HYDROData_SequenceOfObjects aRefZones = GetZones();
130 if ( aRefZones.IsEmpty() )
134 void HYDROData_Region::RemoveZones()
136 ClearReferenceObjects( DataTag_Zone );
137 myLab.FindChild( DataTag_ChildZone ).ForgetAllAttributes( true );
140 Handle(HYDROData_Zone) HYDROData_Region::addNewZone( const Handle(HYDROData_Document)& theDoc,
141 const QString& thePrefix,
142 const TopoDS_Face& theFace,
143 const QStringList& theRefObjects )
145 TDF_Label aNewLab = myLab.FindChild( DataTag_ChildZone ).NewChild();
147 Handle(HYDROData_Zone) aNewZone =
148 Handle(HYDROData_Zone)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_ZONE ) );
151 QString aZoneName = HYDROData_Tool::GenerateObjectName( theDoc, thePrefix );
152 aNewZone->SetName( aZoneName );
154 aNewZone->SetShape( theFace );
156 // Add the reference object for zone
157 for ( int i = 0, n = theRefObjects.length(); i < n; ++i )
159 const QString& anObjName = theRefObjects.at( i );
160 Handle(HYDROData_Object) aRefObject =
161 Handle(HYDROData_Object)::DownCast( theDoc->FindObjectByName( anObjName ) );
162 if ( aRefObject.IsNull() )
165 aNewZone->AddGeometryObject( aRefObject );
171 void getUsedGroups( const TopoDS_Shape& theShape,
172 HYDROData_ShapesGroup::SeqOfGroupsDefs& theOriGroups,
173 HYDROData_ShapesGroup::SeqOfGroupsDefs& theUsedGroups )
175 #ifdef DEB_GET_REGION_SHAPE
176 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Zone face edges:", theShape, TopAbs_EDGE );
179 TopTools_IndexedMapOfShape aMapOfSubShapes;
180 TopExp::MapShapes( theShape, TopAbs_EDGE, aMapOfSubShapes );
182 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anIter( theOriGroups );
183 for ( ; anIter.More(); anIter.Next() )
185 HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anIter.ChangeValue();
186 if ( anOriGroupDef.Shapes.IsEmpty() )
189 for ( int i = 1; i <= anOriGroupDef.Shapes.Length(); ++i )
191 TopoDS_Shape aGroupEdge = anOriGroupDef.Shapes.Value( i );
193 int aShapeIndex = aMapOfSubShapes.FindIndex( aGroupEdge );
194 if ( aShapeIndex <= 0 )
197 anOriGroupDef.Shapes.Remove( i );
200 bool anIsAdded = false;
202 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( theUsedGroups );
203 for ( ; aUsedIter.More(); aUsedIter.Next() )
205 HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.ChangeValue();
206 if ( aUsedGroupDef.Name != anOriGroupDef.Name )
209 aUsedGroupDef.Shapes.Append( aGroupEdge );
216 HYDROData_ShapesGroup::GroupDefinition aUsedGroupDef;
217 aUsedGroupDef.Name = anOriGroupDef.Name;
218 aUsedGroupDef.Shapes.Append( aGroupEdge );
219 theUsedGroups.Append( aUsedGroupDef );
225 TopoDS_Shape HYDROData_Region::GetShape( HYDROData_ShapesGroup::SeqOfGroupsDefs* theSeqOfGroups ) const
227 HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfGroups;
228 HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfUsedGroups;
229 if ( theSeqOfGroups )
230 aSeqOfGroups = *theSeqOfGroups;
232 #ifdef DEB_GET_REGION_SHAPE
233 HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfGroups );
236 TopoDS_Shape aResShape;
238 // Unite the region zones (each zone is a face) into one face (united face)
239 // If the zones can't be united into the single face - unite them into shell
241 // Collect the list of region faces
242 TopTools_ListOfShape aRegionFacesList;
244 HYDROData_SequenceOfObjects aZones = GetZones();
245 HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones );
246 for ( ; aZoneIter.More(); aZoneIter.Next() )
248 Handle(HYDROData_Zone) aZone =
249 Handle(HYDROData_Zone)::DownCast( aZoneIter.Value() );
250 if ( aZone.IsNull() )
253 TopoDS_Shape aZoneShape = aZone->GetShape();
254 if ( aZoneShape.IsNull() || aZoneShape.ShapeType() != TopAbs_FACE )
257 TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape );
258 aRegionFacesList.Append( aZoneFace );
260 getUsedGroups( aZoneFace, aSeqOfGroups, aSeqOfUsedGroups );
263 if ( aRegionFacesList.IsEmpty() )
266 // The unite region face
267 TopoDS_Face aRegionFace;
269 if ( aRegionFacesList.Extent() == 1 )
271 aRegionFace = TopoDS::Face( aRegionFacesList.First() );
275 #ifdef DEB_GET_REGION_SHAPE
276 HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfUsedGroups );
279 // Try to fuse all region faces into one common face
280 TopoDS_Shape aFuseShape;
281 TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
282 for ( ; aFaceIter.More(); aFaceIter.Next() )
284 if ( aFuseShape.IsNull() )
286 aFuseShape = aFaceIter.Value();
290 BRepAlgoAPI_Fuse aFuse( aFuseShape, aFaceIter.Value() );
291 if ( !aFuse.IsDone() )
293 aFuseShape.Nullify();
297 aFuseShape = aFuse.Shape();
298 HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &aFuse );
301 #ifdef DEB_GET_REGION_SHAPE
302 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Fused face edges:", aFuseShape, TopAbs_EDGE );
305 // Check the result of fuse operation
306 if ( !aFuseShape.IsNull() )
308 ShapeUpgrade_UnifySameDomain anUnifier( aFuseShape );
311 const TopoDS_Shape& anUnitedShape = anUnifier.Shape();
313 TopTools_SequenceOfShape aShapeFaces;
314 HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_FACE, aShapeFaces );
315 if ( aShapeFaces.Length() == 1 )
317 aRegionFace = TopoDS::Face( aShapeFaces.Value( 1 ) );
319 #ifdef DEB_GET_REGION_SHAPE
320 HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Result face edges:", aRegionFace, TopAbs_EDGE );
323 HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &anUnifier );
325 // Update the sequence of groups
326 if ( theSeqOfGroups )
328 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( aSeqOfUsedGroups );
329 for ( ; aUsedIter.More(); aUsedIter.Next() )
331 const HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.Value();
332 if ( aUsedGroupDef.Shapes.IsEmpty() )
335 HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anOriIter( aSeqOfGroups );
336 for ( ; anOriIter.More(); anOriIter.Next() )
338 HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anOriIter.ChangeValue();
339 if ( anOriGroupDef.Name != aUsedGroupDef.Name )
342 HYDROData_ShapesTool::AddShapes( anOriGroupDef.Shapes, aUsedGroupDef.Shapes );
347 *theSeqOfGroups = aSeqOfGroups;
353 if ( !aRegionFace.IsNull() )
355 // result shape is a face
356 aResShape = aRegionFace;
360 // result shape is a shell
362 BRep_Builder aBuilder;
363 aBuilder.MakeShell( aShell );
365 TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
366 for ( ; aFaceIter.More(); aFaceIter.Next() )
367 aBuilder.Add( aShell, aFaceIter.Value() );
375 QStringList HYDROData_Region::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
377 QStringList aResList;
380 findPythonReferenceObject( theTreatedObjects, aResList );
383 HYDROData_SequenceOfObjects aZones = GetZones();
384 HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
385 for ( ; aZonesIter.More(); aZonesIter.Next() ) {
386 Handle(HYDROData_Zone) aZone =
387 Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
388 if ( aZone.IsNull() ) {
393 aZone->findPythonReferenceObject( theTreatedObjects, aResList );
394 theTreatedObjects.insert( aZone->GetName(), aZone );
396 // set zone merge type
397 QString aMergeTypeStr;
398 HYDROData_Zone::MergeAltitudesType aMergeType = aZone->GetMergeType();
399 if ( aMergeType == HYDROData_Zone::Merge_ZMIN ) {
400 aMergeTypeStr = "HYDROData_Zone.Merge_ZMIN";
401 } else if ( aMergeType == HYDROData_Zone::Merge_ZMAX ) {
402 aMergeTypeStr = "HYDROData_Zone.Merge_ZMAX";
403 } else if ( aMergeType == HYDROData_Zone::Merge_Object ) {
404 aMergeTypeStr = "HYDROData_Zone.Merge_Object";
407 if ( !aMergeTypeStr.isEmpty() ) {
408 aResList << QString( "%1.SetMergeType( %2 )" ).arg( aZone->GetObjPyName() ).arg( aMergeTypeStr );
410 if ( aMergeType == HYDROData_Zone::Merge_Object ) {
411 Handle(HYDROData_IAltitudeObject) aMergeAltitude = aZone->GetMergeAltitude();
412 if ( !aMergeAltitude.IsNull() ) {
413 aMergeAltitude->findPythonReferenceObject( theTreatedObjects, aResList );
414 aResList << QString( "%1.SetMergeAltitude( %2 )" ).arg( aZone->GetObjPyName() )
415 .arg( aMergeAltitude->GetObjPyName() );
420 setPythonReferenceObject( theTreatedObjects, aResList, aZone, "AddZone" );