Salome HOME
HYDROData_Obstacle has been wrapped for Python.
[modules/hydro.git] / src / HYDROData / HYDROData_Region.cxx
index 166806535995977ecdb0d576de304e449544c235..12103c787be22250d261167419a95149ea3ec36f 100644 (file)
@@ -1,20 +1,33 @@
 
 #include "HYDROData_Region.h"
 
-#include <TNaming_Builder.hxx>
-#include <TNaming_NamedShape.hxx>
+#include "HYDROData_CalculationCase.h"
+#include "HYDROData_Document.h"
+#include "HYDROData_Iterator.h"
+#include "HYDROData_Zone.h"
+
 #include <TopoDS.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopExp.hxx>
+#include <BRep_Builder.hxx>
+#include <BRepAlgoAPI_Fuse.hxx>
+#include <ShapeUpgrade_UnifySameDomain.hxx>
 
-#include <QString>
+#include <QStringList>
 
 #define PYTHON_REGION_ID "KIND_REGION"
 
-
-IMPLEMENT_STANDARD_HANDLE(HYDROData_Region, HYDROData_Domain)
-IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Domain)
+IMPLEMENT_STANDARD_HANDLE(HYDROData_Region, HYDROData_Entity)
+IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Entity)
 
 
 HYDROData_Region::HYDROData_Region()
+ : HYDROData_Entity()
 {
 }
 
@@ -22,24 +35,217 @@ HYDROData_Region::~HYDROData_Region()
 {
 }
 
-void HYDROData_Region::SetFace( const TopoDS_Face& theFace )
+QStringList HYDROData_Region::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
+{
+  QStringList aResList;
+
+  Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
+  if ( aDocument.IsNull() )
+    return aResList;
+
+  QString aDocName = aDocument->GetDocPyName();
+  QString aRegionName = GetName();
+
+  aResList << QString( "%1 = %2.CreateObject( %3 );" )
+              .arg( aRegionName ).arg( aDocName ).arg( PYTHON_REGION_ID );
+  aResList << QString( "%1.SetName( \"%2\" );" )
+              .arg( aRegionName ).arg( aRegionName );
+  aResList << QString( "" );
+
+  HYDROData_SequenceOfObjects aZones = GetZones();
+  HYDROData_SequenceOfObjects::Iterator anIter( aZones );
+  for ( ; anIter.More(); anIter.Next() )
+  {
+    Handle(HYDROData_Zone) aRefZone =
+      Handle(HYDROData_Zone)::DownCast( anIter.Value() );
+    if ( !aRefZone.IsNull() )
+      setPythonReferenceObject( theTreatedObjects, aResList, aRefZone, "AddZone" );
+  }
+  aResList << QString( "" );
+
+  return aResList;
+}
+
+bool HYDROData_Region::CanBeUpdated() const
+{
+  return false;
+}
+
+void HYDROData_Region::Remove()
+{
+  Handle(HYDROData_CalculationCase) aFatherCalc = 
+    Handle(HYDROData_CalculationCase)::DownCast( GetFatherObject() );
+
+  HYDROData_Entity::Remove();
+
+  if ( !aFatherCalc.IsNull() )
+    aFatherCalc->UpdateRegionsOrder();
+}
+
+bool HYDROData_Region::CanRemove()
+{
+  return false;
+}
+
+HYDROData_SequenceOfObjects HYDROData_Region::GetAllReferenceObjects() const
+{
+  HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
+
+  HYDROData_SequenceOfObjects aSeqOfZones = GetZones();
+  aResSeq.Append( aSeqOfZones );
+
+  return aResSeq;
+}
+
+bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone )
+{
+  if ( theZone.IsNull() )
+    return false;
+  
+  if ( HasReference( theZone, DataTag_Zone ) )
+    return false; // Object is already in reference list
+
+  // Move the zone from other region
+  Handle(HYDROData_Region) aFatherRegion = 
+    Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
+  if ( !aFatherRegion.IsNull() && aFatherRegion->Label() != myLab )
+  {
+    Handle(HYDROData_Zone) aNewZone = addNewZone();
+    theZone->CopyTo( aNewZone );
+
+    aFatherRegion->RemoveZone( theZone );
+
+    theZone->SetLabel( aNewZone->Label() );
+  }
+  else
+  {
+    AddReferenceObject( theZone, DataTag_Zone );
+  }
+
+  return true;
+}
+
+HYDROData_SequenceOfObjects HYDROData_Region::GetZones() const
 {
-  TNaming_Builder aBuilder( myLab );
-  aBuilder.Generated( theFace );
+  return GetReferenceObjects( DataTag_Zone );
 }
 
