Salome HOME
Lot 2: change bathy associated to natural object propagated to all cases without...
[modules/hydro.git] / src / HYDROData / HYDROData_StreamLinearInterpolation.cxx
index f7c9d1a8497ac7f74d3d73fb7b6e9561f2e380a3..23eab97ec0a30466d10ae142e26394099fac8f1f 100644 (file)
@@ -54,6 +54,9 @@
 #include <Geom_Plane.hxx>
 #include <TopoDS_Wire.hxx>
 #include <BRepLib.hxx>
+#include <BRepLib_MakePolygon.hxx>
+#include <TopoDS_Compound.hxx>
+#include <BRep_Builder.hxx>
 
 static std::vector<gp_Pnt2d> GetProfileUZPoints(const Handle(HYDROData_Profile)& theProfile)
 {
@@ -104,7 +107,7 @@ static void GetMaxDist(const std::vector<gp_Pnt2d>& PNTS,
 static void InsertPoints(std::vector<gp_Pnt2d>& points, int nbpoints)
 {
   points.reserve(points.size() + nbpoints);
-  while (nbpoints)
+  while (nbpoints>0)
   {
     double dmax=0, dmax2=0;
     int imax=-1;
@@ -121,6 +124,8 @@ static void InsertPoints(std::vector<gp_Pnt2d>& points, int nbpoints)
     double Y0 = p1.Y();
     double X1 = p2.X();
     double Y1 = p2.Y();
+    if (nbPins>nbpoints) //deny to add more points than needed
+      nbPins = nbpoints;
     for (int i=0;i<nbPins;i++)
     {
       double t = ((double)i+1)/((double)nbPins+1);
@@ -131,6 +136,7 @@ static void InsertPoints(std::vector<gp_Pnt2d>& points, int nbpoints)
     }
     nbpoints-=nbPins;
   }
+  assert (nbpoints == 0);
 }
 
 static void PolyToCurve2d(const Handle(HYDROData_PolylineXY)& poly, Handle(Geom2d_Curve)& c2d)
@@ -165,14 +171,15 @@ static void PolyToCurve2d(const Handle(HYDROData_PolylineXY)& poly, Handle(Geom2
 static void InterProfilesAndHAX(const HYDROData_SequenceOfObjects& profiles, 
   const Handle(Geom2d_Curve)& Hax2d, 
   std::map<double, Handle(HYDROData_Profile)>& profToInterParam,
+  std::vector<bool>& paramToSwapFlag,
   std::vector<std::string>* warnings)
 {
   for (int i=1;i<=profiles.Size();i++)
   {
     Handle(HYDROData_Profile) aProfile = Handle(HYDROData_Profile)::DownCast(profiles(i)); 
     gp_XY LP, RP;
-    aProfile->GetLeftPoint( LP, true, true );
-    aProfile->GetRightPoint( RP, true, true );
+    aProfile->GetLeftPoint( LP, false, true );
+    aProfile->GetRightPoint( RP, false, true );
     gp_Pnt2d P1(LP), P2(RP);
     double d = P2.Distance(P1);
     if (d < gp::Resolution())
@@ -182,6 +189,7 @@ static void InterProfilesAndHAX(const HYDROData_SequenceOfObjects& profiles,
       continue;
     }
     Handle(Geom2d_Line) lin2d = new Geom2d_Line(P1,gp_Dir2d(P2.XY()-P1.XY()));
+    gp_Dir2d prof_dir2d = lin2d->Direction();
 
     Geom2dAdaptor_Curve linAd(lin2d, 0, d);
     Geom2dAdaptor_Curve haxAd(Hax2d);
@@ -205,6 +213,15 @@ static void InterProfilesAndHAX(const HYDROData_SequenceOfObjects& profiles,
       continue; 
     }
     double param = isec.Point(1).ParamOnSecond();
+    gp_Pnt2d int_p2d;
+    gp_Vec2d vec_on_hax_intersec;
+    haxAd.D1(param, int_p2d, vec_on_hax_intersec);
+    gp_Dir2d d_hax(vec_on_hax_intersec);
+    double ang = d_hax.Angle(prof_dir2d);
+    if (ang>0)    
+      paramToSwapFlag.push_back(true);
+    else
+      paramToSwapFlag.push_back(false);
     profToInterParam[param] = aProfile;
   }
 }
@@ -226,8 +243,9 @@ static void GetPointsOnBanks(const std::vector<double>& gua_params,
   const Handle(Geom2d_Curve)& Hax2d,
   const Handle(Geom2d_Curve)& LB2d, 
   const Handle(Geom2d_Curve)& RB2d,
-  std::map<double, std::pair<gp_Pnt2d, gp_Pnt2d>>& parToBankPoints,
-  std::vector<std::string>* warnings)
+  std::map<double, std::pair<IntRes2d_IntersectionPoint, IntRes2d_IntersectionPoint>>& parToBankPoints,  
+  std::vector<std::string>* warnings,
+  const std::map<double, std::pair<Handle(HYDROData_Profile), Handle(HYDROData_Profile)>>* intermParamToProfPair)
 { 
   for(int i = 0; i < gua_params.size(); i++)
   {
@@ -249,19 +267,35 @@ static void GetPointsOnBanks(const std::vector<double>& gua_params,
     if (warnings && intL.NbPoints()==0 )
     {
       std::string coord = (QString::number(p2d.X()) + ", "+QString::number(p2d.Y())).toStdString();
-      warnings->push_back("no intersection between intermediate profile (point on h.axis:("+ coord +")) and left bank found; skipped");
+      if (intermParamToProfPair && intermParamToProfPair->count(par) != 0)
+      {
+        std::string fpn = intermParamToProfPair->at(par).first->GetName().toStdString();
+        std::string spn = intermParamToProfPair->at(par).second->GetName().toStdString();
+        warnings->push_back("no intersection between intermediate profile (point on h.axis:("+ 
+          coord +"), located between " + fpn + " & " + spn + ") and left bank found; skipped");
+      }
+      else
+        warnings->push_back("no intersection between intermediate profile (point on h.axis:("+ coord +")) and left bank found; skipped");
     }
 
     if (warnings && intR.NbPoints()==0)
     {
       std::string coord = (QString::number(p2d.X()) + ", "+QString::number(p2d.Y())).toStdString();
-      warnings->push_back("no intersection between intermediate profile (point on h.axis:("+ coord +")) and right bank found; skipped");
+      if (intermParamToProfPair && intermParamToProfPair->count(par) != 0)
+      {
+        std::string fpn = intermParamToProfPair->at(par).first->GetName().toStdString();
+        std::string spn = intermParamToProfPair->at(par).second->GetName().toStdString();
+        warnings->push_back("no intersection between intermediate profile (point on h.axis:("+ 
+          coord +"), located between " + fpn + " & " + spn + ") and right bank found; skipped");
+      }
+      else
+        warnings->push_back("no intersection between intermediate profile (point on h.axis:("+ coord +")) and right bank found; skipped");
     }
 
     if ( intL.NbPoints()==0 || intR.NbPoints()==0)
       continue;
 
-    gp_Pnt2d aNearSolL, aNearSolR;
+    IntRes2d_IntersectionPoint aNearSolL, aNearSolR;
     double min_sq_dist = Precision::Infinite();
     for (int j=1;j<=intL.NbPoints();j++)
     {
@@ -269,7 +303,8 @@ static void GetPointsOnBanks(const std::vector<double>& gua_params,
       if (min_sq_dist > sq_dist)
       {
         min_sq_dist = sq_dist;
-        aNearSolL = intL.Point(j);
+        //aNearSolL = intL.Point(j);
+        aNearSolL = intL.Intersector().Point(j);
       }
     }
     min_sq_dist = Precision::Infinite();
@@ -279,42 +314,18 @@ static void GetPointsOnBanks(const std::vector<double>& gua_params,
       if (min_sq_dist > sq_dist)
       {
         min_sq_dist = sq_dist;
-        aNearSolR = intR.Point(j);
+        //aNearSolR = intR.Point(j);
+        aNearSolR =  intR.Intersector().Point(j);
       }
     }
 
-    std::pair<gp_Pnt2d, gp_Pnt2d> int_pair(aNearSolL, aNearSolR);
+    std::pair<IntRes2d_IntersectionPoint, IntRes2d_IntersectionPoint> int_pair(aNearSolL, aNearSolR);
     parToBankPoints[par]=int_pair;
   }
 }
 
 
-bool GetItersectionParam(const Handle(HYDROData_Profile)& aProfile, const Handle(Geom2d_Curve)& B2d, double& outIntersectionParam)
-{ 
-  gp_XY LP, RP;
-  aProfile->GetLeftPoint( LP, true, true );
-  aProfile->GetRightPoint( RP, true, true );
-  gp_Pnt2d P1(LP), P2(RP);
-  double d = P2.Distance(P1);
-  if (d < gp::Resolution())
-    return false;
-  Handle(Geom2d_Line) lin2d = new Geom2d_Line(P1,gp_Dir2d(P2.XY()-P1.XY()));
-
-  Geom2dAdaptor_Curve linAd(lin2d, 0, d);
-  Geom2dAdaptor_Curve BAd(B2d);
-  Geom2dInt_GInter isec( linAd, BAd, 1.0e-6, 1.0e-6);
-  if (!isec.IsDone())
-    return false;
-  if (isec.NbPoints() == 0)
-    return false;
-  if (isec.NbPoints() > 1)
-    return false;
-  outIntersectionParam = isec.Point(1).ParamOnSecond();
-  return true;
-}
-
-void BuildFace(const Handle(HYDROData_Profile)& F_prof,
-  const Handle(HYDROData_Profile)& S_prof,
+void BuildFace(const std::map<double, std::pair<IntRes2d_IntersectionPoint, IntRes2d_IntersectionPoint>>& parToBankPoints, 
   const Handle(Geom2d_Curve)& LB2d,
   const Handle(Geom2d_Curve)& RB2d,
   HYDROData_Stream::PrsDefinition& prsDef)
@@ -326,46 +337,54 @@ void BuildFace(const Handle(HYDROData_Profile)& F_prof,
   prsDef.myInlet.Nullify();     
   prsDef.myOutlet.Nullify();  
 
-  bool stat = true;
   double lb_1, lb_2, rb_1, rb_2;
-  stat = GetItersectionParam(F_prof, LB2d, lb_1) && GetItersectionParam(F_prof, RB2d, rb_1)
-    && GetItersectionParam(S_prof, LB2d, lb_2) && GetItersectionParam(S_prof, RB2d, rb_2);
-  if (stat)
+  lb_1 = parToBankPoints.begin()->second.first.ParamOnFirst();
+  rb_1 = parToBankPoints.begin()->second.second.ParamOnFirst();
+
+  lb_2 = parToBankPoints.rbegin()->second.first.ParamOnFirst();
+  rb_2 = parToBankPoints.rbegin()->second.second.ParamOnFirst();
+
+  //stat = GetItersectionParam(F_prof, LB2d, lb_1) && GetItersectionParam(F_prof, RB2d, rb_1)
+  //  && GetItersectionParam(S_prof, LB2d, lb_2) && GetItersectionParam(S_prof, RB2d, rb_2);
+  
+  BRepBuilderAPI_MakeEdge2d LEM(LB2d, lb_1, lb_2);
+  if (!LEM.IsDone())
+    return;
+  BRepBuilderAPI_MakeEdge2d REM(RB2d, rb_1, rb_2);
+  if (!REM.IsDone())
+    return;
+  TopoDS_Edge LBE = LEM.Edge();
+  TopoDS_Edge RBE = REM.Edge();
+  if (LBE.IsNull() || RBE.IsNull())
+    return;
+  BRepBuilderAPI_MakeEdge PFEM(BRep_Tool::Pnt(LEM.Vertex1()), BRep_Tool::Pnt(REM.Vertex1()));
+  BRepBuilderAPI_MakeEdge PLEM(BRep_Tool::Pnt(LEM.Vertex2()), BRep_Tool::Pnt(REM.Vertex2()));
+  if (!PFEM.IsDone())
+    return;
+  if (!PLEM.IsDone())
+    return;
+  TopoDS_Edge FProfE = PFEM.Edge();
+  TopoDS_Edge SProfE = PLEM.Edge();
+  BRepBuilderAPI_MakeWire WM(FProfE, LBE, SProfE, RBE);
+  if (WM.IsDone())
   {
-    BRepBuilderAPI_MakeEdge2d LEM(LB2d, lb_1, lb_2);
-    if (!LEM.IsDone())
-      return;
-    BRepBuilderAPI_MakeEdge2d REM(RB2d, rb_1, rb_2);
-    if (!REM.IsDone())
-      return;
-    TopoDS_Edge LBE = LEM.Edge();
-    TopoDS_Edge RBE = REM.Edge();
-    if (LBE.IsNull() || RBE.IsNull())
-      return;
-    BRepBuilderAPI_MakeEdge PFEM(BRep_Tool::Pnt(LEM.Vertex1()), BRep_Tool::Pnt(REM.Vertex1()));
-    BRepBuilderAPI_MakeEdge PLEM(BRep_Tool::Pnt(LEM.Vertex2()), BRep_Tool::Pnt(REM.Vertex2()));
-    if (!PFEM.IsDone())
-      return;
-    if (!PLEM.IsDone())
-      return;
-    TopoDS_Edge FProfE = PFEM.Edge();
-    TopoDS_Edge SProfE = PLEM.Edge();
-    BRepBuilderAPI_MakeWire WM(FProfE, LBE, SProfE, RBE);
-    if (WM.IsDone())
+    TopoDS_Wire W = WM.Wire();
+    BRepLib::BuildCurves3d(W);
+    BRepBuilderAPI_MakeFace FM(Geom_Plane(gp::XOY()).Pln(), WM.Wire()); 
+    if (FM.IsDone())
     {
-      TopoDS_Wire W = WM.Wire();
-      BRepLib::BuildCurves3d(W);
-      BRepBuilderAPI_MakeFace FM(Geom_Plane(gp::XOY()).Pln(), WM.Wire()); 
-      if (FM.IsDone())
-      {
-        prsDef.myPrs2D = FM.Face();
-        prsDef.myLeftBank = LBE;
-        prsDef.myRightBank = RBE;
-        prsDef.myInlet = FProfE;
-        prsDef.myOutlet = SProfE;
-      }
+      prsDef.myPrs2D = FM.Face();
+      prsDef.myLeftBank = LBE;
+      prsDef.myRightBank = RBE;
+      prsDef.myInlet = FProfE;
+      prsDef.myOutlet = SProfE;
     }
-  }
+  }  
+}
+
+void reversePoints(std::vector<gp_Pnt2d>& points)
+{
+  std::reverse(points.begin(), points.end());
 }
 
 void HYDROData_StreamLinearInterpolation::Perform(const HYDROData_SequenceOfObjects& profiles,
@@ -386,7 +405,7 @@ void HYDROData_StreamLinearInterpolation::Perform(const HYDROData_SequenceOfObje
 
   Handle(Geom2d_Curve) Hax2d;
   PolyToCurve2d(hax, Hax2d);
-  if (Hax2d->IsClosed()) //can't be closed
+  if (hax->IsClosed() || Hax2d->IsClosed()) //can't be closed
   {
     if (warnings)
       warnings->push_back(hax->GetName().toStdString() + " is closed; abort");
@@ -394,8 +413,9 @@ void HYDROData_StreamLinearInterpolation::Perform(const HYDROData_SequenceOfObje
   }
 
   std::map<double, Handle(HYDROData_Profile)> InterParamToProf;
+  std::vector<bool> paramToSwapFlag;
   //profToInterParam is output param map: profile to intersection param on hydr.axis
-  InterProfilesAndHAX(profiles, Hax2d, InterParamToProf, warnings);
+  InterProfilesAndHAX(profiles, Hax2d, InterParamToProf, paramToSwapFlag, warnings);
   //
   std::vector<std::vector<gp_Pnt2d>> profilesPoints;
   profilesPoints.reserve(InterParamToProf.size());
@@ -427,14 +447,25 @@ void HYDROData_StreamLinearInterpolation::Perform(const HYDROData_SequenceOfObje
   std::vector<std::vector<double>> ParamsPerSegm;
   std::set<double>::iterator it_params_hax = paramsOnHAX.begin();
   std::map<double, Handle(HYDROData_Profile)>::iterator it_p = InterParamToProf.begin();
+  //
+  std::map<double, std::pair<Handle(HYDROData_Profile), Handle(HYDROData_Profile)>> intermParamToProfPair; //for warnings only
+  //
   it_p++; 
   ParamsPerSegm.resize(profilesPoints.size()-1);
   for( int k=0; it_p != InterParamToProf.end(); )
   {
     if (*it_params_hax < it_p->first)
     {
-      ParamsPerSegm[k].push_back(*it_params_hax);
-      it_params_hax++;     
+      double val = *it_params_hax;
+      ParamsPerSegm[k].push_back(val);
+      it_params_hax++;
+
+      it_p--;
+      const Handle(HYDROData_Profile)& cp = it_p->second;
+      it_p++;
+      const Handle(HYDROData_Profile)& np = it_p->second;
+      std::pair<Handle(HYDROData_Profile), Handle(HYDROData_Profile)> profPair(cp, np);
+      intermParamToProfPair[val] = profPair;
     }
     else
     {
@@ -444,7 +475,7 @@ void HYDROData_StreamLinearInterpolation::Perform(const HYDROData_SequenceOfObje
   }
   ParamsPerSegm.back().push_back(*paramsOnHAX.rbegin());
   //
-  std::map<double, std::pair<gp_Pnt2d, gp_Pnt2d>> parToBankPoints;
+  std::map<double, std::pair<IntRes2d_IntersectionPoint, IntRes2d_IntersectionPoint>> parToBankPoints;
   std::vector<double> paramHAXVec;
   paramHAXVec.reserve(paramsOnHAX.size());
   for( std::set<double>::iterator it = paramsOnHAX.begin(); it != paramsOnHAX.end(); ++it )
@@ -453,13 +484,16 @@ void HYDROData_StreamLinearInterpolation::Perform(const HYDROData_SequenceOfObje
   Handle(Geom2d_Curve) LB2d, RB2d;
   PolyToCurve2d(LB, LB2d);
   PolyToCurve2d(RB, RB2d);
-  GetPointsOnBanks( paramHAXVec, Hax2d, LB2d, RB2d, parToBankPoints, warnings);
+  GetPointsOnBanks( paramHAXVec, Hax2d, LB2d, RB2d, parToBankPoints, warnings, &intermParamToProfPair);
 
   if (buildPresentationShapes)
   {
-    Handle(HYDROData_Profile) F_prof = InterParamToProf.begin()->second;
-    Handle(HYDROData_Profile) S_prof = InterParamToProf.rbegin()->second;
-    BuildFace(F_prof, S_prof, LB2d, RB2d, prsDef);
+    //parToBankPoints.begin()->second.;
+    //double lp1 = parToBankPoints.rbegin()->first;
+
+    //Handle(HYDROData_Profile) F_prof = InterParamToProf.begin()->second;
+    //Handle(HYDROData_Profile) S_prof = InterParamToProf.rbegin()->second;
+    BuildFace(parToBankPoints, LB2d, RB2d, prsDef);
   }
   //
 
@@ -476,6 +510,24 @@ void HYDROData_StreamLinearInterpolation::Perform(const HYDROData_SequenceOfObje
     InsertPoints(profilesPoints[i], nbPointsToInsert);
   }
 
+  for (int i=0;i<profilesPoints.size();i++)
+  {
+    bool toSwap = paramToSwapFlag[i];     
+    if (toSwap)
+    {
+      std::vector<gp_Pnt2d>& prof = profilesPoints[i];
+      reversePoints(prof);
+    }
+  }
+
+  TopoDS_Compound cmp2d;
+  if ( buildPresentationShapes)
+  {
+    BRep_Builder().MakeCompound(cmp2d);
+    BRep_Builder().Add(cmp2d, prsDef.myLeftBank);
+    BRep_Builder().Add(cmp2d, prsDef.myRightBank);
+  }
+
   for (int i=0;i<profilesPoints.size()-1;i++)
   {
     const std::vector<gp_Pnt2d>& prof1 = profilesPoints[i];
@@ -520,9 +572,9 @@ void HYDROData_StreamLinearInterpolation::Perform(const HYDROData_SequenceOfObje
     {
       const std::vector<gp_Pnt2d>& im_prof = IntermProf[m];
       double param = it->second;
-      const std::pair<gp_Pnt2d, gp_Pnt2d>& BB = parToBankPoints[param]; //param is included in map; no checks
-      gp_Pnt2d LP = BB.first;
-      gp_Pnt2d RP = BB.second;
+      const std::pair<IntRes2d_IntersectionPoint, IntRes2d_IntersectionPoint>& BB = parToBankPoints[param]; //param is included in map; no checks
+      gp_Pnt2d LP = BB.first.Value();
+      gp_Pnt2d RP = BB.second.Value();
       HYDROData_ProfileUZ::PointsList pl;
       for (int k=0;k<im_prof.size();k++)
         pl.Append(im_prof[k].XY());
@@ -532,8 +584,26 @@ void HYDROData_StreamLinearInterpolation::Perform(const HYDROData_SequenceOfObje
         HYDROData_Bathymetry::AltitudePoint AP(profile_points3d(k).X(), profile_points3d(k).Y(), profile_points3d(k).Z());
         outBathypoints.push_back(AP);
       }
+      if (buildPresentationShapes)
+      {
+        if (m==0 || i == profilesPoints.size()-2 && param == indToParam.rbegin()->second) //if last prof1/prof2 segment => take a last profile too
+        {
+          BRepLib_MakePolygon PM;
+          for (int k=1;k<=profile_points3d.Length();k++)
+            PM.Add(gp_Pnt(profile_points3d(k)));
+          if (PM.IsDone())
+          {
+            const TopoDS_Wire& resW = PM.Wire();
+            BRep_Builder().Add(cmp2d, resW);
+          }
+        }
+      }
     }
   }
+  if (buildPresentationShapes)
+  {
+    prsDef.myPrs3D = cmp2d;
+  }
   //outBathy->SetAltitudePoints(bathypoints);
 }