Salome HOME
Updated copyright comment
[modules/hexablock.git] / src / HEXABLOCK / HexQuad.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 32089b2..9dd8158
@@ -1,17 +1,39 @@
 
 // C++ : Gestion des Quadrangles
 
+// Copyright (C) 2009-2024  CEA, EDF
+//
+// 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 "HexQuad.hxx"
 
 #include "HexDocument.hxx"
 #include "HexHexa.hxx"
 #include "HexElements.hxx"
+#include "HexGlobale.hxx"
 
 #include "HexXmlWriter.hxx"
-#include "HexShape.hxx"
+#include "HexNewShape.hxx"
+#include "HexFaceShape.hxx"
 
 BEGIN_NAMESPACE_HEXA
 
+bool db = on_debug();
+
 // ======================================================== Constructeur
 Quad::Quad (Vertex* va, Vertex* vb, Vertex* vc, Vertex* vd)
     : EltBase (va->dad(), EL_QUAD)
@@ -20,13 +42,24 @@ Quad::Quad (Vertex* va, Vertex* vb, Vertex* vc, Vertex* vd)
    q_vertex [E_B] = vb;
    q_vertex [E_C] = vc;
    q_vertex [E_D] = vd;
+   q_clone        = NULL;
+   q_orientation  = Q_UNDEFINED;
 
    for (int nro=0 ; nro<QUAD4 ; nro++)
        {
-       q_edge [nro] = new Edge (q_vertex[nro], 
+       q_edge [nro] = new Edge (q_vertex[nro],
                                 q_vertex[(nro+1) MODULO QUAD4]);
+
+       if (BadElement (q_vertex [nro]) || BadElement (q_edge [nro]))
+          setError ();
+       else
+          for (int nv=nro+1 ; nv<QUAD4 ; nv++)
+              if (q_vertex[nv] == q_vertex[nro])
+                 setError ();
        }
 
+   if (el_root != NULL && el_status==HOK)
+       el_root->addQuad (this);
    majReferences ();
 }
 // ======================================================== Constructeur bis
@@ -37,20 +70,60 @@ Quad::Quad (Edge* ea, Edge* eb, Edge* ec, Edge* ed)
    q_edge [E_B] = eb;
    q_edge [E_C] = ec;
    q_edge [E_D] = ed;
+   q_clone       = NULL;
+   q_orientation = Q_UNDEFINED;
 
    for (int nro=0 ; nro<QUAD4 ; nro++)
        {
-       int ns = (nro+1) MODULO QUAD4; 
+       if (BadElement (q_edge[nro]))
+          setError (886);
+       else
+          {
+          for (int nv=nro+1 ; nv<QUAD4 ; nv++)
+              if (q_edge[nv] == q_edge[nro])
+                  setError (887);
+          }
+       }
+
+   if (isValid())
+      {
+                // Cond necessaire : ea disjoint de ec (opposes)
+      int nc = ea->inter (ec);
+      if (nc>=0)
+         {
+         nc = ea->inter (eb);
+         if (nc<0)
+            {
+            q_edge [E_C] = eb;
+            q_edge [E_B] = ec;
+            }
+         else
+            {
+            nc = ea->inter (ed);
+            if (nc<0)
+               {
+               q_edge [E_C] = ed;
+               q_edge [E_D] = ec;
+               }
+            else
+               setError (880);
+            }
+         }
+      }
+
+   for (int nro=0 ; nro<QUAD4 ; nro++)
+       {
+       int prec = (nro+1) MODULO QUAD4;
        Vertex* node = NULL;
-       int nc  = q_edge[nro] -> inter (q_edge[ns]);
+       int nc  = q_edge[nro] -> inter (q_edge[prec]);
        if (nc>=0)
           node = q_edge[nro]->getVertex (nc);
-       else  
-          el_status = 888;
-       q_vertex [ns] = node;
+       else
+          setError (888);
+       q_vertex [prec] = node;
        }
 