-TopoDS_Face HYDROData_Region::Face() const
+void HYDROData_Region::RemoveZone( const Handle(HYDROData_Zone)& theZone )
 {
-  Handle(TNaming_NamedShape) aNamedShape;
-  if( myLab.FindAttribute( TNaming_NamedShape::GetID(), aNamedShape ) )
-    return TopoDS::Face( aNamedShape->Get() );
-  return TopoDS_Face();
+  if ( theZone.IsNull() )
+    return;
+
+  RemoveReferenceObject( theZone->Label(), DataTag_Zone );
+
+  // Remove zone from data model
+  Handle(HYDROData_Region) aFatherRegion = 
+    Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
+  if ( !aFatherRegion.IsNull() && aFatherRegion->Label() == myLab )
+    theZone->Remove();
+
+  // If the last zone has been removed from region we remove this region
+  HYDROData_SequenceOfObjects aRefZones = GetZones();
+  if ( aRefZones.IsEmpty() )
+    Remove();
 }
 
-QString HYDROData_Region::getPythonKindId() const
+void HYDROData_Region::RemoveZones()
 {
-  return QString( PYTHON_REGION_ID );
+  ClearReferenceObjects( DataTag_Zone );
+  myLab.FindChild( DataTag_ChildZone ).ForgetAllAttributes( true );
 }
 
+Handle(HYDROData_Zone) HYDROData_Region::addNewZone()
+{
+  TDF_Label aNewLab = myLab.FindChild( DataTag_ChildZone ).NewChild();
 
+  Handle(HYDROData_Zone) aNewZone =
+    Handle(HYDROData_Zone)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_ZONE ) );
+  AddZone( aNewZone );
 
+  return aNewZone;
+}
+
+TopoDS_Shape HYDROData_Region::GetShape() const
+{
+  TopoDS_Shape aResShape;
+
+  // Unite the region zones (each zone is a face) into one face (united face)
+  // If the zones can't be united into the single face - unite them into shell
+
+  // Collect the list of region faces
+  TopTools_ListOfShape aRegionFacesList;
+
+  HYDROData_SequenceOfObjects aZones = GetZones();
+  HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones );
+  for ( ; aZoneIter.More(); aZoneIter.Next() ) {
+    Handle(HYDROData_Zone) aZone =
+      Handle(HYDROData_Zone)::DownCast( aZoneIter.Value() );
+  
+    if ( aZone.IsNull() ) {
+      continue;
+    }
+
+    TopoDS_Face aFace = TopoDS::Face( aZone->GetShape() );
+    if ( !aFace.IsNull() ) {
+      aRegionFacesList.Append( aFace );
+    }
+  } // zones iterator
+  
+  // Check number of faces
+  int aNbFaces = aRegionFacesList.Extent();
+  if ( aNbFaces > 0 ) {
+    // The unite region face
+    TopoDS_Face aRegionFace;
+  
+    if ( aNbFaces == 1 ) {
+      aRegionFace = TopoDS::Face( aRegionFacesList.First() );
+    } else {
+      // Fuse faces into one
+      TopoDS_Shape aFuseShape;
+      TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
+      for ( ; aFaceIter.More(); aFaceIter.Next() ) {
+        if ( aFuseShape.IsNull() ) {
+          aFuseShape = aFaceIter.Value();
+        } else {
+          BRepAlgoAPI_Fuse aFuse(aFuseShape, aFaceIter.Value());
+          if ( !aFuse.IsDone() ) {
+            aFuseShape.Nullify();
+            break;
+          }
+          aFuseShape = aFuse.Shape();
+        }
+      } // faces iterator
+
+      // Check the result of fuse operation
+      if ( !aFuseShape.IsNull() ) {
+        ShapeUpgrade_UnifySameDomain anUnifier( aFuseShape );
+        anUnifier.Build();
+        TopoDS_Shape anUnitedShape = anUnifier.Shape();
+
+        TopTools_IndexedMapOfShape aMapOfFaces;
+        TopExp::MapShapes( anUnitedShape, TopAbs_FACE, aMapOfFaces );
+        if ( aMapOfFaces.Extent() == 1 ) {
+          aRegionFace = TopoDS::Face( aMapOfFaces(1) );
+        }
+      }
+    }
+
+    if ( !aRegionFace.IsNull() ) { // result shape is a face
+      aResShape = aRegionFace;
+    } else { // result shape is a shell
+      TopoDS_Shell aShell;
+      BRep_Builder aBuilder;
+      aBuilder.MakeShell( aShell );
+
+      TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
+      for ( ; aFaceIter.More(); aFaceIter.Next() ) {
+        aBuilder.Add( aShell, aFaceIter.Value() );
+      }
+
+      aResShape = aShell;
+    }
+  }
+  
+  return aResShape;
+}