2 #include "HYDROData_StreamAltitude.h"
4 #include "HYDROData_Document.h"
5 #include "HYDROData_Profile.h"
6 #include "HYDROData_Stream.h"
7 #include "HYDROData_ShapesTool.h"
9 #include <BRep_Tool.hxx>
11 #include <BRepTopAdaptor_FClass2d.hxx>
13 #include <BRepBuilderAPI_MakeEdge.hxx>
14 #include <BRepBuilderAPI_MakeFace.hxx>
15 #include <BRepBuilderAPI_MakeWire.hxx>
17 #include <Extrema_ExtElC.hxx>
19 #include <GeomAPI_ProjectPointOnCurve.hxx>
23 #include <Precision.hxx>
25 #include <TopExp_Explorer.hxx>
28 #include <TopoDS_Wire.hxx>
29 #include <TopoDS_Edge.hxx>
31 #include <TopTools_SequenceOfShape.hxx>
33 #include <QStringList>
35 #define PYTHON_STREAM_ALTITUDE_ID "KIND_STREAM_ALTITUDE"
38 IMPLEMENT_STANDARD_HANDLE(HYDROData_StreamAltitude, HYDROData_IAltitudeObject)
39 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_StreamAltitude, HYDROData_IAltitudeObject)
41 HYDROData_StreamAltitude::HYDROData_StreamAltitude()
42 : HYDROData_IAltitudeObject()
46 HYDROData_StreamAltitude::~HYDROData_StreamAltitude()
50 QStringList HYDROData_StreamAltitude::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
54 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
55 if ( aDocument.IsNull() )
58 QString aDocName = aDocument->GetDocPyName();
59 QString anAltitudeName = GetName();
61 aResList << QString( "%1 = %2.CreateObject( %3 );" )
62 .arg( anAltitudeName ).arg( aDocName ).arg( PYTHON_STREAM_ALTITUDE_ID );
63 aResList << QString( "%1.SetName( \"%2\" );" )
64 .arg( anAltitudeName ).arg( anAltitudeName );
71 Standard_Real getAltitudeFromProfile( const Handle(HYDROData_Profile)& theProfile,
72 const Standard_Real& theLeftDist,
73 const Standard_Real& theRightDist )
75 Standard_Real aResAlt = 0.0;
77 gp_XY aFirstPoint, aLastPoint;
78 if ( !theProfile->GetLeftPoint( aFirstPoint ) ||
79 !theProfile->GetRightPoint( aLastPoint ) )
82 gp_Pnt aPnt1( aFirstPoint.X(), aFirstPoint.Y(), 0 );
83 gp_Pnt aPnt2( aLastPoint.X(), aLastPoint.Y(), 0 );
85 Standard_Real aProfileDist = aPnt1.Distance( aPnt2 );
87 Standard_Real aCoeff = aProfileDist / ( theLeftDist + theRightDist );
89 gp_Pnt anIntPoint( aPnt1.XYZ() + ( aCoeff * theLeftDist ) * gp_Dir( gp_Vec( aPnt1, aPnt2 ) ).XYZ() );
91 gp_Lin aPointLine( anIntPoint, gp::DZ() );
95 HYDROData_Profile::ProfilePoints aProfilePoints = theProfile->GetProfilePoints();
96 for ( int i = 1, n = aProfilePoints.Length(); i <= n; ++i )
98 gp_Pnt aProfPoint( aProfilePoints.Value( i ) );
100 Standard_Real aDist = aPointLine.Distance( aProfPoint );
101 if ( aDist <= gp::Resolution() )
103 // We found the intersected point
104 aResAlt = aProfPoint.Z();
108 gp_Lin aNormal = aPointLine.Normal( aProfPoint );
111 aPrevNormal = aNormal;
112 aPrevPoint = aProfPoint;
116 if ( aPrevNormal.Direction().Dot( aNormal.Direction() ) < 0 )
118 // We found the intersected edge
119 gp_Lin anEdgeLine( aPrevPoint, gp_Dir( gp_Vec( aPrevPoint, aProfPoint ) ) );
121 Extrema_ExtElC anExtrema( aPointLine, anEdgeLine, Precision::Angular() );
122 if ( !anExtrema.IsParallel() )
124 Extrema_POnCurv aFirstPnt, aSecPnt;
125 anExtrema.Points( 1, aFirstPnt, aSecPnt );
127 const gp_Pnt& anIntPnt = aSecPnt.Value();
128 aResAlt = anIntPnt.Z();
134 aPrevNormal = aNormal;
135 aPrevPoint = aProfPoint;
141 bool HYDROData_StreamAltitude::getBoundaryProfilesForPoint(
142 const gp_XY& thePoint,
143 Handle(HYDROData_Profile)& theLeftProfile,
144 Handle(HYDROData_Profile)& theRightProfile ) const
146 Handle(HYDROData_Stream) aStream =
147 Handle(HYDROData_Stream)::DownCast( GetFatherObject() );
148 if ( aStream.IsNull() )
151 HYDROData_SequenceOfObjects aStreamProfiles = aStream->GetProfiles();
152 if ( aStreamProfiles.Length() < 2 )
155 Handle(HYDROData_Profile) aPrevProfile;
156 gp_Pnt aPrevPnt1, aPrevPnt2;
157 for ( int i = 1, n = aStreamProfiles.Length(); i <= n; ++i )
159 Handle(HYDROData_Profile) aProfile =
160 Handle(HYDROData_Profile)::DownCast( aStreamProfiles.Value( i ) );
161 if ( aProfile.IsNull() )
164 gp_XY aFirstPoint, aLastPoint;
165 if ( !aProfile->GetLeftPoint( aFirstPoint ) || !aProfile->GetRightPoint( aLastPoint ) )
168 gp_Pnt aPnt1( aFirstPoint.X(), aFirstPoint.Y(), 0 );
169 gp_Pnt aPnt2( aLastPoint.X(), aLastPoint.Y(), 0 );
171 if ( !aPrevProfile.IsNull() )
173 BRepBuilderAPI_MakeEdge aLeftMakeEdge( aPrevPnt1, aPrevPnt2 );
174 BRepBuilderAPI_MakeEdge aBotMakeEdge( aPrevPnt2, aPnt2 );
175 BRepBuilderAPI_MakeEdge aRightMakeEdge( aPnt2, aPnt1 );
176 BRepBuilderAPI_MakeEdge aTopMakeEdge( aPnt1, aPrevPnt1 );
178 BRepBuilderAPI_MakeWire aMakeWire( aLeftMakeEdge.Edge(), aBotMakeEdge.Edge(),
179 aRightMakeEdge.Edge(), aTopMakeEdge.Edge() );
181 BRepBuilderAPI_MakeFace aMakeFace( aMakeWire.Wire() );
183 TopoDS_Face aProfilesFace = aMakeFace.Face();
185 BRepTopAdaptor_FClass2d aClassifier( aProfilesFace, Precision::Confusion() );
186 TopAbs_State aPointState = aClassifier.Perform( gp_Pnt2d( thePoint ), Standard_False );
187 if ( aPointState != TopAbs_OUT )
189 theLeftProfile = aPrevProfile;
190 theRightProfile = aProfile;
195 aPrevProfile = aProfile;
200 return !theLeftProfile.IsNull() && !theRightProfile.IsNull();
203 double HYDROData_StreamAltitude::GetAltitudeForPoint( const gp_XY& thePoint ) const
205 double aResAltitude = GetInvalidAltitude();
207 Handle(HYDROData_Stream) aStream =
208 Handle(HYDROData_Stream)::DownCast( GetFatherObject() );
209 if ( aStream.IsNull() )
212 TopoDS_Shape aStreamShape = aStream->GetTopShape();
213 if ( aStreamShape.IsNull() )
216 TopExp_Explorer aStreamFaceExp( aStreamShape, TopAbs_FACE );
217 if ( !aStreamFaceExp.More() )
220 // Get only face because of 2d profile wires is in compound
221 TopoDS_Face aStreamFace = TopoDS::Face( aStreamFaceExp.Current() );
223 // Check if point is inside of stream presentation
224 BRepTopAdaptor_FClass2d aClassifier( aStreamFace, Precision::Confusion() );
225 TopAbs_State aPointState = aClassifier.Perform( gp_Pnt2d( thePoint ), Standard_False );
226 if ( aPointState == TopAbs_OUT )
229 // Find the two profiles between which the point is lies
230 Handle(HYDROData_Profile) aLeftProfile, aRightProfile;
231 if ( !getBoundaryProfilesForPoint( thePoint, aLeftProfile, aRightProfile ) )
234 // Find the projections of point to borders of stream
235 gp_XYZ aPointToTest( thePoint.X(), thePoint.Y(), 0.0 );
237 TopoDS_Edge aStreamLeftEdge = TopoDS::Edge( aStream->GetLeftShape() );
238 TopoDS_Edge aStreamRightEdge = TopoDS::Edge( aStream->GetRightShape() );
240 Standard_Real aFirst = 0.0, aLast = 0.0;
241 Handle(Geom_Curve) anEdgeLeftCurve = BRep_Tool::Curve( aStreamLeftEdge, aFirst, aLast );
242 Handle(Geom_Curve) anEdgeRightCurve = BRep_Tool::Curve( aStreamRightEdge, aFirst, aLast );
244 GeomAPI_ProjectPointOnCurve aLeftProject( aPointToTest, anEdgeLeftCurve );
245 GeomAPI_ProjectPointOnCurve aRightProject( aPointToTest, anEdgeRightCurve );
247 Standard_Real aLeftDist = aLeftProject.LowerDistance();
248 Standard_Real aRightDist = aRightProject.LowerDistance();
250 // Find the altitude in profiles
251 Standard_Real aLeftAlt = getAltitudeFromProfile( aLeftProfile, aLeftDist, aRightDist );
252 Standard_Real aRightAlt = getAltitudeFromProfile( aRightProfile, aLeftDist, aRightDist );
254 // Interpolate altitudes
255 Standard_Real aFirstCoeff = aLeftDist / ( aLeftDist + aRightDist );
256 Standard_Real aSecCoeff = aRightDist / ( aLeftDist + aRightDist );
258 aResAltitude = aLeftAlt * aFirstCoeff + aRightAlt * aSecCoeff;