Salome HOME
refs #492: Implement bottom of the river creation in the data model
authormzn <mzn@opencascade.com>
Fri, 27 Mar 2015 14:48:59 +0000 (17:48 +0300)
committermzn <mzn@opencascade.com>
Fri, 27 Mar 2015 14:48:59 +0000 (17:48 +0300)
src/HYDROData/HYDROData_Profile.cxx
src/HYDROData/HYDROData_Profile.h
src/HYDROData/HYDROData_Stream.cxx
src/HYDROData/HYDROData_Stream.h
src/HYDROGUI/HYDROGUI_DataModel.cxx
src/HYDROGUI/HYDROGUI_RiverBottomOp.cxx
src/HYDROGUI/HYDROGUI_RiverBottomOp.h
src/HYDROPy/HYDROData_Stream.sip

index b970af45591789d80234e81da632f4e373fa6715..3a628a74c4b8e321e955cc780f3bca15a1e05bc6 100755 (executable)
@@ -663,4 +663,58 @@ void HYDROData_Profile::UpdateLocalCS( double theDx, double theDy )
   SetRightPoint( aPnt, false );
 }
 
+HYDROData_Profile::ProfilePoint HYDROData_Profile::GetBottomPoint() const
+{
+  ProfilePoint aBottom;
+
+  // Get parametric points
+  HYDROData_ProfileUZ::PointsList aParametricPoints = GetParametricPoints();
+  if ( aParametricPoints.Length() < 1 ) {
+    return aBottom;
+  }
+
+  // Calculate midvalue for U parameter
+  Standard_Real anUMidValue = aParametricPoints.First().X();
+  Standard_Real anUMinValue = anUMidValue;
+  Standard_Real anUMaxValue = anUMidValue;
+
+  for ( int i = 2, aNbPoints = aParametricPoints.Size(); i <= aNbPoints; i++ ) {
+    const HYDROData_IPolyline::Point& aParPoint = aParametricPoints.Value( i );
+    Standard_Real anU = aParPoint.X();
+
+    if ( anU < anUMinValue ) {
+      anUMinValue = anU;
+    } else if ( anU > anUMaxValue ) {
+      anUMaxValue = anU;
+    }
+  }
+
+  anUMidValue = ( anUMinValue + anUMaxValue ) / 2;
+
+  // Find index of the parametric point with minimal Z value
+  int aBottomIndex = 1;
+  HYDROData_IPolyline::Point aParBottom = aParametricPoints.First();
+
+  for ( int i = 2, aNbPoints = aParametricPoints.Size(); i <= aNbPoints; i++ ) {
+    const HYDROData_IPolyline::Point& aParPoint = aParametricPoints.Value( i );
+    if ( aParPoint.Y() < aParBottom.Y() ) {
+      aBottomIndex = i;
+      aParBottom = aParPoint;
+    } else if ( aParPoint.Y() == aParBottom.Y() ) {
+      // Check which point is neares to the U = 0.5
+      if ( fabs( aParPoint.X() - anUMidValue ) < fabs( aParBottom.X() - anUMidValue ) ) {
+        aBottomIndex = i;
+        aParBottom = aParPoint;
+      }
+    }
+  }
+
+  // Find the corresponding profile point
+  ProfilePoints aProfilePoints = GetProfilePoints( false );
+  if ( aBottomIndex >= 1 && aBottomIndex <= aProfilePoints.Length() ) {
+    aBottom = aProfilePoints.Value( aBottomIndex );
+  }
+
+  return aBottom;
+}
 
index 1470105351b694998396db91bac19b9421dc4398..03339e1f52d851b229697bced5820d9612d6d526 100644 (file)
@@ -191,6 +191,13 @@ public:
    */
   HYDRODATA_EXPORT ProfilePoints GetProfilePoints( bool IsConvertToGlobal = false ) const;
 
+
+  /**
+   * Return profile point with minimal Z value.
+   * \return non-parametric profile point
+   */
+  HYDRODATA_EXPORT ProfilePoint GetBottomPoint() const;
+
 public:
   // Public methods to work with files.
 
index 9573c8bd0b4457be805e08d9928a94645683b321..656e1b02b63be1012b24b7a7dcd7b670eb001c20 100644 (file)
 
 #include "HYDROData_Document.h"
 #include "HYDROData_PolylineXY.h"
+#include "HYDROData_Polyline3D.h"
 #include "HYDROData_Profile.h"
 #include "HYDROData_ShapesGroup.h"
 #include "HYDROData_ShapesTool.h"
 #include "HYDROData_IAltitudeObject.h"
