From a6bf312064b7f44f38fee1e32f529f28da98a735 Mon Sep 17 00:00:00 2001 From: adv Date: Wed, 25 Dec 2013 08:27:18 +0000 Subject: [PATCH] Altitude object implemented for stream (Feature #260). --- src/HYDROData/HYDROData_Stream.cxx | 348 ++++++++++++--------- src/HYDROData/HYDROData_Stream.h | 26 +- src/HYDROData/HYDROData_StreamAltitude.cxx | 213 +++++++++++++ src/HYDROData/HYDROData_StreamAltitude.h | 7 + 4 files changed, 446 insertions(+), 148 deletions(-) diff --git a/src/HYDROData/HYDROData_Stream.cxx b/src/HYDROData/HYDROData_Stream.cxx index 5c50dc56..9aa3d235 100644 --- a/src/HYDROData/HYDROData_Stream.cxx +++ b/src/HYDROData/HYDROData_Stream.cxx @@ -6,6 +6,7 @@ #include "HYDROData_Profile.h" #include "HYDROData_ShapesGroup.h" #include "HYDROData_ShapesTool.h" +#include "HYDROData_IAltitudeObject.h" #include @@ -147,6 +148,161 @@ void HYDROData_Stream::Update() UpdatePrs(); } +void HYDROData_Stream::UpdatePrs() +{ + HYDROData_NaturalObject::Update(); + + Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis(); + HYDROData_SequenceOfObjects aRefProfiles = GetProfiles(); + if ( aHydAxis.IsNull() || aRefProfiles.Length() < 2 ) + return; + + bool anIsFirst = true; + gp_Pnt aPrevFirstPoint, aPrevLastPoint; + Handle(TColgp_HArray1OfPnt) anArrayOfFPnt = new TColgp_HArray1OfPnt(1, aRefProfiles.Length()); + Handle(TColgp_HArray1OfPnt) anArrayOfLPnt = new TColgp_HArray1OfPnt(1, aRefProfiles.Length()); + TopTools_Array1OfShape anArrOfProfiles(1, aRefProfiles.Length()); + TopTools_Array1OfShape anArrOf2DProfiles(1, aRefProfiles.Length()); + + // Pre-processing + HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles ); + for (int i=1 ; anIter.More(); anIter.Next(),i++ ) + { + Handle(HYDROData_Profile) aProfile = + Handle(HYDROData_Profile)::DownCast( anIter.Value() ); + if ( aProfile.IsNull() ) + continue; + const TopoDS_Shape& aProf3d = aProfile->GetShape3D(); + gp_XY aPnt1, aPnt2; + if ( !aProfile->GetLeftPoint( aPnt1 ) || !aProfile->GetRightPoint( aPnt2 ) ) + continue; + anArrOfProfiles.SetValue(i,aProfile->GetShape3D());//aProfile->GetTopShape(); + anArrOf2DProfiles.SetValue(i,aProfile->GetTopShape()); + + gp_Pnt aCurFirstPoint( aPnt1.X(), aPnt1.Y(), 0 ), aCurFP; + gp_Pnt aCurLastPoint( aPnt2.X(), aPnt2.Y(), 0 ), aCurLP; + TopoDS_Vertex aV1, aV2; + TopExp::Vertices(TopoDS::Wire(aProf3d), aV1, aV2); + gp_Pnt aP1 = BRep_Tool::Pnt(aV1); + if(aP1.X() == aPnt1.X() && aP1.Y() == aPnt1.Y()) + aCurFP = aP1; + else + aCurLP = aP1; + aP1 = BRep_Tool::Pnt(aV2); + if(aP1.X() == aPnt2.X() && aP1.Y() == aPnt2.Y()) + aCurLP = aP1; + else + aCurFP = aP1; + anArrayOfFPnt->SetValue(i,aCurFP); + anArrayOfLPnt->SetValue(i,aCurLP); + } + + // Construct of the 3D presentation + Handle(Geom_BSplineCurve) aBSpline = buildInterpolationCurve (anArrayOfFPnt); + if(aBSpline.IsNull()) + return; + TopoDS_Edge anEdgLeft, anEdgRight; + BRepBuilderAPI_MakeEdge aMakeEdge(aBSpline); + if(aMakeEdge.IsDone()) + anEdgLeft = aMakeEdge.Edge(); + if(anEdgLeft.IsNull()) + return; + aBSpline.Nullify(); + aBSpline = buildInterpolationCurve (anArrayOfLPnt); + if(aBSpline.IsNull()) + return; + aMakeEdge.Init(aBSpline); + if(aMakeEdge.IsDone()) + anEdgRight = aMakeEdge.Edge(); + if(anEdgRight.IsNull()) + return; + BRep_Builder aBB; + TopoDS_Compound aCmp; + aBB.MakeCompound(aCmp); + anIter.Init( aRefProfiles ); + for (int i=1 ; i < anArrOfProfiles.Length() +1; i++ ) + aBB.Add(aCmp, anArrOfProfiles.Value(i)); + aBB.Add(aCmp,anEdgLeft); + aBB.Add(aCmp,anEdgRight); + BRepCheck_Analyzer aCh(aCmp); + if(aCh.IsValid()) + SetShape3D(aCmp); +#ifdef DEB_UPDATE + else { + BRepTools::Write(aCmp, "str3d.brep"); + SetShape3D(aCmp); + } +#endif + + // Construct the top presentation + for(int i=1;i<= anArrayOfLPnt->Length();i++) { + gp_Pnt aPnt = anArrayOfFPnt->Value(i); + aPnt.SetZ(.0); // make 2d + anArrayOfFPnt->SetValue(i, aPnt); + aPnt = anArrayOfLPnt->Value(i); + aPnt.SetZ(.0); + anArrayOfLPnt->SetValue(i, aPnt); + } + aBSpline.Nullify(); + aBSpline = buildInterpolationCurve (anArrayOfFPnt); + if(aBSpline.IsNull()) + return; + aMakeEdge.Init(aBSpline); + if(aMakeEdge.IsDone()) + anEdgLeft = aMakeEdge.Edge(); + aBSpline.Nullify(); + aBSpline = buildInterpolationCurve (anArrayOfLPnt); + if(aBSpline.IsNull()) + return; + aMakeEdge.Init(aBSpline); + if(aMakeEdge.IsDone()) + anEdgRight = aMakeEdge.Edge(); + if(anEdgRight.IsNull()) + return; + BRepBuilderAPI_MakeEdge aMakeEdge2(anArrayOfFPnt->Value(1),anArrayOfLPnt->Value(1)); + TopoDS_Edge aBotEdge, aTopEdge; + if(aMakeEdge2.IsDone()) + aBotEdge = aMakeEdge2.Edge(); + BRepBuilderAPI_MakeEdge aMakeEdge3(anArrayOfFPnt->Value(anArrayOfFPnt->Length()),anArrayOfLPnt->Value(anArrayOfLPnt->Length())); + if(aMakeEdge3.IsDone()) + aTopEdge = aMakeEdge3.Edge(); + + BRepBuilderAPI_MakeWire aMakeWire( aBotEdge, anEdgLeft, aTopEdge,anEdgRight); + TopoDS_Wire aSectProfileWire; + if(aMakeWire.IsDone()) + aSectProfileWire = aMakeWire.Wire(); + BRepBuilderAPI_MakeFace aMakeFace( aSectProfileWire, Standard_True ); + TopoDS_Face aFace; + aMakeFace.Build(); + if( aMakeFace.IsDone() ) + aFace = aMakeFace.Face(); + aCmp.Nullify(); + aBB.MakeCompound(aCmp); + aBB.Add(aCmp,aFace); + for(int i=1;i <= anArrOf2DProfiles.Length(); i++) + aBB.Add(aCmp,anArrOf2DProfiles.Value(i)); + aCh.Init(aCmp); + if(aCh.IsValid()) + SetTopShape(aCmp); +#ifdef DEB_UPDATE + else { + BRepTools::Write(aCmp, "str2d.brep"); + SetTopShape(aCmp); + } +#endif + + // Create the stream groups + createGroupObjects(); + + // This peace of code is for testing of functionality of altitude, + // will be removed by adv when testing will be finished + Handle(HYDROData_IAltitudeObject) anAltObj = GetAltitudeObject(); + gp_XY aTestPnt( 5, 0 ); + anAltObj->GetAltitudeForPoint( aTestPnt ); + // End of test code + +} + QColor HYDROData_Stream::DefaultFillingColor() { return QColor( Qt::green ); @@ -171,6 +327,51 @@ bool HYDROData_Stream::IsValidAsAxis( const Handle(HYDROData_PolylineXY)& theHyd return true; } +TopoDS_Shape getShapeFromGroup( const HYDROData_SequenceOfObjects& theGroups, + const int theGroupId ) +{ + TopoDS_Shape aResShape; + if ( theGroups.Length() != 4 ) + return aResShape; + + Handle(HYDROData_ShapesGroup) aGroup = + Handle(HYDROData_ShapesGroup)::DownCast( theGroups.Value( theGroupId ) ); + if ( aGroup.IsNull() ) + return aResShape; + + TopTools_SequenceOfShape aGroupShapes; + aGroup->GetShapes( aGroupShapes ); + + if ( !aGroupShapes.IsEmpty() ) + aResShape = aGroupShapes.First(); + + return aResShape; +} + +TopoDS_Shape HYDROData_Stream::GetLeftShape() const +{ + HYDROData_SequenceOfObjects aGroups = GetGroups(); + return getShapeFromGroup( aGroups, 1 ); +} + +TopoDS_Shape HYDROData_Stream::GetRightShape() const +{ + HYDROData_SequenceOfObjects aGroups = GetGroups(); + return getShapeFromGroup( aGroups, 2 ); +} + +TopoDS_Shape HYDROData_Stream::GetInletShape() const +{ + HYDROData_SequenceOfObjects aGroups = GetGroups(); + return getShapeFromGroup( aGroups, 3 ); +} + +TopoDS_Shape HYDROData_Stream::GetOutletShape() const +{ + HYDROData_SequenceOfObjects aGroups = GetGroups(); + return getShapeFromGroup( aGroups, 4 ); +} + QColor HYDROData_Stream::getDefaultFillingColor() const { return DefaultFillingColor(); @@ -774,150 +975,3 @@ void HYDROData_Stream::removeParameter( const int& theIndex ) setParametersArray( aNewArr ); } - -void HYDROData_Stream::UpdatePrs() -{ - HYDROData_NaturalObject::Update(); - - Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis(); - HYDROData_SequenceOfObjects aRefProfiles = GetProfiles(); - if ( aHydAxis.IsNull() || aRefProfiles.Length() < 2 ) - return; - - bool anIsFirst = true; - gp_Pnt aPrevFirstPoint, aPrevLastPoint; - Handle(TColgp_HArray1OfPnt) anArrayOfFPnt = new TColgp_HArray1OfPnt(1, aRefProfiles.Length()); - Handle(TColgp_HArray1OfPnt) anArrayOfLPnt = new TColgp_HArray1OfPnt(1, aRefProfiles.Length()); - TopTools_Array1OfShape anArrOfProfiles(1, aRefProfiles.Length()); - TopTools_Array1OfShape anArrOf2DProfiles(1, aRefProfiles.Length()); - - // Pre-processing - HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles ); - for (int i=1 ; anIter.More(); anIter.Next(),i++ ) - { - Handle(HYDROData_Profile) aProfile = - Handle(HYDROData_Profile)::DownCast( anIter.Value() ); - if ( aProfile.IsNull() ) - continue; - const TopoDS_Shape& aProf3d = aProfile->GetShape3D(); - gp_XY aPnt1, aPnt2; - if ( !aProfile->GetLeftPoint( aPnt1 ) || !aProfile->GetRightPoint( aPnt2 ) ) - continue; - anArrOfProfiles.SetValue(i,aProfile->GetShape3D());//aProfile->GetTopShape(); - anArrOf2DProfiles.SetValue(i,aProfile->GetTopShape()); - - gp_Pnt aCurFirstPoint( aPnt1.X(), aPnt1.Y(), 0 ), aCurFP; - gp_Pnt aCurLastPoint( aPnt2.X(), aPnt2.Y(), 0 ), aCurLP; - TopoDS_Vertex aV1, aV2; - TopExp::Vertices(TopoDS::Wire(aProf3d), aV1, aV2); - gp_Pnt aP1 = BRep_Tool::Pnt(aV1); - if(aP1.X() == aPnt1.X() && aP1.Y() == aPnt1.Y()) - aCurFP = aP1; - else - aCurLP = aP1; - aP1 = BRep_Tool::Pnt(aV2); - if(aP1.X() == aPnt2.X() && aP1.Y() == aPnt2.Y()) - aCurLP = aP1; - else - aCurFP = aP1; - anArrayOfFPnt->SetValue(i,aCurFP); - anArrayOfLPnt->SetValue(i,aCurLP); - } - - // Construct of the 3D presentation - Handle(Geom_BSplineCurve) aBSpline = buildInterpolationCurve (anArrayOfFPnt); - if(aBSpline.IsNull()) - return; - TopoDS_Edge anEdgLeft, anEdgRight; - BRepBuilderAPI_MakeEdge aMakeEdge(aBSpline); - if(aMakeEdge.IsDone()) - anEdgLeft = aMakeEdge.Edge(); - if(anEdgLeft.IsNull()) - return; - aBSpline.Nullify(); - aBSpline = buildInterpolationCurve (anArrayOfLPnt); - if(aBSpline.IsNull()) - return; - aMakeEdge.Init(aBSpline); - if(aMakeEdge.IsDone()) - anEdgRight = aMakeEdge.Edge(); - if(anEdgRight.IsNull()) - return; - BRep_Builder aBB; - TopoDS_Compound aCmp; - aBB.MakeCompound(aCmp); - anIter.Init( aRefProfiles ); - for (int i=1 ; i < anArrOfProfiles.Length() +1; i++ ) - aBB.Add(aCmp, anArrOfProfiles.Value(i)); - aBB.Add(aCmp,anEdgLeft); - aBB.Add(aCmp,anEdgRight); - BRepCheck_Analyzer aCh(aCmp); - if(aCh.IsValid()) - SetShape3D(aCmp); -#ifdef DEB_UPDATE - else { - BRepTools::Write(aCmp, "str3d.brep"); - SetShape3D(aCmp); - } -#endif - - // Construct the top presentation - for(int i=1;i<= anArrayOfLPnt->Length();i++) { - gp_Pnt aPnt = anArrayOfFPnt->Value(i); - aPnt.SetZ(.0); // make 2d - anArrayOfFPnt->SetValue(i, aPnt); - aPnt = anArrayOfLPnt->Value(i); - aPnt.SetZ(.0); - anArrayOfLPnt->SetValue(i, aPnt); - } - aBSpline.Nullify(); - aBSpline = buildInterpolationCurve (anArrayOfFPnt); - if(aBSpline.IsNull()) - return; - aMakeEdge.Init(aBSpline); - if(aMakeEdge.IsDone()) - anEdgLeft = aMakeEdge.Edge(); - aBSpline.Nullify(); - aBSpline = buildInterpolationCurve (anArrayOfLPnt); - if(aBSpline.IsNull()) - return; - aMakeEdge.Init(aBSpline); - if(aMakeEdge.IsDone()) - anEdgRight = aMakeEdge.Edge(); - if(anEdgRight.IsNull()) - return; - BRepBuilderAPI_MakeEdge aMakeEdge2(anArrayOfFPnt->Value(1),anArrayOfLPnt->Value(1)); - TopoDS_Edge aBotEdge, aTopEdge; - if(aMakeEdge2.IsDone()) - aBotEdge = aMakeEdge2.Edge(); - BRepBuilderAPI_MakeEdge aMakeEdge3(anArrayOfFPnt->Value(anArrayOfFPnt->Length()),anArrayOfLPnt->Value(anArrayOfLPnt->Length())); - if(aMakeEdge3.IsDone()) - aTopEdge = aMakeEdge3.Edge(); - - BRepBuilderAPI_MakeWire aMakeWire( aBotEdge, anEdgLeft, aTopEdge,anEdgRight); - TopoDS_Wire aSectProfileWire; - if(aMakeWire.IsDone()) - aSectProfileWire = aMakeWire.Wire(); - BRepBuilderAPI_MakeFace aMakeFace( aSectProfileWire, Standard_True ); - TopoDS_Face aFace; - aMakeFace.Build(); - if( aMakeFace.IsDone() ) - aFace = aMakeFace.Face(); - aCmp.Nullify(); - aBB.MakeCompound(aCmp); - aBB.Add(aCmp,aFace); - for(int i=1;i <= anArrOf2DProfiles.Length(); i++) - aBB.Add(aCmp,anArrOf2DProfiles.Value(i)); - aCh.Init(aCmp); - if(aCh.IsValid()) - SetTopShape(aCmp); -#ifdef DEB_UPDATE - else { - BRepTools::Write(aCmp, "str2d.brep"); - SetTopShape(aCmp); - } -#endif - - // Create the stream groups - createGroupObjects(); -} \ No newline at end of file diff --git a/src/HYDROData/HYDROData_Stream.h b/src/HYDROData/HYDROData_Stream.h index 0b57d707..fd340d33 100644 --- a/src/HYDROData/HYDROData_Stream.h +++ b/src/HYDROData/HYDROData_Stream.h @@ -84,8 +84,32 @@ public: HYDRODATA_EXPORT static bool IsValidAsAxis( const Handle(HYDROData_PolylineXY)& theAxis ); public: - // Public methods to work with Stream + // Public methods to work with Stream presentation + /** + * Returns the left edge of the stream. + */ + HYDRODATA_EXPORT virtual TopoDS_Shape GetLeftShape() const; + + /** + * Returns the right edge of the stream. + */ + HYDRODATA_EXPORT virtual TopoDS_Shape GetRightShape() const; + + /** + * Returns the inlet edge of the stream. + */ + HYDRODATA_EXPORT virtual TopoDS_Shape GetInletShape() const; + + /** + * Returns the outlet edge of the stream. + */ + HYDRODATA_EXPORT virtual TopoDS_Shape GetOutletShape() const; + + +public: + // Public methods to work with Stream data fields + /** * Sets reference hydraulic axis object for stream. */ diff --git a/src/HYDROData/HYDROData_StreamAltitude.cxx b/src/HYDROData/HYDROData_StreamAltitude.cxx index b701b3af..7d3673b4 100644 --- a/src/HYDROData/HYDROData_StreamAltitude.cxx +++ b/src/HYDROData/HYDROData_StreamAltitude.cxx @@ -1,6 +1,34 @@ #include "HYDROData_StreamAltitude.h" + #include "HYDROData_Document.h" +#include "HYDROData_Profile.h" +#include "HYDROData_Stream.h" +#include "HYDROData_ShapesTool.h" + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include + +#include + +#include + +#include +#include +#include + +#include #include @@ -40,10 +68,195 @@ QStringList HYDROData_StreamAltitude::DumpToPython( MapOfTreatedObjects& theTrea return aResList; } +Standard_Real getAltitudeFromProfile( const Handle(HYDROData_Profile)& theProfile, + const Standard_Real& theLeftDist, + const Standard_Real& theRightDist ) +{ + Standard_Real aResAlt = 0.0; + + gp_XY aFirstPoint, aLastPoint; + if ( !theProfile->GetLeftPoint( aFirstPoint ) || + !theProfile->GetRightPoint( aLastPoint ) ) + return aResAlt; + + gp_Pnt aPnt1( aFirstPoint.X(), aFirstPoint.Y(), 0 ); + gp_Pnt aPnt2( aLastPoint.X(), aLastPoint.Y(), 0 ); + + Standard_Real aProfileDist = aPnt1.Distance( aPnt2 ); + + Standard_Real aCoeff = aProfileDist / ( theLeftDist + theRightDist ); + + gp_Pnt anIntPoint( aPnt1.XYZ() + ( aCoeff * theLeftDist ) * gp_Dir( gp_Vec( aPnt1, aPnt2 ) ).XYZ() ); + + gp_Lin aPointLine( anIntPoint, gp::DZ() ); + + gp_Pnt aPrevPoint; + gp_Lin aPrevNormal; + HYDROData_Profile::ProfilePoints aProfilePoints = theProfile->GetProfilePoints(); + for ( int i = 1, n = aProfilePoints.Length(); i <= n; ++i ) + { + gp_Pnt aProfPoint( aProfilePoints.Value( i ) ); + + Standard_Real aDist = aPointLine.Distance( aProfPoint ); + if ( aDist <= gp::Resolution() ) + { + // We found the intersected point + aResAlt = aProfPoint.Z(); + break; + } + + gp_Lin aNormal = aPointLine.Normal( aProfPoint ); + if ( i == 1 ) + { + aPrevNormal = aNormal; + aPrevPoint = aProfPoint; + continue; + } + + if ( aPrevNormal.Direction().Dot( aNormal.Direction() ) < 0 ) + { + // We found the intersected edge + gp_Lin anEdgeLine( aPrevPoint, gp_Dir( gp_Vec( aPrevPoint, aProfPoint ) ) ); + + Extrema_ExtElC anExtrema( aPointLine, anEdgeLine, Precision::Angular() ); + if ( !anExtrema.IsParallel() ) + { + Extrema_POnCurv aFirstPnt, aSecPnt; + anExtrema.Points( 1, aFirstPnt, aSecPnt ); + + const gp_Pnt& anIntPnt = aSecPnt.Value(); + aResAlt = anIntPnt.Z(); + + break; + } + } + + aPrevNormal = aNormal; + aPrevPoint = aProfPoint; + } + + return aResAlt; +} + +bool HYDROData_StreamAltitude::getBoundaryProfilesForPoint( + const gp_XY& thePoint, + Handle(HYDROData_Profile)& theLeftProfile, + Handle(HYDROData_Profile)& theRightProfile ) const +{ + Handle(HYDROData_Stream) aStream = + Handle(HYDROData_Stream)::DownCast( GetFatherObject() ); + if ( aStream.IsNull() ) + return false; + + HYDROData_SequenceOfObjects aStreamProfiles = aStream->GetProfiles(); + if ( aStreamProfiles.Length() < 2 ) + return false; + + Handle(HYDROData_Profile) aPrevProfile; + gp_Pnt aPrevPnt1, aPrevPnt2; + for ( int i = 1, n = aStreamProfiles.Length(); i <= n; ++i ) + { + Handle(HYDROData_Profile) aProfile = + Handle(HYDROData_Profile)::DownCast( aStreamProfiles.Value( i ) ); + if ( aProfile.IsNull() ) + continue; + + gp_XY aFirstPoint, aLastPoint; + if ( !aProfile->GetLeftPoint( aFirstPoint ) || !aProfile->GetRightPoint( aLastPoint ) ) + continue; + + gp_Pnt aPnt1( aFirstPoint.X(), aFirstPoint.Y(), 0 ); + gp_Pnt aPnt2( aLastPoint.X(), aLastPoint.Y(), 0 ); + + if ( !aPrevProfile.IsNull() ) + { + BRepBuilderAPI_MakeEdge aLeftMakeEdge( aPrevPnt1, aPrevPnt2 ); + BRepBuilderAPI_MakeEdge aBotMakeEdge( aPrevPnt2, aPnt2 ); + BRepBuilderAPI_MakeEdge aRightMakeEdge( aPnt2, aPnt1 ); + BRepBuilderAPI_MakeEdge aTopMakeEdge( aPnt1, aPrevPnt1 ); + + BRepBuilderAPI_MakeWire aMakeWire( aLeftMakeEdge.Edge(), aBotMakeEdge.Edge(), + aRightMakeEdge.Edge(), aTopMakeEdge.Edge() ); + + BRepBuilderAPI_MakeFace aMakeFace( aMakeWire.Wire() ); + + TopoDS_Face aProfilesFace = aMakeFace.Face(); + + BRepTopAdaptor_FClass2d aClassifier( aProfilesFace, Precision::Confusion() ); + TopAbs_State aPointState = aClassifier.Perform( gp_Pnt2d( thePoint ), Standard_False ); + if ( aPointState != TopAbs_OUT ) + { + theLeftProfile = aPrevProfile; + theRightProfile = aProfile; + break; + } + } + + aPrevProfile = aProfile; + aPrevPnt1 = aPnt1; + aPrevPnt2 = aPnt2; + } + + return !theLeftProfile.IsNull() && !theRightProfile.IsNull(); +} + double HYDROData_StreamAltitude::GetAltitudeForPoint( const gp_XY& thePoint ) const { double aResAltitude = GetInvalidAltitude(); + Handle(HYDROData_Stream) aStream = + Handle(HYDROData_Stream)::DownCast( GetFatherObject() ); + if ( aStream.IsNull() ) + return aResAltitude; + + TopoDS_Shape aStreamShape = aStream->GetTopShape(); + if ( aStreamShape.IsNull() ) + return aResAltitude; + + TopExp_Explorer aStreamFaceExp( aStreamShape, TopAbs_FACE ); + if ( !aStreamFaceExp.More() ) + return aResAltitude; + + // Get only face because of 2d profile wires is in compound + TopoDS_Face aStreamFace = TopoDS::Face( aStreamFaceExp.Current() ); + + // Check if point is inside of stream presentation + BRepTopAdaptor_FClass2d aClassifier( aStreamFace, Precision::Confusion() ); + TopAbs_State aPointState = aClassifier.Perform( gp_Pnt2d( thePoint ), Standard_False ); + if ( aPointState == TopAbs_OUT ) + return aResAltitude; + + // Find the two profiles between which the point is lies + Handle(HYDROData_Profile) aLeftProfile, aRightProfile; + if ( !getBoundaryProfilesForPoint( thePoint, aLeftProfile, aRightProfile ) ) + return aResAltitude; + + // Find the projections of point to borders of stream + gp_XYZ aPointToTest( thePoint.X(), thePoint.Y(), 0.0 ); + + TopoDS_Edge aStreamLeftEdge = TopoDS::Edge( aStream->GetLeftShape() ); + TopoDS_Edge aStreamRightEdge = TopoDS::Edge( aStream->GetRightShape() ); + + Standard_Real aFirst = 0.0, aLast = 0.0; + Handle(Geom_Curve) anEdgeLeftCurve = BRep_Tool::Curve( aStreamLeftEdge, aFirst, aLast ); + Handle(Geom_Curve) anEdgeRightCurve = BRep_Tool::Curve( aStreamRightEdge, aFirst, aLast ); + + GeomAPI_ProjectPointOnCurve aLeftProject( aPointToTest, anEdgeLeftCurve ); + GeomAPI_ProjectPointOnCurve aRightProject( aPointToTest, anEdgeRightCurve ); + + Standard_Real aLeftDist = aLeftProject.LowerDistance(); + Standard_Real aRightDist = aRightProject.LowerDistance(); + + // Find the altitude in profiles + Standard_Real aLeftAlt = getAltitudeFromProfile( aLeftProfile, aLeftDist, aRightDist ); + Standard_Real aRightAlt = getAltitudeFromProfile( aRightProfile, aLeftDist, aRightDist ); + + // Interpolate altitudes + Standard_Real aFirstCoeff = aLeftDist / ( aLeftDist + aRightDist ); + Standard_Real aSecCoeff = aRightDist / ( aLeftDist + aRightDist ); + + aResAltitude = aLeftAlt * aFirstCoeff + aRightAlt * aSecCoeff; + return aResAltitude; } diff --git a/src/HYDROData/HYDROData_StreamAltitude.h b/src/HYDROData/HYDROData_StreamAltitude.h index 4304545d..2f47af8e 100644 --- a/src/HYDROData/HYDROData_StreamAltitude.h +++ b/src/HYDROData/HYDROData_StreamAltitude.h @@ -5,6 +5,7 @@ #include "HYDROData_IAltitudeObject.h" +class Handle(HYDROData_Profile); DEFINE_STANDARD_HANDLE(HYDROData_StreamAltitude, HYDROData_IAltitudeObject) @@ -51,6 +52,12 @@ public: */ HYDRODATA_EXPORT virtual double GetAltitudeForPoint( const gp_XY& thePoint ) const; +protected: + + bool getBoundaryProfilesForPoint( const gp_XY& thePoint, + Handle(HYDROData_Profile)& theLeftProfile, + Handle(HYDROData_Profile)& theRightProfile ) const; + protected: friend class HYDROData_Iterator; -- 2.39.2