From b0759ef35e28020af9766fc25ae9b8796f851b80 Mon Sep 17 00:00:00 2001 From: adv Date: Fri, 29 Nov 2013 07:05:29 +0000 Subject: [PATCH] Polyline 3d first implementstion. --- src/HYDROData/CMakeLists.txt | 2 + src/HYDROData/HYDROData_BSplineOperation.cxx | 46 ++-- src/HYDROData/HYDROData_BSplineOperation.h | 20 +- src/HYDROData/HYDROData_Polyline3D.cxx | 184 ++++++++++++++ src/HYDROData/HYDROData_Polyline3D.h | 116 +++++++++ src/HYDROData/HYDROData_PolylineXY.cxx | 226 +++++++++++++----- src/HYDROData/HYDROData_PolylineXY.h | 27 ++- src/HYDROData/HYDROData_ProfileUZ.cxx | 37 +++ src/HYDROData/HYDROData_ProfileUZ.h | 5 + .../test_HYDROData_BSplineOperation.cxx | 51 ++-- 10 files changed, 599 insertions(+), 115 deletions(-) create mode 100644 src/HYDROData/HYDROData_Polyline3D.cxx create mode 100644 src/HYDROData/HYDROData_Polyline3D.h diff --git a/src/HYDROData/CMakeLists.txt b/src/HYDROData/CMakeLists.txt index bd03c1f1..3a838760 100644 --- a/src/HYDROData/CMakeLists.txt +++ b/src/HYDROData/CMakeLists.txt @@ -25,6 +25,7 @@ set(PROJECT_HEADERS HYDROData_OperationsFactory.h # HYDROData_Polyline.h HYDROData_PolylineXY.h + HYDROData_Polyline3D.h HYDROData_Profile.h HYDROData_ProfileUZ.h HYDROData_Region.h @@ -60,6 +61,7 @@ set(PROJECT_SOURCES HYDROData_OperationsFactory.cxx # HYDROData_Polyline.cxx HYDROData_PolylineXY.cxx + HYDROData_Polyline3D.cxx HYDROData_Profile.cxx HYDROData_ProfileUZ.cxx HYDROData_Region.cxx diff --git a/src/HYDROData/HYDROData_BSplineOperation.cxx b/src/HYDROData/HYDROData_BSplineOperation.cxx index df0b2e44..128f4aec 100644 --- a/src/HYDROData/HYDROData_BSplineOperation.cxx +++ b/src/HYDROData/HYDROData_BSplineOperation.cxx @@ -1,41 +1,41 @@ -#include -#include -#include -#include -#include +#include + +#include + +#include +#include +#include + +#include HYDROData_BSplineOperation::HYDROData_BSplineOperation( - const QList& thePoints, - const double theZValue, - const bool theIsClosed) + const NCollection_Sequence& thePoints, + const bool theIsClosed ) { // fill array for algorithm by the received coordinates - int aLen = thePoints.size() / 2; - Handle(TColgp_HArray1OfPnt) aHCurvePoints = new TColgp_HArray1OfPnt (1, aLen); - QList::const_iterator aListIter = thePoints.begin(); - for (int ind = 1; ind <= aLen; ind++) { - gp_Pnt aPnt(gp::Origin()); - aPnt.SetX(*aListIter); - aListIter++; - aPnt.SetY(*aListIter); - aListIter++; - aPnt.SetZ(theZValue); - aHCurvePoints->SetValue(ind, aPnt); + int aNbPoints = thePoints.Size(); + + Handle(TColgp_HArray1OfPnt) aHCurvePoints = new TColgp_HArray1OfPnt( 1, aNbPoints ); + for ( int i = 1; i <= aNbPoints; i++ ) + { + gp_Pnt aPnt( thePoints.Value( i ) ); + aHCurvePoints->SetValue( i, aPnt ); } + // compute BSpline - GeomAPI_Interpolate aGBC(aHCurvePoints, theIsClosed, gp::Resolution()); + GeomAPI_Interpolate aGBC( aHCurvePoints, theIsClosed, gp::Resolution() ); aGBC.Perform(); - if (aGBC.IsDone()) { + if ( aGBC.IsDone() ) myCurve = aGBC.Curve(); - } } QPainterPath HYDROData_BSplineOperation::ComputePath() const { QPainterPath aResult; - if (myCurve.IsNull()) // returns an empty Path if original curve is invalid + if ( myCurve.IsNull() ) // returns an empty Path if original curve is invalid return aResult; + GeomConvert_BSplineCurveToBezierCurve aConverter(myCurve); int a, aNumArcs = aConverter.NbArcs(); for(a = 1; a <= aNumArcs; a++) { diff --git a/src/HYDROData/HYDROData_BSplineOperation.h b/src/HYDROData/HYDROData_BSplineOperation.h index 96be8d09..6c91bf86 100644 --- a/src/HYDROData/HYDROData_BSplineOperation.h +++ b/src/HYDROData/HYDROData_BSplineOperation.h @@ -1,11 +1,16 @@ + #ifndef HYDROData_BSplineOperation_HeaderFile #define HYDROData_BSplineOperation_HeaderFile #include -#include -#include + #include +#include + +class QPainterPath; +class gp_XYZ; + /**\class HYDROData_BSplineOperation * * \brief Allows to work with splines: create, convert to Qt ToolPath. @@ -19,20 +24,19 @@ class HYDRODATA_EXPORT HYDROData_BSplineOperation public: //! Creates a spline by list of coordinates: pairs X and Y - //! \param thePoints coordinates in format X1, Y1, X2, Y2, etc. must be even number of elements - //! \param theZValue constant value of the spline Z coordinate + //! \param thePoints coordinates of curve //! \param theIsClosed flag indicating that the result spline should be closed - HYDROData_BSplineOperation(const QList& thePoints, - const double theZValue, - const bool theIsClosed); + HYDROData_BSplineOperation( const NCollection_Sequence& thePoints, + const bool theIsClosed ); //! Returns the BSpline curve passing through the points //! \returns Null if Computation of BSpline was failed - Handle(Geom_BSplineCurve) Curve() const {return myCurve;} + Handle(Geom_BSplineCurve) Curve() const { return myCurve; } //! Performs conversion from BSpline curve to QPainterPath made from Bezier curves //! \returns computed PainterPath, not stored in this class, so calling of this method is not fast QPainterPath ComputePath() const; + private: Handle(Geom_BSplineCurve) myCurve; ///< resulting BSpline, null if something is wrong }; diff --git a/src/HYDROData/HYDROData_Polyline3D.cxx b/src/HYDROData/HYDROData_Polyline3D.cxx new file mode 100644 index 00000000..bb8d172b --- /dev/null +++ b/src/HYDROData/HYDROData_Polyline3D.cxx @@ -0,0 +1,184 @@ + +#include "HYDROData_Polyline3D.h" + +#include "HYDROData_Document.h" +#include "HYDROData_PolylineXY.h" +#include "HYDROData_ProfileUZ.h" + +#include +#include +#include + +#include +#include + +#include + +#define PYTHON_POLYLINE_ID "KIND_POLYLINE" + +IMPLEMENT_STANDARD_HANDLE(HYDROData_Polyline3D,HYDROData_Object) +IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Polyline3D,HYDROData_Object) + + +HYDROData_Polyline3D::HYDROData_Polyline3D() +: HYDROData_Object() +{ +} + +HYDROData_Polyline3D::~HYDROData_Polyline3D() +{ +} + +QStringList HYDROData_Polyline3D::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const +{ + QStringList aResList; + + Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab ); + if ( aDocument.IsNull() ) + return aResList; + + QString aDocName = aDocument->GetDocPyName(); + QString aPolylineName = GetName(); + + aResList << QString( "%1 = %2.CreateObject( %3 );" ) + .arg( aPolylineName ).arg( aDocName ).arg( PYTHON_POLYLINE_ID ); + aResList << QString( "%1.SetName( \"%1\" );" ).arg( aPolylineName ); + aResList << QString( "" ); + + // TODO + + return aResList; +} + +TopoDS_Shape HYDROData_Polyline3D::GetTopShape() const +{ + return getTopShape(); +} + +TopoDS_Shape HYDROData_Polyline3D::GetShape3D() const +{ + return getShape3D(); +} + +void HYDROData_Polyline3D::Update() +{ + removeTopShape(); + removeShape3D(); + + Handle(HYDROData_PolylineXY) aPolylineXY = GetPolylineXY(); + Handle(HYDROData_ProfileUZ) aProfileUZ = GetProfileUZ(); + if ( aPolylineXY.IsNull() || aProfileUZ.IsNull() ) + return; + + bool anIsSectionClosed = aPolylineXY->IsClosedSection( 0 ); + HYDROData_IPolyline::SectionType aSectionType = aPolylineXY->GetSectionType( 0 ); + HYDROData_IPolyline::PointsList aPolylinePoints = aPolylineXY->GetPoints( 0 ); + HYDROData_IPolyline::PointsList aProfilePoints = aProfileUZ->GetPoints(); + if ( aPolylinePoints.IsEmpty() || aProfilePoints.IsEmpty() ) + return; + + const HYDROData_IPolyline::Point& aFirstPoint = aPolylinePoints.First(); + const HYDROData_IPolyline::Point& aLastPoint = aPolylinePoints.Last(); + + const HYDROData_IPolyline::Point& aFirstParPoint = aProfilePoints.First(); + const HYDROData_IPolyline::Point& aLastParPoint = aProfilePoints.Last(); + + double aPolylineCommonDist = aPolylineXY->GetDistance( 0, aPolylinePoints.Size() - 1 ); + double aParCommonDist = gp_Pnt2d( aFirstParPoint.X(), 0 ).Distance( gp_Pnt2d( aLastParPoint.X(), 0 ) ); + + NCollection_Sequence aResPoints; + + // Add first point as is + aResPoints.Append( Polyline3DPoint( aFirstPoint.X(), aFirstPoint.Y(), aFirstParPoint.Y() ) ); + + for ( int i = 2, aNbPoints = aPolylinePoints.Size(); i < aNbPoints; ++i ) + { + const HYDROData_IPolyline::Point& aPolylinePoint = aPolylinePoints.Value( i ); + + double aDistance = aPolylineXY->GetDistance( 0, i - 1 ); + + double aParLen = ( aDistance / aPolylineCommonDist ) * aParCommonDist; + double aDepth = aProfileUZ->GetDepthFromDistance( aParLen ); + + Polyline3DPoint aCompPoint( aPolylinePoint.X(), aPolylinePoint.Y(), aDepth ); + aResPoints.Append( aCompPoint ); + } + + // Add last point as is + aResPoints.Append( Polyline3DPoint( aLastPoint.X(), aLastPoint.Y(), aLastParPoint.Y() ) ); + + TopoDS_Wire aResWire = HYDROData_PolylineXY::BuildWire( aSectionType, anIsSectionClosed, aResPoints ); + SetTopShape( aResWire ); + SetShape3D( aResWire ); +} + +bool HYDROData_Polyline3D::SetPolylineXY( const Handle(HYDROData_PolylineXY)& thePolyline ) +{ + if ( thePolyline.IsNull() ) + return false; + + Handle(HYDROData_PolylineXY) aPrevPolyline = GetPolylineXY(); + if ( IsEqual( aPrevPolyline, thePolyline ) ) + return true; + + SetReferenceObject( thePolyline, DataTag_PolylineXY ); + + // Indicate model of the need to update the polyline presentation + SetToUpdate( true ); + + return true; +} + +Handle(HYDROData_PolylineXY) HYDROData_Polyline3D::GetPolylineXY() const +{ + return Handle(HYDROData_PolylineXY)::DownCast( + GetReferenceObject( DataTag_PolylineXY ) ); +} + +void HYDROData_Polyline3D::RemovePolylineXY() +{ + Handle(HYDROData_PolylineXY) aPrevPolyline = GetPolylineXY(); + if ( aPrevPolyline.IsNull() ) + return; + + ClearReferenceObjects( DataTag_PolylineXY ); + + // Indicate model of the need to update the polyline presentation + SetToUpdate( true ); +} + +bool HYDROData_Polyline3D::SetProfileUZ( const Handle(HYDROData_ProfileUZ)& theProfile ) +{ + if ( theProfile.IsNull() ) + return false; + + Handle(HYDROData_ProfileUZ) aPrevProfile = GetProfileUZ(); + if ( IsEqual( aPrevProfile, theProfile ) ) + return true; + + SetReferenceObject( theProfile, DataTag_ProfileUZ ); + + // Indicate model of the need to update the polyline presentation + SetToUpdate( true ); + + return true; +} + +Handle(HYDROData_ProfileUZ) HYDROData_Polyline3D::GetProfileUZ() const +{ + return Handle(HYDROData_ProfileUZ)::DownCast( + GetReferenceObject( DataTag_ProfileUZ ) ); +} + +void HYDROData_Polyline3D::RemoveProfileUZ() +{ + Handle(HYDROData_ProfileUZ) aPrevProfile = GetProfileUZ(); + if ( aPrevProfile.IsNull() ) + return; + + ClearReferenceObjects( DataTag_ProfileUZ ); + + // Indicate model of the need to update the polyline presentation + SetToUpdate( true ); +} + diff --git a/src/HYDROData/HYDROData_Polyline3D.h b/src/HYDROData/HYDROData_Polyline3D.h new file mode 100644 index 00000000..f45091b8 --- /dev/null +++ b/src/HYDROData/HYDROData_Polyline3D.h @@ -0,0 +1,116 @@ + +#ifndef HYDROData_Polyline3D_HeaderFile +#define HYDROData_Polyline3D_HeaderFile + +#include "HYDROData_Object.h" + +DEFINE_STANDARD_HANDLE(HYDROData_Polyline3D, HYDROData_Object) + +class Handle(HYDROData_PolylineXY); +class Handle(HYDROData_ProfileUZ); +class gp_XYZ; + +/**\class HYDROData_Polyline3D + * \brief + * + */ +class HYDROData_Polyline3D : public HYDROData_Object +{ +public: + + typedef gp_XYZ Polyline3DPoint; + typedef NCollection_Sequence Polyline3DPoints; + +protected: + /** + * Enumeration of tags corresponding to the persistent object parameters. + */ + enum DataTag + { + DataTag_First = HYDROData_Object::DataTag_First + 100, ///< first tag, to reserve + DataTag_PolylineXY, ///< reference hydraulic axis + DataTag_ProfileUZ, ///< reference profiles + }; + +public: + DEFINE_STANDARD_RTTI(HYDROData_Polyline3D); + + /** + * Returns the kind of this object. Must be redefined in all objects of known type. + */ + HYDRODATA_EXPORT virtual const ObjectKind GetKind() const {return KIND_STREAM;} + + /** + * Dump object to Python script representation. + */ + HYDRODATA_EXPORT virtual QStringList DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const; + + /** + * Returns the top shape of the object. + */ + HYDRODATA_EXPORT virtual TopoDS_Shape GetTopShape() const; + + /** + * Returns the 3d shape of the object. + */ + HYDRODATA_EXPORT virtual TopoDS_Shape GetShape3D() const; + + /** + * Update the shape presentations of stream. + * Call this method whenever you made changes for stream data. + */ + HYDRODATA_EXPORT virtual void Update(); + + +public: + // Public methods to work with 3D polyline + + /** + * Sets reference x,y polyline object for 3D polyline. + */ + HYDRODATA_EXPORT virtual bool SetPolylineXY( const Handle(HYDROData_PolylineXY)& thePolyline ); + + /** + * Returns reference x,y polyline object of 3D polyline. + */ + HYDRODATA_EXPORT virtual Handle(HYDROData_PolylineXY) GetPolylineXY() const; + + /** + * Remove reference x,y polyline object from 3D polyline. + */ + HYDRODATA_EXPORT virtual void RemovePolylineXY(); + + + /** + * Sets reference u,z profile object for 3D polyline. + */ + HYDRODATA_EXPORT virtual bool SetProfileUZ( const Handle(HYDROData_ProfileUZ)& theProfile ); + + /** + * Returns reference u,z profile object of 3D polyline. + */ + HYDRODATA_EXPORT virtual Handle(HYDROData_ProfileUZ) GetProfileUZ() const; + + /** + * Remove reference u,z profile object from 3D polyline. + */ + HYDRODATA_EXPORT virtual void RemoveProfileUZ(); + + +protected: + + friend class HYDROData_Iterator; + + /** + * Creates new object in the internal data structure. Use higher level objects + * to create objects with real content. + */ + HYDRODATA_EXPORT HYDROData_Polyline3D(); + + /** + * Destructs properties of the object and object itself, removes it from the document. + */ + virtual HYDRODATA_EXPORT ~HYDROData_Polyline3D(); +}; + +#endif diff --git a/src/HYDROData/HYDROData_PolylineXY.cxx b/src/HYDROData/HYDROData_PolylineXY.cxx index 6c17dd6d..0d79dd23 100755 --- a/src/HYDROData/HYDROData_PolylineXY.cxx +++ b/src/HYDROData/HYDROData_PolylineXY.cxx @@ -9,6 +9,11 @@ #include #include +#include +#include + +#include + #include #include @@ -80,7 +85,7 @@ QStringList HYDROData_PolylineXY::DumpToPython( MapOfTreatedObjects& theTreatedO HYDROData_PolylineXY::PointsList aSectPointsList = GetPoints( i ); for ( int k = 1, aNbPoints = aSectPointsList.Size(); k <= aNbPoints; ++k ) { - const HYDROData_PolylineXY::Point& aSectPoint = aSectPointsList.Value( k ); + const Point& aSectPoint = aSectPointsList.Value( k ); aResList << QString( "%1.AddPoint( %2, QPointF( %3, %4 ) );" ).arg( aPolylineName ) .arg( i - 1 ).arg( aSectPoint.X() ).arg( aSectPoint.Y() ); @@ -105,6 +110,85 @@ TopoDS_Shape HYDROData_PolylineXY::GetShape() return getPolylineShape(); } +TopoDS_Wire HYDROData_PolylineXY::BuildWire( const SectionType& theType, + const bool& theIsClosed, + const NCollection_Sequence& thePoints ) +{ + BRepBuilderAPI_MakeWire aMakeWire; + + if( theType == SECTION_POLYLINE ) + { + for( int i = 1, n = thePoints.Size(); i <= n; ++i ) + { + const gp_XYZ& aFirstPoint = thePoints.Value( i ); + + gp_XYZ aLastPoint; + if ( i == n ) + { + if( theIsClosed ) + aLastPoint = thePoints.Value( 1 ); + else + break; + } + else + { + aLastPoint = thePoints.Value( i + 1 ); + } + + gp_Pnt aPnt1( aFirstPoint.X(), aFirstPoint.Y(), aFirstPoint.Z() ); + gp_Pnt aPnt2( aLastPoint.X(), aLastPoint.Y(), aLastPoint.Z() ); + + TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aPnt1, aPnt2 ).Edge(); + aMakeWire.Add( anEdge ); + } + } + else //if( theType == PolylineSection::SECTION_SPLINE ) + { + HYDROData_BSplineOperation aBSpline( thePoints, theIsClosed ); + + TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aBSpline.Curve() ).Edge(); + aMakeWire.Add( anEdge ); + } + + TopoDS_Wire aWire; + aMakeWire.Build(); + if ( aMakeWire.IsDone() ) + aWire = aMakeWire; + + return aWire; +} + +QPainterPath HYDROData_PolylineXY::BuildPainterPath( const SectionType& theType, + const bool& theIsClosed, + const NCollection_Sequence& thePoints ) +{ + QPainterPath aPath; + if ( thePoints.IsEmpty() ) + return aPath; + + if ( theType == SECTION_POLYLINE ) + { + aPath.moveTo( thePoints.Value( 1 ).X(), thePoints.Value( 1 ).Y() ); + + for( int i = 2, n = thePoints.Size(); i <= n; ++i ) + { + const gp_XYZ& aSectPoint = thePoints.Value( i ); + + aPath.lineTo( aSectPoint.X(), aSectPoint.Y() ); + } + + if( theIsClosed ) + aPath.closeSubpath(); + } + else + { + HYDROData_BSplineOperation aBSpline( thePoints, theIsClosed ); + aPath = aBSpline.ComputePath(); + } + + return aPath; +} + void HYDROData_PolylineXY::Update() { NCollection_Sequence aSectNames; @@ -125,50 +209,17 @@ void HYDROData_PolylineXY::Update() PointsList aSectPointsList = GetPoints( aSectionId - 1 ); if ( aSectPointsList.IsEmpty() ) continue; - - BRepBuilderAPI_MakeWire aMakeSectionWire; - if( aSectionType == SECTION_POLYLINE ) + + NCollection_Sequence aPoints; + for( int i = 1, n = aSectPointsList.Size(); i <= n; ++i ) { - for( int i = 1, n = aSectPointsList.Size(); i <= n; ++i ) - { - const Point& aFirstPoint = aSectPointsList.Value( i ); - - Point aLastPoint; - if ( i == n ) - { - if( anIsSectionClosed ) - aLastPoint = aSectPointsList.Value( 1 ); - else - break; - } - else - { - aLastPoint = aSectPointsList.Value( i + 1 ); - } - - gp_Pnt aPnt1( aFirstPoint.X(), aFirstPoint.Y(), 0.0 ); - gp_Pnt aPnt2( aLastPoint.X(), aLastPoint.Y(), 0.0 ); + const Point& aSectPoint = aSectPointsList.Value( i ); - TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aPnt1, aPnt2 ).Edge(); - aMakeSectionWire.Add( anEdge ); - } + gp_XYZ aPoint( aSectPoint.X(), aSectPoint.Y(), 0.0 ); + aPoints.Append( aPoint ); } - else //if( aSectionType == PolylineSection::SECTION_SPLINE ) - { - QList aPoints; - for( int i = 1, n = aSectPointsList.Size(); i <= n; ++i ) - { - const Point& aSectPoint = aSectPointsList.Value( i ); - aPoints << aSectPoint.X() << aSectPoint.Y(); - } - HYDROData_BSplineOperation aBSpline( aPoints, 0.0, anIsSectionClosed ); - - TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aBSpline.Curve() ).Edge(); - aMakeSectionWire.Add( anEdge ); - } - - TopoDS_Wire aSectionWire = aMakeSectionWire.Wire(); + TopoDS_Wire aSectionWire = BuildWire( aSectionType, anIsSectionClosed, aPoints ); aSectionWiresList.Append( aSectionWire ); aMakeWire.Add( aSectionWire ); } @@ -218,6 +269,70 @@ bool HYDROData_PolylineXY::IsClosed() const return anIsClosed; } +double HYDROData_PolylineXY::GetDistance( const int theSectionIndex, + const int thePointIndex ) const +{ + double aResDistance = -1; + if ( theSectionIndex < 0 || theSectionIndex >= NbSections() ) + return aResDistance; + + if ( thePointIndex == 0 ) + return 0.0; + + SectionType aSectionType = GetSectionType( theSectionIndex ); + bool anIsSectionClosed = IsClosedSection( theSectionIndex ); + PointsList aSectPointsList = GetPoints( theSectionIndex ); + if ( thePointIndex < 0 || thePointIndex >= aSectPointsList.Size() ) + return aResDistance; + + if ( aSectionType == SECTION_POLYLINE ) + { + aResDistance = 0.0; + + Point aPrevPoint = aSectPointsList.Value( 1 ); + for ( int i = 2, aNbPoints = aSectPointsList.Size(); i <= aNbPoints; ++i ) + { + const Point& aSectPoint = aSectPointsList.Value( i ); + aResDistance += gp_Pnt2d( aPrevPoint ).Distance( aSectPoint ); + aPrevPoint = aSectPoint; + } + } + else + { + gp_XYZ aPointToTest; + + int aSectNbPoints = aSectPointsList.Size(); + NCollection_Sequence aPoints; + for( int i = 1 ; i <= aSectNbPoints; ++i ) + { + const Point& aSectPoint = aSectPointsList.Value( i ); + + gp_XYZ aPoint( aSectPoint.X(), aSectPoint.Y(), 0.0 ); + aPoints.Append( aPoint ); + + if ( thePointIndex == i - 1 ) + aPointToTest = aPoint; + } + + HYDROData_BSplineOperation aBSpline( aPoints, anIsSectionClosed ); + + Quantity_Parameter aFirstParam = aBSpline.Curve()->FirstParameter(); + Quantity_Parameter aSecondParam = aBSpline.Curve()->LastParameter(); + + if ( thePointIndex != aSectNbPoints - 1 ) + { + GeomAPI_ProjectPointOnCurve aProject( aPointToTest, aBSpline.Curve() ); + aSecondParam = aProject.LowerDistanceParameter(); + } + + GeomAdaptor_Curve anAdap( aBSpline.Curve() ); + + aResDistance = GCPnts_AbscissaPoint::Length( anAdap, aFirstParam, aSecondParam ); + } + + return aResDistance; +} + int HYDROData_PolylineXY::NbSections() const { Handle(TDataStd_ExtStringList) aNamesList; @@ -636,34 +751,19 @@ QPainterPath HYDROData_PolylineXY::GetPainterPath() const SectionType aSectionType = aSectTypes.Value( 1 ); bool anIsSectionClosed = aSectClosures.Value( 1 ); - if ( aSectionType == SECTION_POLYLINE ) + NCollection_Sequence aPoints; + for( int i = 1, n = aSectPointsList.Size(); i <= n; ++i ) { - aPath.moveTo( aSectPointsList.Value( 1 ).X(), aSectPointsList.Value( 1 ).Y() ); - - for( int i = 2, n = aSectPointsList.Size(); i <= n; ++i ) - { - const Point& aSectPoint = aSectPointsList.Value( i ); + const Point& aSectPoint = aSectPointsList.Value( i ); - aPath.lineTo( aSectPoint.X(), aSectPoint.Y() ); - } - - if( anIsSectionClosed ) - aPath.closeSubpath(); + gp_XYZ aPoint( aSectPoint.X(), aSectPoint.Y(), 0.0 ); + aPoints.Append( aPoint ); } - else - { - QList aPoints; - for( int i = 1, n = aSectPointsList.Size(); i <= n; ++i ) - { - const Point& aSectPoint = aSectPointsList.Value( i ); - aPoints << aSectPoint.X() << aSectPoint.Y(); - } - HYDROData_BSplineOperation aBSpline( aPoints, 0, anIsSectionClosed ); - aPath = aBSpline.ComputePath(); - } + aPath = BuildPainterPath( aSectionType, anIsSectionClosed, aPoints ); return aPath; + } diff --git a/src/HYDROData/HYDROData_PolylineXY.h b/src/HYDROData/HYDROData_PolylineXY.h index 315fe7f1..45ea7459 100644 --- a/src/HYDROData/HYDROData_PolylineXY.h +++ b/src/HYDROData/HYDROData_PolylineXY.h @@ -7,6 +7,8 @@ DEFINE_STANDARD_HANDLE(HYDROData_PolylineXY, HYDROData_IPolyline) class QPainterPath; +class TopoDS_Wire; +class gp_XYZ; /**\class HYDROData_PolylineXY * \brief Class that stores/retreives information about the @@ -43,6 +45,22 @@ public: */ HYDRODATA_EXPORT virtual QVariant GetDataVariant(); +public: + + /** + * Returns the presentation of polyline section in CAS maner. + */ + HYDRODATA_EXPORT static TopoDS_Wire BuildWire( const SectionType& theType, + const bool& theIsClosed, + const NCollection_Sequence& thePoints ); + + /** + * Returns the presentation of polyline section in Qt maner. + */ + HYDRODATA_EXPORT static QPainterPath BuildPainterPath( const SectionType& theType, + const bool& theIsClosed, + const NCollection_Sequence& thePoints ); + public: /** @@ -62,7 +80,14 @@ public: */ HYDRODATA_EXPORT bool IsClosed() const; - + /** + * Returns the distance beetwen first and point with index thePointIndex + * at the section with index theSectionIndex. -1 is returned if error is occurred. + */ + HYDRODATA_EXPORT double GetDistance( const int theSectionIndex, + const int thePointIndex ) const; + + /** * Returns number of sections. */ diff --git a/src/HYDROData/HYDROData_ProfileUZ.cxx b/src/HYDROData/HYDROData_ProfileUZ.cxx index d8ccba4e..80fe9987 100755 --- a/src/HYDROData/HYDROData_ProfileUZ.cxx +++ b/src/HYDROData/HYDROData_ProfileUZ.cxx @@ -4,6 +4,7 @@ #include "HYDROData_Tool.h" #include +#include #include @@ -30,6 +31,42 @@ TopoDS_Shape HYDROData_ProfileUZ::GetShape() return TopoDS_Shape(); } +double HYDROData_ProfileUZ::GetDepthFromDistance( const double& theDistance ) const +{ + double aResDepth = 0.0; + + HYDROData_IPolyline::PointsList aPoints = GetPoints(); + int aNbPoints = aPoints.Size(); + if ( aNbPoints < 2 ) + return aResDepth; + + double aCompDist = 0.0; + HYDROData_IPolyline::Point aPrevPoint = aPoints.First(); + for ( int i = 2; i <= aNbPoints; ++i ) + { + const Point& aCurPoint = aPoints.Value( i ); + + double aPntDist = gp_Pnt2d( aPrevPoint.X(), 0 ).Distance( gp_Pnt2d( aCurPoint.X(), 0 ) ); + + aCompDist += aPntDist; + + if ( theDistance < aCompDist ) + { + double aComPntDist = gp_Pnt2d( aPoints.First().X(), 0 ).Distance( gp_Pnt2d( aPrevPoint.X(), 0 ) ); + + double aFindDist = theDistance - aComPntDist; + double aRatio = aFindDist / ( aPntDist - aFindDist ); + + aResDepth = ( aPrevPoint.Y() + aRatio * aCurPoint.Y() ) / ( 1 + aRatio ); + break; + } + + aPrevPoint = aCurPoint; + } + + return aResDepth; +} + int HYDROData_ProfileUZ::NbSections() const { return 1; diff --git a/src/HYDROData/HYDROData_ProfileUZ.h b/src/HYDROData/HYDROData_ProfileUZ.h index 3ec8fabc..c485e944 100644 --- a/src/HYDROData/HYDROData_ProfileUZ.h +++ b/src/HYDROData/HYDROData_ProfileUZ.h @@ -37,6 +37,11 @@ public: */ HYDRODATA_EXPORT virtual TopoDS_Shape GetShape(); + /** + * Returns the 3D presentation of all points. + */ + HYDRODATA_EXPORT virtual double GetDepthFromDistance( const double& theDistance ) const; + /** * Returns number of sections. diff --git a/src/HYDROData/test_HYDROData_BSplineOperation.cxx b/src/HYDROData/test_HYDROData_BSplineOperation.cxx index 33658760..f5310176 100644 --- a/src/HYDROData/test_HYDROData_BSplineOperation.cxx +++ b/src/HYDROData/test_HYDROData_BSplineOperation.cxx @@ -7,22 +7,27 @@ void test_HYDROData_BSplineOperation::testCurve() { // prepare points: function of sin(x) - QList aPoints; - double x; - for(x = 0; x < 6.28; x += 0.1) - aPoints< aPoints; + for ( double x = 0; x < 6.28; x += 0.1 ) + { + gp_XYZ aPoint( x, sin( x ), 0.0 ); + aPoints.Append( aPoint ); + } // compute BSpline - HYDROData_BSplineOperation aBSpline(aPoints, 0, false); + HYDROData_BSplineOperation aBSpline( aPoints, false ); + Handle(Geom_BSplineCurve) aBS = aBSpline.Curve(); - CPPUNIT_ASSERT(!aBS.IsNull()); - CPPUNIT_ASSERT(!aBS->IsClosed()); - CPPUNIT_ASSERT_EQUAL(aBS->Continuity(), GeomAbs_C2); + CPPUNIT_ASSERT( !aBS.IsNull() ); + CPPUNIT_ASSERT( !aBS->IsClosed() ); + CPPUNIT_ASSERT_EQUAL( aBS->Continuity(), GeomAbs_C2 ); + // check that values of BSpline are not far from original "sin" function // in all points of the curve - for(x = 0; x < 6.29; x += 0.001) { - double aDiff = aBS->Value(x).Y() - sin(aBS->Value(x).X()); - if (aDiff < 0) aDiff = -aDiff; - CPPUNIT_ASSERT(aDiff < 3.e-6); // this number is found manually + for ( double x = 0; x < 6.29; x += 0.001 ) + { + double aDiff = aBS->Value( x ).Y() - sin( aBS->Value( x ).X() ); + if ( aDiff < 0 ) aDiff = -aDiff; + CPPUNIT_ASSERT( aDiff < 3.e-6 ); // this number is found manually } } @@ -30,15 +35,21 @@ void test_HYDROData_BSplineOperation::testPath() { // prepare points: function of sin(x) static const double aScale = 10000000.; - QList aPoints; - double x; - for(x = 0; x < 6.28; x += 0.1) - aPoints< aPoints; + for ( double x = 0; x < 6.28; x += 0.1 ) + { + gp_XYZ aPoint( x * aScale, sin( x ) * aScale, 0.0 ); + aPoints.Append( aPoint ); + } + // convert to QPainterPath - HYDROData_BSplineOperation aBSpline(aPoints, 0, false); - CPPUNIT_ASSERT(!aBSpline.Curve().IsNull()); + HYDROData_BSplineOperation aBSpline( aPoints, false ); + + CPPUNIT_ASSERT( !aBSpline.Curve().IsNull() ); + QPainterPath aPath = aBSpline.ComputePath(); - CPPUNIT_ASSERT(!aPath.isEmpty()); + CPPUNIT_ASSERT( !aPath.isEmpty() ); /* QImage aPic(1300, 600, QImage::Format_RGB32); @@ -50,7 +61,7 @@ void test_HYDROData_BSplineOperation::testPath() // check that values of Path are not far from original "sin" function // in all points of the curve - QList aPolyF = aPath.toSubpathPolygons(QTransform()); + QList aPolyF = aPath.toSubpathPolygons( QTransform() ); QList::iterator aFIter = aPolyF.begin(); for(; aFIter != aPolyF.end();aFIter++) { QPolygon aPoly = aFIter->toPolygon(); -- 2.39.2