+#include "HYDROData_Tool.h"
 
 #include <TDataStd_RealArray.hxx>
 
@@ -119,6 +121,12 @@ QStringList HYDROData_Stream::DumpToPython( MapOfTreatedObjects& theTreatedObjec
     setPythonReferenceObject( theTreatedObjects, aResList, aProfile, "AddProfile" );
   }
 
+  // Create bottom polyline if exists
+  const Handle(HYDROData_Polyline3D) aBottomPolyline = GetBottomPolyline();
+  if ( !aBottomPolyline.IsNull() ) {
+    aResList << QString( "%1.GenerateBottomPolyline();" ).arg( aName );
+  }
+
   aResList << QString( "" );
   aResList << QString( "%1.Update();" ).arg( aName );
   aResList << QString( "" );
@@ -164,6 +172,19 @@ Handle(Geom_BSplineCurve) HYDROData_Stream::buildInterpolationCurve(
 void HYDROData_Stream::Update()
 {
   updateProfilesOrder();
+
+  // Update bottom polyline if exists
+  const Handle(HYDROData_Polyline3D) aBottomPolyline = GetBottomPolyline();
+  if ( !aBottomPolyline.IsNull() ) {
+    if ( GenerateBottomPolyline() ) {
+      Handle(HYDROData_PolylineXY) aPolylineXY = aBottomPolyline->GetPolylineXY();
+      if ( !aPolylineXY.IsNull() ) {
+        aPolylineXY->Update();
+      }
+      aBottomPolyline->Update();
+    }
+  }
+
   UpdatePrs();
 }
 
@@ -382,7 +403,7 @@ void HYDROData_Stream::UpdatePrs()
   anInGroup->AddShape( aResultPrs.myInlet );
 
   QString anOutGroupName = GetName() + "_Outlet";
-
+  
   Handle(HYDROData_ShapesGroup) anOutGroup = createGroupObject();
   anOutGroup->SetName( anOutGroupName );
   anOutGroup->AddShape( aResultPrs.myOutlet );
@@ -997,3 +1018,106 @@ void HYDROData_Stream::removeParameter( const int& theIndex )
 
   setParametersArray( aNewArr );
 }
+
+bool HYDROData_Stream::GenerateBottomPolyline()
+{
+  // Get the document
+  Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
+  if ( aDocument.IsNull() ) {
+    return false;
+  }
+
+  // Collect bottom points ( one bottom point from each profile of the stream )
+  HYDROData_Profile::ProfilePoints aBottomPoints;
+  
+  HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
+  for ( int i = 1, aNb = aSeqOfProfiles.Size(); i <= aNb; i++ ) {
+    const Handle(HYDROData_Profile) aProfile = 
+      Handle(HYDROData_Profile)::DownCast( aSeqOfProfiles.Value( i ) );
+    if ( aProfile.IsNull() ) {
+      continue;
+    }
+    
+    aBottomPoints.Append( aProfile->GetBottomPoint() );
+  }
+
+  int aNbBottomPoints = aBottomPoints.Size();
+
+  if ( aNbBottomPoints < 2 ) {
+    return false;
+  }
+
+  // Create bottom polyline object if the stream doesn't contain it yet
+  Handle(HYDROData_Polyline3D) aBottom = GetBottomPolyline();
+  if ( aBottom.IsNull() ) {
+    aBottom = Handle(HYDROData_Polyline3D)::DownCast( aDocument->CreateObject( KIND_POLYLINE ) );  
+    QString aBaseName = GetName() + "_bottom";
+    QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName, QStringList(), true );
+    aBottom->SetName( aName );
+
+    SetReferenceObject( aBottom, DataTag_BottomPolyline );
+  }
+  
+  // Create 2D polyline if the bottom polyline doesn't contain it yet
+  Handle(HYDROData_PolylineXY) aPolylineXY = aBottom->GetPolylineXY();
+  if ( aPolylineXY.IsNull() ) {
+    aPolylineXY = Handle(HYDROData_PolylineXY)::DownCast( aDocument->CreateObject( KIND_POLYLINEXY ) );
+    QString aBaseName = GetName() + "_bottom_2d";
+    QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName, QStringList(), true );
+    aPolylineXY->SetName( aName );
+    aBottom->SetPolylineXY( aPolylineXY, false );
+  }
+
+  aPolylineXY->RemoveSections();
+  aPolylineXY->AddSection( "", HYDROData_PolylineXY::SECTION_SPLINE, false );
+  
+  // Create profile if the bottom polyline doesn't contain it yet
+  Handle(HYDROData_ProfileUZ) aProfileUZ = aBottom->GetProfileUZ();
+  if ( aProfileUZ.IsNull() ) {
+    Handle(HYDROData_Profile) aProfile = 
+      Handle(HYDROData_Profile)::DownCast( aDocument->CreateObject( KIND_PROFILE ) );
+    QString aBaseName = GetName() + "_bottom_profile";
+    QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName, QStringList(), true );
+    aProfile->SetName( aName );
+    aProfileUZ = aProfile->GetProfileUZ( true );
+    aBottom->SetProfileUZ( aProfileUZ );
+  }
+  
+  aProfileUZ->RemoveSection( 0 );
+
+  // Fill 2D polyline
+  for ( int i = 1; i <= aNbBottomPoints; i++ ) {
+    const HYDROData_Profile::ProfilePoint& aBottomPoint = aBottomPoints.Value( i );
+    aPolylineXY->AddPoint( 0, HYDROData_PolylineXY::Point( aBottomPoint.X(), aBottomPoint.Y() ) );
+  }
+  
+  // Calculate profile UZ points
+
+  // First point
+  const HYDROData_Profile::ProfilePoint& aFirstBottomPoint = aBottomPoints.First();
+  aProfileUZ->AddPoint( 0, HYDROData_ProfileUZ::Point( 0, aFirstBottomPoint.Z() ) );
+
+  // Intermediate points
+  double aPolylineCommonDist = aPolylineXY->GetDistance( 0, aPolylineXY->NbPoints( 0 ) - 1 );
+
+  for ( int i = 2, aNbPoints = aBottomPoints.Size(); i < aNbPoints; i++ ) {
+    const HYDROData_Profile::ProfilePoint& aBottomPoint = aBottomPoints.Value( i );
+    
+    double aDistance = aPolylineXY->GetDistance( 0, i - 1 );
+    
+    Standard_Real anU = aDistance; // = ( aDistance / aPolylineCommonDist ) * aPolylineCommonDist;
+    aProfileUZ->AddPoint( 0, HYDROData_ProfileUZ::Point( anU, aBottomPoint.Z() ) );
+  }
+  
+  // Last point
+  const HYDROData_Profile::ProfilePoint& aLastBottomPoint = aBottomPoints.Last();
+  aProfileUZ->AddPoint( 0, HYDROData_ProfileUZ::Point( aPolylineCommonDist, aLastBottomPoint.Z() ) );
+  
+  return true;
+}
+
+Handle(HYDROData_Polyline3D) HYDROData_Stream::GetBottomPolyline() const
+{
+  return Handle(HYDROData_Polyline3D)::DownCast( 
+           GetReferenceObject( DataTag_BottomPolyline ) );
+}
index 45a81943493c1a8cb4c07474f372e15bded0bc13..4af7d1c6e73e18606c90c23bf3d2ad5a7caf0712 100644 (file)
@@ -33,6 +33,7 @@
 DEFINE_STANDARD_HANDLE(HYDROData_Stream, HYDROData_NaturalObject)
 
 class Handle(HYDROData_PolylineXY);
+class Handle(HYDROData_Polyline3D);
 class Handle(HYDROData_Profile);
 class TColStd_Array1OfReal;
 
@@ -63,7 +64,8 @@ protected:
     DataTag_First = HYDROData_NaturalObject::DataTag_First + 100, ///< first tag, to reserve
     DataTag_HydraulicAxis,     ///< reference hydraulic axis
     DataTag_Profile,           ///< reference profiles
-    DataTag_ParamsArray        ///< parameters array
+    DataTag_ParamsArray,       ///< parameters array
+    DataTag_BottomPolyline     ///< reference bottom polyline
   };
 
 public:
@@ -229,6 +231,17 @@ public:
    * Removes all reference profile objects from stream.
    */
   HYDRODATA_EXPORT virtual void RemoveProfiles();
+
+  /**
+   * Generates bottom polyline for stream or update the existing bottom polyline.
+   * \return true in case of success
+   */
+  HYDRODATA_EXPORT virtual bool GenerateBottomPolyline();
+
+  /**
+   * Returns reference bottom polyline object of stream.
+   */
+  HYDRODATA_EXPORT virtual Handle(HYDROData_Polyline3D) GetBottomPolyline() const;
   
 protected:
 
