]> SALOME platform Git repositories - modules/hydro.git/commitdiff
Salome HOME
merge BR_v14_rc
authorPaul RASCLE <paul.rascle@edf.fr>
Mon, 24 Aug 2015 13:48:59 +0000 (15:48 +0200)
committerPaul RASCLE <paul.rascle@edf.fr>
Mon, 24 Aug 2015 13:48:59 +0000 (15:48 +0200)
29 files changed:
src/HYDROData/CMakeLists.txt
src/HYDROData/HYDROData_AltitudeObject.cxx
src/HYDROData/HYDROData_Bathymetry.cxx
src/HYDROData/HYDROData_Bathymetry.h
src/HYDROData/HYDROData_CalculationCase.cxx
src/HYDROData/HYDROData_Channel.cxx
src/HYDROData/HYDROData_ChannelAltitude.cxx [new file with mode: 0644]
src/HYDROData/HYDROData_ChannelAltitude.h [new file with mode: 0644]
src/HYDROData/HYDROData_Entity.cxx
src/HYDROData/HYDROData_Entity.h
src/HYDROData/HYDROData_IInterpolator.cxx
src/HYDROData/HYDROData_Iterator.cxx
src/HYDROData/HYDROData_Object.cxx
src/HYDROData/HYDROData_Object.h
src/HYDROData/HYDROData_Obstacle.cxx
src/HYDROData/HYDROData_ObstacleAltitude.cxx
src/HYDROData/HYDROData_Octree.cxx [new file with mode: 0644]
src/HYDROData/HYDROData_Octree.hxx [new file with mode: 0644]
src/HYDROData/HYDROData_OctreeNode.cxx [new file with mode: 0644]
src/HYDROData/HYDROData_OctreeNode.hxx [new file with mode: 0644]
src/HYDROData/HYDROData_Polyline3D.cxx
src/HYDROData/HYDROData_Quadtree.cxx [new file with mode: 0644]
src/HYDROData/HYDROData_Quadtree.hxx [new file with mode: 0644]
src/HYDROData/HYDROData_QuadtreeNode.cxx [new file with mode: 0644]
src/HYDROData/HYDROData_QuadtreeNode.hxx [new file with mode: 0644]
src/HYDROData/HYDROData_StreamAltitude.cxx
src/HYDROData/HYDROData_Tree.hxx [new file with mode: 0644]
src/HYDROData/HYDROData_Zone.cxx
src/HYDROData/HYDRO_trace.hxx [new file with mode: 0644]