-   if (el_status != HOK)
+   if (isBad())
       {
       printf (" +++++++++++++++++++++++++++++++++++++++++++ \n");
       printf (" +++ Quadrangle impossible \n");
@@ -58,7 +131,7 @@ Quad::Quad (Edge* ea, Edge* eb, Edge* ec, Edge* ed)
       dump ();
       printf (" +++++++++++++++++++++++++++++++++++++++++++ \n");
       // el_root->dump ();
-      for (int ned=0; ned<QUAD4; ned++) 
+      for (int ned=0; ned<QUAD4; ned++)
           {
           q_edge[ned]->dumpPlus ();
           }
@@ -68,12 +141,14 @@ Quad::Quad (Edge* ea, Edge* eb, Edge* ec, Edge* ed)
       HexDump (q_vertex[3]);
 
       printf (" +++++++++++++++++++++++++++++++++++++++++++ \n");
-      // exit (1);
+      fatal_error ("Quadrangle impossible");
       }
 
+   if (el_root != NULL && el_status==HOK)
+       el_root->addQuad (this);
    majReferences ();
 }
-// ======================================================== Constructeur bis
+// ======================================================== Constructeur ter
 Quad::Quad (Quad* other)
     : EltBase (other->dad(), EL_QUAD)
 {
@@ -82,14 +157,41 @@ Quad::Quad (Quad* other)
        q_edge   [nro] = NULL;
        q_vertex [nro] = NULL;
        }
+   q_orientation = Q_UNDEFINED;
+   q_clone       = NULL;
+
+   if (el_root != NULL && el_status==HOK)
+       el_root->addQuad (this);
+}
+// ============================================================  getEdge
+Edge* Quad::getEdge (int nro)
+{
+   Edge* elt = NULL;
+   if (nro >=0 && nro < QUAD4 && el_status == HOK && q_edge [nro]->isValid())
+      elt = q_edge [nro];
+
+   DumpStart  ("getEdge", nro);
+   DumpReturn (elt);
+   return elt;
+}
+// ============================================================  getVertex
+Vertex* Quad::getVertex (int nro)
+{
+   Vertex* elt = NULL;
+   if (nro >=0 && nro < QUAD4 && el_status == HOK && q_vertex [nro]->isValid())
+      elt = q_vertex [nro];
+
+   DumpStart  ("getVertex", nro);
+   DumpReturn (elt);
+   return elt;
 }
-// ========================================================= getParent 
+// ========================================================= majReferences
 void Quad::majReferences ()
 {
    for (int nro=0 ; nro<QUAD4 ; nro++)
        q_edge [nro] -> addParent (this);
 }
-// ========================================================= getParent 
+// ========================================================= getParent
 Hexa* Quad::getParent  (int nro)
 {
    return static_cast <Hexa*> (getFather (nro));
@@ -108,7 +210,7 @@ int Quad::anaMerge (Vertex* v1, Vertex* v2, Vertex* tv1[], Edge* te1[])
    int nsp1 = (orig+1)       MODULO QUAD4;
    int nsm1 = (orig+QUAD4-1) MODULO QUAD4;
 
-   if (q_vertex [nsp1] == v2) 
+   if (q_vertex [nsp1] == v2)
       {
       for (int nro=0 ; nro < QUAD4 ; nro++)
           {
@@ -116,7 +218,7 @@ int Quad::anaMerge (Vertex* v1, Vertex* v2, Vertex* tv1[], Edge* te1[])
           te1 [nro] = q_edge   [(orig+nro) MODULO QUAD4];
           }
       }
-   else if (q_vertex [nsm1] == v2) 
+   else if (q_vertex [nsm1] == v2)
       {
       for (int nro=0 ; nro < QUAD4 ; nro++)
           {
@@ -124,13 +226,13 @@ int Quad::anaMerge (Vertex* v1, Vertex* v2, Vertex* tv1[], Edge* te1[])
           te1 [nro] = q_edge   [(orig+QUAD4-nro) MODULO QUAD4];
           }
       }
-   else 
+   else
       return 588;
 
    return HOK;
 }
 // ======================================================== ordoVertex