index d061b7de74f35da887fea150b29845eb1d2a2797..37e4ec0b61e2dc7a6265f4d1e9de13843e58ad85 100644 (file)
@@ -982,6 +982,11 @@ void HYDROGUI_DataModel::buildObjectTree( SUIT_DataObject* theParent,
 
     HYDROData_SequenceOfObjects aProfiles = aStreamObj->GetProfiles();
     buildObjectPartition( aGuiObj, aProfiles, tr( "STREAM_PROFILES" ), true );
+
+    Handle(HYDROData_Polyline3D) aBottomPolyline = aStreamObj->GetBottomPolyline();
+    if ( !aBottomPolyline.IsNull() && !aBottomPolyline->IsRemoved() ) {
+      createObject( aGuiObj, aBottomPolyline, aGuiObj->entry(), false );
+    }
   }
 }
 
index f0312216e068e5ebec0e4e6dff85c56761f477ec..3bd6c64fa8e430cd4046202ea8e4c90b45cb2cb8 100644 (file)
@@ -98,7 +98,7 @@ bool HYDROGUI_RiverBottomOp::processApply( int& theUpdateFlags, QString& theErro
   if ( !aPanel )
     return false;
 
-  Handle(HYDROData_River) aRiver = riverObject( aPanel->getRiverName() );
+  Handle(HYDROData_Stream) aRiver = riverObject( aPanel->getRiverName() );
   if ( aRiver.IsNull() )
   {
     theErrorMsg = tr( "INCORRECT_RIVER_OBJECT" );
@@ -107,6 +107,8 @@ bool HYDROGUI_RiverBottomOp::processApply( int& theUpdateFlags, QString& theErro
 
   startDocOperation();
 
+  aRiver->GenerateBottomPolyline();
+  aRiver->Update();
 //  Handle(HYDRO_RiverBottom) aBottom = createNewObject();
 //  aBottom->SetName( QString( "%1_Bottom" ).arg( aRiver->GetName() ) );
 
@@ -130,9 +132,9 @@ Handle(HYDROData_RiverBottom) HYDROGUI_RiverBottomOp::createNewObject()
 }
 */
 
-Handle(HYDROData_River) HYDROGUI_RiverBottomOp::riverObject( const QString& theName ) const
+Handle(HYDROData_Stream) HYDROGUI_RiverBottomOp::riverObject( const QString& theName ) const
 {
-    return Handle(HYDROData_River)::DownCast( HYDROGUI_Tool::FindObjectByName( module(), theName ) );
+    return Handle(HYDROData_Stream)::DownCast( HYDROGUI_Tool::FindObjectByName( module(), theName ) );
 }
 QStringList HYDROGUI_RiverBottomOp::riverNames( bool all ) const
 {
index b99b666f86eda7c4580ee7935a776705ba8f1f6f..525df1f764c43fb46ddcb066aade3f99a8abc636 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "HYDROGUI_Operation.h"
 
-#include <HYDROData_River.h>
+#include <HYDROData_Stream.h>
 
 class HYDROGUI_RiverBottomOp : public HYDROGUI_Operation
 {
@@ -46,7 +46,7 @@ protected:
                                              QStringList& theBrowseObjectsEntries );
 
 private:
-  Handle(HYDROData_River)      riverObject( const QString& ) const;
+  Handle(HYDROData_Stream)     riverObject( const QString& ) const;
   QStringList                  riverNames( bool all = false ) const;
 
 protected:
index 57bdbdb518f066305d410ccb591e8b98c52ec930..1b64e7c8bb997fd9a63095a19684a4333d0b0dd7 100644 (file)
@@ -146,6 +146,27 @@ public:
    * Removes all reference profile objects from stream.
    */
   void RemoveProfiles();
+
+  /**
+   * Generates bottom polyline for stream or update the existing bottom polyline.
+   */
+  bool GenerateBottomPolyline();
+
+  /**
+   * Returns reference bottom polyline object of stream.
+   */
+  HYDROData_Polyline3D GetBottomPolyline() const
+  [Handle_HYDROData_Polyline3D ()];
+  %MethodCode
+    Handle(HYDROData_Polyline3D) aRef;
+    
+    Py_BEGIN_ALLOW_THREADS
+    aRef = sipSelfWasArg ? sipCpp->HYDROData_Stream::GetBottomPolyline() : 
+                           sipCpp->GetBottomPolyline();
+    Py_END_ALLOW_THREADS
+    
+    sipRes = (HYDROData_Polyline3D*)createPointer( aRef );
+  %End
   
 protected:
   /**