Salome HOME
refs #1330: basic implementation of the not zoomable polyline arrows
[modules/hydro.git] / src / HYDROData / HYDROData_DTM.cxx
index 9393ac04e45a453ff112b6ced298092917c2db59..b31cdbcfe4ed812a783ce2ccc1a1336665094564 100644 (file)
@@ -36,7 +36,6 @@
 #include <BRep_Builder.hxx>
 #include <GeomProjLib.hxx>
 #include <Geom_TrimmedCurve.hxx>
-#include <Geom_Plane.hxx>
 #include <BRepTools_WireExplorer.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
 #include <BRepBuilderAPI_MakeFace.hxx>
 #include <ShapeUpgrade_UnifySameDomain.hxx>
 #include <BRepBuilderAPI_MakePolygon.hxx>
 #include <BOPAlgo_Builder.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <GeomProjLib.hxx>
 #include <gp_Pln.hxx>
 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_SequenceOfShape.hxx>
 #include <assert.h>
 
-IMPLEMENT_STANDARD_HANDLE( HYDROData_DTM, HYDROData_Bathymetry )
 IMPLEMENT_STANDARD_RTTIEXT( HYDROData_DTM, HYDROData_Bathymetry )
 
-HYDROData_DTM::CurveUZ::CurveUZ( double theXCurv, const gp_Vec2d& theProfileDir, double theDeltaZ )
-  : myXcurv( theXCurv ), myProfileDir( theProfileDir ), myDeltaZ( theDeltaZ )
+HYDROData_DTM::CurveUZ::CurveUZ( double theXCurv, const gp_Vec2d& theProfileDir, double theDeltaZ, double theMaxZ )
+  : myXcurv( theXCurv ), myProfileDir( theProfileDir ), myDeltaZ( theDeltaZ ), myMaxZ (theMaxZ)
 {
 }
 
@@ -85,9 +85,14 @@ double HYDROData_DTM::CurveUZ::DeltaZ() const
   return myDeltaZ;
 }
 