-int Quad::ordoVertex (Vertex* v1, Vertex* v2, Vertex* tv1[])
+int Quad::ordoVertex (Vertex* v1, Vertex* v2, Vertex* tver[])
 {
    int orig = NOTHING;
    for (int nro=0 ; orig == NOTHING && nro < QUAD4 ; nro++)
@@ -143,21 +245,36 @@ int Quad::ordoVertex (Vertex* v1, Vertex* v2, Vertex* tv1[])
    int nsp1 = (orig+1)       MODULO QUAD4;
    int nsm1 = (orig+QUAD4-1) MODULO QUAD4;
 
-   if (q_vertex [nsp1] == v2) 
+   if (q_vertex [nsp1] == v2)
       {
       for (int nro=0 ; nro < QUAD4 ; nro++)
-          tv1 [nro] = q_vertex [(orig+nro) MODULO QUAD4];
+          tver [nro] = q_vertex [(orig+nro) MODULO QUAD4];
       }
-   else if (q_vertex [nsm1] == v2) 
+   else if (q_vertex [nsm1] == v2)
       {
       for (int nro=0 ; nro < QUAD4 ; nro++)
-          tv1 [nro] = q_vertex [(orig+QUAD4-nro) MODULO QUAD4];
+          tver [nro] = q_vertex [(orig+QUAD4-nro) MODULO QUAD4];
       }
-   else 
+   else
       return 588;
 
    return HOK;
 }
+// ======================================================== ordonner
+int Quad::ordonner (Vertex* v1, Vertex* v2, Vertex* tver[], Edge* ted[])
+{
+   tver [0] = tver [1] = tver [2] = tver [3] = NULL;
+   ted  [0] = ted  [1] = ted  [2] = ted  [3] = NULL;
+
+   int ier = ordoVertex (v1, v2, tver);
+   if (ier != HOK)
+       return ier;
+
+   for (int nro=0 ; nro < QUAD4 ; nro++)
+       ted [nro] = findEdge (tver[nro], tver [(nro+1) MODULO QUAD4]);
+
+   return HOK;
+}
 // ======================================================== getBrother
 Quad* Quad::getBrother (StrOrient* orient)
 {
@@ -184,8 +301,8 @@ Quad* Quad::getBrother (StrOrient* orient)
            break;
       case OR_RIGHT : n21 = n22 + sens;
            break;
-      case OR_FRONT : n21 += 2; 
-                      n22 += 2; 
+      case OR_FRONT : n21 += 2;
+                      n22 += 2;
            break;
       default : ;
       }
@@ -197,7 +314,7 @@ Quad* Quad::getBrother (StrOrient* orient)
    orient->v22 = q_vertex [n22];
 
    Edge* arete  = findEdge (orient->v21, orient->v22);
-   arete->printName("\n");
+   // arete->printName("\n");
 
    int nbfreres = arete->getNbrParents ();
 
@@ -211,7 +328,7 @@ Quad* Quad::getBrother (StrOrient* orient)
           int   mark  = next->getMark();
           int   mark2 = dad ? dad->getMark() : IS_NONE;
 
-          if (nbp  <= 1  && mark2 != IS_MARRIED && mark == IS_NONE)
+          if (nbp  == 1  && mark2 != IS_MARRIED && mark == IS_NONE)
              return next;
           // if (nbp  <= 1  && mark == IS_NONE)
              // return next;
