Salome HOME
fix Lot19, interpolation on a new bathymetry for a mesh group
[modules/hydro.git] / src / HYDROData / HYDROData_Tool.cxx
old mode 100644 (file)
new mode 100755 (executable)
index 750b897..241131a
@@ -23,6 +23,7 @@
 #include <HYDROData_Iterator.h>
 #include <HYDROData_NaturalObject.h>
 #include <HYDROData_ShapesGroup.h>
+#include <HYDROData_PolylineXY.h>
 #include <QColor>
 #include <QFile>
 #include <QStringList>
@@ -46,8 +47,6 @@
 
 #include <BRepTools.hxx>
 #include <NCollection_Map.hxx>
-#include <TopExp_Explorer.hxx>
-#include <TopoDS_Face.hxx>
 #include <TopTools_ShapeMapHasher.hxx>
 #include <BRep_Builder.hxx>
 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 #include <NCollection_List.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 
+#include <BRepBuilderAPI_MakeFace.hxx>
+
+#include <TopExp_Explorer.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_HSequenceOfShape.hxx>
+
+#include <BRep_Builder.hxx>
+#include <BRepAlgo_FaceRestrictor.hxx>
+#include <BRepCheck_Analyzer.hxx>
+
+#include <ShapeAnalysis.hxx>
+#include <ShapeAnalysis_FreeBounds.hxx>
+
+#include <HYDROData_PolylineXY.h>
+#include <HYDROData_Polyline3D.h>
+#include <HYDROData_Bathymetry.h>
+#include <Geom_Line.hxx>
+#include <Geom2d_BSplineCurve.hxx>
+#include <Standard_Type.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
+#include <Geom2d_Line.hxx>
+#include <Geom_BSplineCurve.hxx>
+
+#include <GeomAPI.hxx>
+#include <gp.hxx>
+#include <Geom_Plane.hxx>
+#include <QFileInfo>
+#define BLOCK_SIZE 10000
+
+HYDROData_Tool::ExecStatus HYDROData_Tool::myTriangulationStatus = ExecStatus::None;
+
 static int aMaxNameId = INT_MAX;
 static int aMaxColorNb = 92000;
 void HYDROData_Tool::WriteStringsToFile( QFile&             theFile,
@@ -495,6 +525,422 @@ TopoDS_Shape HYDROData_Tool::RebuildCmp(const TopoDS_Shape& in)
   
 }
 