+double HYDROData_DTM::CurveUZ::MaxZ() const
+{
+  return myMaxZ;
+}
+
 HYDROData_DTM::CurveUZ HYDROData_DTM::CurveUZ::operator + ( const CurveUZ& c ) const
 {
-  HYDROData_DTM::CurveUZ res( Xcurv() + c.Xcurv(), ProfileDir() + c.ProfileDir(), DeltaZ() + c.DeltaZ() );
+  HYDROData_DTM::CurveUZ res( Xcurv() + c.Xcurv(), ProfileDir() + c.ProfileDir(), DeltaZ() + c.DeltaZ(), MaxZ() + c.MaxZ() );
   size_t n = size(), n1 = c.size();
   if( n!=n1 )
   {
@@ -106,7 +111,7 @@ HYDROData_DTM::CurveUZ HYDROData_DTM::CurveUZ::operator + ( const CurveUZ& c ) c
 
 HYDROData_DTM::CurveUZ HYDROData_DTM::CurveUZ::operator * ( double d ) const
 {
-  HYDROData_DTM::CurveUZ res( Xcurv()*d, ProfileDir()*d, DeltaZ()*d );
+  HYDROData_DTM::CurveUZ res( Xcurv()*d, ProfileDir()*d, DeltaZ()*d, MaxZ()*d );
   size_t n = size();
   res.reserve( n );
   for( int i=0; i<n; i++ )
@@ -184,7 +189,7 @@ void HYDROData_DTM::PointsToEdge(const AltitudePoints& pnts, TopoDS_Edge& E )
   anInterpolator.Perform() ;
   if (anInterpolator.IsDone()) 
   {
-    Handle(Geom_Curve) C = anInterpolator.Curve();
+    Handle(Geom_BSplineCurve) C = anInterpolator.Curve();
     E = BRepBuilderAPI_MakeEdge(C).Edge();
   }
 }
@@ -284,7 +289,7 @@ void HYDROData_DTM::CreateProfilesFromDTM (const HYDROData_SequenceOfObjects& In
   int aLower = InpProfiles.Lower(), anUpper = InpProfiles.Upper();
   size_t n = anUpper - aLower + 1;
 
-  std::vector<Handle_HYDROData_Profile> profiles;
+  std::vector<Handle(HYDROData_Profile)> profiles;
   profiles.reserve( n ); 
   for( int i=aLower; i<=anUpper; i++ )
   {
@@ -315,19 +320,20 @@ bool HYDROData_DTM::GetPlanarFaceFromBanks( const TopoDS_Edge& LB, const TopoDS_
   BRep_Builder BB;
   TopoDS_Face F;
   Handle_Geom_Plane refpl = new Geom_Plane(gp_Pnt(0,0,0), gp_Dir(0,0,1));
-  BB.MakeFace(F, refpl, Precision::Confusion());
-  BRepAlgo_NormalProjection nproj(F);
-  nproj.Add(LB);
-  nproj.Add(RB);
-  nproj.SetDefaultParams();
-  nproj.Build();
-  if(!nproj.IsDone())
-    return false;
 
-  //TopoDS_Shape projBanks = nproj.Projection();
   TopoDS_Vertex VFI, VLI, VFO, VLO;
-  TopoDS_Edge prLB = TopoDS::Edge(nproj.Generated(LB).First());
-  TopoDS_Edge prRB = TopoDS::Edge(nproj.Generated(RB).First());
+  TopoDS_Edge prLB;
+  TopoDS_Edge prRB;
+
+
+  BRepAdaptor_Curve LBAD(LB);
+  Handle_Geom_Curve LBPC = GeomProjLib::ProjectOnPlane(LBAD.Curve().Curve(), refpl, gp_Dir(0, 0, -1), 1 );
+  prLB = BRepLib_MakeEdge(LBPC).Edge();
+
+  BRepAdaptor_Curve RBAD(RB);
+  Handle_Geom_Curve RBPC = GeomProjLib::ProjectOnPlane(RBAD.Curve().Curve(), refpl, gp_Dir(0, 0, -1), 1 );
+  prRB = BRepLib_MakeEdge(RBPC).Edge();
+
   TopExp::Vertices(prLB, VFI, VFO, 1);
   TopExp::Vertices(prRB, VLI, VLO, 1);
   TopoDS_Edge prIL = BRepLib_MakeEdge(VFI, VLI).Edge();
@@ -348,7 +354,7 @@ bool HYDROData_DTM::GetPlanarFaceFromBanks( const TopoDS_Edge& LB, const TopoDS_
   return !res;
 }
 
-void HYDROData_DTM::CreateProfiles(const std::vector<Handle_HYDROData_Profile>& theProfiles,
+void HYDROData_DTM::CreateProfiles(const std::vector<Handle(HYDROData_Profile)>& theProfiles,
                                    double theDDZ,
                                    double theSpatialStep,
                                    AltitudePoints& theOutLeft,
@@ -405,7 +411,7 @@ void HYDROData_DTM::CreateProfiles(const std::vector<Handle_HYDROData_Profile>&
 
 
 
-void HYDROData_DTM::GetProperties( const Handle_HYDROData_Profile& theProfile,
+void HYDROData_DTM::GetProperties( const Handle(HYDROData_Profile)& theProfile,
                     gp_Pnt& theLowestPoint, gp_Vec2d& theDir,
                     double& theZMin, double& theZMax )
 {
@@ -473,7 +479,7 @@ Handle(Geom2d_Curve) CurveTo2D( const Handle(Geom_Curve)& theCurve,
       aLast2d = To2D( aLastPnt, theTr, theUMin, theUMax );
 
     gp_Vec2d dir( aFirst2d, aLast2d );
-    Handle_Geom2d_Line aLine2d = new Geom2d_Line( aFirst2d, gp_Dir2d( dir.X(), dir.Y() ) );
+    Handle(Geom2d_Line) aLine2d = new Geom2d_Line( aFirst2d, gp_Dir2d( dir.X(), dir.Y() ) );
     return new Geom2d_TrimmedCurve( aLine2d, 0, aLast2d.Distance( aFirst2d ) );
   }
 
@@ -494,8 +500,8 @@ Handle(Geom2d_Curve) CurveTo2D( const Handle(Geom_Curve)& theCurve,
 
 #include <GCE2d_MakeSegment.hxx>
 #include <Geom2dAPI_InterCurveCurve.hxx>
-bool IsCooriented( const Handle_HYDROData_Profile& theProfile1,
-                   const Handle_HYDROData_Profile& theProfile2 ) 
+bool IsCooriented( const Handle(HYDROData_Profile)& theProfile1,
+                   const Handle(HYDROData_Profile)& theProfile2 ) 
 {
   if( theProfile1==theProfile2 )
     return true;
@@ -510,15 +516,15 @@ bool IsCooriented( const Handle_HYDROData_Profile& theProfile1,
   GCE2d_MakeSegment s2(rp1, rp2);
 
   Geom2dAPI_InterCurveCurve inter;
-  inter.Init(s1, s2);
+  inter.Init(s1.Value(), s2.Value());
   if (inter.NbPoints() == 0)
     return true;
   else
     return false;
 }
 
-Handle_Geom2d_BSplineCurve HYDROData_DTM::CreateHydraulicAxis( 
-  const std::vector<Handle_HYDROData_Profile>& theProfiles,
+Handle(Geom2d_BSplineCurve) HYDROData_DTM::CreateHydraulicAxis( 
+  const std::vector<Handle(HYDROData_Profile)>& theProfiles,
   std::vector<double>& theDistances )
 {
   size_t n = theProfiles.size();
@@ -531,13 +537,14 @@ Handle_Geom2d_BSplineCurve HYDROData_DTM::CreateHydraulicAxis(
   TColgp_Array1OfVec2d tangents( 1, (int)n );
   Handle(TColStd_HArray1OfBoolean) flags = new TColStd_HArray1OfBoolean( 1, (int)n );
 
-  for( size_t i = 1; i <= n; i++ )
+  // Stage 1. Orient all profiles to be co-oriented with the first profile
+  theProfiles[0]->Update();
+  for( size_t i = 1; i < n; i++ )
   {
-    Handle_HYDROData_Profile aProfile = theProfiles[i-1];
-    Handle_HYDROData_Profile aPrevProfile = i==1 ? theProfiles[i-1] : theProfiles[i-2];
-    Handle_HYDROData_Profile aNextProfile = i==n ? theProfiles[i-1] : theProfiles[i];
+    Handle(HYDROData_Profile) aProfile = theProfiles[i];
+    Handle(HYDROData_Profile) aPrevProfile = theProfiles[i-1];
 
-    if( !IsCooriented( aProfile, aNextProfile ) )
+    if( !IsCooriented( aProfile, aPrevProfile ) )
     {
       gp_XY lp, rp;
       aProfile->GetLeftPoint( lp, true );
@@ -546,20 +553,22 @@ Handle_Geom2d_BSplineCurve HYDROData_DTM::CreateHydraulicAxis(
       aProfile->SetRightPoint( lp, true );
     }
     aProfile->Update();
+  }
+
+  // Stage 2. Calculate normals so that each normal "points" to the next profile
+  for( size_t i = 0; i < n; i++ )
+  {
+    Handle(HYDROData_Profile) aProfile = theProfiles[i];
+    Handle(HYDROData_Profile) aNextProfile = i==n-1 ? theProfiles[i-1] : theProfiles[i+1];
 
     gp_Pnt aLowest;
     gp_Vec2d aNormal;
     double zmin, zmax;
 
-    gp_XYZ curP = aProfile->GetBottomPoint();
+    gp_XYZ curP = aProfile->GetBottomPoint(true);
     gp_XY curP2d = gp_XY(curP.X(), curP.Y());
 
-    gp_XYZ nextP;
-    if( i==n )
-      nextP = aPrevProfile->GetBottomPoint(true);
-    else
-      nextP = aNextProfile->GetBottomPoint(true);
-
+    gp_XYZ nextP = aNextProfile->GetBottomPoint(true);
     gp_XY nextP2d = gp_XY(nextP.X(), nextP.Y());
 
     gp_Vec2d aPrTangent;
@@ -567,16 +576,17 @@ Handle_Geom2d_BSplineCurve HYDROData_DTM::CreateHydraulicAxis(
     aNormal.SetCoord( -aPrTangent.Y(), aPrTangent.X() );
 
     gp_Vec2d aDirToNextProfile(nextP2d.X() - curP2d.X(), nextP2d.Y() - curP2d.Y() );
-    if( i==n )
+    if( i==n-1 )
       aDirToNextProfile.Reverse();
+
     if (aNormal.Dot(aDirToNextProfile) < 0)
       aNormal.Reverse();
 
     aNormal.Normalize();
 
-    points->SetValue( (int)i, gp_Pnt2d( aLowest.X(), aLowest.Y() ) );
-    tangents.SetValue( (int)i, aNormal );
-    flags->SetValue( (int)i, Standard_True );
+    points->SetValue( (int)(i+1), gp_Pnt2d( aLowest.X(), aLowest.Y() ) );
+    tangents.SetValue( (int)(i+1), aNormal );
+    flags->SetValue( (int)(i+1), Standard_True );
   }
 
   Geom2dAPI_Interpolate anInterpolator( points, Standard_False, Standard_False );
@@ -604,11 +614,11 @@ Handle_Geom2d_BSplineCurve HYDROData_DTM::CreateHydraulicAxis(
   return aResult;
 }
 
-std::vector<Handle_Geom2d_Curve> HYDROData_DTM::ProfileToParametric( 
-  const Handle_HYDROData_Profile& theProfile,
+std::vector<Handle(Geom2d_Curve)> HYDROData_DTM::ProfileToParametric( 
+  const Handle(HYDROData_Profile)& theProfile,
   double& theUMin, double& theUMax, gp_Vec2d& theDir )
 {
-  std::vector<Handle_Geom2d_Curve> curves;
+  std::vector<Handle(Geom2d_Curve)> curves;
   
   // Transformation of the coordinate systems
   gp_Pnt aLowest;
@@ -666,8 +676,8 @@ bool CalcMidWidth( const std::set<double>& intersections, double& theMid, double
   return true;
 }
 
-void HYDROData_DTM::ProfileDiscretization( const Handle_HYDROData_Profile& theProfile, 
-                                           double theXCurv, double theMinZ, double theMaxZ, double theDDZ,
+void HYDROData_DTM::ProfileDiscretization( const Handle(HYDROData_Profile)& theProfile, 
+                                           double theXCurv, double theMinZ, double theMaxZ, double theTopZ, double theDDZ,
                                            CurveUZ& theMidPointCurve,
                                            CurveUZ& theWidthCurve,                                           
                                            int& intersection_nb,
@@ -679,7 +689,7 @@ void HYDROData_DTM::ProfileDiscretization( const Handle_HYDROData_Profile& thePr
          aVMax = 1000000;
   
   gp_Vec2d aProfileDir;
-  std::vector<Handle_Geom2d_Curve> curves = ProfileToParametric( theProfile, aUMin, aUMax, aProfileDir );
+  std::vector<Handle(Geom2d_Curve)> curves = ProfileToParametric( theProfile, aUMin, aUMax, aProfileDir );
   size_t n = curves.size();
 
   if( n==0 )
@@ -699,9 +709,9 @@ void HYDROData_DTM::ProfileDiscretization( const Handle_HYDROData_Profile& thePr
   curves.push_back( aT2 );
   
   int psize = ( int )( ( theMaxZ-theMinZ ) / theDDZ + 1 );
-  theMidPointCurve = CurveUZ( theXCurv, aProfileDir, theMinZ );
+  theMidPointCurve = CurveUZ( theXCurv, aProfileDir, theMinZ, theTopZ);
   theMidPointCurve.reserve( psize );
-  theWidthCurve = CurveUZ( theXCurv, aProfileDir, theMinZ );
+  theWidthCurve = CurveUZ( theXCurv, aProfileDir, theMinZ, theTopZ );
   theWidthCurve.reserve( psize );
 
   n = curves.size();
@@ -712,7 +722,7 @@ void HYDROData_DTM::ProfileDiscretization( const Handle_HYDROData_Profile& thePr
     std::set<double> intersections;
     for( size_t i = 0; i < n; i++ )
     {
-      Handle_Geom2d_Curve aCurve = curves[i];
+      Handle(Geom2d_Curve) aCurve = curves[i];
       Geom2dAPI_InterCurveCurve anIntersect( aCurve, aLine, theTolerance );
       for( int k=1, m=anIntersect.NbPoints(); k<=m; k++ )
         intersections.insert( anIntersect.Point( k ).X() );
@@ -758,7 +768,7 @@ void HYDROData_DTM::Interpolate( const CurveUZ& theCurveA, const CurveUZ& theCur
     theInterpolation.push_back( theCurveB );
 }
 #include <BRepLib_MakeEdge2d.hxx>
-void HYDROData_DTM::CurveTo3D( const Handle_Geom2d_BSplineCurve& theHydraulicAxis,
+void HYDROData_DTM::CurveTo3D( const Handle(Geom2d_BSplineCurve)& theHydraulicAxis,
                                const CurveUZ& theMidCurve, const CurveUZ& theWidthCurve,
                                AltitudePoints& thePoints )
 {
@@ -775,7 +785,8 @@ void HYDROData_DTM::CurveTo3D( const Handle_Geom2d_BSplineCurve& theHydraulicAxi
   
   size_t n = theMidCurve.size();
   std::map<double, AltitudePoint> sorted_points;
-  for( size_t i=0; i<n; i++ )
+  bool isOnTop = false;
+  for( size_t i=0; i<n; i++ ) // build the two banks of the interpolated profile, from bottom to top
   {
     double param1 = theMidCurve[i].U - theWidthCurve[i].U / 2;
     double param2 = theMidCurve[i].U + theWidthCurve[i].U / 2;
@@ -783,12 +794,24 @@ void HYDROData_DTM::CurveTo3D( const Handle_Geom2d_BSplineCurve& theHydraulicAxi
     gp_Pnt2d p1 = point.Translated( param1 * profile_dir);
     gp_Pnt2d p2 = point.Translated( param2 * profile_dir);
 
-    double z = theMidCurve[i].Z + theMidCurve.DeltaZ();
-
-    AltitudePoint p3d_1( p1.X(), p1.Y(), z ), p3d_2( p2.X(), p2.Y(), z );
-
-    sorted_points[param1] = p3d_1;
-    sorted_points[param2] = p3d_2;
+    bool arrivedOnTop = false;
+    double z = 0;
+    if (theMidCurve[i].Z <= theMidCurve.MaxZ())
+      z = theMidCurve[i].Z + theMidCurve.DeltaZ();
+    else
+      {
+        z = theMidCurve.MaxZ() + theMidCurve.DeltaZ(); // limit z to linear interpolation between maxima on extremity profiles
+        arrivedOnTop = true; // do not keep points after this one
+      }
+    if (!isOnTop)
+      {
+        AltitudePoint p3d_1( p1.X(), p1.Y(), z ), p3d_2( p2.X(), p2.Y(), z );
+
+        sorted_points[param1] = p3d_1;
+        sorted_points[param2] = p3d_2;
+      }
+    //if (arrivedOnTop)
+    //  isOnTop =true; // do not keep points after this one (commented: leads to strange limits of 2D shape)
   }
 
   thePoints.reserve( sorted_points.size() );
@@ -818,10 +841,10 @@ inline double min( double a, double b )
 #include <BRepLib_MakeWire.hxx>
 
 std::vector<HYDROData_Bathymetry::AltitudePoints> HYDROData_DTM::Interpolate
-  ( const Handle_Geom2d_BSplineCurve& theHydraulicAxis,
-    const Handle_HYDROData_Profile& theProfileA,
+  ( const Handle(Geom2d_BSplineCurve)& theHydraulicAxis,
+    const Handle(HYDROData_Profile)& theProfileA,
     double theXCurvA,
-    const Handle_HYDROData_Profile& theProfileB,
+    const Handle(HYDROData_Profile)& theProfileB,
     double theXCurvB,
     double theDDZ, int theNbSteps, bool isAddSecond,
     int& inter_nb_1, int& inter_nb_2)
@@ -840,11 +863,11 @@ std::vector<HYDROData_Bathymetry::AltitudePoints> HYDROData_DTM::Interpolate
   //double zmin = min( zminA, zminB );
   //double zmax = max( zmaxA, zmaxB );
 
-  CurveUZ midA(0, gp_Vec2d(), 0), midB(0, gp_Vec2d(), 0);
-  CurveUZ widA(0, gp_Vec2d(), 0), widB(0, gp_Vec2d(), 0);
+  CurveUZ midA(0, gp_Vec2d(), 0, 0), midB(0, gp_Vec2d(), 0, 0);
+  CurveUZ widA(0, gp_Vec2d(), 0, 0), widB(0, gp_Vec2d(), 0, 0);
 
-  ProfileDiscretization( theProfileA, theXCurvA, zminA, zminA+hmax, theDDZ, midA, widA, inter_nb_1 ); 
-  ProfileDiscretization( theProfileB, theXCurvB, zminB, zminB+hmax, theDDZ, midB, widB, inter_nb_2 );
+  ProfileDiscretization( theProfileA, theXCurvA, zminA, zminA+hmax, zmaxA-zminA, theDDZ, midA, widA, inter_nb_1 );
+  ProfileDiscretization( theProfileB, theXCurvB, zminB, zminB+hmax, zmaxB-zminB, theDDZ, midB, widB, inter_nb_2 );
 
   std::vector<CurveUZ> mid, wid;
   Interpolate( midA, midB, theNbSteps, mid, isAddSecond );
@@ -865,7 +888,7 @@ std::vector<HYDROData_Bathymetry::AltitudePoints> HYDROData_DTM::Interpolate
 }
 
 HYDROData_Bathymetry::AltitudePoints HYDROData_DTM::Interpolate
-  ( const std::vector<Handle_HYDROData_Profile>& theProfiles,
+  ( const std::vector<Handle(HYDROData_Profile)>& theProfiles,
     double theDDZ, double theSpatialStep,
     AltitudePoints& theLeft,
     AltitudePoints& theRight,
@@ -878,7 +901,7 @@ HYDROData_Bathymetry::AltitudePoints HYDROData_DTM::Interpolate
     return points;
 
   std::vector<double> distances;
-  Handle_Geom2d_BSplineCurve aHydraulicAxis = CreateHydraulicAxis( theProfiles, distances );
+  Handle(Geom2d_BSplineCurve) aHydraulicAxis = CreateHydraulicAxis( theProfiles, distances );
   if( aHydraulicAxis.IsNull() )
     return points;
 
@@ -933,7 +956,7 @@ HYDROData_Bathymetry::AltitudePoints HYDROData_DTM::Interpolate
   return points;
 }
 
-int HYDROData_DTM::EstimateNbPoints( const std::vector<Handle_HYDROData_Profile>& theProfiles,
+int HYDROData_DTM::EstimateNbPoints( const std::vector<Handle(HYDROData_Profile)>& theProfiles,
                                      double theDDZ, double theSpatialStep )
 {
   size_t n = theProfiles.size();
@@ -943,7 +966,7 @@ int HYDROData_DTM::EstimateNbPoints( const std::vector<Handle_HYDROData_Profile>
     return 1 << 20;
 
   std::vector<double> distances;
-  Handle_Geom2d_BSplineCurve aHydraulicAxis = CreateHydraulicAxis( theProfiles, distances );
+  Handle(Geom2d_BSplineCurve) aHydraulicAxis = CreateHydraulicAxis( theProfiles, distances );
   if( aHydraulicAxis.IsNull() )
     return 0;