index fd9899d428291a90221b1dbe83b150ef2d6c409a..4ce848b2fb309ff3b884f725e3aa55c18c916fbb 100644 (file)
@@ -1,6 +1,7 @@
 #include(../../CMake/Common.cmake)
 
 set(PROJECT_HEADERS
+    HYDRO_trace.hxx
     HYDROData.h
     HYDROData_AltitudeObject.h
     HYDROData_Application.h
@@ -9,6 +10,7 @@ set(PROJECT_HEADERS
     HYDROData_BSplineOperation.h
     HYDROData_CalculationCase.h
     HYDROData_Channel.h
+    HYDROData_ChannelAltitude.h
     HYDROData_Confluence.h
     HYDROData_Digue.h
     HYDROData_Document.h
@@ -50,6 +52,11 @@ set(PROJECT_HEADERS
     HYDROData_VisualState.h
     HYDROData_Warning.h
     HYDROData_Zone.h
+    HYDROData_Tree.hxx
+    HYDROData_Quadtree.hxx
+    HYDROData_QuadtreeNode.hxx
+    HYDROData_Octree.hxx
+    HYDROData_OctreeNode.hxx
     HYDROData_GeomTool.h
     HYDROData_IProfilesInterpolator.h
     HYDROData_LinearInterpolator.h
@@ -66,6 +73,7 @@ set(PROJECT_SOURCES
     HYDROData_BSplineOperation.cxx
     HYDROData_CalculationCase.cxx
     HYDROData_Channel.cxx
+    HYDROData_ChannelAltitude.cxx
     HYDROData_Confluence.cxx
     HYDROData_Digue.cxx
     HYDROData_Document.cxx
@@ -106,6 +114,10 @@ set(PROJECT_SOURCES
     HYDROData_Transform.cxx
     HYDROData_VisualState.cxx
     HYDROData_Zone.cxx
+    HYDROData_Quadtree.cxx
+    HYDROData_QuadtreeNode.cxx
+    HYDROData_Octree.cxx
+    HYDROData_OctreeNode.cxx
     HYDROData_GeomTool.cxx
     HYDROData_IProfilesInterpolator.cxx
     HYDROData_LinearInterpolator.cxx
index deac2dc0cf2d0bcd4970587c4361f63e0bc5d217..5c4edcb8ab02573cc8d77d9e25b115590e9a8c81 100644 (file)
@@ -21,6 +21,9 @@
 
 #include <QStringList>
 
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
 IMPLEMENT_STANDARD_HANDLE(HYDROData_AltitudeObject, HYDROData_IAltitudeObject)
 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_AltitudeObject, HYDROData_IAltitudeObject)
 
@@ -49,6 +52,7 @@ QStringList HYDROData_AltitudeObject::DumpToPython( MapOfTreatedObjects& theTrea
 
 double HYDROData_AltitudeObject::GetAltitudeForPoint( const gp_XY& thePoint ) const
 {
+  DEBTRACE("HYDROData_AltitudeObject::GetAltitudeForPoint");
   double aResAltitude = GetInvalidAltitude();
 
   return aResAltitude;
index e48d04ffd93f6e3eae9ced1edeb14187b0a66f12..2f09868e9f9dfed3c3c8cddb5cee210e6b6e498a 100644 (file)
 #include <OSD_Timer.hxx>
 #endif
 
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
 IMPLEMENT_STANDARD_HANDLE(HYDROData_Bathymetry, HYDROData_IAltitudeObject)
 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Bathymetry, HYDROData_IAltitudeObject)
 
+//HYDROData_QuadtreeNode* HYDROData_Bathymetry::myQuadtree = 0;
+std::map<int, HYDROData_QuadtreeNode*> HYDROData_Bathymetry::myQuadtrees;
+
 HYDROData_Bathymetry::HYDROData_Bathymetry()
 : HYDROData_IAltitudeObject()
 {
+  //DEBTRACE("HYDROData_Bathymetry constructor start " << this);
+//  if (! myQuadtree)
+//    myQuadtree = new HYDROData_QuadtreeNode(0, 30, 5, 0.);
+  //DEBTRACE("HYDROData_Bathymetry constructor end   " << this);
 }
 
 HYDROData_Bathymetry::~HYDROData_Bathymetry()
 {
+  //DEBTRACE("HYDROData_Bathymetry destructor start " << this);
+//  if (myQuadtree)
+//    delete myQuadtree;
+//     Nodes_3D::iterator it = myListOfNodes.begin();
+//     for( ; it != myListOfNodes.end(); ++it)
+//             delete *it;
+//    myListOfNodes.clear();
 }
 
 QStringList HYDROData_Bathymetry::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
@@ -130,14 +147,57 @@ HYDROData_Bathymetry::AltitudePoints HYDROData_Bathymetry::GetAltitudePoints(boo
   return aPoints;
 }
 
+HYDROData_QuadtreeNode* HYDROData_Bathymetry::GetQuadtreeNodes() const
+{
+  TDF_Label aLabel = myLab.FindChild(DataTag_AltitudePoints, false);
+  if (aLabel.IsNull())
+    return 0;
+  int labkey = myLab.Tag();
+  int altkey = aLabel.Tag();
+  //DEBTRACE("GetQuadtreeNodes this labkey altkey "<<this<<" "<<labkey<<" "<<altkey);
+//  if (myQuadtree->isEmpty() )
+  if (myQuadtrees.find(labkey) == myQuadtrees.end())
+    {
+      DEBTRACE("GetQuadtreeNodes init " << this << " " << labkey);
+      HYDROData_QuadtreeNode* aQuadtree = new HYDROData_QuadtreeNode(0, 30, 5, 0.);
+      myQuadtrees[labkey] = aQuadtree;
+      TDF_Label aLabel = myLab.FindChild(DataTag_AltitudePoints, false);
+      if (aLabel.IsNull())
+        return 0;
+
+      Handle(TDataStd_RealArray) aCoordsArray;
+      if (!aLabel.FindAttribute(TDataStd_RealArray::GetID(), aCoordsArray))
+        return 0;
+
+      Nodes_3D* aListOfNodes = new Nodes_3D();
+
+      for (int i = aCoordsArray->Lower(), n = aCoordsArray->Upper(); i <= n;)
+        {
+          if (i + 3 > n + 1)
+            break;
+
+          double x = aCoordsArray->Value(i++);
+          double y = aCoordsArray->Value(i++);
+          double z = aCoordsArray->Value(i++);
+          gp_XYZ* aPoint = new gp_XYZ(x, y, z);
+          aListOfNodes->push_back(aPoint);
+        }
+      DEBTRACE("  GetQuadtreeNodes call setNodesAndCompute");
+      aQuadtree->setNodesAndCompute(aListOfNodes);
+      return aQuadtree;
+    }
+  else
+    return myQuadtrees[labkey];
+}
+
 void HYDROData_Bathymetry::RemoveAltitudePoints()
 {
-  TDF_Label aLabel = myLab.FindChild( DataTag_AltitudePoints, false );
-  if ( !aLabel.IsNull() )
-  {
-    aLabel.ForgetAllAttributes();
-    SetToUpdate( true );
-  }
+  TDF_Label aLabel = myLab.FindChild(DataTag_AltitudePoints, false);
+  if (!aLabel.IsNull())
+    {
+      aLabel.ForgetAllAttributes();
+      SetToUpdate(true);
+    }
 }
 
 void interpolateAltitudeForPoints( const gp_XY&                               thePoint,
@@ -193,140 +253,171 @@ void interpolateAltitudeForPoints( const gp_XY&                               th
   theResPoint.SetZ( aResVal );
 }
 
-double HYDROData_Bathymetry::GetAltitudeForPoint( const gp_XY& thePoint ) const
+double HYDROData_Bathymetry::GetAltitudeForPoint(const gp_XY& thePoint) const
 {
+  DEBTRACE("GetAltitudeForPoint p(" << thePoint.X() << ", " << thePoint.Y() << ")");
   double anInvalidAltitude = GetInvalidAltitude();
   double aResAltitude = anInvalidAltitude;
-  
-  AltitudePoints anAltitudePoints = GetAltitudePoints();
-  if ( anAltitudePoints.IsEmpty() )
-    return aResAltitude;
-
-  QPolygonF aBoundingRect;
-
-  // Boundary plane
-  // [ 0 (top-left) ]          [ 1 (top-right) ]
-  //                  thePoint
-  // [ 2 (bot-left) ]          [ 3 (bot-right) ] 
-  AltitudePoint aBounds[ 4 ] = { AltitudePoint( -DBL_MAX, -DBL_MAX, anInvalidAltitude ),
-                                 AltitudePoint(  DBL_MAX, -DBL_MAX, anInvalidAltitude ),
-                                 AltitudePoint( -DBL_MAX,  DBL_MAX, anInvalidAltitude ),
-                                 AltitudePoint(  DBL_MAX,  DBL_MAX, anInvalidAltitude ) }; 
 
-  AltitudePoints::Iterator anIter( anAltitudePoints );
-  for ( ; anIter.More(); anIter.Next() )
-  {
-    const AltitudePoint& aPoint = anIter.Value();
-
-    double aDeltaX = Abs( aPoint.X() ) - Abs( thePoint.X() );
-    double aDeltaY = Abs( aPoint.Y() ) - Abs( thePoint.Y() );
+  HYDROData_QuadtreeNode* aQuadtree = GetQuadtreeNodes();
+  if (!aQuadtree)
+    {
+      DEBTRACE("  no Quadtree");
+      return aResAltitude;
+    }
 
-    if ( ValuesEquals( aDeltaX, 0.0 ) ) // Both left and right sides
+  std::map<double, const gp_XYZ*> dist2nodes;
+  aQuadtree->NodesAround(thePoint, dist2nodes, aQuadtree->getPrecision());
+  while (dist2nodes.size() == 0)
     {
-      if ( ValuesEquals( aDeltaY, 0.0 ) ) // Both top and bottom sides
-      {
-        aResAltitude = aPoint.Z();
-        return aResAltitude;
-      }
-      else if ( aDeltaY < 0 ) // top side
-      {
-        // top border
-        if ( ValuesMoreEquals( aPoint.X(), aBounds[ 0 ].X() ) && ValuesMoreEquals( aPoint.Y(), aBounds[ 0 ].Y() ) )
-          aBounds[ 0 ] = aPoint;
-        if ( ValuesLessEquals( aPoint.X(), aBounds[ 1 ].X() ) && ValuesMoreEquals( aPoint.Y(), aBounds[ 1 ].Y() ) )
-          aBounds[ 1 ] = aPoint;
-      }
-      else
-      {
-        // bottom border
-        if ( ValuesMoreEquals( aPoint.X(), aBounds[ 2 ].X() ) && ValuesLessEquals( aPoint.Y(), aBounds[ 2 ].Y() ) )
-          aBounds[ 2 ] = aPoint;
-        if ( ValuesLessEquals( aPoint.X(), aBounds[ 3 ].X() ) && ValuesLessEquals( aPoint.Y(), aBounds[ 3 ].Y() ) )
-          aBounds[ 3 ] = aPoint;
-      }
+      aQuadtree->setPrecision(aQuadtree->getPrecision() *2);
+      DEBTRACE("adjust precision to: " << aQuadtree->getPrecision());
+      aQuadtree->NodesAround(thePoint, dist2nodes, aQuadtree->getPrecision());
     }
-    else if ( aDeltaX < 0 ) // left side
+  aQuadtree->NodesAround(thePoint, dist2nodes, 5.0);
+  if (dist2nodes.size())
     {
-      if ( ValuesEquals( aDeltaY, 0.0 ) )
-      {
-        // Left border
-        if ( ValuesMoreEquals( aPoint.X(), aBounds[ 0 ].X() ) && ValuesMoreEquals( aPoint.Y(), aBounds[ 0 ].Y() ) )
-          aBounds[ 0 ] = aPoint;
-        if ( ValuesMoreEquals( aPoint.X(), aBounds[ 2 ].X() ) && ValuesLessEquals( aPoint.Y(), aBounds[ 2 ].Y() ) )
-          aBounds[ 2 ] = aPoint;
-      }
-      else if ( aDeltaY < 0 )
-      {
-        // top left corner
-        if ( ValuesMoreEquals( aPoint.X(), aBounds[ 0 ].X() ) && ValuesMoreEquals( aPoint.Y(), aBounds[ 0 ].Y() ) )
-          aBounds[ 0 ] = aPoint;
-      }
-      else
-      {
-        // bottom left corner
-        if ( ValuesMoreEquals( aPoint.X(), aBounds[ 2 ].X() ) && ValuesLessEquals( aPoint.Y(), aBounds[ 2 ].Y() ) )
-          aBounds[ 2 ] = aPoint;
-      }
+      std::map<double, const gp_XYZ*>::const_iterator it = dist2nodes.begin();
+      aResAltitude = it->second->Z();
+      DEBTRACE("  number of points found: " << dist2nodes.size() << " nearest z: " << aResAltitude);
     }
-    else // right side
+  else
     {
-      if ( ValuesEquals( aDeltaY, 0.0 ) )
-      {
-        // Right border
-        if ( ValuesLessEquals( aPoint.X(), aBounds[ 1 ].X() ) && ValuesMoreEquals( aPoint.Y(), aBounds[ 1 ].Y() ) )
-          aBounds[ 1 ] = aPoint;
-        if ( ValuesLessEquals( aPoint.X(), aBounds[ 3 ].X() ) && ValuesLessEquals( aPoint.Y(), aBounds[ 3 ].Y() ) )
-          aBounds[ 3 ] = aPoint;
-      }
-      else if ( aDeltaY < 0 )
-      {
-        // top right corner
-        if ( ValuesLessEquals( aPoint.X(), aBounds[ 1 ].X() ) && ValuesMoreEquals( aPoint.Y(), aBounds[ 1 ].Y() ) )
-          aBounds[ 1 ] = aPoint;
-      }
-      else
-      {
-        // bottom right corner
-        if ( ValuesLessEquals( aPoint.X(), aBounds[ 3 ].X() ) && ValuesLessEquals( aPoint.Y(), aBounds[ 3 ].Y() ) )
-          aBounds[ 3 ] = aPoint;
-      }
+      DEBTRACE("  number of points found: 0");
     }
 
-    // Update bounding rectangle of our global grid
-    aBoundingRect << QPointF( aPoint.X(), aPoint.Y() );
-  }
-
-  const double LIMIT = 1E300;
-  if( fabs( aBounds[ 0 ].X() ) > LIMIT || fabs( aBounds[ 0 ].Y() ) > LIMIT ||
-      fabs( aBounds[ 1 ].X() ) > LIMIT || fabs( aBounds[ 1 ].Y() ) > LIMIT ||
-      fabs( aBounds[ 2 ].X() ) > LIMIT || fabs( aBounds[ 2 ].Y() ) > LIMIT ||
-      fabs( aBounds[ 3 ].X() ) > LIMIT || fabs( aBounds[ 3 ].Y() ) > LIMIT )
-    return anInvalidAltitude;
-
-
-  // Check if requested point is inside of our bounding rectangle
-  if ( !aBoundingRect.boundingRect().contains( thePoint.X(), thePoint.Y() ) )
-    return aResAltitude;
-
-  // Calculate result altitude for point
-  AltitudePoint aFirstPoint( aBounds[ 0 ] ), aSecPoint( aBounds[ 1 ] );
-
-  // At first we merge top and bottom borders
-  if ( aBounds[ 0 ].Y() != aBounds[ 2 ].Y() || aBounds[ 0 ].X() != aBounds[ 2 ].X() )
-    interpolateAltitudeForPoints( thePoint, aBounds[ 0 ], aBounds[ 2 ], aFirstPoint, true );
-
-  if ( aBounds[ 1 ].Y() != aBounds[ 3 ].Y() || aBounds[ 1 ].X() != aBounds[ 3 ].X() )
-    interpolateAltitudeForPoints( thePoint, aBounds[ 1 ], aBounds[ 3 ], aSecPoint, true );
-
-  AltitudePoint aResPoint( aFirstPoint );
-
-  // At last we merge left and right borders
-  if ( aFirstPoint.Y() != aSecPoint.Y() || aFirstPoint.X() != aSecPoint.X() )
-    interpolateAltitudeForPoints( thePoint, aFirstPoint, aSecPoint, aResPoint, false );
-    
-  aResAltitude = aResPoint.Z();
-
   return aResAltitude;
+  
+
+//  AltitudePoints anAltitudePoints = GetAltitudePoints();
+//  if ( anAltitudePoints.IsEmpty() )
+//    return aResAltitude;
+//
+//  QPolygonF aBoundingRect;
+//
+//  // Boundary plane
+//  // [ 0 (top-left) ]          [ 1 (top-right) ]
+//  //                  thePoint
+//  // [ 2 (bot-left) ]          [ 3 (bot-right) ]
+//  AltitudePoint aBounds[ 4 ] = { AltitudePoint( -DBL_MAX, -DBL_MAX, anInvalidAltitude ),
+//                                 AltitudePoint(  DBL_MAX, -DBL_MAX, anInvalidAltitude ),
+//                                 AltitudePoint( -DBL_MAX,  DBL_MAX, anInvalidAltitude ),
+//                                 AltitudePoint(  DBL_MAX,  DBL_MAX, anInvalidAltitude ) };
+//
+//  AltitudePoints::Iterator anIter( anAltitudePoints );
+//  for ( ; anIter.More(); anIter.Next() )
+//  {
+//    const AltitudePoint& aPoint = anIter.Value();
+//
+//    double aDeltaX = Abs( aPoint.X() ) - Abs( thePoint.X() );
+//    double aDeltaY = Abs( aPoint.Y() ) - Abs( thePoint.Y() );
+//
+//    if ( ValuesEquals( aDeltaX, 0.0 ) ) // Both left and right sides
+//    {
+//      if ( ValuesEquals( aDeltaY, 0.0 ) ) // Both top and bottom sides
+//      {
+//        aResAltitude = aPoint.Z();
+//        return aResAltitude;
+//      }
+//      else if ( aDeltaY < 0 ) // top side
+//      {
+//        // top border
+//        if ( ValuesMoreEquals( aPoint.X(), aBounds[ 0 ].X() ) && ValuesMoreEquals( aPoint.Y(), aBounds[ 0 ].Y() ) )
+//          aBounds[ 0 ] = aPoint;
+//        if ( ValuesLessEquals( aPoint.X(), aBounds[ 1 ].X() ) && ValuesMoreEquals( aPoint.Y(), aBounds[ 1 ].Y() ) )
+//          aBounds[ 1 ] = aPoint;
+//      }
+//      else
+//      {
+//        // bottom border
+//        if ( ValuesMoreEquals( aPoint.X(), aBounds[ 2 ].X() ) && ValuesLessEquals( aPoint.Y(), aBounds[ 2 ].Y() ) )
+//          aBounds[ 2 ] = aPoint;
+//        if ( ValuesLessEquals( aPoint.X(), aBounds[ 3 ].X() ) && ValuesLessEquals( aPoint.Y(), aBounds[ 3 ].Y() ) )
+//          aBounds[ 3 ] = aPoint;
+//      }
+//    }
+//    else if ( aDeltaX < 0 ) // left side
+//    {
+//      if ( ValuesEquals( aDeltaY, 0.0 ) )
+//      {
+//        // Left border
+//        if ( ValuesMoreEquals( aPoint.X(), aBounds[ 0 ].X() ) && ValuesMoreEquals( aPoint.Y(), aBounds[ 0 ].Y() ) )
+//          aBounds[ 0 ] = aPoint;
+//        if ( ValuesMoreEquals( aPoint.X(), aBounds[ 2 ].X() ) && ValuesLessEquals( aPoint.Y(), aBounds[ 2 ].Y() ) )
+//          aBounds[ 2 ] = aPoint;
+//      }
+//      else if ( aDeltaY < 0 )
+//      {
+//        // top left corner
+//        if ( ValuesMoreEquals( aPoint.X(), aBounds[ 0 ].X() ) && ValuesMoreEquals( aPoint.Y(), aBounds[ 0 ].Y() ) )
+//          aBounds[ 0 ] = aPoint;
+//      }
+//      else
+//      {
+//        // bottom left corner
+//        if ( ValuesMoreEquals( aPoint.X(), aBounds[ 2 ].X() ) && ValuesLessEquals( aPoint.Y(), aBounds[ 2 ].Y() ) )
+//          aBounds[ 2 ] = aPoint;
+//      }
+//    }
+//    else // right side
+//    {
+//      if ( ValuesEquals( aDeltaY, 0.0 ) )
+//      {
+//        // Right border
+//        if ( ValuesLessEquals( aPoint.X(), aBounds[ 1 ].X() ) && ValuesMoreEquals( aPoint.Y(), aBounds[ 1 ].Y() ) )
+//          aBounds[ 1 ] = aPoint;
+//        if ( ValuesLessEquals( aPoint.X(), aBounds[ 3 ].X() ) && ValuesLessEquals( aPoint.Y(), aBounds[ 3 ].Y() ) )
+//          aBounds[ 3 ] = aPoint;
+//      }
+//      else if ( aDeltaY < 0 )
+//      {
+//        // top right corner
+//        if ( ValuesLessEquals( aPoint.X(), aBounds[ 1 ].X() ) && ValuesMoreEquals( aPoint.Y(), aBounds[ 1 ].Y() ) )
+//          aBounds[ 1 ] = aPoint;
+//      }
+//      else
+//      {
+//        // bottom right corner
+//        if ( ValuesLessEquals( aPoint.X(), aBounds[ 3 ].X() ) && ValuesLessEquals( aPoint.Y(), aBounds[ 3 ].Y() ) )
+//          aBounds[ 3 ] = aPoint;
+//      }
+//    }
+//
+//    // Update bounding rectangle of our global grid
+//    aBoundingRect << QPointF( aPoint.X(), aPoint.Y() );
+//  }
+//
+//  const double LIMIT = 1E300;
+//  if( fabs( aBounds[ 0 ].X() ) > LIMIT || fabs( aBounds[ 0 ].Y() ) > LIMIT ||
+//      fabs( aBounds[ 1 ].X() ) > LIMIT || fabs( aBounds[ 1 ].Y() ) > LIMIT ||
+//      fabs( aBounds[ 2 ].X() ) > LIMIT || fabs( aBounds[ 2 ].Y() ) > LIMIT ||
+//      fabs( aBounds[ 3 ].X() ) > LIMIT || fabs( aBounds[ 3 ].Y() ) > LIMIT )
+//    return anInvalidAltitude;
+//
+//
+//  // Check if requested point is inside of our bounding rectangle
+//  if ( !aBoundingRect.boundingRect().contains( thePoint.X(), thePoint.Y() ) )
+//    return aResAltitude;
+//
+//  // Calculate result altitude for point
+//  AltitudePoint aFirstPoint( aBounds[ 0 ] ), aSecPoint( aBounds[ 1 ] );
+//
+//  // At first we merge top and bottom borders
+//  if ( aBounds[ 0 ].Y() != aBounds[ 2 ].Y() || aBounds[ 0 ].X() != aBounds[ 2 ].X() )
+//    interpolateAltitudeForPoints( thePoint, aBounds[ 0 ], aBounds[ 2 ], aFirstPoint, true );
+//
+//  if ( aBounds[ 1 ].Y() != aBounds[ 3 ].Y() || aBounds[ 1 ].X() != aBounds[ 3 ].X() )
+//    interpolateAltitudeForPoints( thePoint, aBounds[ 1 ], aBounds[ 3 ], aSecPoint, true );
+//
+//  AltitudePoint aResPoint( aFirstPoint );
+//
+//  // At last we merge left and right borders
+//  if ( aFirstPoint.Y() != aSecPoint.Y() || aFirstPoint.X() != aSecPoint.X() )
+//    interpolateAltitudeForPoints( thePoint, aFirstPoint, aSecPoint, aResPoint, false );
+//
+//  aResAltitude = aResPoint.Z();
+//
+//  return aResAltitude;
 }
 
 void HYDROData_Bathymetry::SetFilePath( const TCollection_AsciiString& theFilePath )
index 5c3551997e1ba8ec082dd48654cfe3726f97cb9e..d33a35231fe1fcfffcb8737d22f3e8940797a140 100644 (file)
@@ -20,6 +20,7 @@
 #define HYDROData_Bathymetry_HeaderFile
 
 #include "HYDROData_IAltitudeObject.h"
+#include "HYDROData_QuadtreeNode.hxx"
 
 class QFile;
 class gp_XYZ;
@@ -82,6 +83,7 @@ public:
    * \return points list
    */
   HYDRODATA_EXPORT virtual AltitudePoints   GetAltitudePoints(bool IsConvertToGlobal = false) const;
+  HYDRODATA_EXPORT virtual HYDROData_QuadtreeNode* GetQuadtreeNodes() const;
 
   /**
    * Remove all altitude points.
@@ -141,6 +143,7 @@ private:
    */
   bool                                      importFromXYZFile( QFile&          theFile,
                                                                AltitudePoints& thePoints ) const;
+  static std::map<int, HYDROData_QuadtreeNode*> myQuadtrees;
 
   bool                                      importFromASCFile( QFile&          theFile,
                                                                AltitudePoints& thePoints ) const;
index be8f1a8bc754b1ae72501518a4222e840f5c55e3..4f95d9ec0f293286a81437d81e3412a4655dac6e 100644 (file)
 
 #define EXPORT_NAME "HYDRO_" + GetName()
 
+#include <SALOME_NamingService.hxx>
+#include <SALOME_LifeCycleCORBA.hxx>
+
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
 IMPLEMENT_STANDARD_HANDLE(HYDROData_CalculationCase, HYDROData_Entity)
 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_CalculationCase, HYDROData_Entity)
 
@@ -370,6 +376,7 @@ void HYDROData_CalculationCase::CreateRegionsAuto( const Handle(HYDROData_Docume
                                                    const HYDROData_SplitToZonesTool::SplitDataList& theZones,
                                                    const bool theLandCover )
 {
+  DEBTRACE("HYDROData_CalculationCase::CreateRegionsAuto");
   QMap<QString, Handle(HYDROData_Region)> aRegionsMap; //object name to region
   QMap<QString, QString> aRegionNameToObjNameMap;
   QString aZonesPref = theLandCover ? CALCULATION_LANDCOVER_ZONES_PREF : CALCULATION_ZONES_PREF;
@@ -413,6 +420,7 @@ void HYDROData_CalculationCase::CreateRegionsAuto( const Handle(HYDROData_Docume
     if ( !theLandCover ) {
       Handle(HYDROData_Object) aMergeObject = Handle(HYDROData_Object)::DownCast( aMergeEntity );
       if ( !aMergeObject.IsNull() ) {
+       DEBTRACE("aMergeEntity " << aMergeEntity->GetName().toStdString());
         aMergeEntity = aMergeObject->GetAltitudeObject();
       }
     }
@@ -792,10 +800,20 @@ double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY&
   Handle(HYDROData_Zone) aZone = GetZoneFromPoint( thePoint, false );
   if ( !aZone.IsNull() )
   {
+    //DEBTRACE("GetAltitudeForPoint Region " << theRegion->GetName().toStdString() << " Zone " << aZone->GetName().toStdString());
     Handle(HYDROData_Region) aRefRegion = Handle(HYDROData_Region)::DownCast( aZone->GetFatherObject() );
     if ( IsEqual( aRefRegion, theRegion ) )
       aResAltitude = GetAltitudeForPoint( thePoint, aZone );
+    else
+      {
+        DEBTRACE("GetAltitudeForPoint Region " << aRefRegion->GetName().toStdString() << " Zone " << aZone->GetName().toStdString() << " ---------------------------");
+        aResAltitude = GetAltitudeForPoint( thePoint, aZone );
+      }
   }
+  else
+    {
+      DEBTRACE(" --- GetAltitudeForPoint No Zone ---");
+    }
 
   return aResAltitude;
 }
@@ -803,17 +821,24 @@ double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY&
 double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY&                  thePoint,
                                                        const Handle(HYDROData_Zone)& theZone ) const
 {
+  //DEBTRACE("GetAltitudeForPoint Zone " << theZone->GetName().toStdString());
   double aResAltitude = HYDROData_IAltitudeObject::GetInvalidAltitude();
   if ( theZone.IsNull() )
+  {
+       DEBTRACE("Zone nulle");
     return aResAltitude;
+  }
 
   HYDROData_Zone::MergeType aZoneMergeType = theZone->GetMergeType();
+  //DEBTRACE("aZoneMergeType " << aZoneMergeType);
   if ( !theZone->IsMergingNeed() )
   {
     aZoneMergeType = HYDROData_Zone::Merge_UNKNOWN;
+    //DEBTRACE("---");
   }
   else if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
   {
+       DEBTRACE("GetAltitudeForPoint Zone " << theZone->GetName().toStdString() << " Merge_UNKNOWN");
     return aResAltitude;
   }
 
@@ -826,15 +851,20 @@ double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY&
     {
       if ( aZoneInterpolator != NULL )
       {
+       DEBTRACE("aZoneInterpolator != NULL");
         aZoneInterpolator->SetAltitudeObject( aMergeAltitude );
         aResAltitude = aZoneInterpolator->GetAltitudeForPoint( thePoint );
       }
       else
+      {
+       DEBTRACE("aZoneInterpolator == NULL");
         aResAltitude = aMergeAltitude->GetAltitudeForPoint( thePoint );
+      }
     }
   }
   else
   {
+       //DEBTRACE("aZoneMergeType != HYDROData_Zone::Merge_Object");
     HYDROData_SequenceOfObjects aZoneObjects = theZone->GetObjects();
     HYDROData_SequenceOfObjects::Iterator anIter( aZoneObjects );
     for ( ; anIter.More(); anIter.Next() )
@@ -851,11 +881,15 @@ double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY&
       double aPointAltitude = 0.0;
       if ( aZoneInterpolator != NULL )
       {
+       DEBTRACE("aZoneInterpolator != NULL");
         aZoneInterpolator->SetAltitudeObject( anObjAltitude );
         aPointAltitude = aZoneInterpolator->GetAltitudeForPoint( thePoint );
       }
       else
+      {
+       //DEBTRACE("aZoneInterpolator == NULL");
         aPointAltitude = anObjAltitude->GetAltitudeForPoint( thePoint );
+      }
 
       if ( ValuesEquals( aPointAltitude, HYDROData_IAltitudeObject::GetInvalidAltitude() ) )
         continue;
@@ -891,6 +925,7 @@ NCollection_Sequence<double> HYDROData_CalculationCase::GetAltitudesForPoints(
   const NCollection_Sequence<gp_XY>& thePoints,
   const Handle(HYDROData_Region)&    theRegion ) const
 {
+  //DEBTRACE("HYDROData_CalculationCase::GetAltitudesForPoints " << theRegion->GetName().toStdString());
   NCollection_Sequence<double> aResSeq;
 
   for ( int i = 1, n = thePoints.Length(); i <= n; ++i )
index a2bb6f47f942b7eff54e58cfebe2fd0067187877..841359413c29366c227a79411a3c3c5d674b853e 100644 (file)
@@ -59,7 +59,7 @@
 #include <TopoDS_Wire.hxx>
 #include <TopoDS_Vertex.hxx>
 
-//#define DEB_CHANNEL 1
+#define DEB_CHANNEL 1
 #ifdef DEB_CHANNEL
 #include <BRepTools.hxx>
 #endif
@@ -67,6 +67,9 @@
 #include <QColor>
 #include <QStringList>
 
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
 IMPLEMENT_STANDARD_HANDLE(HYDROData_Channel,HYDROData_ArtificialObject)
 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Channel,HYDROData_ArtificialObject)
 
@@ -139,8 +142,14 @@ bool HYDROData_Channel::CreatePresentations( const Handle(HYDROData_Polyline3D)&
   }
 
 #ifdef DEB_CHANNEL
-  BRepTools::Write( aPathWire, "guideline.brep" );
-  BRepTools::Write( aProfileWire, "profile.brep" );
+  std::string brepName = "guideline_";
+  brepName += theGuideLine->GetName().toStdString();
+  brepName += ".brep";
+  BRepTools::Write( aPathWire, brepName.c_str() );
+  brepName = "profile_";
+  brepName += theGuideLine->GetName().toStdString();
+  brepName += ".brep";
+  BRepTools::Write( aProfileWire, brepName.c_str() );
 #endif
 
   // Pre-processing
@@ -456,6 +465,7 @@ void HYDROData_Channel::RemoveProfile()
 
 ObjectKind HYDROData_Channel::getAltitudeObjectType() const
 {
-  return KIND_OBSTACLE_ALTITUDE;
+  DEBTRACE("HYDROData_Channel::getAltitudeObjectType");
+  return KIND_CHANNEL_ALTITUDE;
 }
 
diff --git a/src/HYDROData/HYDROData_ChannelAltitude.cxx b/src/HYDROData/HYDROData_ChannelAltitude.cxx
new file mode 100644 (file)
index 0000000..413685f
--- /dev/null
@@ -0,0 +1,330 @@
+// Copyright (C) 2014-2015  EDF-R&D
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "HYDROData_ChannelAltitude.h"
+
+#include "HYDROData_Document.h"
+#include "HYDROData_Object.h"
+#include "HYDROData_Channel.h"
+#include "HYDROData_Projection.h"
+#include "HYDROData_Polyline3D.h"
+#include "HYDROData_PolylineXY.h"
+#include "HYDROData_ProfileUZ.h"
+#include "HYDROData_Profile.h"
+
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+#include <QString>
+
+#include <BRepBuilderAPI_MakeVertex.hxx>
+#include <BRepExtrema_DistShapeShape.hxx>
+
+#include <Precision.hxx>
+#include <TopAbs.hxx>
+#include <TopExp.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopAbs_ShapeEnum.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepTools.hxx>
+#include <Geom_Curve.hxx>
+
+#include <gp_Trsf.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+
+IMPLEMENT_STANDARD_HANDLE(HYDROData_ChannelAltitude, HYDROData_IAltitudeObject)
+IMPLEMENT_STANDARD_RTTIEXT(HYDROData_ChannelAltitude, HYDROData_IAltitudeObject)
+
+HYDROData_ChannelAltitude::HYDROData_ChannelAltitude()
+: HYDROData_IAltitudeObject()
+{
+}
+
+HYDROData_ChannelAltitude::~HYDROData_ChannelAltitude()
+{
+}
+
+double HYDROData_ChannelAltitude::GetAltitudeForPoint( const gp_XY& thePoint ) const
+{
+  DEBTRACE("GetAltitudeForPoint p(" << thePoint.X() << ", " << thePoint.Y() << ")");
+  double aResAltitude = GetInvalidAltitude();
+
+  Handle(HYDROData_Channel) aChannel =
+  Handle(HYDROData_Channel)::DownCast(GetFatherObject());
+  if (aChannel.IsNull())
+    {
+      DEBTRACE("aChannel.IsNull()");
+      return aResAltitude;
+    }
+  DEBTRACE("aChannel: " << aChannel->GetName().toStdString());
+
+  Handle(HYDROData_Polyline3D) aGuideLine = aChannel->GetGuideLine();
+  if (aGuideLine.IsNull())
+    {
+      DEBTRACE("aGuideLine.IsNull()");
+      return aResAltitude;
+    }
+  //DEBTRACE("aGuideLine: " << aGuideLine->GetName().toStdString());
+
+  Handle(HYDROData_PolylineXY) aGuideXY = aGuideLine->GetPolylineXY();
+  if (aGuideXY.IsNull())
+    {
+      DEBTRACE("aGuideXY.IsNull()");
+      return aResAltitude;
+    }
+  //DEBTRACE("aGuideXY: " << aGuideXY->GetName().toStdString());
+
+  Handle(HYDROData_ProfileUZ) aGuideUZ = aGuideLine->GetProfileUZ();
+  if (aGuideUZ.IsNull())
+    {
+      aGuideUZ = aGuideLine->GetChildProfileUZ(); // profile obtained from bathymetry
+    }
+  if (aGuideUZ.IsNull())
+    {
+      DEBTRACE("aGuideUZ.IsNull()");
+      return aResAltitude;
+    }
+  //DEBTRACE("aGuideUZ: " << aGuideUZ->GetName().toStdString());
+
+  Handle (HYDROData_Profile) aProfile = aChannel->GetProfile();
+  if (aProfile.IsNull())
+    {
+      return aResAltitude;
+    }
+  //DEBTRACE("aProfile: " << aProfile->GetName().toStdString());
+
+  // --- See GEOMImpl_ProjectionDriver.cxx
+
+  TopoDS_Shape aShape =  aGuideXY->GetShape();
+  gp_Pnt P1(thePoint.X(), thePoint.Y(), 0);
+  TopoDS_Shape aPoint = BRepBuilderAPI_MakeVertex(P1).Shape();
+
+  if (aPoint.IsNull() || aShape.IsNull())
+    {
+      DEBTRACE("aPoint.IsNull() || aShape.IsNull()");
+      return aResAltitude;
+    }
+
+  if (aShape.ShapeType() != TopAbs_EDGE && aShape.ShapeType() != TopAbs_WIRE)
+    {
+      DEBTRACE("Projection aborted : the shape is neither an edge nor a wire");
+      return aResAltitude;
+    }
+
+  // Perform projection.
+  BRepExtrema_DistShapeShape aDistShSh(aPoint, aShape, Extrema_ExtFlag_MIN);
+
+  if (aDistShSh.IsDone() == Standard_False)
+    {
+      DEBTRACE("Projection not done");
+      return aResAltitude;
+    }
+
+  Standard_Boolean hasValidSolution = Standard_False;
+  Standard_Integer aNbSolutions = aDistShSh.NbSolution();
+  Standard_Integer i;
+  double aParam = 0.;
+  Standard_Real aTolConf = BRep_Tool::Tolerance(TopoDS::Vertex(aPoint));
+  Standard_Real aTolAng = 1.e-4;
+
+  for (i = 1; i <= aNbSolutions; i++)
+    {
+      Standard_Boolean isValid = Standard_False;
+      BRepExtrema_SupportType aSupportType = aDistShSh.SupportTypeShape2(i);
+      TopoDS_Shape aSupportShape = aDistShSh.SupportOnShape2(i);
+
+      if (aSupportType == BRepExtrema_IsOnEdge)
+        {
+          // Minimal distance inside edge is really a projection.
+          isValid = Standard_True;
+          aDistShSh.ParOnEdgeS2(i, aParam);
+        }
+      else if (aSupportType == BRepExtrema_IsVertex)
+        {
+          TopExp_Explorer anExp(aShape, TopAbs_EDGE);
+
+          if (aDistShSh.Value() <= aTolConf)
+            {
+              // The point lies on the shape. This means this point
+              // is really a projection.
+              for (; anExp.More() && !isValid; anExp.Next())
+                {
+                  TopoDS_Edge aCurEdge = TopoDS::Edge(anExp.Current());
+
+                  if (aCurEdge.IsNull() == Standard_False)
+                    {
+                      TopoDS_Vertex aVtx[2];
+
+                      TopExp::Vertices(aCurEdge, aVtx[0], aVtx[1]);
+
+                      for (int j = 0; j < 2; j++)
+                        {
+                          if (aSupportShape.IsSame(aVtx[j]))
+                            {
+                              // The current edge is a projection edge.
+                              isValid = Standard_True;
+                              aSupportShape = aCurEdge;
+                              aParam = BRep_Tool::Parameter(aVtx[j], aCurEdge);
+                              break;
+                            }
+                        }
+                    }
+                }
+            }
+          else
+            {
+              // Minimal distance to vertex is not always a real projection.
+              gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aPoint));
+              gp_Pnt aPrjPnt = BRep_Tool::Pnt(TopoDS::Vertex(aSupportShape));
+              gp_Vec aDProjP(aPrjPnt, aPnt);
+
+              for (; anExp.More() && !isValid; anExp.Next())
+                {
+                  TopoDS_Edge aCurEdge = TopoDS::Edge(anExp.Current());
+
+                  if (aCurEdge.IsNull() == Standard_False)
+                    {
+                      TopoDS_Vertex aVtx[2];
+
+                      TopExp::Vertices(aCurEdge, aVtx[0], aVtx[1]);
+
+                      for (int j = 0; j < 2; j++)
+                        {
+                          if (aSupportShape.IsSame(aVtx[j]))
+                            {
+                              // Check if the point is a projection to the current edge.
+                              Standard_Real anEdgePars[2];
+                              Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aCurEdge, anEdgePars[0], anEdgePars[1]);
+                              gp_Pnt aVal;
+                              gp_Vec aD1;
+
+                              aParam = BRep_Tool::Parameter(aVtx[j], aCurEdge);
+                              aCurve->D1(aParam, aVal, aD1);
+
+                              if (Abs(aD1.Dot(aDProjP)) <= aTolAng)
+                                {
+                                  // The current edge is a projection edge.
+                                  isValid = Standard_True;
+                                  aSupportShape = aCurEdge;
+                                  break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+      if (isValid)
+        {
+          if (hasValidSolution)
+            {
+              DEBTRACE("Projection aborted : multiple solutions");
+              return aResAltitude;
+            }
+
+          // Store the valid solution.
+          hasValidSolution = Standard_True;
+
+          // profile altitude at projection point
+          HYDROData_IPolyline::PointsList aProfilePoints = aGuideUZ->GetPoints();
+          if ( aProfilePoints.IsEmpty() )
+            {
+              DEBTRACE("empty profile UZ");
+              return aResAltitude;
+            }
+          double aDepth = HYDROData_ProfileUZ::GetDepthFromDistance( aProfilePoints, aParam );
+          //DEBTRACE("profile altitude: " << aDepth);
+
+          // Compute edge index.
+          TopExp_Explorer anExp(aShape, TopAbs_EDGE);
+          int anIndex = 0;
+          for (; anExp.More(); anExp.Next(), anIndex++)
+            {
+              if (aSupportShape.IsSame(anExp.Current()))
+                {
+                  break;
+                }
+            }
+
+          // get the XY distance from point to guideline
+          const gp_Pnt &aPntProj = aDistShSh.PointOnShape2(i);
+          //DEBTRACE("projection: (" << aPntProj.X() << ", " << aPntProj.Y() << ", " << aPntProj.Z() << ")");
+          gp_XY aProjXY = gp_XY(aPntProj.X(), aPntProj.Y());
+          aProjXY.Subtract(thePoint);
+          double distance = aProjXY.Modulus();
+          //DEBTRACE("distance to guideline " << distance);
+
+          // get delta altitude on section (supposed symmetric) from guideline distance (aParam)
+          double delta = 0;
+          int i1 = 0;
+          gp_XY pt1 = gp_XY();
+          gp_XY pt2 = gp_XY();
+          HYDROData_ProfileUZ::PointsList aSectionPoints = aProfile->GetParametricPoints();
+          for ( int i = 1, aNbPoints = aSectionPoints.Size(); i <= aNbPoints; ++i )
+            {
+              const HYDROData_IPolyline::Point& aPolylinePoint = aSectionPoints.Value( i );
+              //DEBTRACE("  profile point: " << aPolylinePoint.X() << " " << aPolylinePoint.Y());
+              if (aPolylinePoint.X() < distance)
+                {
+                  i1 = i;
+                  pt1 = aPolylinePoint;
+                }
+              if (aPolylinePoint.X() >= distance)
+                {
+                  pt2 = aPolylinePoint;
+                  break;
+                }
+            }
+          if ((i1 == 0) && (distance > 0))
+            {
+              DEBTRACE("Projection aborted : non centered profile");
+              return aResAltitude;
+            }
+          if (i1 == aProfilePoints.Size()) // distance >= profile width
+            {
+              delta = pt1.Y();
+            }
+          else
+            {
+              delta = pt1.Y() + (pt2.Y() - pt1.Y())*(distance -pt1.X())/(pt2.X()-pt1.X());
+            }
+          aResAltitude = delta + aDepth;
+          DEBTRACE("distance XY: "<< aParam << " distance to guideline: " << distance << " final altitude: " << aResAltitude << " delta: " << delta);
+          return aResAltitude;
+        }
+    }
+
+  if (!hasValidSolution)
+    {
+      DEBTRACE("Projection aborted : no projection");
+      return aResAltitude;
+    }
+
+  return aResAltitude;
+}
+
+
+
+
diff --git a/src/HYDROData/HYDROData_ChannelAltitude.h b/src/HYDROData/HYDROData_ChannelAltitude.h
new file mode 100644 (file)
index 0000000..0eb7b70
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright (C) 2014-2015  EDF-R&D
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef HYDROData_ChannelAltitude_HeaderFile
+#define HYDROData_ChannelAltitude_HeaderFile
+
+
+#include "HYDROData_IAltitudeObject.h"
+
+
+DEFINE_STANDARD_HANDLE(HYDROData_ChannelAltitude, HYDROData_IAltitudeObject)
+
+
+/**\class HYDROData_ChannelAltitude
+ * \brief Class that stores/retrieves information about the Channel altitude.
+ *
+ */
+class HYDROData_ChannelAltitude : public HYDROData_IAltitudeObject
+{
+protected:
+
+  /**
+   * Enumeration of tags corresponding to the persistent object parameters.
+   */
+  enum DataTag
+  {
+    DataTag_First = HYDROData_IAltitudeObject::DataTag_First + 100, ///< first tag, to reserve
+  };
+
+public:
+
+  DEFINE_STANDARD_RTTI(HYDROData_ChannelAltitude);
+
+  /**
+   * Returns the kind of this object. 
+   */
+  HYDRODATA_EXPORT virtual const ObjectKind GetKind() const { return KIND_CHANNEL_ALTITUDE; }
+
+public:      
+
+  // Public methods to work with altitudes.
+
+  /**
+   * Returns altitude for given point.
+   * \param thePoint the point to examine
+   * \return altitude value
+   */
+  HYDRODATA_EXPORT virtual double           GetAltitudeForPoint( const gp_XY& thePoint ) const;
+
+protected:
+
+  friend class HYDROData_Iterator;
+
+  /**
+   * Creates new object in the internal data structure. Use higher level objects 
+   * to create objects with real content.
+   */
+  HYDRODATA_EXPORT HYDROData_ChannelAltitude();
+
+  /**
+   * Destructs properties of the object and object itself, removes it from the document.
+   */
+  HYDRODATA_EXPORT  ~HYDROData_ChannelAltitude();
+};
+
+#endif
index bd47a0901b01a77cefa535af91340f540d39da8c..ac0c59620697b369915318c24728f6f98c711215 100644 (file)
@@ -38,6 +38,9 @@
 #include <QStringList>
 #include <QVariant>
 
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
 static const Standard_GUID GUID_MUST_BE_UPDATED("80f2bb81-3873-4631-8ddd-940d2119f000");
 
 IMPLEMENT_STANDARD_HANDLE(HYDROData_Entity,MMgt_TShared)
@@ -572,6 +575,7 @@ QStringList HYDROData_Entity::dumpObjectCreation( MapOfTreatedObjects& theTreate
 
 QString HYDROData_Entity::getPyTypeID() const
 {
+  DEBTRACE("HYDROData_Entity::getPyTypeID " << GetKind());
   switch( GetKind() )
   {
     case KIND_IMAGE:             return "KIND_IMAGE";
@@ -601,6 +605,7 @@ QString HYDROData_Entity::getPyTypeID() const
     case KIND_OBSTACLE_ALTITUDE: return "KIND_OBSTACLE_ALTITUDE";
     case KIND_STRICKLER_TABLE:   return "KIND_STRICKLER_TABLE";
     case KIND_LAND_COVER:        return "KIND_LAND_COVER";
+    case KIND_CHANNEL_ALTITUDE:  return "KIND_CHANNEL_ALTITUDE";
     default:                     return "KIND_UNKNOWN"; ///! Unrecognized object
   }
 }
index 8e4937291bcf518b08e967f2bba8e24f7cf72ca9..8661f3e212fb9ca5e214f27f282105c320911300 100644 (file)
@@ -65,7 +65,8 @@ const ObjectKind KIND_STREAM_ALTITUDE   = 24;
 const ObjectKind KIND_OBSTACLE_ALTITUDE = 25;
 const ObjectKind KIND_STRICKLER_TABLE   = 26;
 const ObjectKind KIND_LAND_COVER        = 27;
-const ObjectKind KIND_LAST              = KIND_LAND_COVER;
+const ObjectKind KIND_CHANNEL_ALTITUDE  = 28;
+const ObjectKind KIND_LAST              = KIND_CHANNEL_ALTITUDE;
 
 DEFINE_STANDARD_HANDLE(HYDROData_Entity, MMgt_TShared)
 
index 72344d9009331b50252b6ccf70e619d4aba93960..d80375117dc2980e87e16b794710a609c3649610 100644 (file)
@@ -20,6 +20,9 @@
 
 #include <gp_XY.hxx>
 
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
 HYDROData_IInterpolator::HYDROData_IInterpolator()
 {
 }
@@ -42,11 +45,13 @@ Handle(HYDROData_IAltitudeObject) HYDROData_IInterpolator::GetAltitudeObject() c
 double HYDROData_IInterpolator::GetAltitudeForPoint( 
   const double theCoordX, const double theCoordY ) const
 {
+  DEBTRACE("HYDROData_IInterpolator::GetAltitudeForPoint");
   return myAltitudeObject.IsNull() ? HYDROData_IAltitudeObject::GetInvalidAltitude() :
          myAltitudeObject->GetAltitudeForPoint( gp_XY( theCoordX, theCoordY ) );
 }
 
 double HYDROData_IInterpolator::GetAltitudeForPoint( const gp_XY& thePoint ) const
 {
+  DEBTRACE("HYDROData_IInterpolator::GetAltitudeForPoint");
   return GetAltitudeForPoint( thePoint.X(), thePoint.Y() );
-}
\ No newline at end of file
+}
index a52f932836fc2536b5be1dc6cba83c9ea9cc86c2..beec42dc5ca864249e2c8999eb0f96aa110a6974 100644 (file)
@@ -30,6 +30,7 @@
 #include "HYDROData_ImmersibleZone.h"
 #include "HYDROData_Obstacle.h"
 #include "HYDROData_ObstacleAltitude.h"
+#include "HYDROData_ChannelAltitude.h"
 #include "HYDROData_Polyline3D.h"
 #include "HYDROData_PolylineXY.h"
 #include "HYDROData_Profile.h"
@@ -49,6 +50,9 @@
 
 #include <NCollection_DataMap.hxx>
 
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
 //! Returns label by root objects kind and the kind of the object
 static TDF_Label GetLabelByKind(TDF_Label theRoot, ObjectKind theKind)
 {
@@ -128,6 +132,7 @@ Handle(HYDROData_Entity) HYDROData_Iterator::Object( const TDF_Label& theLabel )
   
   switch( aKind )
   {
+    DEBTRACE("HYDROData_Iterator::Object " << aKind);
     case KIND_IMAGE:              aResult = new HYDROData_Image();                break;
     case KIND_POLYLINE:           aResult = new HYDROData_Polyline3D();           break;
     case KIND_BATHYMETRY:         aResult = new HYDROData_Bathymetry();           break;
@@ -153,6 +158,7 @@ Handle(HYDROData_Entity) HYDROData_Iterator::Object( const TDF_Label& theLabel )
     case KIND_OBSTACLE_ALTITUDE:  aResult = new HYDROData_ObstacleAltitude();     break;
     case KIND_STRICKLER_TABLE:    aResult = new HYDROData_StricklerTable();       break;
     case KIND_LAND_COVER:         aResult = new HYDROData_LandCover();            break;
+    case KIND_CHANNEL_ALTITUDE:   aResult = new HYDROData_ChannelAltitude();      break;
     default:                                                                      break;
   }
 
index 25b9e2625187447f1a6a2ad224eb99c530b2da13..6a8ee297c192992bf666164f6d383a04a2c74673 100644 (file)
 
 #include <TopoDS_Shape.hxx>
 #include <TDataStd_Integer.hxx>
+#include <TDataStd_Real.hxx>
 
 #include <QColor>
 
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
 IMPLEMENT_STANDARD_HANDLE(HYDROData_Object,HYDROData_Entity)
 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Object,HYDROData_Entity)
 
@@ -299,6 +303,7 @@ void HYDROData_Object::checkAndSetAltitudeObject()
   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
 
   ObjectKind anAltitudeObjectType = getAltitudeObjectType();
+  DEBTRACE("HYDROData_Object::checkAndSetAltitudeObject anAltitudeObjectType="<< anAltitudeObjectType);
   if ( anAltitudeObjectType == KIND_UNKNOWN )
     return; // No need to create altitude object
 
@@ -313,6 +318,7 @@ void HYDROData_Object::checkAndSetAltitudeObject()
       HYDROData_Iterator::CreateObject( aChildLabel, anAltitudeObjectType ) );
 
   QString anAltitudePref = GetName() + "_Altitude";
+  DEBTRACE("anAltitudePref " << anAltitudePref.toStdString());
   QString anAltitudeName = HYDROData_Tool::GenerateObjectName( aDocument, anAltitudePref );
   anAltitudeObject->SetName( anAltitudeName );
 
index 520a70ab3515a41ea4d248f438fc6c70d821ae74..56e1c4a02159acd577083c0a8060fdac92d3e931 100644 (file)
@@ -99,7 +99,6 @@ public:
    */
   HYDRODATA_EXPORT virtual TopoDS_Shape GetShape3D() const = 0;
 
-  
   /**
    * Returns reference object which represent the 3D shape of object.
    */
index 1218bbc4ed6ae14e24c8b08e8b6bca2439eca375..00f332b94b1c497d7ebecca0e5902b9d3c0595fd 100644 (file)
@@ -57,6 +57,9 @@
 
 #include <HYDROData_Projection.h>
 
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
 IMPLEMENT_STANDARD_HANDLE(HYDROData_Obstacle,HYDROData_ArtificialObject)
 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Obstacle,HYDROData_ArtificialObject)
 
@@ -470,6 +473,7 @@ QColor HYDROData_Obstacle::getDefaultBorderColor() const
 
 ObjectKind HYDROData_Obstacle::getAltitudeObjectType() const
 {
+  DEBTRACE("HYDROData_Obstacle::getAltitudeObjectType");
   return KIND_OBSTACLE_ALTITUDE;
 }
 
index f8d56d9ffe2d41718d12ae1917b6a1c3f520dd34..a91e835968edd9402bfb5223371e7a5f551fde80 100644 (file)
 #include "HYDROData_Object.h"
 #include "HYDROData_Projection.h"
 
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+#include <QString>
+
 #include <Precision.hxx>
 
 #include <TopoDS_Shape.hxx>
+#include <BRepTools.hxx>
 
 IMPLEMENT_STANDARD_HANDLE(HYDROData_ObstacleAltitude, HYDROData_IAltitudeObject)
 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_ObstacleAltitude, HYDROData_IAltitudeObject)
@@ -40,23 +45,36 @@ HYDROData_ObstacleAltitude::~HYDROData_ObstacleAltitude()
 
 double HYDROData_ObstacleAltitude::GetAltitudeForPoint( const gp_XY& thePoint ) const
 {
+  DEBTRACE("HYDROData_ObstacleAltitude::GetAltitudeForPoint");
   double aResAltitude = GetInvalidAltitude();
 
   Handle(HYDROData_Object) anObject =
     Handle(HYDROData_Object)::DownCast( GetFatherObject() );
   if ( anObject.IsNull() )
+  {
+       DEBTRACE("anObject.IsNull()");
     return aResAltitude;
+  }
+//  DEBTRACE("object: " << anObject->GetName().toStdString());
 
   TopoDS_Shape anObjectShape3D = anObject->GetShape3D();
   if ( anObjectShape3D.IsNull() )
+  {
+       DEBTRACE("anObjectShape3D.IsNull()");
     return aResAltitude;
+  }
+//  else
+//  {
+//     DEBTRACE("anObjectShape3D type " << anObjectShape3D.ShapeType());
+//     BRepTools::Write(anObjectShape3D, "digue3D.brep");
+//  }
 
   HYDROData_Make3dMesh aMesher3D( anObjectShape3D, Precision::Intersection() );
 
   gp_Pnt aHighestPoint;
   if ( aMesher3D.GetHighestOriginal( thePoint.X(), thePoint.Y(), aHighestPoint ) )
     aResAltitude = aHighestPoint.Z();
-
+  DEBTRACE("aResAltitude=" << aResAltitude);
   return aResAltitude;
 }
 
diff --git a/src/HYDROData/HYDROData_Octree.cxx b/src/HYDROData/HYDROData_Octree.cxx
new file mode 100644 (file)
index 0000000..2db14da
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  HYDRO  HYDROData_Octree : Octree implementation (from SMESH module)
+//  File      : HYDROData_Octree.cxx
+//  Created   : Tue Jan 16 16:00:00 2007
+//  Author    : Nicolas Geimer & Aurélien Motteux(OCC)
+//  Module    : HYDROData
+//
+#include "HYDROData_Octree.hxx"
+
+/*!
+ * Constructor. limit must be provided at tree root construction.
+ * limit will be deleted by HYDROData_Octree.
+ */
+HYDROData_Octree::HYDROData_Octree(HYDROData_TreeLimit* limit) :
+    TBaseTree(limit)
+{
+}
+
+/*!
+ * \brief Allocate a bndbox according to childIndex. childIndex is zero based
+ */
+Bnd_B3d* HYDROData_Octree::newChildBox(int childIndex) const
+{
+  gp_XYZ min = getBox()->CornerMin();
+  gp_XYZ max = getBox()->CornerMax();
+  gp_XYZ HSize = (max - min) / 2.;
+  gp_XYZ childHsize = HSize / 2.;
+
+  gp_XYZ minChild(min.X() + childIndex % 2 * HSize.X(),
+                  min.Y() + (childIndex % 4) / 2 * HSize.Y(),
+                  min.Z() + (childIndex >= 4) * HSize.Z());
+
+  return new Bnd_B3d(minChild + childHsize, childHsize);
+}
+
+/*!
+ * \brief Compute the bigger dimension of my box
+ */
+double HYDROData_Octree::maxSize() const
+{
+  if (getBox() && !getBox()->IsVoid())
+    {
+      gp_XYZ min = getBox()->CornerMin();
+      gp_XYZ max = getBox()->CornerMax();
+      gp_XYZ Size = (max - min);
+      double returnVal = (Size.X() > Size.Y()) ? Size.X() : Size.Y();
+      return (returnVal > Size.Z()) ? returnVal : Size.Z();
+    }
+  return 0.;
+}
diff --git a/src/HYDROData/HYDROData_Octree.hxx b/src/HYDROData/HYDROData_Octree.hxx
new file mode 100644 (file)
index 0000000..1ad44c6
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  HYDRO HYDROData_Octree : Octree implementation (from SMESH module)
+//  File      : HYDROData_Octree.hxx
+//  Created   : Tue Jan 16 16:00:00 2007
+//  Author    : Nicolas Geimer & Aurélien Motteux (OCC)
+//  Module    : HYDROData
+//
+#ifndef _HYDROData_OCTREE_HXX_
+#define _HYDROData_OCTREE_HXX_
+
+#include <Standard.hxx>
+#include <Standard_Macro.hxx>
+
+#include "HYDROData_Tree.hxx"
+#include <Bnd_B3d.hxx>
+
+//================================================================================
+
+/*!
+ * \brief 3D tree of anything.
+ * Methods to implement in a descendant are:
+ * - Bnd_B3d*       buildRootBox(); // box of the whole tree
+ * - descendant*    newChild() const; // a new child instance
+ * - void           buildChildrenData(); // Fill in data of the children
+ */
+class Standard_EXPORT HYDROData_Octree: public HYDROData_Tree<Bnd_B3d, 8>
+{
+public:
+  typedef HYDROData_Tree<Bnd_B3d, 8> TBaseTree;
+
+  //! Constructor. limit must be provided at tree root construction.
+  //! limit will be deleted by HYDROData_Octree
+  HYDROData_Octree(HYDROData_TreeLimit* limit = 0);
+  virtual ~HYDROData_Octree() {};
+
+  //! Compute the biggest dimension of my box
+  double maxSize() const;
+
+  //! Return index of a child the given point is in
+  inline static int getChildIndex(double x, double y, double z, const gp_XYZ& boxMiddle)
+  {
+    return (x > boxMiddle.X()) + (y > boxMiddle.Y()) * 2 + (z > boxMiddle.Z()) * 4;
+  };
+
+protected:
+
+  //! Allocate a bndbox according to childIndex. childIndex is zero based
+  virtual Bnd_B3d* newChildBox(int childIndex) const;
+};
+
+#endif
diff --git a/src/HYDROData/HYDROData_OctreeNode.cxx b/src/HYDROData/HYDROData_OctreeNode.cxx
new file mode 100644 (file)
index 0000000..9be8911
--- /dev/null
@@ -0,0 +1,446 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  HYDRO HYDROData_OctreeNode : Octree with Nodes set (from SMESH module)
+//  inherites class HYDROData_Octree
+//  File      : HYDROData_OctreeNode.cxx
+//  Created   : Tue Jan 16 16:00:00 2007
+//  Author    : Nicolas Geimer & Aurelien Motteux (OCC)
+//  Module    : HYDROData
+//
+#include "HYDROData_OctreeNode.hxx"
+
+//#include "SMDS_SetIterator.hxx"
+//#include "HYDROData_TypeDefs.hxx"
+#include <gp_Pnt.hxx>
+
+using namespace std;
+
+//===============================================================
+/*!
+ * \brief Constructor : Build all the Octree using Compute()
+ * \param theNodes - Set of nodes, the Octree is built from this nodes
+ * \param maxLevel - Maximum level for the leaves
+ * \param maxNbNodes - Maximum number of nodes, a leaf can contain
+ * \param minBoxSize - Minimal size of the Octree Box
+ */
+//================================================================
+
+HYDROData_OctreeNode::HYDROData_OctreeNode (const Nodes3D& theNodes, const int maxLevel,
+                                            const int maxNbNodes , const double minBoxSize )
+  :HYDROData_Octree( new Limit( maxLevel,minBoxSize,maxNbNodes)),
+   myNodes(theNodes)
+{
+  compute();
+}
+
+//================================================================================
+/*!
+ * \brief Constructor used to allocate a child
+ */
+//================================================================================
+
+HYDROData_OctreeNode::HYDROData_OctreeNode ():HYDROData_Octree()
+{
+       myNodes.clear();
+}
+
+//================================================================================
+/*!
+ * \brief Return max number of nodes in a tree leaf
+ */
+//================================================================================
+
+int HYDROData_OctreeNode::getMaxNbNodes() const
+{
+  return ((Limit*)myLimit)->myMaxNbNodes;
+}
+
+//==================================================================================
+/*!
+ * \brief Construct an empty HYDROData_OctreeNode used by HYDROData_Octree::buildChildren()
+ */
+//==================================================================================
+
+HYDROData_Octree* HYDROData_OctreeNode::newChild() const
+{
+  return new HYDROData_OctreeNode();
+}
+
+//======================================
+/*!
+ * \brief Compute the first bounding box
+ *
+ * We take the max/min coord of the nodes
+ */
+//======================================
+
+Bnd_B3d* HYDROData_OctreeNode::buildRootBox()
+{
+  Bnd_B3d* box = new Bnd_B3d;
+  Nodes3D::iterator it = myNodes.begin();
+  for (; it != myNodes.end(); it++) {
+    const gp_XYZ* n1 = *it;
+    gp_XYZ p1(*n1);
+    box->Add(p1);
+  }
+  if ( myNodes.size() <= getMaxNbNodes() )
+    myIsLeaf = true;
+
+  return box;
+}
+
+//====================================================================================
+/*!
+ * \brief Tells us if Node is inside the current box with the precision "precision"
+ * \param Node - Node
+ * \param precision - The box is enlarged with this precision
+ * \retval bool - True if Node is in the box within precision
+ */
+//====================================================================================
+
+const bool HYDROData_OctreeNode::isInside (const gp_XYZ& p, const double precision)
+{
+  if (precision <= 0.)
+    return !(getBox()->IsOut(p));
+  Bnd_B3d BoxWithPrecision = *getBox();
+  BoxWithPrecision.Enlarge(precision);
+  return ! BoxWithPrecision.IsOut(p);
+}
+
+//================================================
+/*!
+ * \brief Set the data of the children
+ * Shares the father's data with each of his child
+ */
+//================================================
+void HYDROData_OctreeNode::buildChildrenData()
+{
+  gp_XYZ min = getBox()->CornerMin();
+  gp_XYZ max = getBox()->CornerMax();
+  gp_XYZ mid = (min + max)/2.;
+
+  Nodes3D::iterator it = myNodes.begin();
+  while (it != myNodes.end())
+  {
+    const gp_XYZ* n1 = *it;
+    int ChildBoxNum = getChildIndex( n1->X(), n1->Y(), n1->Z(), mid );
+    HYDROData_OctreeNode* myChild = dynamic_cast<HYDROData_OctreeNode*> (myChildren[ChildBoxNum]);
+    myChild->myNodes.push_back(n1);
+    myNodes.erase( it );
+    it = myNodes.begin();
+  }
+  for (int i = 0; i < 8; i++)
+  {
+    HYDROData_OctreeNode* myChild = dynamic_cast<HYDROData_OctreeNode*> (myChildren[i]);
+    if ( myChild->myNodes.size() <= getMaxNbNodes() )
+      myChild->myIsLeaf = true;
+  }
+}
+
+//===================================================================
+/*!
+ * \brief Return in Result a list of Nodes potentials to be near Node
+ * \param Node - Node
+ * \param precision - precision used
+ * \param Result - list of Nodes potentials to be near Node
+ */
+//====================================================================
+void HYDROData_OctreeNode::NodesAround (const Node3D* Node,
+                                        list<const Node3D*>* Result,
+                                        const double precision)
+{
+  gp_XYZ p(*Node);
+  if (isInside(p, precision))
+  {
+    if (isLeaf())
+    {
+      Result->insert(Result->end(), myNodes.begin(), myNodes.end());
+    }
+    else
+    {
+      for (int i = 0; i < 8; i++)
+      {
+        HYDROData_OctreeNode* myChild = dynamic_cast<HYDROData_OctreeNode*> (myChildren[i]);
+        myChild->NodesAround(Node, Result, precision);
+      }
+    }
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Return in dist2Nodes nodes mapped to their square distance from Node
+ *  \param node - node to find nodes closest to
+ *  \param dist2Nodes - map of found nodes and their distances
+ *  \param precision - radius of a sphere to check nodes inside
+ *  \retval bool - true if an exact overlapping found !!!
+ */
+//================================================================================
+
+bool HYDROData_OctreeNode::NodesAround(const gp_XYZ &node,
+                                       map<double, const Node3D*>& dist2Nodes,
+                                       double precision)
+{
+  if ( !dist2Nodes.empty() )
+    precision = min ( precision, sqrt( dist2Nodes.begin()->first ));
+  else if ( precision == 0. )
+    precision = maxSize() / 2;
+
+  if (isInside(node, precision))
+  {
+    if (!isLeaf())
+    {
+      // first check a child containing node
+      gp_XYZ mid = (getBox()->CornerMin() + getBox()->CornerMax()) / 2.;
+      int nodeChild  = getChildIndex( node.X(), node.Y(), node.Z(), mid );
+      if ( ((HYDROData_OctreeNode*) myChildren[nodeChild])->NodesAround(node, dist2Nodes, precision))
+        return true;
+      
+      for (int i = 0; i < 8; i++)
+        if ( i != nodeChild )
+          if (((HYDROData_OctreeNode*) myChildren[i])->NodesAround(node, dist2Nodes, precision))
+            return true;
+    }
+    else if ( NbNodes() > 0 )
+    {
+      double minDist = precision * precision;
+      Nodes3D::iterator nIt = myNodes.begin();
+      for ( ; nIt != myNodes.end(); ++nIt )
+      {
+       const gp_XYZ* p = *nIt;
+        gp_XYZ p2( *p );
+        double dist2 = ( node - p2 ).SquareModulus();
+        if ( dist2 < minDist )
+          dist2Nodes.insert( make_pair( minDist = dist2, &p2 ));
+      }
+//       if ( dist2Nodes.size() > 1 ) // leave only closest node in dist2Nodes
+//         dist2Nodes.erase( ++dist2Nodes.begin(), dist2Nodes.end());
+
+      // true if an exact overlapping found
+      return ( sqrt( minDist ) <= precision * 1e-12 );
+    }
+  }
+  return false;
+}
+
+//=============================
+/*!
+ * \brief  Return in theGroupsOfNodes a list of group of nodes close to each other within theTolerance
+ * Search for all the nodes in theSetOfNodes
+ * Static Method : no need to create an HYDROData_OctreeNode
+ * \param theSetOfNodes - set of nodes we look at, modified during research
+ * \param theGroupsOfNodes - list of nodes closed to each other returned
+ * \param theTolerance - Precision used, default value is 0.00001
+ * \param maxLevel - Maximum level for HYDROData_OctreeNode constructed, default value is -1 (Infinite)
+ * \param maxNbNodes - maximum Nodes in a Leaf of the HYDROData_OctreeNode constructed, default value is 5
+ */
+//=============================
+//void HYDROData_OctreeNode::FindCoincidentNodes (TIDSortedNodeSet& theSetOfNodes,
+//                                            list< list< const SMDS_MeshNode*> >* theGroupsOfNodes,
+//                                            const double theTolerance,
+//                                            const int maxLevel,
+//                                            const int maxNbNodes)
+//{
+//  // VSR 14/10/2011: limit max number of the levels in order to avoid endless recursing
+//  const int MAX_LEVEL = 10;
+//  HYDROData_OctreeNode theOctreeNode(theSetOfNodes, maxLevel < 0 ? MAX_LEVEL : maxLevel, maxNbNodes, theTolerance);
+//  theOctreeNode.FindCoincidentNodes (&theSetOfNodes, theTolerance, theGroupsOfNodes);
+//}
+
+//=============================
+/*!
+ * \brief  Return in theGroupsOfNodes a list of group of nodes close to each other within theTolerance
+ * Search for all the nodes in theSetOfNodes
+ * \note  The Octree itself is also modified by this method
+ * \param theSetOfNodes - set of nodes we look at, modified during research
+ * \param theTolerance - Precision used
+ * \param theGroupsOfNodes - list of nodes closed to each other returned
+ */
+//=============================
+//void HYDROData_OctreeNode::FindCoincidentNodes ( TIDSortedNodeSet* theSetOfNodes,
+//                                             const double               theTolerance,
+//                                             list< list< const SMDS_MeshNode*> >* theGroupsOfNodes)
+//{
+//  TIDSortedNodeSet::iterator it1 = theSetOfNodes->begin();
+//  list<const SMDS_MeshNode*>::iterator it2;
+//
+//  while (it1 != theSetOfNodes->end())
+//  {
+//    const SMDS_MeshNode * n1 = *it1;
+//
+//    list<const SMDS_MeshNode*> ListOfCoincidentNodes;// Initialize the lists via a declaration, it's enough
+//
+//    list<const SMDS_MeshNode*> * groupPtr = 0;
+//
+//    // Searching for Nodes around n1 and put them in ListofCoincidentNodes.
+//    // Found nodes are also erased from theSetOfNodes
+//    FindCoincidentNodes(n1, theSetOfNodes, &ListOfCoincidentNodes, theTolerance);
+//
+//    // We build a list {n1 + his neigbours} and add this list in theGroupsOfNodes
+//    for (it2 = ListOfCoincidentNodes.begin(); it2 != ListOfCoincidentNodes.end(); it2++)
+//    {
+//      const SMDS_MeshNode* n2 = *it2;
+//      if ( !groupPtr )
+//      {
+//        theGroupsOfNodes->push_back( list<const SMDS_MeshNode*>() );
+//        groupPtr = & theGroupsOfNodes->back();
+//        groupPtr->push_back( n1 );
+//      }
+//      if (groupPtr->front() > n2)
+//        groupPtr->push_front( n2 );
+//      else
+//        groupPtr->push_back( n2 );
+//    }
+//    if (groupPtr != 0)
+//      groupPtr->sort();
+//
+//    theSetOfNodes->erase(it1);
+//    it1 = theSetOfNodes->begin();
+//  }
+//}
+
+//======================================================================================
+/*!
+ * \brief Return a list of nodes closed to Node and remove it from SetOfNodes
+ * \note  The Octree itself is also modified by this method
+ * \param Node - We're searching the nodes next to him.
+ * \param SetOfNodes - set of nodes in which we erase the found nodes
+ * \param Result - list of nodes closed to Node
+ * \param precision - Precision used
+ */
+//======================================================================================
+//void HYDROData_OctreeNode::FindCoincidentNodes (const SMDS_MeshNode *       Node,
+//                                            TIDSortedNodeSet*           SetOfNodes,
+//                                            list<const SMDS_MeshNode*>* Result,
+//                                            const double                precision)
+//{
+//  gp_Pnt p1 (Node->X(), Node->Y(), Node->Z());
+//  bool isInsideBool = isInside( p1.XYZ(), precision );
+//
+//  if (isInsideBool)
+//  {
+//    // I'm only looking in the leaves, since all the nodes are stored there.
+//    if (isLeaf())
+//    {
+//      TIDSortedNodeSet::iterator it = myNodes.begin();
+//      const double tol2 = precision * precision;
+//      bool squareBool;
+//
+//      while (it != myNodes.end())
+//      {
+//        const SMDS_MeshNode* n2 = *it;
+//        squareBool = false;
+//        // We're only looking at nodes with a superior Id.
+//        // JFA: Why?
+//        //if (Node->GetID() < n2->GetID())
+//        if (Node->GetID() != n2->GetID()) // JFA: for bug 0020185
+//        {
+//          gp_Pnt p2 (n2->X(), n2->Y(), n2->Z());
+//          // Distance optimized computation
+//          squareBool = (p1.SquareDistance( p2 ) <= tol2);
+//
+//          // If n2 inside the SquareDistance, we add it in Result and remove it from SetOfNodes and myNodes
+//          if (squareBool)
+//          {
+//            Result->insert(Result->begin(), n2);
+//            SetOfNodes->erase( n2 );
+//            myNodes.erase( *it++ ); // it++ goes forward and returns it's previous position
+//          }
+//        }
+//        if ( !squareBool )
+//          it++;
+//      }
+//      if ( !Result->empty() )
+//        myNodes.erase(Node); // JFA: for bug 0020185
+//    }
+//    else
+//    {
+//      // If I'm not a leaf, I'm going to see my children !
+//      for (int i = 0; i < 8; i++)
+//      {
+//        HYDROData_OctreeNode* myChild = dynamic_cast<HYDROData_OctreeNode*> (myChildren[i]);
+//        myChild->FindCoincidentNodes(Node, SetOfNodes, Result, precision);
+//      }
+//    }
+//  }
+//}
+
+//================================================================================
+/*!
+ * \brief Update data according to node movement
+ */
+//================================================================================
+
+//void HYDROData_OctreeNode::UpdateByMoveNode( const Node3D* node, const gp_Pnt& toPnt )
+//{
+//  if ( isLeaf() )
+//  {
+//    Nodes3D::iterator pNode = myNodes.find( node );
+//    bool nodeInMe = ( pNode != myNodes.end() );
+//
+//    bool pointInMe = isInside( toPnt.Coord(), 1e-10 );
+//
+//    if ( pointInMe != nodeInMe )
+//    {
+//      if ( pointInMe )
+//        myNodes.insert( node );
+//      else
+//        myNodes.erase( node );
+//    }
+//  }
+//  else if ( myChildren )
+//  {
+//    gp_XYZ mid = (getBox()->CornerMin() + getBox()->CornerMax()) / 2.;
+//    int nodeChild  = getChildIndex( node->X(), node->Y(), node->Z(), mid );
+//    int pointChild = getChildIndex( toPnt.X(), toPnt.Y(), toPnt.Z(), mid );
+//    if ( nodeChild != pointChild )
+//    {
+//      ((HYDROData_OctreeNode*) myChildren[ nodeChild  ])->UpdateByMoveNode( node, toPnt );
+//      ((HYDROData_OctreeNode*) myChildren[ pointChild ])->UpdateByMoveNode( node, toPnt );
+//    }
+//  }
+//}
+
+//================================================================================
+/*!
+ * \brief Return iterator over children
+ */
+//================================================================================
+//HYDROData_OctreeNodeIteratorPtr HYDROData_OctreeNode::GetChildrenIterator()
+//{
+//  return HYDROData_OctreeNodeIteratorPtr
+//    ( new SMDS_SetIterator< HYDROData_OctreeNode*, TBaseTree** >
+//      ( myChildren, (( isLeaf() || !myChildren ) ? myChildren : &myChildren[ 8 ] )));
+//}
+
+//================================================================================
+/*!
+ * \brief Return nodes iterator
+ */
+//================================================================================
+//SMDS_NodeIteratorPtr HYDROData_OctreeNode::GetNodeIterator()
+//{
+//  return SMDS_NodeIteratorPtr
+//    ( new SMDS_SetIterator< SMDS_pNode, TIDSortedNodeSet::const_iterator >
+//      ( myNodes.begin(), myNodes.size() ? myNodes.end() : myNodes.begin()));
+//}
diff --git a/src/HYDROData/HYDROData_OctreeNode.hxx b/src/HYDROData/HYDROData_OctreeNode.hxx
new file mode 100644 (file)
index 0000000..e18190c
--- /dev/null
@@ -0,0 +1,143 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  HYDROData HYDROData_OctreeNode : Octree with Nodes set (from SMESH module)
+//  inherites global class HYDROData_Octree
+//  File      : HYDROData_OctreeNode.hxx
+//  Created   : Tue Jan 16 16:00:00 2007
+//  Author    : Nicolas Geimer & Aurelien Motteux  (OCC)
+//  Module    : HYDROData
+//
+#ifndef _HYDROData_OCTREENODE_HXX_
+#define _HYDROData_OCTREENODE_HXX_
+
+#include <Standard.hxx>
+#include <Standard_Macro.hxx>
+
+#include "HYDROData_Octree.hxx"
+#include <gp_Pnt.hxx>
+
+#include <list>
+#include <set>
+#include <vector>
+#include <map>
+
+//forward declaration
+class HYDROData_OctreeNode;
+class gp_XYZ;
+
+typedef gp_XYZ Node3D;
+//typedef NCollection_Sequence<Node3D> Nodes3D;
+typedef std::list<const Node3D*> Nodes3D;
+
+class Standard_EXPORT HYDROData_OctreeNode : public HYDROData_Octree {
+
+public:
+
+  // Constructor
+  HYDROData_OctreeNode (const Nodes3D& theNodes,  const int maxLevel = 8,
+                        const int maxNbNodes = 5, const double minBoxSize = 0.);
+
+//=============================
+/*!
+ * \brief Empty destructor
+ */
+//=============================
+  virtual ~HYDROData_OctreeNode () {};
+
+  // Tells us if Node is inside the current box with the precision "precision"
+  virtual const bool isInside(const gp_XYZ& p, const double precision = 0.);
+
+  // Return in Result a list of Nodes potentials to be near Node
+  void               NodesAround(const Node3D *            Node,
+                                 std::list<const Node3D*>* Result,
+                                 const double              precision = 0.);
+
+  // Return in dist2Nodes nodes mapped to their square distance from Node
+  bool               NodesAround(const gp_XYZ&                    node,
+                                 std::map<double, const Node3D*>& dist2Nodes,
+                                 double                           precision);
+
+  // Return in theGroupsOfNodes a list of group of nodes close to each other within theTolerance
+  // Search for all the nodes in nodes
+//  void               FindCoincidentNodes ( TIDSortedNodeSet*           nodes,
+//                                           const double                theTolerance,
+//                                           std::list< std::list< const Node3D*> >* theGroupsOfNodes);
+
+  // Static method that return in theGroupsOfNodes a list of group of nodes close to each other within
+  // theTolerance search for all the nodes in nodes
+//  static void        FindCoincidentNodes ( TIDSortedNodeSet&                              nodes,
+//                                           std::list< std::list< const Node3D*> >* theGroupsOfNodes,
+//                                           const double theTolerance = 0.00001,
+//                                           const int maxLevel = -1,
+//                                           const int maxNbNodes = 5);
+  /*!
+   * \brief Update data according to node movement
+   */
+  void                        UpdateByMoveNode( const Node3D* node, const gp_Pnt& toPnt );
+  /*!
+   * \brief Return iterator over children
+   */
+//  HYDROData_OctreeNodeIteratorPtr GetChildrenIterator();
+  /*!
+   * \brief Return nodes iterator
+   */
+  //SMDS_NodeIteratorPtr        GetNodeIterator();
+  /*!
+   * \brief Return nb nodes in a tree
+   */
+  int                         NbNodes() const { return myNodes.size(); }
+
+protected:
+
+  struct Limit : public HYDROData_TreeLimit
+  {
+    int myMaxNbNodes;
+    Limit(int maxLevel, double minSize, int maxNbNodes)
+      :HYDROData_TreeLimit(maxLevel, minSize), myMaxNbNodes(maxNbNodes) {}
+  };
+
+  int                   getMaxNbNodes() const;
+
+  HYDROData_OctreeNode();
+
+  // Compute the bounding box of the whole set of nodes myNodes
+  virtual Bnd_B3d*      buildRootBox();
+
+  // Shares the father's data with each of his child
+  virtual void          buildChildrenData();
+
+  // Construct an empty HYDROData_OctreeNode used by HYDROData_Octree::buildChildren()
+  virtual HYDROData_Octree* newChild() const;
+
+//  // Return in result a list of nodes closed to Node and remove it from SetOfNodes
+//  void                  FindCoincidentNodes( const Node3D *            Node,
+//                                             TIDSortedNodeSet*                SetOfNodes,
+//                                             std::list<const Node3D*>* Result,
+//                                             const double                     precision);
+
+  // The set of nodes inside the box of the Octree (Empty if Octree is not a leaf)
+  Nodes3D   myNodes;
+
+};
+
+#endif
index 67098e95e274235ccb83efbfa17e14121e35af3c..508224597315e978bfa0a3537c69e87dbf76e9c0 100644 (file)
@@ -47,6 +47,9 @@
 
 #include <TopTools_SequenceOfShape.hxx>
 
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
 #include <QColor>
 #include <QStringList>
 
diff --git a/src/HYDROData/HYDROData_Quadtree.cxx b/src/HYDROData/HYDROData_Quadtree.cxx
new file mode 100644 (file)
index 0000000..0ec9f1a
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  HYDROData_Quadtree : Quadtree implementation  (from SMESH module)
+//  File      : HYDROData_Quadtree.cxx
+//  Module    : HYDROData
+//
+#include "HYDROData_Quadtree.hxx"
+
+/*!
+ * Constructor. limit must be provided at tree root construction.
+ * limit will be deleted by HYDROData_Quadtree.
+ */
+HYDROData_Quadtree::HYDROData_Quadtree(HYDROData_TreeLimit* limit) :
+    TBaseTree(limit)
+{
+}
+
+/*!
+ * \brief Allocate a bndbox according to childIndex. childIndex is zero based
+ */
+Bnd_B2d* HYDROData_Quadtree::newChildBox(int childIndex) const
+{
+  gp_XY ming = getBox()->CornerMin();
+  gp_XY maxg = getBox()->CornerMax();
+  gp_XY HSize = (maxg - ming) / 2.;
+  gp_XY childHsize = HSize / 2.;
+
+  gp_XY minChild(ming.X() + childIndex % 2 * HSize.X(), ming.Y() + (childIndex > 1) * HSize.Y());
+
+  return new Bnd_B2d(minChild + childHsize, childHsize);
+}
+
+/*!
+ * \brief Compute the biggest dimension of my box
+ */
+double HYDROData_Quadtree::maxSize() const
+{
+  if (getBox() && !getBox()->IsVoid())
+    {
+      gp_XY ming = getBox()->CornerMin();
+      gp_XY maxg = getBox()->CornerMax();
+      gp_XY Size = (maxg - ming);
+      double returnVal = (Size.X() > Size.Y()) ? Size.X() : Size.Y();
+      return returnVal;
+    }
+  return 0.;
+}
diff --git a/src/HYDROData/HYDROData_Quadtree.hxx b/src/HYDROData/HYDROData_Quadtree.hxx
new file mode 100644 (file)
index 0000000..ac42cb8
--- /dev/null
@@ -0,0 +1,69 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  HYDROData_Quadtree : Quadtree implementation (from SMESH module)
+//  File      : HYDROData_Quadtree.hxx
+//  Module    : HYDROData
+//
+#ifndef _HYDROData_Quadtree_HXX_
+#define _HYDROData_Quadtree_HXX_
+
+#include <Standard.hxx>
+#include <Standard_Macro.hxx>
+
+#include "HYDROData_Tree.hxx"
+#include <Bnd_B2d.hxx>
+
+//================================================================================
+
+/*!
+ * \brief 2D tree of anything.
+ * Methods to implement in a descendant are:
+ * - Bnd_B2d*       buildRootBox(); // box of the whole tree
+ * - descendant*    newChild() const; // a new child instance
+ * - void           buildChildrenData(); // Fill in data of the children
+ */
+class Standard_EXPORT HYDROData_Quadtree: public HYDROData_Tree<Bnd_B2d, 4>
+{
+public:
+  typedef HYDROData_Tree<Bnd_B2d, 4> TBaseTree;
+
+  //! Constructor. limit must be provided at tree root construction.
+  //! limit will be deleted by HYDROData_Quadtree
+  HYDROData_Quadtree(HYDROData_TreeLimit* limit = 0);
+
+  //! Compute the biggest dimension of my box
+  double maxSize() const;
+
+  //! Return index of a child the given point is in
+  inline int getChildIndex(double x, double y, const gp_XY& boxMiddle) const
+  {
+    return (x > boxMiddle.X()) + (y > boxMiddle.Y()) * 2;
+  };
+
+protected:
+
+  //! Allocate a bndbox according to childIndex. childIndex is zero based
+  virtual Bnd_B2d* newChildBox(int childIndex) const;
+};
+
+#endif
diff --git a/src/HYDROData/HYDROData_QuadtreeNode.cxx b/src/HYDROData/HYDROData_QuadtreeNode.cxx
new file mode 100644 (file)
index 0000000..ba940da
--- /dev/null
@@ -0,0 +1,263 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  HYDRO HYDROData_QuadtreeNode : Quadtree with Nodes set (from SMESH module)
+//  inherites class HYDROData_Quadtree
+//  File      : HYDROData_QuadtreeNode.cxx
+//  Created   : Tue Jan 16 16:00:00 2007
+//  Author    : Nicolas Geimer & Aurelien Motteux (OCC)
+//  Module    : HYDROData
+//
+#include "HYDROData_QuadtreeNode.hxx"
+
+#include <gp_Pnt.hxx>
+
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
+using namespace std;
+
+/*!
+ * \brief Constructor : Build all the Quadtree using Compute()
+ * \param theNodes - Set of nodes, the Quadtree is built from this nodes
+ * \param maxLevel - Maximum level for the leaves
+ * \param maxNbNodes - Maximum number of nodes, a leaf can contain
+ * \param minBoxSize - Minimal size of the Quadtree Box
+ */
+HYDROData_QuadtreeNode::HYDROData_QuadtreeNode(Nodes_3D* theNodes,
+                                               const int maxLevel,
+                                               const int maxNbNodes,
+                                               const double minBoxSize) :
+    HYDROData_Quadtree(new Limit(maxLevel, minBoxSize, maxNbNodes)), myNodes(theNodes), myPrecision(0.25)
+{
+  DEBTRACE("---------------------------- HYDROData_QuadtreeNode root constructor");
+   if (myNodes)
+    {
+      DEBTRACE(" --- start compute");
+      compute();
+      DEBTRACE(" --- end compute");
+    }
+}
+
+/*!
+ * \brief Constructor used to allocate a child
+ */
+HYDROData_QuadtreeNode::HYDROData_QuadtreeNode() :
+    HYDROData_Quadtree(), myNodes(0), myPrecision(0.25)
+{
+  myNodes = new Nodes_3D();
+}
+
+/*!
+ * \brief virtual destructor: deletes myNodes
+ */
+HYDROData_QuadtreeNode::~HYDROData_QuadtreeNode()
+{
+  if (myNodes)
+    {
+      delete myNodes;
+      myNodes = 0;
+    }
+}
+
+/*!
+ * \brief Set the nodes and compute the quadtree,
+ * when the nodes are not given to the public constructor (delayed compute)
+ */
+void HYDROData_QuadtreeNode::setNodesAndCompute(Nodes_3D* theNodes)
+{
+  myNodes = theNodes;
+  if (myNodes)
+    {
+      DEBTRACE(" --- start compute");
+      compute();
+      DEBTRACE(" --- end compute : children & height " << this->nbChildren() << " " << this->getHeight());
+      DEBTRACE("Bounding box min: " << this->myBox->CornerMin().X() << " "  << this->myBox->CornerMin().Y());
+      DEBTRACE("Bounding box max: " << this->myBox->CornerMax().X() << " "  << this->myBox->CornerMax().Y());
+    }
+}
+
+/*!
+ * \brief Return max number of nodes in a tree leaf
+ */
+int HYDROData_QuadtreeNode::getMaxNbNodes() const
+{
+  return ((Limit*) myLimit)->myMaxNbNodes;
+}
+
+/*!
+ * \brief Construct an empty HYDROData_QuadtreeNode used by HYDROData_Quadtree::buildChildren()
+ */
+HYDROData_Quadtree* HYDROData_QuadtreeNode::newChild() const
+{
+  return new HYDROData_QuadtreeNode();
+}
+
+/*!
+ * \brief Compute the first bounding box
+ *
+ * We take the max/min coord of the nodes
+ */
+Bnd_B2d* HYDROData_QuadtreeNode::buildRootBox()
+{
+  Bnd_B2d* box = new Bnd_B2d;
+  Nodes_3D::iterator it = myNodes->begin();
+  for (; it != myNodes->end(); it++)
+    {
+      const gp_XYZ* n1 = *it;
+      gp_XY p1(n1->X(), n1->Y());
+      box->Add(p1);
+    }
+  if (myNodes->size() <= getMaxNbNodes())
+    myIsLeaf = true;
+
+  return box;
+}
+
+/*!
+ * \brief Tells us if Node is inside the current box with the precision "precision"
+ * \param Node - Node
+ * \param precision - The box is enlarged with this precision
+ * \retval bool - True if Node is in the box within precision
+ */
+const bool HYDROData_QuadtreeNode::isInside(const gp_XY& p, const double precision)
+{
+  if (precision <= 0.)
+    return !(getBox()->IsOut(p));
+  Bnd_B2d BoxWithPrecision = *getBox();
+  BoxWithPrecision.Enlarge(precision);
+  return !BoxWithPrecision.IsOut(p);
+}
+
+/*!
+ * \brief Set the data of the children
+ * Shares the father's data with each of his child
+ */
+void HYDROData_QuadtreeNode::buildChildrenData()
+{
+  gp_XY min = getBox()->CornerMin();
+  gp_XY max = getBox()->CornerMax();
+  gp_XY mid = (min + max) / 2.;
+
+  //DEBTRACE("buildChildrenData level, min, max, nbNodes "<<level()<< " ("<< min.X()<<","<< min.Y()<<") ("<< max.X()<<","<< max.Y()<<") "<< myNodes->size());
+  Nodes_3D::iterator it = myNodes->begin();
+  while (it != myNodes->end())
+    {
+      gp_XYZ* n1 = *it;
+      int ChildBoxNum = getChildIndex(n1->X(), n1->Y(), mid);
+      HYDROData_QuadtreeNode* myChild = dynamic_cast<HYDROData_QuadtreeNode*>(myChildren[ChildBoxNum]);
+      myChild->myNodes->push_back(n1);
+      myNodes->erase(it);
+      it = myNodes->begin();
+    }
+  for (int i = 0; i < 4; i++)
+    {
+      HYDROData_QuadtreeNode* myChild = dynamic_cast<HYDROData_QuadtreeNode*>(myChildren[i]);
+      if (myChild->myNodes->size() <= getMaxNbNodes())
+        {
+          myChild->myIsLeaf = true;
+          //DEBTRACE("buildChildrenData leaf nbNodes "<< myChild->myNodes->size());
+        }
+    }
+}
+
+/*!
+ * \brief Return in Result a list of Nodes potentials to be near Node
+ * \param Node - Node
+ * \param precision - precision used
+ * \param Result - list of Nodes potentials to be near Node
+ */
+void HYDROData_QuadtreeNode::NodesAround(const gp_XY& Node,
+                                         list<const gp_XYZ*>* Result,
+                                         const double precision)
+{
+  gp_XY p(Node);
+  if (isInside(p, precision))
+    {
+      if (isLeaf())
+        {
+          Result->insert(Result->end(), myNodes->begin(), myNodes->end());
+          //DEBTRACE("Leaf result "<< Result->size());
+        }
+      else
+        {
+          for (int i = 0; i < 4; i++)
+            {
+              HYDROData_QuadtreeNode* myChild = dynamic_cast<HYDROData_QuadtreeNode*>(myChildren[i]);
+              myChild->NodesAround(p, Result, precision);
+            }
+        }
+    }
+}
+
+/*!
+ * \brief Return in dist2Nodes nodes mapped to their square distance from Node
+ *  \param node - node to find nodes closest to
+ *  \param dist2Nodes - map of found nodes and their distances
+ *  \param precision - radius of a sphere to check nodes inside
+ *  \retval bool - true if an exact overlapping found !!!
+ */
+bool HYDROData_QuadtreeNode::NodesAround(const gp_XY& node,
+                                         map<double, const gp_XYZ*>& dist2Nodes,
+                                         double precision)
+{
+  if (!dist2Nodes.empty())
+    precision = min(precision, sqrt(dist2Nodes.begin()->first));
+  else if (precision == 0.)
+    precision = maxSize() / 2;
+
+  if (isInside(node, precision))
+    {
+      if (!isLeaf())
+        {
+          // first check a child containing node
+          gp_XY mid = (getBox()->CornerMin() + getBox()->CornerMax()) / 2.;
+          int nodeChild = getChildIndex(node.X(), node.Y(), mid);
+          if (((HYDROData_QuadtreeNode*) myChildren[nodeChild])->NodesAround(node, dist2Nodes, precision))
+            return true;
+
+          for (int i = 0; i < 4; i++)
+            if (i != nodeChild)
+              if (((HYDROData_QuadtreeNode*) myChildren[i])->NodesAround(node, dist2Nodes, precision))
+                return true;
+        }
+      else if (NbNodes() > 0)
+        {
+          double minDist = precision * precision;
+          Nodes_3D::iterator nIt = myNodes->begin();
+          for (; nIt != myNodes->end(); ++nIt)
+            {
+              const gp_XYZ* p = *nIt;
+              gp_XY p2(p->X(), p->Y());
+              double dist2 = (node - p2).SquareModulus();
+              if (dist2 < minDist)
+                dist2Nodes.insert(make_pair(minDist = dist2, p));
+            }
+//       if ( dist2Nodes.size() > 1 ) // leave only closest node in dist2Nodes
+//         dist2Nodes.erase( ++dist2Nodes.begin(), dist2Nodes.end());
+
+// true if an exact overlapping found
+          return (sqrt(minDist) <= precision * 1e-12);
+        }
+    }
+  return false;
+}
diff --git a/src/HYDROData/HYDROData_QuadtreeNode.hxx b/src/HYDROData/HYDROData_QuadtreeNode.hxx
new file mode 100644 (file)
index 0000000..78497ff
--- /dev/null
@@ -0,0 +1,128 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  HYDROData HYDROData_QuadtreeNode : Quadtree with Nodes set (from SMESH module)
+//  inherits global class HYDROData_Quadtree
+//  File      : HYDROData_QuadtreeNode.hxx
+//  Created   : Tue Jan 16 16:00:00 2007
+//  Author    : Nicolas Geimer & Aurelien Motteux  (OCC)
+//  Module    : HYDROData
+//
+#ifndef _HYDROData_QUADTREENODE_HXX_
+#define _HYDROData_QUADTREENODE_HXX_
+
+#include <Standard.hxx>
+#include <Standard_Macro.hxx>
+
+#include "HYDROData_Quadtree.hxx"
+#include <gp_Pnt.hxx>
+
+#include <list>
+#include <set>
+#include <vector>
+#include <map>
+
+//forward declaration
+class HYDROData_QuadtreeNode;
+class gp_XY;
+class gp_XYZ;
+
+typedef std::list<gp_XYZ*> Nodes_3D;
+
+class Standard_EXPORT HYDROData_QuadtreeNode: public HYDROData_Quadtree
+{
+
+public:
+
+  //! public constructor: when theNodes is non null, compute the quadtree
+  HYDROData_QuadtreeNode(Nodes_3D* theNodes,
+                         const int maxLevel = 8,
+                         const int maxNbNodes = 5,
+                         const double minBoxSize = 0.);
+
+  //! destructor
+  virtual ~HYDROData_QuadtreeNode();
+
+  //! tu use when no nodes where given to the public constructor
+  virtual void setNodesAndCompute(Nodes_3D* theNodes);
+
+  //! Tells us if Node is inside the current box with the precision "precision"
+  virtual const bool isInside(const gp_XY& p, const double precision = 0.);
+
+  //! Return in Result a list of Nodes potentials to be near Node
+  void NodesAround(const gp_XY& Node,
+                   std::list<const gp_XYZ*>* Result,
+                   const double precision = 0.);
+
+  //! Return in dist2Nodes nodes mapped to their square distance from Node
+  bool NodesAround(const gp_XY& node,
+                   std::map<double, const gp_XYZ*>& dist2Nodes,
+                   double precision);
+
+  //! Update data according to node movement
+  void UpdateByMoveNode(const gp_XYZ* node, const gp_Pnt& toPnt);
+
+  //! Return nb nodes in a tree
+  int NbNodes() const
+  {
+    if (myNodes)
+      return myNodes->size();
+    else
+      return 0;
+  }
+
+  //! tells us if the tree as already bin computed
+  bool isEmpty() const { return myChildren == 0; }
+
+  inline double getPrecision() {return myPrecision; }
+  inline double setPrecision(double precision)  {myPrecision = precision; }
+
+protected:
+
+  struct Limit: public HYDROData_TreeLimit
+  {
+    int myMaxNbNodes;
+    Limit(int maxLevel, double minSize, int maxNbNodes) :
+        HYDROData_TreeLimit(maxLevel, minSize), myMaxNbNodes(maxNbNodes) {}
+  };
+
+  int getMaxNbNodes() const;
+
+  HYDROData_QuadtreeNode();
+
+  //! Compute the bounding box of the whole set of nodes myNodes
+  virtual Bnd_B2d* buildRootBox();
+
+  //! Shares the father's data with each of his child
+  virtual void buildChildrenData();
+
+  //! Construct an empty HYDROData_QuadtreeNode used by HYDROData_Quadtree::buildChildren()
+  virtual HYDROData_Quadtree* newChild() const;
+
+  //! The set of nodes inside the box of the Quadtree (Empty if Quadtree is not a leaf)
+  Nodes_3D* myNodes;
+
+  //! distance to look for nearest nodes
+  double myPrecision;
+};
+
+#endif
index 50443a315d707f139085652189815ade803b395f..893be4427bfaf905da9f35dc4c5bdffb0b3dc18b 100644 (file)
@@ -49,6 +49,9 @@
 
 #include <QStringList>
 
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
 #ifdef DEB_CLASS2D
 #include <BRepTools.hxx>
 #include <BRep_Builder.hxx>
@@ -214,20 +217,30 @@ bool HYDROData_StreamAltitude::getBoundaryProfilesForPoint(
 
 double HYDROData_StreamAltitude::GetAltitudeForPoint( const gp_XY& thePoint ) const
 {
+  DEBTRACE("GetAltitudeForPoint p(" << thePoint.X() << ", " << thePoint.Y() << ")");
   double aResAltitude = GetInvalidAltitude();
 
   Handle(HYDROData_Stream) aStream =
     Handle(HYDROData_Stream)::DownCast( GetFatherObject() );
   if ( aStream.IsNull() )
+  {
+       DEBTRACE("aStream.IsNull()");
     return aResAltitude;
+  }
 
   TopoDS_Shape aStreamShape = aStream->GetTopShape();
   if ( aStreamShape.IsNull() )
+  {
+       DEBTRACE("aStreamShape.IsNull()");
     return aResAltitude;
+  }
 
   TopExp_Explorer aStreamFaceExp( aStreamShape, TopAbs_FACE );
   if ( !aStreamFaceExp.More() )
+  {
+       DEBTRACE("!aStreamFaceExp.More()");
     return aResAltitude;
+  }
 
   // Get only face because of 2d profile wires is in compound
   TopoDS_Face aStreamFace = TopoDS::Face( aStreamFaceExp.Current() );
@@ -247,12 +260,18 @@ double HYDROData_StreamAltitude::GetAltitudeForPoint( const gp_XY& thePoint ) co
          BRepTools::Write(aCmp, "FCL2d.brep");
 #endif
   if ( aPointState == TopAbs_OUT )
+  {
+       DEBTRACE("aPointState == TopAbs_OUT");
     return aResAltitude;
+  }
 
   // Find the two profiles between which the point is lies
   Handle(HYDROData_Profile) aLeftProfile, aRightProfile;
   if ( !getBoundaryProfilesForPoint( thePoint, aLeftProfile, aRightProfile ) )
+  {
+       DEBTRACE("!getBoundaryProfilesForPoint( thePoint, aLeftProfile, aRightProfile )");
     return aResAltitude;
+  }
 
   // Find the projections of point to borders of stream
   gp_XYZ aPointToTest( thePoint.X(), thePoint.Y(), 0.0 );
@@ -302,7 +321,7 @@ double HYDROData_StreamAltitude::GetAltitudeForPoint( const gp_XY& thePoint ) co
   Standard_Real aSecCoeff = aRightProfileDist / ( aLeftProfileDist + aRightProfileDist );
 
   aResAltitude = aLeftAlt * ( 1 - aFirstCoeff ) + aRightAlt * ( 1 - aSecCoeff );
-
+  DEBTRACE("aResAltitude=" << aResAltitude);
   return aResAltitude;
 }
 
diff --git a/src/HYDROData/HYDROData_Tree.hxx b/src/HYDROData/HYDROData_Tree.hxx
new file mode 100644 (file)
index 0000000..c946caa
--- /dev/null
@@ -0,0 +1,264 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  HYDRO HYDROData_Tree : tree implementation (from SMESH module)
+//  File      : HYDROData_Tree.hxx
+//  Created   : Tue Jan 16 16:00:00 2007
+//  Author    : Nicolas Geimer & Aurélien Motteux (OCC)
+//  Module    : HYDRO
+//
+#ifndef _HYDROData_Tree_HXX_
+#define _HYDROData_Tree_HXX_
+
+//================================================================================
+
+//! Data limiting the tree height
+struct HYDROData_TreeLimit
+{
+  int myMaxLevel; //!<MaxLevel of the Tree
+  double myMinBoxSize; //!< Minimal size of the Box
+
+  /*! \brief Constructor with default values
+   *
+   * maxLevel-> 8^8 = 16777216 terminal trees at most
+   * minSize -> 0 : box size not checked
+   */
+  HYDROData_TreeLimit(int maxLevel = 8, double minSize = 0.) :
+      myMaxLevel(maxLevel), myMinBoxSize(minSize)
+  {
+  }
+
+  virtual ~HYDROData_TreeLimit()
+  {
+  } //!< virtual destructor can be inherited
+};
+
+//================================================================================
+
+/*!
+ * \brief Base class for 2D and 3D trees
+ */
+template<class BND_BOX, int NB_CHILDREN>
+class HYDROData_Tree
+{
+public:
+
+  typedef BND_BOX box_type;
+
+  //! Constructor. limit must be provided at tree root construction.
+  //! limit will be deleted by HYDROData_Tree
+  HYDROData_Tree(HYDROData_TreeLimit* limit = 0);
+
+  //! Destructor
+  virtual ~HYDROData_Tree();
+
+  //! Compute the Tree. Must be called by constructor of inheriting class
+  void compute();
+
+  //! Tell if Tree is a leaf or not.
+  //! An inheriting class can influence it via myIsLeaf protected field
+  bool isLeaf() const;
+
+  //! Return its level
+  int level() const
+  {
+    return myLevel;
+  }
+
+  //! Return Bounding Box of the Tree
+  const box_type* getBox() const
+  {
+    return myBox;
+  }
+
+  //! Return height of the tree, full or from this level to top leaf
+  int getHeight(const bool full = true) const;
+
+  static int nbChildren()
+  {
+    return NB_CHILDREN;
+  }
+
+  //! Compute the biggest dimension of my box
+  virtual double maxSize() const = 0;
+
+protected:
+  //! Return box of the whole tree
+  virtual box_type* buildRootBox() = 0;
+
+  //! Allocate a child
+  virtual HYDROData_Tree* newChild() const = 0;
+
+  //! Allocate a bndbox according to childIndex. childIndex is zero based
+  virtual box_type* newChildBox(int childIndex) const = 0;
+
+  //! Fill in data of the children
+  virtual void buildChildrenData() = 0;
+
+  //! Build the children recursively
+  void buildChildren();
+
+  // --- members
+
+  HYDROData_Tree** myChildren; //!< Array of children
+
+  HYDROData_Tree* myFather; //!< Point the father, NULL for the level 0
+
+  const HYDROData_TreeLimit* myLimit; //!< Tree limit
+
+  box_type* myBox; //!< Bounding box of a tree
+
+  int myLevel; //!< Level of the Tree
+
+  bool myIsLeaf; //!< Tell us if the Tree is a leaf or not
+};
+
+/*!
+ * Constructor. limit must be provided at tree root construction.
+ * limit will be deleted by HYDROData_Tree.
+ */
+template<class BND_BOX, int NB_CHILDREN>
+HYDROData_Tree<BND_BOX, NB_CHILDREN>::HYDROData_Tree(HYDROData_TreeLimit* limit) :
+    myChildren(0), myFather(0), myLimit(limit), myBox(0), myLevel(0), myIsLeaf(false)
+{
+  //if ( !myLimit ) myLimit = new HYDROData_TreeLimit();
+}
+
+/*!
+ * \brief Compute the Tree
+ */
+template<class BND_BOX, int NB_CHILDREN>
+void HYDROData_Tree<BND_BOX, NB_CHILDREN>::compute()
+{
+  if (myLevel == 0)
+    {
+      if (!myLimit)
+        myLimit = new HYDROData_TreeLimit();
+      myBox = buildRootBox();
+      if (myLimit->myMinBoxSize > 0. && maxSize() <= myLimit->myMinBoxSize)
+        myIsLeaf = true;
+      else
+        buildChildren();
+    }
+}
+
+/*!
+ * \brief HYDROData_Tree Destructor
+ */
+template<class BND_BOX, int NB_CHILDREN>
+HYDROData_Tree<BND_BOX, NB_CHILDREN>::~HYDROData_Tree()
+{
+  if (myChildren)
+    {
+      if (!isLeaf())
+        {
+          for (int i = 0; i < NB_CHILDREN; i++)
+            delete myChildren[i];
+          delete[] myChildren;
+          myChildren = 0;
+        }
+    }
+  if (myBox)
+    delete myBox;
+  myBox = 0;
+  if (level() == 0)
+    delete myLimit;
+  myLimit = 0;
+}
+
+/*!
+ * \brief Build the children boxes and call buildChildrenData()
+ */
+template<class BND_BOX, int NB_CHILDREN>
+void HYDROData_Tree<BND_BOX, NB_CHILDREN>::buildChildren()
+{
+  if (isLeaf())
+    return;
+
+  myChildren = new HYDROData_Tree*[NB_CHILDREN];
+
+  // get the whole model size
+  double rootSize = 0;
+    {
+      HYDROData_Tree* root = this;
+      while (root->myLevel > 0)
+        root = root->myFather;
+      rootSize = root->maxSize();
+    }
+  for (int i = 0; i < NB_CHILDREN; i++)
+    {
+      // The child is of the same type than its father (For instance, a HYDROData_OctreeNode)
+      // We allocate the memory we need for the child
+      myChildren[i] = newChild();
+      // and we assign to him its box.
+      myChildren[i]->myFather = this;
+      if (myChildren[i]->myLimit)
+        delete myChildren[i]->myLimit;
+      myChildren[i]->myLimit = myLimit;
+      myChildren[i]->myLevel = myLevel + 1;
+      myChildren[i]->myBox = newChildBox(i);
+      myChildren[i]->myBox->Enlarge(rootSize * 1e-10);
+      if (myLimit->myMinBoxSize > 0. && myChildren[i]->maxSize() <= myLimit->myMinBoxSize)
+        myChildren[i]->myIsLeaf = true;
+    }
+
+  // --- After building the NB_CHILDREN boxes, we put the data into the children.
+  buildChildrenData();
+
+  // --- After we pass to the next level of the Tree
+  for (int i = 0; i < NB_CHILDREN; i++)
+    myChildren[i]->buildChildren();
+}
+
+/*!
+ * \brief Tell if Tree is a leaf or not
+ *        An inheriting class can influence it via myIsLeaf protected field
+ */
+template<class BND_BOX, int NB_CHILDREN>
+bool HYDROData_Tree<BND_BOX, NB_CHILDREN>::isLeaf() const
+{
+  return myIsLeaf || ((myLimit->myMaxLevel > 0) ? (level() >= myLimit->myMaxLevel) : false);
+}
+
+/*!
+ * \brief Return height of the tree, full or from this level to top leaf
+ */
+template<class BND_BOX, int NB_CHILDREN>
+int HYDROData_Tree<BND_BOX, NB_CHILDREN>::getHeight(const bool full) const
+{
+  if (full && myFather)
+    return myFather->getHeight(true);
+
+  if (isLeaf())
+    return 1;
+
+  int heigth = 0;
+  for (int i = 0; i < NB_CHILDREN; i++)
+    {
+      int h = myChildren[i]->getHeight(false);
+      if (h > heigth)
+        heigth = h;
+    }
+  return heigth + 1;
+}
+
+#endif
index c6e3da1af9650fb148aa9bdd0946e87c38a3cd7d..97e1da6c1e39c46da179889af2e8af8233cfa60b 100644 (file)
@@ -33,6 +33,9 @@
 
 #include <TDataStd_Integer.hxx>
 
+#define _DEVDEBUG_
+#include "HYDRO_trace.hxx"
+
 IMPLEMENT_STANDARD_HANDLE(HYDROData_Zone, HYDROData_Entity)
 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Zone, HYDROData_Entity)
 
@@ -178,6 +181,7 @@ HYDROData_Zone::MergeType HYDROData_Zone::GetMergeType() const
 
 void HYDROData_Zone::SetMergeObject( const Handle(HYDROData_Entity)& theObject )
 {
+  //DEBTRACE("HYDROData_Zone::SetMergeObject");
   SetReferenceObject( theObject, DataTag_MergeObject );
 }
 
diff --git a/src/HYDROData/HYDRO_trace.hxx b/src/HYDROData/HYDRO_trace.hxx
new file mode 100644 (file)
index 0000000..55f0817
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __HYDROTRACE_HXX__
+#define __HYDROTRACE_HXX__
+
+#include <iostream>
+#include <sstream>
+
+#ifdef _DEVDEBUG_
+#define DEBTRACE(msg) {std::cerr<<std::flush<<__FILE__<<" ["<<__LINE__<<"] : "<<msg<<std::endl<<std::flush;}
+#else
+#define DEBTRACE(msg)
+#endif
+
+#endif