+TopoDS_Shape HYDROData_Tool::PolyXY2Face( const Handle(HYDROData_PolylineXY)& aPolyline )
+{
+  //DEBTRACE("generateTopShape");
+  TopoDS_Face aResultFace = TopoDS_Face(); // --- result: default = null face
+
+  if (!aPolyline.IsNull())
+    {
+      TopoDS_Shape aPolylineShape = aPolyline->GetShape();
+#ifdef DEB_IMZ
+      std::string brepName = "imz.brep";
+      BRepTools::Write(aPolylineShape, brepName.c_str());
+#endif
+      TopTools_ListOfShape aWiresList;
+
+      if (!aPolylineShape.IsNull() && aPolylineShape.ShapeType() == TopAbs_WIRE)
+        {
+          // --- only one wire: try to make a face
+          //DEBTRACE("one wire: try to build a face");
+          const TopoDS_Wire& aPolylineWire = TopoDS::Wire(aPolylineShape);
+          if (!aPolylineWire.IsNull())
+            {
+              BRepBuilderAPI_MakeFace aMakeFace(aPolylineWire, Standard_True);
+              aMakeFace.Build();
+              if (aMakeFace.IsDone())
+                {
+                  //DEBTRACE(" a face with the only wire given");
+                  aResultFace = aMakeFace.Face();
+                }
+            }
+        }
+      else
+        {
+          // --- a list of wires ? inventory of wires and edges
+          Handle(TopTools_HSequenceOfShape) aSeqWires = new TopTools_HSequenceOfShape;
+          Handle(TopTools_HSequenceOfShape) aSeqEdges = new TopTools_HSequenceOfShape;
+          TopExp_Explorer anExp(aPolylineShape, TopAbs_WIRE);
+          //DEBTRACE("list of wires ?");
+          for (; anExp.More(); anExp.Next())
+            {
+              if (!anExp.Current().IsNull())
+                {
+                  const TopoDS_Wire& aWire = TopoDS::Wire(anExp.Current());
+                  aWiresList.Append(aWire);
+                  //DEBTRACE("  append wire");
+                  TopExp_Explorer it2(aWire, TopAbs_EDGE);
+                  for (; it2.More(); it2.Next())
+                    aSeqEdges->Append(it2.Current());
+                }
+            }
+          if (aWiresList.IsEmpty())
+            return aResultFace; // --- no wires: null result
+
+          if (aSeqEdges->Length() > 1)
+            {
+              //DEBTRACE("try to connect all the edges together, build a unique wire and a face");
+              // --- try to create one wire by connecting edges with a distance tolerance (no necessity of sharing points)
+              ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdges, 1E-5, Standard_False, aSeqWires);
+
+              if (aSeqWires->Length() == 1)
+                {
+                  // --- one wire: try to make a face
+                  const TopoDS_Wire& aPolylineWire = TopoDS::Wire(aSeqWires->Value(1));
+                  if (!aPolylineWire.IsNull())
+                    {
+                      BRepBuilderAPI_MakeFace aMakeFace(aPolylineWire, Standard_True);
+                      aMakeFace.Build();
+                      if (aMakeFace.IsDone())
+                        {
+                          //DEBTRACE("  a face from all the wires connected");
+                          aResultFace = aMakeFace.Face();
+                        }
+                    }
+                }
+            }
+
+          if (aResultFace.IsNull())
+            {
+              //DEBTRACE("try to make a face with the first wire of the list and other wires as restrictions");
+              // --- try to make a face with the first wire of the list and other wires as restrictions
+              BRepAlgo_FaceRestrictor aFR;
+              TopoDS_Face aRefFace;
+              TopoDS_Shape aS = aWiresList.First();
+              BRepBuilderAPI_MakeFace aMakeFace(TopoDS::Wire(aWiresList.First()), Standard_True);
+              aMakeFace.Build();
+              if (aMakeFace.IsDone())
+                {
+                  //DEBTRACE("  a face with first wire");
+                  aRefFace = aMakeFace.Face();
+                }
+              if (!aRefFace.IsNull())
+                {
+                  aFR.Init(aRefFace, Standard_False, Standard_True);
+                  TopTools_ListIteratorOfListOfShape anIt(aWiresList);
+                  for (; anIt.More(); anIt.Next())
+                    {
+                      TopoDS_Wire& aWire = TopoDS::Wire(anIt.Value());
+                      if (aWire.IsNull())
+                        continue;
+                      aFR.Add(aWire);
+                    }
+                  aFR.Perform();
+                  if (aFR.IsDone())
+                    {
+                      for (; aFR.More(); aFR.Next())
+                        {
+                          //DEBTRACE("  a restricted face");
+                          aResultFace = aFR.Current();
+                          break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+  if (aResultFace.IsNull())
+    return aResultFace;
+
+  //DEBTRACE("check the face");
+  BRepCheck_Analyzer anAnalyzer(aResultFace);
+  if (anAnalyzer.IsValid() && aResultFace.ShapeType() == TopAbs_FACE)
+  {
+    //DEBTRACE("face OK");
+    return aResultFace;
+  }
+  else
+  {
+    //DEBTRACE("bad face");
+  }
+  return TopoDS_Face();
+}
+
+void HYDROData_Tool::SetSIProgress(const Handle(Message_ProgressIndicator)& thePI)
+{
+  StricklerInterpolationProgress() = thePI;
+}
+  
+const Handle(Message_ProgressIndicator)& HYDROData_Tool::GetSIProgress()
+{
+  return StricklerInterpolationProgress();
+}
+
+Handle(Message_ProgressIndicator)& HYDROData_Tool::StricklerInterpolationProgress()
+{
+  static Handle(Message_ProgressIndicator) aPI = NULL;
+  return aPI;
+}
+
+void HYDROData_Tool::SetZIProgress(const Handle(Message_ProgressIndicator)& thePI)
+{
+  BathymetryInterpolationProgress() = thePI;
+}
+  
+const Handle(Message_ProgressIndicator)& HYDROData_Tool::GetZIProgress()
+{
+  return BathymetryInterpolationProgress();
+}
+
+Handle(Message_ProgressIndicator)& HYDROData_Tool::BathymetryInterpolationProgress()
+{
+  static Handle(Message_ProgressIndicator) aPI = NULL;
+  return aPI;
+}
+
+void HYDROData_Tool::SetTriangulationStatus(const ExecStatus& theStatus)
+{
+  myTriangulationStatus = theStatus;
+}
+
+const HYDROData_Tool::ExecStatus& HYDROData_Tool::GetTriangulationStatus()
+{
+  return myTriangulationStatus;
+}
+
+static bool AddXYZ(bool bImportXY, 
+                   double x,
+                   double y, 
+                   double z,
+                   std::vector<gp_XYZ>& thePointsXYZ,
+                   std::vector<gp_XY>& thePointsXY)
+{
+  if (!bImportXY)
+  {
+    if ( HYDROData_Tool::IsNan( x ) || HYDROData_Tool::IsInf( x ) ||
+      HYDROData_Tool::IsNan( y ) || HYDROData_Tool::IsInf( y ) ||
+      HYDROData_Tool::IsNan( z ) || HYDROData_Tool::IsInf( z ) )
+      return false;
+
+    if( thePointsXYZ.size()>=thePointsXYZ.capacity() )
+      thePointsXYZ.reserve( thePointsXYZ.size()+BLOCK_SIZE );
+
+    thePointsXYZ.push_back(gp_XYZ(x,y,z));
+  }
+  else
+  {
+    if ( HYDROData_Tool::IsNan( x ) || HYDROData_Tool::IsInf( x ) ||
+      HYDROData_Tool::IsNan( y ) || HYDROData_Tool::IsInf( y ) )
+      return false;
+
+    if( thePointsXY.size()>=thePointsXY.capacity() )
+      thePointsXY.reserve( thePointsXY.size()+BLOCK_SIZE );
+
+    thePointsXY.push_back(gp_XY(x,y));
+  }
+  return true;
+}
+
+bool HYDROData_Tool::importFromXYZ( QString& theFileName,  
+                                    bool bImportXY, 
+                                    std::vector<gp_XYZ>& thePointsXYZ,
+                                    std::vector<gp_XY>& thePointsXY)
+{
+  QFile aFile( theFileName );
+  if ( !aFile.exists() || !aFile.open( QIODevice::ReadOnly ) )
+    return false;
+
+  QString aFileSuf = QFileInfo( aFile ).suffix().toLower();
+
+  double x,y;
+  if ( aFileSuf == "xyz" )
+  {
+    double z;
+    while ( !aFile.atEnd() )
+    {
+      std::string aLine = aFile.readLine().simplified().toStdString();
+      if ( aLine.empty() )
+        continue;
+
+      x = 0;
+      y = 0;
+      z = 0;
+
+      if( sscanf( aLine.c_str(), "%lf %lf %lf", &x, &y, &z )!=3 )
+      {
+        aFile.close();
+        return false;
+      }
+
+      if (!AddXYZ(bImportXY, x, y, z, thePointsXYZ, thePointsXY ))
+      {
+        aFile.close();
+        return false;
+      }
+    }
+  }
+  else if (aFileSuf == "xy" )
+  {
+    while ( !aFile.atEnd() )
+    {
+      std::string aLine = aFile.readLine().simplified().toStdString();
+      if ( aLine.empty() )
+        continue;
+
+      x = 0;
+      y = 0;
+
+      if( sscanf( aLine.c_str(), "%lf %lf", &x, &y )!=2 )
+      {
+        aFile.close();
+        return false;
+      }
+
+      if (!AddXYZ(true, x, y, 0, thePointsXYZ, thePointsXY ))
+      {
+        aFile.close();
+        return false;
+      }
+    }
+  }
+
+  aFile.close();
+
+  return true;
+}
+
+bool HYDROData_Tool::importPolylineFromXYZ(QString aFileName, Handle(HYDROData_Document) theDocument, 
+  bool importXY, NCollection_Sequence<Handle(HYDROData_Entity)>& importedEntities)
+{
+  if (importXY)
+  {
+    std::vector<gp_XY> aPoints2d;
+    std::vector<gp_XYZ> aDPoints3d;
+
+    if (HYDROData_Tool::importFromXYZ(aFileName, importXY, aDPoints3d, aPoints2d))
+    {
+      QString basename = QFileInfo( aFileName ).baseName();
+
+      Handle(HYDROData_PolylineXY) aPolylineXY = Handle(HYDROData_PolylineXY)::DownCast( theDocument->CreateObject( KIND_POLYLINEXY ) );
+      HYDROData_PolylineXY::SectionType aSectType = HYDROData_PolylineXY::SECTION_POLYLINE;    
+      bool IsClosed = false;
+      if ((aPoints2d.front()-aPoints2d.back()).Modulus()<Precision::Confusion())
+      {
+        IsClosed = true;
+        aPolylineXY->AddSection( TCollection_AsciiString("poly_section"), aSectType, true);
+      }
+      else
+        aPolylineXY->AddSection( TCollection_AsciiString("poly_section"), aSectType, false);
+
+      int n = aPoints2d.size();
+      if (IsClosed)
+        n--;
+
+      for ( int i = 0; i < n; i++ )
+      {
+        gp_XY aSectPoint = aPoints2d[i];
+        theDocument->Transform(aSectPoint, true);
+        aPolylineXY->AddPoint( 0, aSectPoint );
+      }      
+
+      aPolylineXY->SetWireColor( HYDROData_PolylineXY::DefaultWireColor() );
+      aPolylineXY->SetName( basename + "_PolyXY_" );
+      aPolylineXY->Update();
+      importedEntities.Append(aPolylineXY);
+      return true;
+    }
+    else 
+      return false;
+  }
+  else //xyz 
+  {
+    std::vector<gp_XY> aDPoints2d;
+    std::vector<gp_XYZ> aPoints3d;
+    if (HYDROData_Tool::importFromXYZ(aFileName, false, aPoints3d, aDPoints2d))
+    {
+      QString basename = QFileInfo( aFileName ).baseName();
+      Handle(HYDROData_PolylineXY) aPolylineXY = Handle(HYDROData_PolylineXY)::DownCast( theDocument->CreateObject( KIND_POLYLINEXY ) );
+      Handle(HYDROData_Polyline3D) aPolylineObj = Handle(HYDROData_Polyline3D)::DownCast( theDocument->CreateObject( KIND_POLYLINE ) );
+      Handle(HYDROData_Bathymetry) aBath = Handle(HYDROData_Bathymetry)::DownCast( theDocument->CreateObject( KIND_BATHYMETRY ) );
+      HYDROData_Bathymetry::AltitudePoints aAPoints;
+      HYDROData_PolylineXY::SectionType aSectType = HYDROData_PolylineXY::SECTION_POLYLINE;    
+      bool IsClosed = false;
+      if ((aPoints3d.front()-aPoints3d.back()).Modulus()<Precision::Confusion())
+      {
+        IsClosed = true;
+        aPolylineXY->AddSection( TCollection_AsciiString("poly_section"), aSectType, true);
+      }
+      else
+        aPolylineXY->AddSection( TCollection_AsciiString("poly_section"), aSectType, false);
+
+      int n = aPoints3d.size();
+      if (IsClosed)
+        n--;
+
+      for ( int i = 0; i < n; i++ )
+      {
+        gp_XY aSectPoint(aPoints3d[i].X(), aPoints3d[i].Y());
+        theDocument->Transform(aSectPoint, true);
+        aPolylineXY->AddPoint( 0, aSectPoint );
+        HYDROData_Bathymetry::AltitudePoint p;
+        p.X = aSectPoint.X();
+        p.Y = aSectPoint.Y();
+        p.Z = aPoints3d[i].Z();
+        aAPoints.push_back(p);
+      }
+
+      QString aBathName = basename + "_bath_";
+      QString aPolyXYName = basename + "_polyXY_";
+      QString aPoly3DName = basename + "_poly3D_";
+
+      aPolylineXY->SetName( aPolyXYName );
+      aPolylineXY->SetWireColor(HYDROData_PolylineXY::DefaultWireColor());
+      aPolylineXY->Update();
+
+      aBath->SetAltitudePoints(aAPoints);
+      aBath->SetName( aBathName );
+
+      aPolylineObj->SetPolylineXY (aPolylineXY, false);
+      aPolylineObj->SetAltitudeObject(aBath);
+
+      aPolylineObj->SetBorderColor( aPolylineObj->DefaultBorderColor() );
+      aPolylineObj->SetName( aPoly3DName );
+
+      aPolylineObj->Update();
+      importedEntities.Append(aPolylineXY);
+      importedEntities.Append(aPolylineObj);
+      return true;
+    }
+    else 
+      return false;
+  }
+}
+
+
+
+
+Handle(Geom2d_Curve) HYDROData_Tool::BRepAdaptorTo2DCurve( const BRepAdaptor_Curve& ad )
+{
+  if( ad.GetType() == GeomAbs_Line)
+  {
+    double f = ad.FirstParameter();
+    double l = ad.LastParameter();
+    return new Geom2d_TrimmedCurve( GeomAPI::To2d(ad.Curve().Curve(), Geom_Plane(gp::XOY()).Pln()), f, l );
+  }
+
+  if( ad.GetType() == GeomAbs_BSplineCurve )
+  {
+    Handle(Geom_BSplineCurve) aSpline = ad.Curve().BSpline();
+    if (aSpline.IsNull())
+      return Handle(Geom2d_Curve)();
+
+    return GeomAPI::To2d(aSpline, gp_Pln(gp::XOY()));
+
+   //TColgp_Array1OfPnt poles3d = aSpline->Poles();
+   //TColgp_HArray1OfPnt2d poles2d(poles3d.Lower(), poles3d.Upper());
+   //for (int i=poles3d.Lower(); i<=poles3d.Upper();i++)
+   //{
+   //  gp_XY p2d(poles3d(i).X(), poles3d(i).Y()); 
+   //  poles2d(i).SetXY(p2d);
+   //}
+   //const TColStd_Array1OfReal& knots = aSpline->Knots();
+   //const TColStd_Array1OfInteger& multiplicities = aSpline->Multiplicities();
+   //int aDegree = aSpline->Degree();
+   //return new Geom2d_BSplineCurve( poles2d, knots, multiplicities, aDegree );
+  }
+  return Handle(Geom2d_Curve)();
+}
 
 std::ostream& operator<<( std::ostream& theStream, const QString& theText )
 {