@@ -222,8 +339,13 @@ Quad* Quad::getBrother (StrOrient* orient)
 // ======================================================== coupler
 int Quad::coupler (Quad* other, StrOrient* orient, Elements* table)
 {
-   if (other==NULL) 
+   if (other==NULL)
       return HERR;
+   if (db)
+      {
+      std::cout << " Quads::coupler " << el_name << " -> " << other->getName () 
+               << std::endl;
+      }
 
    Hexa* hexa = other->getParent(0);
 
@@ -234,8 +356,8 @@ int Quad::coupler (Quad* other, StrOrient* orient, Elements* table)
 
    for (int ned = 0 ; ned < QUAD4 ; ned++)
        {
-       Edge* arete  = q_edge[ned]; 
-       int nbfreres = arete ->getNbrParents (); 
+       Edge* arete  = q_edge[ned];
+       int nbfreres = arete ->getNbrParents ();
        for (int nq = 0 ; nq < nbfreres ; nq++)
            {
            Quad* next = arete->getParent (nq);
@@ -243,8 +365,8 @@ int Quad::coupler (Quad* other, StrOrient* orient, Elements* table)
               {
               StrOrient new_ori (orient);
               new_ori.dir = OR_FRONT;
-              Vertex* va  = arete->getVertex (V_AMONT); 
-              Vertex* vb  = arete->getVertex (V_AVAL); 
+              Vertex* va  = arete->getVertex (V_AMONT);
+              Vertex* vb  = arete->getVertex (V_AVAL);
 
 //    On voit si un point de repere est conserve
               if (va == orient->v11)
@@ -285,13 +407,25 @@ int Quad::coupler (Quad* other, StrOrient* orient, Elements* table)
 
               int nro = next->getMark ();
               Quad* beauf = other->getBrother (&new_ori);
-              table->coupler (nro, beauf, &new_ori);
-              next->coupler (beauf, &new_ori, table);
+              int ier = table->coupler (nro, beauf, &new_ori);
+              if (ier != HOK)
+                 return ier;
+              ier = next->coupler (beauf, &new_ori, table);
+              if (ier != HOK)
+                 return ier;
               }
            }
        }
    return HOK;
 }
+// ======================================================== getOpposVertex
+Vertex* Quad::getOpposVertex (Vertex* start)
+{
+   int  na = indexVertex (start);
+   if (na==NOTHING)
+      return NULL;
+   return  q_vertex [(na+2) MODULO QUAD4];
+}
 // ======================================================== getOpposEdge
 Edge* Quad::getOpposEdge (Edge* start, int& sens)
 {
@@ -318,17 +452,25 @@ Edge* Quad::getOpposEdge (Edge* start, int& sens)
            }
        }
    //             TODO : traiter l'erreur
+   std::cout << " ... Probleme dans Quad::getOpposedEdge :" << std::endl;
+   HexDisplay (el_name);
+   PutName (start);
+   PutName (vaprim);
+   PutName (vbprim);
+   HexDisplay (na);
+   HexDisplay (nb);
    dumpPlus ();
+
    for (int ned = 0 ; ned < QUAD4 ; ned++)
        q_edge[ned]->dump();
 
    return NULL;
 }
