]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
staffan :
authorvbd <vbd>
Tue, 31 Jul 2007 07:17:59 +0000 (07:17 +0000)
committervbd <vbd>
Tue, 31 Jul 2007 07:17:59 +0000 (07:17 +0000)
re-implementation of BoundingBox, MeshElement, MeshRegion, RegionNode
* not yet tested

src/INTERP_KERNEL/BoundingBox.cxx
src/INTERP_KERNEL/BoundingBox.hxx
src/INTERP_KERNEL/Interpolation3D.cxx
src/INTERP_KERNEL/MeshElement.cxx
src/INTERP_KERNEL/MeshElement.hxx
src/INTERP_KERNEL/MeshRegion.cxx
src/INTERP_KERNEL/MeshRegion.hxx
src/INTERP_KERNEL/RegionNode.cxx [new file with mode: 0644]
src/INTERP_KERNEL/RegionNode.hxx

index 9ac02709c066db3071986dbd8afbd1170b8a1553..bb4f17fe56ab718e2047556cd712705875e8681e 100644 (file)
@@ -20,7 +20,7 @@ namespace INTERP_UTILS
    * @param numPts  number of vertices
    *
    */
-   BoundingBox::BoundingBox(const double** pts, const int numPts);
+   BoundingBox::BoundingBox(const double** pts, const int numPts)
    {
      using namespace std;
      assert(numPts > 1);
@@ -44,12 +44,13 @@ namespace INTERP_UTILS
    * Constructor creating box from union of two boxes
    *
    */
-  BoundingBox::BoundingBox(const BoundingBox& box1, const BoundingBox& box1
+  BoundingBox::BoundingBox(const BoundingBox& box1, const BoundingBox& box2
   {
+    using namespace std;
     for(BoxCoord c = XMIN ; c <= ZMIN ; c = BoxCoord(c + 1))
        {
-        _coords[c] = min(box1[c], box2[c]);
-        _coords[c + 3] = max(box1[c + 3], box2[c + 3]);
+        _coords[c] = min(box1._coords[c], box2._coords[c]);
+        _coords[c + 3] = max(box1._coords[c + 3], box2._coords[c + 3]);
        }
   }
 
index daee9bf2d8eeef633a5b9eeda4d96cdc539a81ba..64297d9065a64256335100968dcb972cfbf66549 100644 (file)
@@ -35,7 +35,7 @@ namespace INTERP_UTILS
      * Constructor creating box from union of two boxes
      *
      */
-    BoundingBox(const BoundingBox& box1, const BoundingBox& box1) {}
+    BoundingBox(const BoundingBox& box1, const BoundingBox& box2);
 
     /**
      * Destructor
@@ -72,7 +72,7 @@ namespace INTERP_UTILS
     void updateWithPoint(const double* pt);
 
   private:
-    double[6] _coords;
+    double _coords[6];
 
   };
 
index 6caec3d0fa980ffd63668c9f986c4c6893d62661..69f55d7944c1cab1bef4d4bfb2a71cbf1c7c0921 100644 (file)
@@ -166,7 +166,7 @@ namespace MEDMEM
            } 
          else // recursion 
            {
-             typedef MeshElement::ZoneBBoxComparison Cmp;
+
              // std::cout << " - Recursion" << std::endl;
 
              RegionNode* leftNode = new RegionNode();
@@ -174,14 +174,14 @@ namespace MEDMEM
              
              // split current source region
              //} decide on axis
-             static Cmp::BoxAxis axis = Cmp::X;
+             static BoundingBox::BoxCoord axis = BoundingBox::XMAX;
              
              currNode->getSrcRegion().split(leftNode->getSrcRegion(), rightNode->getSrcRegion(), axis);
 
              // ugly hack to avoid problem with enum which does not start at 0
              // I guess I ought to implement ++ for it instead ...
              // Anyway, it basically chooses the next axis, circually
-             axis = (axis != Cmp::Z) ? static_cast<Cmp::BoxAxis>(axis + 1) : Cmp::X;
+             axis = (axis != BoundingBox::ZMAX) ? static_cast<BoundingBox::BoxCoord>(axis + 1) : BoundingBox::XMAX;
 
              // add target elements of curr node that overlap the two new nodes
              //              std::cout << " -- Adding target elements" << std::endl;
index 52b2c2245042fed8f259902ff482acf0d42ab2b3..1c4d22c54f765cecfcd42e14f2e929c6bd7e913e 100644 (file)
@@ -1,5 +1,8 @@
 #include "MeshElement.hxx"
 
+#include "TetraAffineTransform.hxx"
+#include "TransformedTriangle.hxx"
+
 namespace INTERP_UTILS
 {
 
@@ -10,7 +13,7 @@ namespace INTERP_UTILS
    * @param type    geometric type of the element
    * @param index   global number of element in the mesh
    */
-  MeshElement::MeshElement(const int index, const MEDEN::medGeometryElement type, const MEDMEM::Mesh& mesh)
+  MeshElement::MeshElement(const int index, const MED_EN::medGeometryElement type, const MEDMEM::MESH& mesh)
     : _index(index - 1), _mesh(&mesh), _type(type), _box(0)
   {
     // get coordinates of vertices
@@ -96,7 +99,7 @@ namespace INTERP_UTILS
   const double* MeshElement::getCoordsOfNode(int node) const
   {
     const int nodeOffset = node - 1;
-    const int elemIdx = mesh->getConnectivityIndex(MED_NODAL, MED_CELL)[_index];
+    const int elemIdx = _mesh->getConnectivityIndex(MED_NODAL, MED_CELL)[_index];
     return &(_mesh->getCoordinates(MED_FULL_INTERLACE)[elemIdx + nodeOffset]);
   }
   
@@ -108,7 +111,64 @@ namespace INTERP_UTILS
    */
   void MeshElement::triangulate(std::vector<TransformedTriangle>& triangles, const TetraAffineTransform& T) const
   {
-    // not implemented
+    switch(_type)
+      {
+      case MED_TETRA4 :
+       // triangles == faces
+       const int beginFaceIdx = _mesh->getConnectivityIndex(MED_DESCENDING, MED_CELL)[_index];
+       const int endFaceIdx = _mesh->getConnectivityIndex(MED_DESCENDING, MED_CELL)[_index + 1];
+       
+       for(int i = beginFaceIdx ; i < endFaceIdx ; ++i) // loop over faces of element
+         {
+           const int faceIdx = _mesh->getConnectivity(MED_FULL_INTERLACE, MED_DESCENDING, MED_CELL, MED_ALL_ELEMENTS)[i - 1];
+           const int beginNodeIdx = _mesh->getConnectivityIndex(MED_NODAL, MED_FACE)[faceIdx - 1];
+           const int endNodeIdx = _mesh->getConnectivityIndex(MED_NODAL, MED_FACE)[faceIdx];
+           
+           double transformedPts[9];
+           
+           assert(endNodeIdx - beginNodeIdx == 3);
+           
+           for(int j = 0 ; j < 3 ; ++j) // loop over nodes of face
+             {
+               // { optimise here using getCoordinatesForNode ?
+               // could maybe use the connNodeIdx directly and only transform each node once
+               // instead of once per face
+               const int connNodeIdx = 
+                 _mesh->getConnectivity(MED_FULL_INTERLACE, MED_NODAL, MED_FACE, MED_ALL_ELEMENTS)[beginNodeIdx + j - 1];
+               const double* pt = &(_mesh->getCoordinates(MED_FULL_INTERLACE)[connNodeIdx - 1]);
+
+               // transform
+               T.apply(&transformedPts[3*j], pt);
+             }
+           
+           triangles.push_back(TransformedTriangle(&transformedPts[0], &transformedPts[3], &transformedPts[6]));
+         }
+
+       break;
+      default:
+       break;
+      }
+  }
+
+  int MeshElement::getIndex() const
+  {
+    return _index + 1;
+  }
+  
+
+  /// ElementBBoxOrder
+  bool ElementBBoxOrder::operator()( MeshElement* elem1, MeshElement* elem2)
+  {
+    assert(elem1 != 0);
+    assert(elem2 != 0);
+    assert(elem1->_box != 0);
+    assert(elem2->_box != 0);
+    
+    const double coord1 = elem1->_box->getCoordinate(_coord);
+    const double coord2 = elem2->_box->getCoordinate(_coord);
+    
+    return coord1 < coord2;
   }
 
+  
 };
index cc060a529066f7f1583d27942220075cd71e37a7..ab339da23d8e1a0e6ad0396f00afa11c1fb675d1 100644 (file)
@@ -1,9 +1,23 @@
 #ifndef __MESH_ELEMENT_HXX__
 #define __MESH_ELEMENT_HXX__
 
+#include "MEDMEM_define.hxx"
+#include "MEDMEM_Mesh.hxx"
+
+#include "BoundingBox.hxx"
+
+using namespace MEDMEM;
+using namespace MED_EN;
+
+
+
+
 namespace INTERP_UTILS
 {
 
+  class TransformedTriangle;
+  class TetraAffineTransform;
+
   /**
    * Class representing a single element of a mesh together with its bounding box.
    * It permits access to the nodes of the element, to test for disunion and inclusion with other elements
@@ -11,63 +25,13 @@ namespace INTERP_UTILS
    */
   class MeshElement
   {
-  public:
     
-    /**
-     * Constructor
-     *
-     * @param mesh    mesh that the element belongs to
-     * @param type    geometric type of the element
-     * @param index   connectivity index of element in the mesh
-     */
-    MeshElement(const int index, const MEDEN::medGeometryElement type, const MEDMEM::Mesh& mesh);
-    
-    /**
-     * Destructor
-     *
-     */
-    ~MeshElement();
-
-    /**
-     * Determines if this element is in the interior of another element 
-     * by calculating the triple products for each point of this element with respect
-     * to all the faces of the other object (faces must be triangulated ... ) If all triple
-     * products have the same sign, then the element is in the interior of the other element
-     *
-     * @param otherElement the supposedly enclosing element
-     * @returns true if this element is enclosed in the other element, false if not
-     */
-    bool isElementIncludedIn(const MeshElement& otherElement) const;
-
-    /**
-     * Determines whether the intersection of this element is trivially empty. This is done by checking for each
-     * face of one element if it is such that all the vertices of the other element is on the same side of this face.
-     * If there is such a face, then the intersection is trivially empty. If there is no such face, we do not know if 
-     * the intersection is empty.
-     *
-     * @pre The elements are convex. If this is no true, we return false.
-     * @param otherElement the element believed to be disjoint with this one
-     * @returns true if the two elements are convex and there exists a face of this element such as described 
-     *          above, false otherwise
-     */
-    bool isElementTriviallyDisjointWith(const MeshElement& otherElement) const;
 
-    /**
-     * Returns the number of nodes of this element
-     *
-     * @returns  the number of nodes of this element
-     */
-    int getNumberNodes() const;
-
-    /**
-     * Returns the coordinates of a node of this element
-     * (1 <= node <= #nodes)
-     *
-     * @param      node  the node for which the coordinates are sought
-     * @returns    pointer to an array of 3 doubles containing the coordinates
-     */
-    const double* getCoordsOfNode(int node);
+    friend class ElementBBoxOrder;
+    friend class MeshRegion;
 
+  public:
+    
     /**
      * Constructor
      *
@@ -75,7 +39,7 @@ namespace INTERP_UTILS
      * @param type    geometric type of the element
      * @param index   connectivity index of element in the mesh
      */
-    MeshElement(const int index, const MEDEN::medGeometryElement type, const MEDMEM::Mesh& mesh);
+    MeshElement(const int index, const MED_EN::medGeometryElement type, const MEDMEM::MESH& mesh);
     
     /**
      * Destructor
@@ -121,7 +85,7 @@ namespace INTERP_UTILS
      * @param      node  the node for which the coordinates are sought
      * @returns    pointer to an array of 3 doubles containing the coordinates
      */
-    const double* getCoordsOfNode(int node);
+    const double* getCoordsOfNode(int node) const;
 
     /**
      * Triangulate the faces of this element and apply an affine Transform to the triangles
@@ -129,19 +93,34 @@ namespace INTERP_UTILS
      * @param      triangles  vector in which triangles are stored
      * @param      T          affine transform that is applied to the nodes of the triangles
      */
-    void triangulate(std::vector<TransformedTriangle>& triangles, const TetraAffineTransform& T);
+    void triangulate(std::vector<TransformedTriangle>& triangles, const TetraAffineTransform& T) const;
+    
+    int getIndex() const;
 
   private:
     const int _index;
-    const MEDMEM::Mesh* _mesh;
-    const MEDEN::medGeometryElement _type;
-    BoundingBox _box; // should not change after initialisation
+    const MEDMEM::MESH* _mesh;
+    const MED_EN::medGeometryElement _type;
+    BoundingBox* _box; // should not change after initialisation
     
   };
 
-  // to be added : triangulation methods
 
-};
 
+  class ElementBBoxOrder
+  {
+  public : 
+  
+    ElementBBoxOrder(BoundingBox::BoxCoord coord)
+      : _coord(coord)
+    {
+    }
+  
+    bool operator()(MeshElement* elem1, MeshElement* elem2);
+  
+  private :
+    BoundingBox::BoxCoord _coord;
+  };
 
+};
 #endif
index 93145bf343816f3f91d29b89496ed77f72fb2796..6a58263fd8394bfa4330c1361043f42796c61dbb 100644 (file)
 #include "MeshRegion.hxx"
 
+#include "MeshElement.hxx"
+
+//#include <math.h>
+
 namespace INTERP_UTILS
 {
+    
   /**
-   * Class representing a set of elements in a mesh together with their bounding box.
-   * It permits to split itself in two, which is used in the depth-first search filtering process.
-   *
+   * Default constructor
+   * 
    */
-  class MeshRegion
+  MeshRegion::MeshRegion()
+    : _box(0)
   {
-  public:
-    
-    /**
-     * Default constructor
-     * 
-     */
-    MeshRegion::MeshRegion()
-      : _box(0)
-    {
-    }
+  }
     
-    /**
-     * Destructor
-     *
-     */
-    MeshRegion::~MeshRegion()
-    {
-      if(_box != 0)
-       {
-         delete _box;
-       }
-
-    /**
-     * Adds an element to the region, updating the bounding box.
-     *
-     * @param element pointer to element to add to region
-     *
-     */
-    void MeshRegion::addElement(MeshElement* const element)
+  /**
+   * Destructor
+   *
+   */
+  MeshRegion::~MeshRegion()
+  {
+    if(_box != 0)
       {
-       _elements.push_back(element);
+       delete _box;
+      }
+  }
+
+  /**
+   * Adds an element to the region, updating the bounding box.
+   *
+   * @param element pointer to element to add to region
+   *
+   */
+  void MeshRegion::addElement(MeshElement* const element)
+  {
+    _elements.push_back(element);
        
-       if(_box == 0)
+    if(_box == 0)
+      {
+       const int numNodes = element->getNumberNodes();
+       const double* pts[numNodes];
+           
+       // get coordinates of elements
+       for(int i = 0 ; i < numNodes ; ++i)
          {
-           // get coordinates of elements
-           _box = new BoundingBox();
+           pts[i] = element->getCoordsOfNode(i + 1);
          }
+           
+       _box = new BoundingBox(pts, numNodes);
+           
+      }
+  }
+
+  /**
+   * Splits the region in two along the given axis, copying the elements with bounding boxes whose maximum
+   * coordinate along the axis are smaller than the middle of the bounding box of this region in region1. The
+   * rest of the elements are copied to region2.
+   *
+   * @param region1 region in which to store one half of this region
+   * @param region2 region in which to store the other of this region
+   * @param coord   coordinate of BoundingBox to use when splitting the region
+   *
+   */
+  void MeshRegion::split(MeshRegion& region1, MeshRegion& region2, BoundingBox::BoxCoord coord)
+  {
+    ElementBBoxOrder cmp(coord);
+
+    // sort elements by their bounding boxes
+    std::sort(_elements.begin(), _elements.end(), cmp);
+
+    // put the first half of the elements in region1 and the 
+    // rest in region2
+    std::vector<MeshElement*>::const_iterator iter = _elements.begin();
+    int elemCount = 0;
+
+    while(elemCount < static_cast<int>(_elements.size() / 2))
+      {
+       region1.addElement(*iter);
+       ++iter;
+       ++elemCount;
+      }
+
+    while(iter != _elements.end())
+      {
+       region2.addElement(*iter);
+       ++iter;
       }
 
-    /**
-     * Splits the region in two along the given axis, copying the elements with bounding boxes whose maximum
-     * coordinate along the axis are smaller than the middle of the bounding box of this region in region1. The
-     * rest of the elements are copied to region2.
-     *
-     * @param region1 region in which to store one half of this region
-     * @param region2 region in which to store the other of this region
-     * @param axis    axis along which to split the region
-     *
-     */
-    void MeshRegion::split(Region& region1, Region& region2, int axis) const;
-
-  private:
-    // Vector of pointers to elements. NB : these pointers are not owned by the region object, and are thus
-    // neither allocated or liberated in this class. The elements must therefore be allocated and liberated outside this class
-    std::vector<MeshElement*> _elements;
-    BoundingBox* _box;
-
-  };
+    //    assert(std::abs(region1._elements.size() - region2._elements.size()) < 2);
+       
+  }
+
+  bool MeshRegion::isDisjointWithElementBoundingBox(const MeshElement& elem) const
+  {
+    assert(_box != 0);
+    assert(elem._box != 0);
+
+    return _box->isDisjointWith(*(elem._box));
+  }
 
+  std::vector<MeshElement*>::const_iterator MeshRegion::getBeginElements() const
+  {
+    return _elements.begin();
+  }
+
+  std::vector<MeshElement*>::const_iterator MeshRegion::getEndElements() const
+  {
+    return _elements.end();
+  }
+
+  int MeshRegion::getNumberOfElements() const
+  {
+    return _elements.size();
+  }
 };
 
 
-#endif
+  
index fdbb0df15dd9fbdb04954e652953e51c762eb1c9..62081aaadbdc51846288a94ee00dd2637772feda 100644 (file)
@@ -3,8 +3,12 @@
 
 #include <vector>
 
+#include "BoundingBox.hxx"
+
 namespace INTERP_UTILS
 {
+  class MeshElement;
+
   /**
    * Class representing a set of elements in a mesh together with their bounding box.
    * It permits to split itself in two, which is used in the depth-first search filtering process.
@@ -44,13 +48,21 @@ namespace INTERP_UTILS
      * @param axis    axis along which to split the region
      *
      */
-    void split(Region& region1, Region& region2, int axis) const;
+    void split(MeshRegion& region1, MeshRegion& region2, BoundingBox::BoxCoord coord);
+
+    bool isDisjointWithElementBoundingBox(const MeshElement& elem) const;
+
+    std::vector<MeshElement*>::const_iterator getBeginElements() const;
+
+    std::vector<MeshElement*>::const_iterator getEndElements() const;
+
+    int getNumberOfElements() const;
 
   private:
     // Vector of pointers to elements. NB : these pointers are not owned by the region object, and are thus
     // neither allocated or liberated in this class. The elements must therefore be allocated and liberated outside this class
     std::vector<MeshElement*> _elements;
-    BoundingBox _box;
+    BoundingBox* _box;
 
   };
 
diff --git a/src/INTERP_KERNEL/RegionNode.cxx b/src/INTERP_KERNEL/RegionNode.cxx
new file mode 100644 (file)
index 0000000..6f965e9
--- /dev/null
@@ -0,0 +1,41 @@
+#include "RegionNode.hxx"
+
+namespace INTERP_UTILS
+{
+  /**
+   * Default constructor
+   * 
+   */
+  RegionNode::RegionNode()
+  {
+  }
+    
+  /**
+   * Destructor
+   *
+   */
+  RegionNode::~RegionNode()
+  {
+  }
+
+    
+  /**
+   *  Accessor to source region
+   *
+   * @return   reference to source region
+   */
+  MeshRegion& RegionNode::getSrcRegion()
+  {
+    return _srcRegion;
+  }
+  /**
+   *  Accessor to target region
+   *
+   * @return   reference to target region
+   */
+  MeshRegion& RegionNode::getTargetRegion()
+  {
+    return _targetRegion;
+  }
+
+};
index e21ea864f705ae24cc35ff5e1235684ee6fbfbb3..24caeadca0f52e468e0ba0f8f1300b13ae8712df 100644 (file)
@@ -1,8 +1,11 @@
 #ifndef __REGION_NODE_HXX__
 #define __REGION_NODE_HXX__
 
+#include "MeshRegion.hxx"
+
 namespace INTERP_UTILS
 {
+
   /**
    * Class containing a tuplet of a source region and a target region. 
    * This is used as the object to put on the stack in the depth-first search
@@ -26,14 +29,18 @@ namespace INTERP_UTILS
     ~RegionNode();
 
     /**
+     *  Accessor to source region
      *
+     * @return   reference to source region
      */
-    MeshRegion& getSrcRegion() const;
+    MeshRegion& getSrcRegion();
     
     /**
+     *  Accessor to target region
      *
+     * @return   reference to target region
      */
-    MeshRegion& getTargetRegion() const;
+    MeshRegion& getTargetRegion();
 
 
   private: