2 #include <HYDROData_DTM.h>
3 #include <HYDROData_Profile.h>
5 #include <Geom2d_BSplineCurve.hxx>
6 #include <Geom2dAPI_Interpolate.hxx>
7 #include <TColgp_HArray1OfPnt2d.hxx>
8 #include <TColgp_Array1OfVec2d.hxx>
9 #include <TColStd_HArray1OfBoolean.hxx>
11 #include <TopoDS_Edge.hxx>
12 #include <TopoDS_Wire.hxx>
13 #include <TopExp_Explorer.hxx>
14 #include <BRep_Tool.hxx>
16 #include <Geom_Line.hxx>
17 #include <Geom2d_Line.hxx>
18 #include <Geom2d_TrimmedCurve.hxx>
19 #include <Geom_BSplineCurve.hxx>
20 #include <Geom2d_BSplineCurve.hxx>
21 #include <TColStd_Array1OfReal.hxx>
22 #include <TColStd_Array1OfInteger.hxx>
23 #include <TColgp_Array1OfPnt.hxx>
24 #include <Geom2dAPI_InterCurveCurve.hxx>
27 IMPLEMENT_STANDARD_HANDLE( HYDROData_DTM, HYDROData_Bathymetry )
28 IMPLEMENT_STANDARD_RTTIEXT( HYDROData_DTM, HYDROData_Bathymetry )
31 HYDROData_DTM::CurveUZ::CurveUZ( double theXCurv )
36 HYDROData_DTM::CurveUZ::~CurveUZ()
40 double HYDROData_DTM::CurveUZ::Xcurv() const
45 HYDROData_DTM::CurveUZ HYDROData_DTM::CurveUZ::operator + ( const CurveUZ& c ) const
47 HYDROData_DTM::CurveUZ res( Xcurv() + c.Xcurv() );
50 for( int i=0; i<n; i++ )
53 p.U = operator[]( i ).U + c[i].U;
54 p.Z = operator[]( i ).Z;
60 HYDROData_DTM::CurveUZ HYDROData_DTM::CurveUZ::operator * ( double d ) const
62 HYDROData_DTM::CurveUZ res( Xcurv()*d );
65 for( int i=0; i<n; i++ )
68 p.U = operator[]( i ).U * d;
69 p.Z = operator[]( i ).Z;
77 HYDROData_DTM::HYDROData_DTM()
81 HYDROData_DTM::~HYDROData_DTM()
86 void GetProperties( const Handle_HYDROData_Profile& theProfile,
87 gp_Pnt& theLowestPoint, gp_Vec2d& theDir,
89 double& theZMin, double& theZMax )
91 theLowestPoint = theProfile->GetBottomPoint();
94 theProfile->GetLeftPoint( aLeft, true, true );
95 theProfile->GetRightPoint( aRight, true, true );
96 double x = aRight.X()-aLeft.X();
97 double y = aRight.Y()-aLeft.Y();
99 theDir = gp_Vec2d( -y, x );
101 theDir = gp_Vec2d( x, y );
104 inline gp_Pnt2d To2D( const gp_Pnt& thePnt, const gp_Trsf& theTr,
105 double& theUMin, double& theUMax )
107 gp_Pnt p = thePnt.Transformed( theTr );
114 return gp_Pnt2d( u, z );
117 Handle(TColgp_HArray1OfPnt2d) To2D( const TColgp_Array1OfPnt& thePoints,
118 const gp_Trsf& theTr,
119 double& theUMin, double& theUMax )
121 int low = thePoints.Lower(), up = thePoints.Upper();
122 Handle(TColgp_HArray1OfPnt2d) points = new TColgp_HArray1OfPnt2d( low, up );
123 for( int i=low; i<=up; i++ )
124 points->SetValue( i, To2D( thePoints.Value( i ), theTr, theUMin, theUMax ) );
128 Handle(Geom2d_Curve) CurveTo2D( const Handle(Geom_Curve)& theCurve,
129 Standard_Real theFirst, Standard_Real theLast,
130 const gp_Trsf& theTr,
131 double& theUMin, double& theUMax )
133 if( theCurve->IsKind( STANDARD_TYPE( Geom_Line ) ) )
135 gp_Pnt aFirstPnt, aLastPnt;
136 theCurve->D0( theFirst, aFirstPnt );
137 theCurve->D0( theLast, aLastPnt );
140 aFirst2d = To2D( aFirstPnt, theTr, theUMin, theUMax ),
141 aLast2d = To2D( aLastPnt, theTr, theUMin, theUMax );
143 gp_Vec2d dir( aFirst2d, aLast2d );
144 Handle_Geom2d_Line aLine2d = new Geom2d_Line( aFirst2d, gp_Dir2d( dir.X(), dir.Y() ) );
145 return new Geom2d_TrimmedCurve( aLine2d, 0, aLast2d.Distance( aFirst2d ) );
148 if( theCurve->IsKind( STANDARD_TYPE( Geom_BSplineCurve ) ) )
150 Handle(Geom_BSplineCurve) aSpline = Handle(Geom_BSplineCurve)::DownCast( theCurve );
152 Handle(TColgp_HArray1OfPnt2d) poles = To2D( aSpline->Poles(), theTr, theUMin, theUMax );
153 const TColStd_Array1OfReal& knots = aSpline->Knots();
154 const TColStd_Array1OfInteger& multiplicities = aSpline->Multiplicities();
155 int aDegree = aSpline->Degree();
157 return new Geom2d_BSplineCurve( poles->Array1(), knots, multiplicities, aDegree );
160 return Handle(Geom2d_Curve)();
163 Handle_Geom2d_BSplineCurve HYDROData_DTM::CreateHydraulicAxis(
164 const std::vector<Handle_HYDROData_Profile>& theProfiles,
165 std::vector<double>& theDistances )
167 size_t n = theProfiles.size();
168 Handle_Geom2d_BSplineCurve aResult;
170 Handle(TColgp_HArray1OfPnt2d) points = new TColgp_HArray1OfPnt2d( 1, (int)n );
171 TColgp_Array1OfVec2d tangents( 1, (int)n );
172 Handle(TColStd_HArray1OfBoolean) flags = new TColStd_HArray1OfBoolean( 1, (int)n );
174 for( size_t i = 1; i <= n; i++ )
176 Handle_HYDROData_Profile aProfile = theProfiles[i-1];
182 GetProperties( aProfile, aLowest, aTangent, true, zmin, zmax );
183 aTangent.Normalize();
185 points->SetValue( (int)i, gp_Pnt2d( aLowest.X(), aLowest.Y() ) );
186 tangents.SetValue( (int)i, aTangent );
187 flags->SetValue( (int)i, Standard_True );
190 Geom2dAPI_Interpolate anInterpolator( points, Standard_False, Standard_False );
191 anInterpolator.Load( tangents, flags );
192 anInterpolator.Perform();
193 if( anInterpolator.IsDone() )
195 aResult = anInterpolator.Curve();
196 //TODO: fill the distances vector
201 std::vector<Handle_Geom2d_Curve> HYDROData_DTM::ProfileToParametric(
202 const Handle_HYDROData_Profile& theProfile,
203 double& theUMin, double& theUMax )
205 std::vector<Handle_Geom2d_Curve> curves;
207 // Transformation of the coordinate systems
211 GetProperties( theProfile, aLowest, aDir, false, zmin, zmax );
213 gp_Ax3 aStd3d( gp_Pnt( 0, 0, 0 ), gp_Dir( 0, 0, 1 ), gp_Dir( 1, 0, 0 ) );
214 gp_Ax3 aLocal( aLowest, gp_Dir( 0, 0, 1 ), gp_Dir( aDir.X(), aDir.Y(), 0 ) );
217 aTransf.SetTransformation( aStd3d, aLocal );
219 // Iteration via edges
220 TopoDS_Wire aWire = TopoDS::Wire( theProfile->GetShape3D() );
221 TopExp_Explorer anExp( aWire, TopAbs_EDGE );
222 for( ; anExp.More(); anExp.Next() )
224 // Extract an edge from wire
225 TopoDS_Edge anEdge = TopoDS::Edge( anExp.Current() );
227 // Extract a curve corresponding to the edge
228 TopLoc_Location aLoc;
229 Standard_Real aFirst, aLast;
230 Handle(Geom_Curve) aCurve = BRep_Tool::Curve( anEdge, aLoc, aFirst, aLast );
232 // Convert the curve to 2d CS
233 Handle(Geom2d_Curve) aCurve2d = CurveTo2D( aCurve, aFirst, aLast, aTransf, theUMin, theUMax );
234 if( !aCurve2d.IsNull() )
235 curves.push_back( aCurve2d );
241 double CalcGC( const std::vector<gp_Pnt2d>& intersections )
244 size_t n = intersections.size();
245 for( size_t i = 0; i < n; i++ )
247 u += intersections[i].X();
253 double CalcWidth( const std::vector<gp_Pnt2d>& intersections )
255 double umin = std::numeric_limits<double>::max(),
258 size_t n = intersections.size();
262 for( size_t i = 0; i < n; i++ )
264 double u = intersections[i].X();
273 void HYDROData_DTM::ProfileDiscretization( const Handle_HYDROData_Profile& theProfile,
274 double theXCurv, double theMinZ, double theMaxZ, double theDDZ,
275 CurveUZ& theMidPointCurve,
276 CurveUZ& theWidthCurve,
277 double theTolerance )
279 double aDblMax = std::numeric_limits<double>::max(),
283 std::vector<Handle_Geom2d_Curve> curves = ProfileToParametric( theProfile, aUMin, aUMax );
284 size_t n = curves.size();
289 // we add the "virtual" vertical lines to simulate the intersection with profile
290 gp_Pnt2d aFirst, aLast;
291 curves[0]->D0( curves[0]->FirstParameter(), aFirst );
292 curves[n-1]->D0( curves[n-1]->LastParameter(), aLast );
293 Handle(Geom2d_Line) aV1 = new Geom2d_Line( aFirst, gp_Dir2d( 0, 1 ) );
294 Handle(Geom2d_TrimmedCurve) aT1 = new Geom2d_TrimmedCurve( aV1, 0.0, aDblMax );
296 Handle(Geom2d_Line) aV2 = new Geom2d_Line( aLast, gp_Dir2d( 0, 1 ) );
297 Handle(Geom2d_TrimmedCurve) aT2 = new Geom2d_TrimmedCurve( aV2, 0.0, aDblMax );
299 curves.push_back( aT1 );
300 curves.push_back( aT2 );
302 int psize = ( int )( ( theMaxZ-theMinZ ) / theDDZ + 1 );
303 theMidPointCurve = CurveUZ( theXCurv );
304 theMidPointCurve.reserve( psize );
305 theWidthCurve = CurveUZ( theXCurv );
306 theWidthCurve.reserve( psize );
309 // for each discrete value of z we search intersection with profile
310 for( double z = theMinZ; z <= theMaxZ; z += theDDZ )
312 Handle(Geom2d_Line) aLine = new Geom2d_Line( gp_Pnt2d( 0, z ), gp_Dir2d( 1, 0 ) );
313 std::vector<gp_Pnt2d> intersections;
314 for( size_t i = 0; i < n; i++ )
316 Handle_Geom2d_Curve aCurve = curves[i];
317 Geom2dAPI_InterCurveCurve anIntersect( aCurve, aLine, theTolerance );
318 for( int k=0, m=anIntersect.NbPoints(); k<m; k++ )
319 intersections.push_back( anIntersect.Point( k ) );
322 if( intersections.size() >= 2 )
324 double u_mid = CalcGC( intersections );
328 theMidPointCurve.push_back( p_mid );
330 double u_wid = CalcWidth( intersections );
334 theWidthCurve.push_back( p_wid );
339 void HYDROData_DTM::Interpolate( const CurveUZ& theCurveA, const CurveUZ& theCurveB,
340 int theNbSteps, std::vector<CurveUZ>& theInterpolation,
343 theInterpolation.clear();
344 int d = isAddSecond ? 2 : 1;
345 theInterpolation.reserve( theNbSteps+d );
346 double dt = 1.0 / double( theNbSteps + 1 );
348 theInterpolation.push_back( theCurveA );
349 for( int i=0; i<theNbSteps; i++, t+=dt )
351 CurveUZ anInterp = theCurveA*(1-t) + theCurveB*t;
352 theInterpolation.push_back( anInterp );
355 theInterpolation.push_back( theCurveB );
358 void HYDROData_DTM::CurveTo3d( const CurveUZ& theMidCurve, const CurveUZ& theWidthCurve,
359 AltitudePoints& thePoints )
364 inline double max( double a, double b )
372 void HYDROData_DTM::Interpolate( const Handle_HYDROData_Profile& theProfileA,
374 const Handle_HYDROData_Profile& theProfileB,
376 double theDDZ, int theNbSteps, bool isAddSecond,
377 AltitudePoints& thePoints )
379 double zminA, zmaxA, zminB, zmaxB;
380 gp_Pnt lowestA, lowestB;
383 GetProperties( theProfileA, lowestA, dirA, false, zminA, zmaxA );
384 GetProperties( theProfileB, lowestB, dirB, false, zminB, zmaxB );
386 double zmin = max( zminA, zminB );
387 double zmax = max( zmaxA, zmaxB );
389 CurveUZ midA(0), midB(0);
390 CurveUZ widA(0), widB(0);
392 ProfileDiscretization( theProfileA, theXCurvA, zmin, zmax, theDDZ, midA, widA );
393 ProfileDiscretization( theProfileB, theXCurvB, zmin, zmax, theDDZ, midB, widB );
395 std::vector<CurveUZ> mid, wid;
396 Interpolate( midA, midB, theNbSteps, mid, isAddSecond );
397 Interpolate( widA, widB, theNbSteps, wid, isAddSecond );
399 size_t q = mid.size();
400 for( size_t i=0; i<q; i++ )
401 CurveTo3d( mid[i], wid[i], thePoints );
404 void HYDROData_DTM::Interpolate( const std::vector<Handle_HYDROData_Profile>& theProfiles,
405 double theDDZ, double theSpatialStep, AltitudePoints& thePoints )
407 size_t n = theProfiles.size();
411 std::vector<double> distances;
412 Handle_Geom2d_BSplineCurve aHydraulicAxis = CreateHydraulicAxis( theProfiles, distances );
413 if( aHydraulicAxis.IsNull() )
416 for( size_t i=0, n1=n-1; i<n1; i++ )
418 double aDistance = distances[i+1]-distances[i];
419 int aNbSteps = int(aDistance/theSpatialStep) + 1;
420 bool isAddSecond = i==n1-1;
421 Interpolate( theProfiles[i], distances[i],
422 theProfiles[i+1], distances[i+1], theDDZ, aNbSteps, isAddSecond, thePoints );