-// ========================================================= getParent 
-void Quad::saveXml (XmlWriter& xml)
+// ========================================================= saveXml
+void Quad::saveXml (XmlWriter* xml)
 {
    char buffer[12];
-   string edges;
+   std::string edges;
 
    for (int nro=0 ; nro<QUAD4 ; nro++)
        {
@@ -336,19 +478,24 @@ void Quad::saveXml (XmlWriter& xml)
        edges += q_edge[nro]->getName(buffer);
        }
 
-   xml.openMark     ("Quad");
-   xml.addAttribute ("id",    getName (buffer));
-   xml.addAttribute ("edges", edges);
-   if (el_assoc!=NULL)
-      xml.addAttribute ("shape", el_assoc->getBrep().c_str());
-   xml.closeMark ();
+   xml->openMark     ("Quad");
+   xml->addAttribute ("id",    getName (buffer));
+   xml->addAttribute ("edges", edges);
+   if (el_name!=buffer)
+       xml->addAttribute ("name", el_name);
+   xml->closeMark ();
+
+   int nbass = tab_assoc.size();
+   for (int nro=0 ; nro<nbass ; nro++)
+       if (tab_assoc[nro] != NULL)
+           tab_assoc[nro]->saveXml (xml);
 }
 // ======================================================== replaceEdge
 void Quad::replaceEdge (Edge* old, Edge* par)
 {
    for (int nro=0 ; nro<QUAD4 ; nro++)
        {
-       if (q_edge[nro]==old) 
+       if (q_edge[nro]==old)
            {
            q_edge[nro] = par;
           if (debug())
@@ -367,7 +514,7 @@ void Quad::replaceVertex (Vertex* old, Vertex* par)
 {
    for (int nro=0 ; nro<QUAD4 ; nro++)
        {
-       if (q_vertex [nro]==old) 
+       if (q_vertex [nro]==old)
           {
           q_vertex [nro] = par;
           if (debug())
@@ -393,14 +540,17 @@ void Quad::dump ()
 
    for (int nro=0 ; nro<QUAD4 ; nro++)
         PrintName (q_edge[nro]);
-   printf (")\n" );
+   printf (")\n");
 
-   printf ("        (" );
+   printf ("        (");
    for (int nro=0 ; nro<QUAD4 ; nro++)
         PrintName (q_vertex[nro]);
-   printf (")" );
+   printf (")");
 
    dumpRef ();
+   Real3 cg;
+   getCenter (cg);
+   printf ("     -> (%g, %g, %g)\n", cg[dir_x], cg[dir_y], cg[dir_z]);
 }
 // ======================================================== dumpPlus
 void Quad::dumpPlus ()
@@ -424,4 +574,308 @@ void Quad::dumpPlus ()
           }
        }
 }
+// ======================================================== getOpposEdge (2)
+Edge* Quad::getOpposEdge (Edge* start)
+{
+   int  na = indexEdge (start);
+   if (na<0)
+      return NULL;
+   return q_edge [(na+2) MODULO QUAD4];
+}
+// ======================================================== getPerpendicular
+Edge* Quad::getPerpendicular (Edge* arete, Vertex* node)
+{
+   int na = indexEdge (arete);
+   if (na<0)
+      return NULL;
+
+   int nv = arete->index (node);
+   if (nv<0)
+      return NULL;
+   Edge* perp = q_edge [(na+1) MODULO QUAD4];
+
+   nv = perp->index (node);
+   if (nv>=0)
+      return perp;
+
+   perp = q_edge [(na+3) MODULO QUAD4];
+   nv   = perp->index (node);
+   if (nv>=0)
+      return perp;
+   else
+      return NULL;
+}
+static cpchar t_ori[] = {"Q_INSIDE", "Q_DIRECT", "Q_INVERSE", "Q_UNDEF"};
+// ======================================================== setOrientation
+void Quad::setOrientation (int ori)
+{
+    q_orientation = ori;
+    if (db && (ori==Q_DIRECT || ori==Q_INVERSE))
+       printf (" %s = %s\n", el_name.c_str(), t_ori [ q_orientation ]);
+}
+// ======================================================== setOrientation
+int Quad::setOrientation ()
+{
+    q_orientation = Q_INSIDE;
+    if (getNbrParents() != 1)
+       return q_orientation;
+
+    Real3 cg, orig, pi, pj, vi, vj, vk;
+
+    Hexa* hexa = getParent(0);
+    hexa->getCenter (cg);
+
+/********************************************************************
+    printName (" = ");
+
+    for (int np=0 ; np < QUAD4 ; np++)
+        {
+        q_vertex [np        ] -> getPoint (orig);
+        q_vertex [(np+1) % 4] -> getPoint (pi);
+        q_vertex [(np+3) % 4] -> getPoint (pj);
+
+        calc_vecteur (orig, pi, vi);
+        calc_vecteur (orig, pj, vj);
+        calc_vecteur (orig, cg, vk);
+        double pmixte = prod_mixte (vi, vj, vk);
+        q_orientation = pmixte > ZEROR ? Q_DIRECT : Q_INVERSE;
+        if (pmixte>0) printf (">");
+           else       printf ("<");
+        }
+
+    printf ("\n");
+    return;
+  ******************************************************************* */
+    q_vertex [0] -> getPoint (orig);
+    q_vertex [1] -> getPoint (pi);
+    q_vertex [3] -> getPoint (pj);
+
+    calc_vecteur (orig, pi, vi);
+    calc_vecteur (orig, pj, vj);
+    calc_vecteur (cg, orig, vk);
+
+    double pmixte = prod_mixte (vi, vj, vk);
+    q_orientation = pmixte > ZEROR ? Q_DIRECT : Q_INVERSE;
+    if (db)
+       printf (" %s := %s\n", el_name.c_str(), t_ori [ q_orientation ]);
+    return q_orientation;
+}
+// ========================================================== clearAssociation
+void Quad::clearAssociation ()
+{
+   tab_assoc.clear ();
+   is_associated = false;
+}
+// ========================================================== addAssociation
+int Quad::addAssociation (NewShape* geom, int subid)
+{
+   if (geom == NULL)
+      return HERR;
+
+   FaceShape* face = geom->findFace (subid);
+   int ier = addAssociation (face);
+
+   return ier;
+}
+// ========================================================== addAssociation
+int Quad::addAssociation (FaceShape* face)
+{
+   if (face == NULL)
+      return HERR;
+
+   face->addAssociation (this);
+   tab_assoc.push_back (face);
+   is_associated = true;
+   return HOK;
+}
+// ========================================================== getAssociation
+FaceShape* Quad::getAssociation (int nro)
+{
+   if (nro < 0 || nro >= (int)tab_assoc.size())
+      return NULL;
+
+   return tab_assoc [nro];
+}
+// ======================================================== commonEdge
+Edge* Quad::commonEdge (Quad* other)
+{
+   for (int ne1=0 ; ne1<QUAD4 ; ne1++)
+       for (int ne2=0 ; ne2<QUAD4 ; ne2++)
+           if (q_edge [ne1] == other->q_edge [ne2])
+              return q_edge [ne1];
+
+   return NULL;
+}
+// ======================================================== Inter
+int Quad::inter (Quad* other, int& nother)
+{
+   for (int ne1=0 ; ne1<QUAD4 ; ne1++)
+       for (int ne2=0 ; ne2<QUAD4 ; ne2++)
+           if (q_edge [ne1] == other->q_edge [ne2])
+              {
+              nother = ne2;
+              return  ne1;
+              }
+
+   nother = NOTHING;
+   return NOTHING;
+}
+// ======================================================== Inter (2)
+Edge* Quad::inter (Quad* other)
+{
+   for (int ne1=0 ; ne1<QUAD4 ; ne1++)
+       for (int ne2=0 ; ne2<QUAD4 ; ne2++)
+           if (q_edge [ne1] == other->q_edge [ne2])
+              return  q_edge [ne1];
+   return NULL;
+}
+// ============================================================ definedBy (v)
+bool Quad::definedBy  (Vertex* v1, Vertex* v2)
+{
+   for (int n1=0 ; n1< QUAD4 ; n1++)
+       if (v1 == q_vertex[n1] && v2 == q_vertex[(n1+2) MODULO QUAD4])
+          return true;
+
+   return false;
+}
+// ============================================================ definedBy (e)
+bool Quad::definedBy  (Edge* e1, Edge* e2)
+{
+   if (e1==e2 || BadElement (e1) || BadElement (e2))
+      return false;
+
+   bool f1=false, f2=false;
+   for (int ned=0 ; ned< QUAD4 ; ned++)
+       if      (e1 == q_edge[ned]) f1 = true;
+       else if (e2 == q_edge[ned]) f2 = true;
+    // if (e1 == q_edge[ned] && e2 == q_edge[(ned+2) MODULO QUAD4]) return true;
+
+   return f1 && f2;
+}
+// =============================================================== findEdge
+Edge* Quad::findEdge (Vertex* v1, Vertex* v2)
+{
+   for (int nro=0 ; nro< QUAD4 ; nro++)
+       {
+       Vertex* va = q_edge[nro]->getVertex(V_AMONT) ;
+       Vertex* vb = q_edge[nro]->getVertex(V_AVAL) ;
+       if ((v1==va && v2==vb) || (v1==vb && v2==va))
+           return q_edge [nro];
+       }
+
+   return NULL;
+}
+// =============================================================== indexVertex
+int Quad::indexVertex  (Vertex* elt)
+{
+   for (int n1=0 ; n1< QUAD4 ; n1++)
+       if (elt == q_vertex[n1])
+          return n1;
+
+   return NOTHING;
+}
+// =============================================================== indexEdge
+int Quad::indexEdge  (Edge* elt)
+{
+   for (int n1=0 ; n1< QUAD4 ; n1++)
+       if (elt == q_edge[n1])
+          return n1;
+
+   return NOTHING;
+}
+// =============================================================== setColor
+void Quad::setColor  (double val)
+{
+   for (int n1=0 ; n1< QUAD4 ; n1++)
+       q_vertex[n1] -> setColor (val);
+}
+// =============================================================== duplicate
+void Quad::duplicate  ()
+{
+   q_orientation  = Q_UNDEFINED;
+   q_clone = new Quad (GetClone (q_edge [E_A]),
+                       GetClone (q_edge [E_B]),
+                       GetClone (q_edge [E_C]),
+                       GetClone (q_edge [E_D]));
+   q_clone->tab_assoc  = tab_assoc;
+}
+// ============================================================ nearestVertex
+Vertex* Quad::nearestVertex (Vertex* other)
+{
+   if (BadElement (other))
+      return NULL;
+   Vertex* vsol = NULL;
+   double  dmin = 1e+77;
+   int nbre = countVertex ();
+   for (int nro=0 ; nro<nbre ; nro++)
+       {
+       Vertex* vert = getVertex (nro);
+       double  dist = other->dist2 (vert);
+       if (dist < dmin)
+          {
+          dmin = dist;
+          vsol = vert; 
+          }
+       }
+   return vsol;
+}
+// =============================================================== reorienter
+void Quad::reorienter  ()
+{
+   if (q_orientation != Q_INVERSE)
+         return;
+
+   Edge* edge   = q_edge [E_B];
+   q_edge [E_B] = q_edge [E_D];
+   q_edge [E_B] = edge;
+
+   q_vertex [E_A] = q_edge [E_D]->commonVertex(q_edge [E_A]);
+   q_vertex [E_B] = q_edge [E_A]->commonVertex(q_edge [E_B]);
+   q_vertex [E_C] = q_edge [E_B]->commonVertex(q_edge [E_C]);
+   q_vertex [E_D] = q_edge [E_C]->commonVertex(q_edge [E_D]);
+
+   if (db)
+       printf (" %s est reoriente\n", el_name.c_str());
+   q_orientation = Q_DIRECT;
+}
+// =============================================================== getCenter
+double* Quad::getCenter (double* center)
+{
+   center[dir_x] = center[dir_y] = center[dir_z] =  0;
+   if (BadElement (this))
+      return NULL;
+
+   for (int nv=0 ; nv<QUAD4 ; nv++)
+       {
+       if (BadElement (q_vertex [nv]))
+           return NULL;
+       center [dir_x] += q_vertex[nv]->getX()/4;
+       center [dir_y] += q_vertex[nv]->getY()/4;
+       center [dir_z] += q_vertex[nv]->getZ()/4;
+       }
+    return center;
+}
+// =============================================================== dist2
+double Quad::dist2 (double* point)
+{
+   Real3 center;
+   getCenter (center);
+   double d2 = carre (point[dir_x] - center[dir_x]) 
+             + carre (point[dir_y] - center[dir_y]) 
+             + carre (point[dir_z] - center[dir_z]) ;
+   return d2;
+}
+// =============================================================== opposedHexa
+Hexa* Quad::opposedHexa (Hexa* hexa)
+{
+   int nbre = getNbrParents ();
+   for (int nro=0 ; nro <nbre ; ++nro)
+       { 
+       Hexa* dad = getParent (nro);
+       if (dad!= NULL && dad->isValid() && dad != hexa)
+           return dad;
+       }
+   return NULL;
+}
 END_NAMESPACE_HEXA