From 70c7074d98594928a559f402ed02db0e562f2553 Mon Sep 17 00:00:00 2001 From: mzn Date: Mon, 30 Mar 2015 14:21:43 +0300 Subject: [PATCH] refs #493: add data model methods implementation --- .../HYDROData_IProfilesInterpolator.cxx | 31 +++++++- .../HYDROData_IProfilesInterpolator.h | 35 +++++++++- .../HYDROData_LinearInterpolator.cxx | 70 ++++++++++++++++++- src/HYDROData/HYDROData_LinearInterpolator.h | 2 +- src/HYDROData/HYDROData_Stream.cxx | 57 ++++++++++++++- src/HYDROData/HYDROData_Stream.h | 2 +- .../HYDROGUI_ProfileInterpolateOp.cxx | 13 ++-- src/HYDROGUI/HYDROGUI_ProfileInterpolateOp.h | 2 +- 8 files changed, 196 insertions(+), 16 deletions(-) diff --git a/src/HYDROData/HYDROData_IProfilesInterpolator.cxx b/src/HYDROData/HYDROData_IProfilesInterpolator.cxx index f0c8d420..2af03fd7 100644 --- a/src/HYDROData/HYDROData_IProfilesInterpolator.cxx +++ b/src/HYDROData/HYDROData_IProfilesInterpolator.cxx @@ -80,7 +80,7 @@ std::vector HYDROData_IProfilesInterpolator::GetResultProfile( const int { std::vector aResultProfile; - if ( theProfileIndex > 0 && theProfileIndex < (int) myResultProfiles.size() ) { + if ( theProfileIndex >= 0 && theProfileIndex < (int) myResultProfiles.size() ) { aResultProfile = myResultProfiles.at( theProfileIndex ); } @@ -89,14 +89,43 @@ std::vector HYDROData_IProfilesInterpolator::GetResultProfile( const int void HYDROData_IProfilesInterpolator::Reset() { + // Reset input parameters myProfile1.clear(); myProfile2.clear(); myParameters.clear(); SetResultProfilesNumber( DEFAULT_RESULT_PROFILES_NB ); + // Reset result data + ClearResults(); +} + +std::vector HYDROData_IProfilesInterpolator::GetFirstProfile() const +{ + return myProfile1; +} + +std::vector HYDROData_IProfilesInterpolator::GetSecondProfile() const +{ + return myProfile2; +} + +void HYDROData_IProfilesInterpolator::ClearResults() +{ + // Clear result data myResultProfiles.clear(); + // Reset errors SetErrorCode( OK ); SetErrorMessage( "" ); +} + +int HYDROData_IProfilesInterpolator::GetNbProfilesToCompute() const +{ + return myResultProfilesNumber; +} + +void HYDROData_IProfilesInterpolator::InsertResultProfile( const std::vector& theProfile ) +{ + myResultProfiles.push_back( theProfile ); } \ No newline at end of file diff --git a/src/HYDROData/HYDROData_IProfilesInterpolator.h b/src/HYDROData/HYDROData_IProfilesInterpolator.h index a98c70fc..c1a0949d 100644 --- a/src/HYDROData/HYDROData_IProfilesInterpolator.h +++ b/src/HYDROData/HYDROData_IProfilesInterpolator.h @@ -106,8 +106,12 @@ public: /** * Perform interpolation calculations. */ - HYDRODATA_EXPORT virtual InterpolationError Calculate() = 0; + HYDRODATA_EXPORT virtual void Calculate() = 0; + /** + * Get number of calculated profiles ( could be less than the number of profiles to be computed set as a parameter ). + * @return the number of really calculated profiles + */ HYDRODATA_EXPORT virtual int GetCalculatedProfilesNumber() const; /** @@ -130,6 +134,35 @@ protected: */ HYDRODATA_EXPORT virtual void SetErrorMessage( const std::string& theMessage ); + /** + * Get the first profile. + * \return the first profile points + */ + HYDRODATA_EXPORT std::vector GetFirstProfile() const; + + /** + * Get the second profile. + * \return the second profile points + */ + HYDRODATA_EXPORT std::vector GetSecondProfile() const; + + /** + * Get number of profiles to compute. + * \return the current value of number of result profiles parameter + */ + HYDRODATA_EXPORT virtual int GetNbProfilesToCompute() const; + + /** + * Clear result data (including errors). + */ + HYDRODATA_EXPORT void ClearResults(); + + /** + * Insert the calculated profile to the resuls. + * \param theProfile the profile to insert + */ + HYDRODATA_EXPORT void InsertResultProfile( const std::vector& theProfile ); + private: std::vector myProfile1, myProfile2; ///< the two input profiles int myResultProfilesNumber; ///< the number of profiles to compute diff --git a/src/HYDROData/HYDROData_LinearInterpolator.cxx b/src/HYDROData/HYDROData_LinearInterpolator.cxx index af2eb24c..fedb3f12 100644 --- a/src/HYDROData/HYDROData_LinearInterpolator.cxx +++ b/src/HYDROData/HYDROData_LinearInterpolator.cxx @@ -38,7 +38,73 @@ std::string HYDROData_LinearInterpolator::GetDescription() const return aDescription; } -InterpolationError HYDROData_LinearInterpolator::Calculate() +void HYDROData_LinearInterpolator::Calculate() { - return OK; + // Reset result data + ClearResults(); + + // Check input data + std::vector aProfile1 = GetFirstProfile(); + std::vector aProfile2 = GetSecondProfile(); + int aNbProfilesToCompute = GetNbProfilesToCompute(); + + int aSize1 = aProfile1.size(); + int aSize2 = aProfile2.size(); + + div_t aDiv1 = std::div( aSize1, 3 ); + div_t aDiv2 = std::div( aSize2, 3 ); + + if ( aNbProfilesToCompute < 1 || + aSize1 < 2 || aDiv1.rem != 0 || + aSize2 < 2 || aDiv2.rem != 0 ) { + SetErrorCode( InvalidParametersError ); + return; + } + + bool isSame = false; + if ( aSize1 < aSize2 ) { + isSame = std::equal( aProfile1.begin(), aProfile1.end(), aProfile2.begin() ); + } else { + isSame = std::equal( aProfile2.begin(), aProfile2.end(), aProfile1.begin() ); + } + + if ( isSame ) { + SetErrorCode( InvalidParametersError ); + return; + } + + // Linear interpolation + InterpolationError aStatus = OK; + + // the first profile should have the equal or less number of points than the second profile + int aNbPoints1 = aDiv1.quot; + int aNbPoints2 = aDiv2.quot; + if ( aNbPoints1 > aNbPoints2 ) { + aProfile1.swap( aProfile2 ); + std::swap( aNbPoints1, aNbPoints2 ); + } + + for ( int k = 0; k <= aNbProfilesToCompute - 1; k++ ) { + std::vector aResultProfile; ///< the k-th computed profile + + double aRelParam = (double)( k + 1 ) / ( aNbProfilesToCompute + 1 ); + for ( int i = 0; i <= aNbPoints1 - 1; i++ ) { + double aRel = ( aNbPoints2 - 1 ) / ( aNbPoints1 - 1 ); + int aPointIndex = (int) std::floor( aRel * i ); ///< point index in the second profile + int anXindex1 = i * 3; + int anXindex2 = aPointIndex * 3; + + double anXi = ( aProfile1[anXindex1] * ( 1 - aRelParam ) ) + ( aProfile2[anXindex2] * aRelParam ); + double anYi = ( aProfile1[anXindex1 + 1] * ( 1 - aRelParam ) ) + ( aProfile2[anXindex2 + 1] * aRelParam ); + double aZi = ( aProfile1[anXindex1 + 2] * ( 1 - aRelParam ) ) + ( aProfile2[anXindex2 + 2] * aRelParam ); + + aResultProfile.push_back( anXi ); + aResultProfile.push_back( anYi ); + aResultProfile.push_back( aZi ); + } + + InsertResultProfile( aResultProfile ); + } + + SetErrorCode( aStatus ); } \ No newline at end of file diff --git a/src/HYDROData/HYDROData_LinearInterpolator.h b/src/HYDROData/HYDROData_LinearInterpolator.h index df1bacb5..4cd4e8e7 100644 --- a/src/HYDROData/HYDROData_LinearInterpolator.h +++ b/src/HYDROData/HYDROData_LinearInterpolator.h @@ -53,7 +53,7 @@ public: /** * */ - HYDRODATA_EXPORT virtual InterpolationError Calculate(); + HYDRODATA_EXPORT virtual void Calculate(); }; #endif diff --git a/src/HYDROData/HYDROData_Stream.cxx b/src/HYDROData/HYDROData_Stream.cxx index bf517b24..6610c1fc 100644 --- a/src/HYDROData/HYDROData_Stream.cxx +++ b/src/HYDROData/HYDROData_Stream.cxx @@ -29,6 +29,7 @@ #include "HYDROData_ShapesGroup.h" #include "HYDROData_ShapesTool.h" #include "HYDROData_IAltitudeObject.h" +#include "HYDROData_IProfilesInterpolator.h" #include "HYDROData_Tool.h" #include @@ -1122,8 +1123,58 @@ Handle(HYDROData_Polyline3D) HYDROData_Stream::GetBottomPolyline() const GetReferenceObject( DataTag_BottomPolyline ) ); } -bool HYDROData_Stream::Interpolate( const HYDROData_IProfilesInterpolator* theInterpolator ) +bool HYDROData_Stream::Interpolate( HYDROData_IProfilesInterpolator* theInterpolator ) { - ///< \todo this is just a stub - return true; + // Get the document + Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab ); + if ( aDocument.IsNull() ) { + return false; + } + + if ( theInterpolator->GetCalculatedProfilesNumber() < 1 ) { + theInterpolator->Calculate(); + } + + if ( theInterpolator->GetErrorCode() != OK ) { + return false; + } + + bool isOK = true; + + for ( int aProfileInd = 0; aProfileInd < theInterpolator->GetCalculatedProfilesNumber(); aProfileInd++ ) { + // Get calculated point coordinates + std::vector aResultCoords = theInterpolator->GetResultProfile( aProfileInd ); + div_t aDiv = std::div( aResultCoords.size(), 3 ); + if ( aDiv.rem != 0 ) { + isOK = false; + continue; + } + + // Create profile object + Handle(HYDROData_Profile) aProfile = + Handle(HYDROData_Profile)::DownCast( aDocument->CreateObject( KIND_PROFILE ) ); + QString aBaseName = GetName() + "_interp_profile"; + QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName ); + aProfile->SetName( aName ); + + // Fill the profile with points + HYDROData_Profile::ProfilePoints aProfilePoints; + + int aPointsNb = aDiv.quot; + for ( int aPointInd = 0; aPointInd <= aPointsNb - 1; aPointInd++ ) { + int anXindex = aPointInd * 3; + double anX = aResultCoords[ anXindex ]; + double anY = aResultCoords[ anXindex + 1 ]; + double aZ = aResultCoords[ anXindex + 2 ]; + + aProfilePoints.Append( gp_XYZ( anX, anY, aZ ) ); + } + + aProfile->SetProfilePoints( aProfilePoints ); + + // Add profile to the stream + isOK = AddProfile( aProfile ) && isOK; + } + + return isOK; } \ No newline at end of file diff --git a/src/HYDROData/HYDROData_Stream.h b/src/HYDROData/HYDROData_Stream.h index 800438fe..b80d588a 100644 --- a/src/HYDROData/HYDROData_Stream.h +++ b/src/HYDROData/HYDROData_Stream.h @@ -250,7 +250,7 @@ public: * \param theInterpolator the interpolator * \return true in case of success */ - HYDRODATA_EXPORT virtual bool Interpolate( const HYDROData_IProfilesInterpolator* theInterpolator ); + HYDRODATA_EXPORT virtual bool Interpolate( HYDROData_IProfilesInterpolator* theInterpolator ); protected: diff --git a/src/HYDROGUI/HYDROGUI_ProfileInterpolateOp.cxx b/src/HYDROGUI/HYDROGUI_ProfileInterpolateOp.cxx index dab1a59e..362ceb6e 100644 --- a/src/HYDROGUI/HYDROGUI_ProfileInterpolateOp.cxx +++ b/src/HYDROGUI/HYDROGUI_ProfileInterpolateOp.cxx @@ -136,7 +136,7 @@ bool HYDROGUI_ProfileInterpolateOp::processApply( int& theUpdateFlags, QString& if ( !aRiver.IsNull() ) { startDocOperation(); - //aRiver->Interpolate( anIterp ); + aRiver->Interpolate( anIterp ); if ( anIterp->GetErrorCode() == OK ) commitDocOperation(); else @@ -176,9 +176,10 @@ void HYDROGUI_ProfileInterpolateOp::updatePreview() if ( anIterp ) { updateInterpolator( anIterp ); - if ( anIterp->Calculate() == OK ) + anIterp->Calculate(); + if ( anIterp->GetErrorCode() == OK ) { - TopoDS_Shape aShape = previewShape( anIterp, aDlg->profileNumber() ); + TopoDS_Shape aShape = previewShape( anIterp ); if ( !aShape.IsNull() ) { myPreview = new AIS_Shape( aShape ); @@ -284,18 +285,18 @@ HYDROData_IProfilesInterpolator* HYDROGUI_ProfileInterpolateOp::interpolator( co return aRes; } -TopoDS_Shape HYDROGUI_ProfileInterpolateOp::previewShape( HYDROData_IProfilesInterpolator* theInterp, int theNumber ) const +TopoDS_Shape HYDROGUI_ProfileInterpolateOp::previewShape( HYDROData_IProfilesInterpolator* theInterp ) const { TopoDS_Compound aPreviewShape; if ( theInterp ) { BRep_Builder aBuilder; aBuilder.MakeCompound( aPreviewShape ); - for ( int i = 0; i < theNumber; i++ ) + for ( int i = 0; i < theInterp->GetCalculatedProfilesNumber(); i++ ) { NCollection_Sequence pointSeq; std::vector aPoints = theInterp->GetResultProfile( i ); - for ( int i = 0; i < aPoints.size(); i += 3 ) + for ( int i = 0; i < (int) aPoints.size(); i += 3 ) pointSeq.Append( gp_XYZ( aPoints[i], aPoints[i+1], aPoints[i+2] ) ); TopoDS_Shape aWire = HYDROData_PolylineXY::BuildWire( HYDROData_IPolyline::SECTION_SPLINE, false, pointSeq ); if ( !aWire.IsNull() ) diff --git a/src/HYDROGUI/HYDROGUI_ProfileInterpolateOp.h b/src/HYDROGUI/HYDROGUI_ProfileInterpolateOp.h index dabd86ec..e593acf5 100644 --- a/src/HYDROGUI/HYDROGUI_ProfileInterpolateOp.h +++ b/src/HYDROGUI/HYDROGUI_ProfileInterpolateOp.h @@ -62,7 +62,7 @@ protected: ParamsList parameters( const QString& ) const; QString parameters( const ParamsList& ) const; - TopoDS_Shape previewShape( HYDROData_IProfilesInterpolator*, int ) const; + TopoDS_Shape previewShape( HYDROData_IProfilesInterpolator* ) const; private slots: void updatePreview(); -- 2.39.2