Salome HOME
Merge branch 'V7_dev'
[modules/hexablock.git] / src / HEXABLOCK / HexHexa.cxx
index 1262902b4623a63dc7f390c06c0faf078c2be07c..fd76993f19626797d59f566628517d89fd90df9c 100755 (executable)
@@ -1,6 +1,24 @@
 
 // C++ : Gestion des Hexaedres
 
+// Copyright (C) 2009-2016  CEA/DEN, 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 "HexHexa.hxx"
 #include "HexQuad.hxx"
 
@@ -15,7 +33,6 @@
 #include "HexMatrix.hxx"
 #include "HexElements.hxx"
 
-
 BEGIN_NAMESPACE_HEXA
 
 // ======================================================== Constructeur
@@ -24,14 +41,16 @@ Hexa::Hexa (Vertex* va, Vertex* vb, Vertex* vc, Vertex* vd,
     : EltBase (va->dad(), EL_HEXA)
 {
    h_vertex [V_ACE] = va;
-   h_vertex [V_ACF] = vb;
-   h_vertex [V_ADF] = vc;
-   h_vertex [V_ADE] = vd;
+   h_vertex [V_ACF] = vb;   // = vc ; Modif Abu 30/08/2011
+   h_vertex [V_ADE] = vc;   // = vb ; Modif Abu 30/08/2011
+   h_vertex [V_ADF] = vd;
 
    h_vertex [V_BCE] = ve;
-   h_vertex [V_BCF] = vf;
-   h_vertex [V_BDF] = vg;
-   h_vertex [V_BDE] = vh;
+   h_vertex [V_BCF] = vf;   // = vg ; Modif Abu 30/08/2011
+   h_vertex [V_BDE] = vg;   // = vf ; Modif Abu 30/08/2011
+   h_vertex [V_BDF] = vh;
+
+   h_clone          = NULL;
 
    controlerSommets ();
 
@@ -39,7 +58,7 @@ Hexa::Hexa (Vertex* va, Vertex* vb, Vertex* vc, Vertex* vd,
 
    for (int nro=0 ; nro<HE_MAXI ; nro++)
        {
-       h_edge[nro] = new Edge (h_vertex[glob->EdgeVertex (nro, V_AMONT)], 
+       h_edge[nro] = new Edge (h_vertex[glob->EdgeVertex (nro, V_AMONT)],
                                h_vertex[glob->EdgeVertex (nro, V_AVAL)]);
        }
 
@@ -53,6 +72,8 @@ Hexa::Hexa (Vertex* va, Vertex* vb, Vertex* vc, Vertex* vd,
        h_quad[nro] -> addParent (this);
        }
    majReferences ();
+   if (el_root != NULL && el_status==HOK)
+       el_root->addHexa (this);
 }
 // ======================================================== Constructeur 2
 Hexa::Hexa (Quad* qa, Quad* qb, Quad* qc, Quad* qd, Quad* qe, Quad* qf)
@@ -64,6 +85,7 @@ Hexa::Hexa (Quad* qa, Quad* qb, Quad* qc, Quad* qd, Quad* qe, Quad* qf)
    h_quad [Q_D] = qd;
    h_quad [Q_E] = qe;
    h_quad [Q_F] = qf;
+   h_clone      = NULL;
 
    for (int nb=0 ; nb<HE_MAXI ; nb++) h_edge   [nb] = NULL;
    for (int nb=0 ; nb<HV_MAXI ; nb++) h_vertex [nb] = NULL;
@@ -75,7 +97,7 @@ Hexa::Hexa (Quad* qa, Quad* qb, Quad* qc, Quad* qd, Quad* qe, Quad* qf)
    majReferences   ();
 
    if (el_status != HOK)
-      {      
+      {
       printf (" +++++++++++++++++++++++++++++++++++++++++++ \n");
       printf (" +++ Heaedre impossible \n");
       printf (" +++++++++++++++++++++++++++++++++++++++++++ \n");
@@ -88,6 +110,8 @@ Hexa::Hexa (Quad* qa, Quad* qb, Quad* qc, Quad* qd, Quad* qe, Quad* qf)
       printf (" +++++++++++++++++++++++++++++++++++++++++++ \n");
       // exit (1);
       }
+   else
+       el_root->addHexa (this);
 }
 // =========================================================  Constructeur 3
 // === a utiliser uniquement pour le clonage
@@ -97,6 +121,10 @@ Hexa::Hexa (Hexa* other)
    for (int nro=0 ; nro<HQ_MAXI ; nro++) h_quad   [nro] = NULL;
    for (int nro=0 ; nro<HE_MAXI ; nro++) h_edge   [nro] = NULL;
    for (int nro=0 ; nro<HV_MAXI ; nro++) h_vertex [nro] = NULL;
+   h_clone = NULL;
+
+   if (el_root != NULL && el_status==HOK)
+       el_root->addHexa (this);
 }
 // ======================================================== majReferences
 void Hexa::majReferences  ()
@@ -110,7 +138,7 @@ void Hexa::controlerArete  (int arete, int face1, int face2)
    h_edge [arete] = h_quad[face1]->commonEdge (h_quad[face2]);
    if (h_edge [arete]==NULL)
        {
-       el_root->putError (W_H_BAD_EDGE, 
+       el_root->putError (W_H_BAD_EDGE,
                           el_root->glob->namofHexaEdge (arete));
        el_status = 888;
        }
@@ -125,67 +153,99 @@ void Hexa::controlerSommet  (int node, int ne1, int ne2, int ne3)
     h_vertex [node] = hv;
     if (hv == NULL)
        {
-       el_root->putError (W_H_BAD_VERTEX, 
+       el_root->putError (W_H_BAD_VERTEX,
                           el_root->glob->namofHexaVertex(node));
        el_status = 888;
        }
     else if (hv == NULL || h_edge[ne3]->index (hv)<0)
        {
        char b[10];
-       el_root->putError (W_H_BAD_VERTEX, 
+       el_root->putError (W_H_BAD_VERTEX,
                           el_root->glob->namofHexaVertex(node));
        el_status = 888;
-       printf ("%s = %s\n", el_root->glob->namofHexaVertex(node), 
+       printf ("%s = %s\n", el_root->glob->namofHexaVertex(node),
                             hv->getName(b));
-       printf ("%s = %s\n", el_root->glob->namofHexaEdge(ne1), 
+       printf ("%s = %s\n", el_root->glob->namofHexaEdge(ne1),
                             h_edge[ne1]->getName(b));
-       printf ("%s = %s\n", el_root->glob->namofHexaEdge(ne2), 
+       printf ("%s = %s\n", el_root->glob->namofHexaEdge(ne2),
                             h_edge[ne2]->getName(b));
-       printf ("%s = %s\n", el_root->glob->namofHexaEdge(ne3), 
+       printf ("%s = %s\n", el_root->glob->namofHexaEdge(ne3),
                             h_edge[ne3]->getName(b));
        }
 }
 // ======================================================== controlerFaces
 void Hexa::controlerFaces  ()
 {
-   for (int n1=0 ; n1<HQ_MAXI ; n1++) 
+   for (int n1=0 ; n1<HQ_MAXI ; n1++)
        {
-       if (h_quad [n1] == NULL)
+       if (BadElement (h_quad [n1]))
           {
-          el_root->putError (W_H_NULL_QUAD, 
+          el_root->putError (W_H_NULL_QUAD,
                              el_root->glob->namofHexaQuad (n1));
-          el_status = 886;
-         return;
+          setError (886);
+          return;
           }
-       for (int n2=n1+1 ; n2<HQ_MAXI ; n2++) 
+       for (int n2=n1+1 ; n2<HQ_MAXI ; n2++)
            if (h_quad [n1] == h_quad[n2])
               {
-              el_root->putError (W_H_EQ_QUAD, 
-                         el_root->glob->namofHexaQuad (n1), 
+              el_root->putError (W_H_EQ_QUAD,
+                         el_root->glob->namofHexaQuad (n1),
                          el_root->glob->namofHexaQuad (n2));
-              el_status = 888;
+              setError (888);
               }
        }
+   for (int dd=0 ; dd<DIM3 ; dd++)
+       {
+       Quad* qa  = h_quad [2*dd];
+       Quad* qb  = h_quad [2*dd+1];
+       Edge* cut = qa->inter (qb);
+       if (cut != NULL)
+          {
+          bool more = true;
+          for (int nc=2*dd+2 ; more && nc<HQ_MAXI ; nc++)
+              {
+              Edge* cut = qa->inter (h_quad[nc]);
+              if (cut==NULL)
+                 {
+                 more = false;
+                 // cout << " ... le quad oppose au quad " << 2*dd
+                      // << " est le " << nc << endl;
+                 qb             = h_quad[nc];
+                 h_quad[nc]     = h_quad [2*dd+1];
+                 h_quad[2*dd+1] = qb;
+                 }
+              }
+          if (more)
+             {
+             char num [10];
+             sprintf (num, "%d", 2*dd+1);
+             el_root->putError ("addHexa : the %sth quad has no opposed quad",
+                                 num);
+             setError (886);
+             return ;
+             }
+          }
+       }
 }
 // ======================================================== controlerSommets
 void Hexa::controlerSommets  ()
 {
-   for (int n1=0 ; n1<HV_MAXI ; n1++) 
+   for (int n1=0 ; n1<HV_MAXI ; n1++)
        {
-       if (h_vertex [n1] == NULL)
+       if (BadElement (h_vertex [n1]))
           {
-          el_root->putError (W_H_NULL_QUAD, 
+          el_root->putError (W_H_NULL_QUAD,
                              el_root->glob->namofHexaVertex (n1));
-          el_status = 886;
-         return;
+          setError (886);
+          return;
           }
-       for (int n2=n1+1 ; n2<HQ_MAXI ; n2++) 
+       for (int n2=n1+1 ; n2<HQ_MAXI ; n2++)
            if (h_vertex [n1] == h_vertex[n2])
               {
-              el_root->putError (W_H_EQ_QUAD, 
-                         el_root->glob->namofHexaVertex (n1), 
+              el_root->putError (W_H_EQ_QUAD,
+                         el_root->glob->namofHexaVertex (n1),
                          el_root->glob->namofHexaVertex (n2));
-              el_status = 888;
+              setError (888);
               }
        }
 }
@@ -222,7 +282,7 @@ void Hexa::verifierSommets  ()
    controlerSommet (V_BCE, E_BC, E_BE, E_CE);
    controlerSommet (V_BCF, E_BC, E_BF, E_CF);
    controlerSommet (V_BDF, E_BD, E_BF, E_DF);
-   controlerSommet (V_BDE, E_BD, E_BE, E_DE); 
+   controlerSommet (V_BDE, E_BD, E_BE, E_DE);
 }
 // ======================================================== Inter
 Quad* Hexa::Inter (Hexa* other)
@@ -240,15 +300,15 @@ Quad* Hexa::Inter (Hexa* other)
 // ======================================================= razNodes
 void Hexa::razNodes ()
 {
-   for (int nb=0 ; nb<HV_MAXI ; nb++) 
+   for (int nb=0 ; nb<HV_MAXI ; nb++)
        h_vertex[nb]->setMark (NO_COUNTED);
 }
 // ======================================================= countNodes
 int Hexa::countNodes ()
 {
    int nombre = 0;
-   for (int nb=0 ; nb<HV_MAXI ; nb++) 
-       if (h_vertex[nb]->getMark () == NO_COUNTED) 
+   for (int nb=0 ; nb<HV_MAXI ; nb++)
+       if (h_vertex[nb]->getMark () == NO_COUNTED)
           {
           h_vertex[nb]->setMark (NO_USED);
           nombre ++;
@@ -259,12 +319,18 @@ int Hexa::countNodes ()
 // ======================================================= printNodes
 void Hexa::printNodes (pfile vtk, int& compteur)
 {
-   for (int nb=0 ; nb<HV_MAXI ; nb++) 
+   const double minvtk = 1e-30;
+   Real3 koord;
+
+   for (int nb=0 ; nb<HV_MAXI ; nb++)
        if (h_vertex[nb]->getMark()==NO_USED)
           {
-          fprintf (vtk, "%g %g %g\n", h_vertex[nb]->getX(),
-                                      h_vertex[nb]->getY(), 
-                                      h_vertex[nb]->getZ());
+          h_vertex[nb]->getPoint (koord);
+          for (int nc=dir_x ; nc<=dir_z ; nc++)
+              if (koord [nc] < minvtk &&  koord [nc] > -minvtk)
+                  koord[nc] = 0.0;
+
+          fprintf (vtk, "%g %g %g\n", koord[dir_x], koord[dir_y], koord[dir_z]);
           h_vertex[nb]->setMark (compteur);
           compteur ++;
           }
@@ -272,7 +338,7 @@ void Hexa::printNodes (pfile vtk, int& compteur)
 // ======================================================= colorNodes
 void Hexa::colorNodes (pfile vtk)
 {
-   for (int nb=0 ; nb<HV_MAXI ; nb++) 
+   for (int nb=0 ; nb<HV_MAXI ; nb++)
        if (h_vertex[nb]->getMark()>=0)
           {
           double color = 100*(h_vertex[nb]->getScalar()+1);
@@ -283,7 +349,7 @@ void Hexa::colorNodes (pfile vtk)
 // ======================================================= moveNodes
 void Hexa::moveNodes (Matrix* matrice)
 {
-   for (int nb=0 ; nb<HV_MAXI ; nb++) 
+   for (int nb=0 ; nb<HV_MAXI ; nb++)
        if (h_vertex[nb]->getMark()!=IS_USED)
           {
           matrice->perform (h_vertex[nb]);
@@ -293,7 +359,7 @@ void Hexa::moveNodes (Matrix* matrice)
 // ======================================================= transform
 void Hexa::transform (Matrix* matrice)
 {
-   for (int nb=0 ; nb<HV_MAXI ; nb++) 
+   for (int nb=0 ; nb<HV_MAXI ; nb++)
        matrice->perform (h_vertex[nb]);
 }
 // ======================================================= printHexa
@@ -313,6 +379,23 @@ void Hexa::printHexa  (pfile vtk)
 
    fprintf (vtk, "\n");
 }
+// ======================================================= printHexaVtk
+void Hexa::printHexaVtk (pfile vtk)
+{
+   fprintf (vtk, "%d", HV_MAXI);
+
+   fprintf (vtk, " %d", h_vertex[V_ACE]->getId ());
+   fprintf (vtk, " %d", h_vertex[V_ACF]->getId ());
+   fprintf (vtk, " %d", h_vertex[V_ADF]->getId ());
+   fprintf (vtk, " %d", h_vertex[V_ADE]->getId ());
+
+   fprintf (vtk, " %d", h_vertex[V_BCE]->getId ());
+   fprintf (vtk, " %d", h_vertex[V_BCF]->getId ());
+   fprintf (vtk, " %d", h_vertex[V_BDF]->getId ());
+   fprintf (vtk, " %d", h_vertex[V_BDE]->getId ());
+
+   fprintf (vtk, "\n");
+}
 // ======================================================== hasFreEdges
 bool Hexa::hasFreeEdges ()
 {
@@ -335,8 +418,8 @@ void Hexa::propager (Propagation* prop, int nro)
        if (h_edge[nro]->getMark()<0)
            h_edge[nro]->propager (prop, nro);
 }
-// ========================================================= saveXml 
-void Hexa::saveXml (XmlWriter& xml)
+// ========================================================= saveXml
+void Hexa::saveXml (XmlWriter* xml)
 {
    char ident[12];
    string quads;
@@ -348,12 +431,14 @@ void Hexa::saveXml (XmlWriter& xml)
        }
 
    getName (ident);
-   xml.openMark     ("Hexa");
-   xml.addAttribute ("id",    ident);
-   xml.addAttribute ("quads", quads);
-   xml.closeMark ();
+   xml->openMark     ("Hexa");
+   xml->addAttribute ("id",    ident);
+   xml->addAttribute ("quads", quads);
+   if (el_name!=ident)
+       xml->addAttribute ("name", el_name);
+   xml->closeMark ();
 }
-// ========================================================= findQuad 
+// ========================================================= findQuad
 int Hexa::findQuad (Quad* element)
 {
    for (int nro=0 ; nro<HQ_MAXI ; nro++)
@@ -362,7 +447,7 @@ int Hexa::findQuad (Quad* element)
 
    return NOTHING;
 }
-// ========================================================= findEdge 
+// ========================================================= findEdge
 int Hexa::findEdge (Edge* element)
 {
    for (int nro=0 ; nro<HE_MAXI ; nro++)
@@ -371,7 +456,7 @@ int Hexa::findEdge (Edge* element)
 
    return NOTHING;
 }
-// ========================================================= findVertex 
+// ========================================================= findVertex
 int Hexa::findVertex (Vertex* element)
 {
    for (int nro=0 ; nro<HV_MAXI ; nro++)
@@ -380,7 +465,7 @@ int Hexa::findVertex (Vertex* element)
 
    return NOTHING;
 }
-// ========================================================= disconnectQuad 
+// ========================================================= disconnectQuad
 Elements* Hexa::disconnectQuad (Quad* quad)
 {
    if (quad==NULL)
@@ -399,7 +484,7 @@ Elements* Hexa::disconnectQuad (Quad* quad)
                                        // Face opposee : replace
    // int nfopp = (nface MODULO 2==0) ? nface+1 : nface-1;
 
-   int  ind_edge  [QUAD4], ind_node  [QUAD4], ind_opp_quad [QUAD4];
+   int  ind_edge  [QUAD4], ind_opp_quad [QUAD4];
    bool make_quad [QUAD4], make_edge [QUAD4];
 
    for (int nro=0 ; nro<QUAD4 ; nro++)
@@ -413,7 +498,6 @@ Elements* Hexa::disconnectQuad (Quad* quad)
        int oppq  = findOpposedQuad (quad, quad->getEdge (nro));
 
        ind_edge [nro]     = pedge;
-       ind_node [nro]     = pnode;
        ind_opp_quad [nro] = oppq;
 
        if (pedge==NOTHING || pnode==NOTHING || oppq==NOTHING)
@@ -435,7 +519,7 @@ Elements* Hexa::disconnectQuad (Quad* quad)
              printf (" a dissocier\n");
           else
              printf ("\n");
-             
+
           }
        }
 
@@ -459,16 +543,16 @@ Elements* Hexa::disconnectQuad (Quad* quad)
        if (make_edge[nro])
           {
           Quad*   pface  = h_quad [ind_opp_quad [nro]];
-         int     bid;
-         int     ncut = pface->inter (quad, bid);
-         Edge*   ecut = pface->getEdge ((ncut+1) MODULO QUAD4);  
-         Vertex* vopp = ecut->getVertex(V_AMONT);
+          int     bid;
+          int     ncut = pface->inter (quad, bid);
+          Edge*   ecut = pface->getEdge ((ncut+1) MODULO QUAD4);
+          Vertex* vopp = ecut->getVertex(V_AMONT);
           if (vopp==o_v0)
               vopp = ecut->getVertex (V_AVAL);
           else if (o_v0 != ecut->getVertex (V_AVAL));
               {
-             ecut = pface->getEdge ((ncut+3) MODULO QUAD4);  
-             vopp = ecut->getVertex(V_AMONT);
+              ecut = pface->getEdge ((ncut+3) MODULO QUAD4);
+              vopp = ecut->getVertex(V_AMONT);
               if (vopp==o_v0)
                   vopp = ecut->getVertex (V_AVAL);
               else if (o_v0 != ecut->getVertex (V_AVAL))
@@ -486,7 +570,7 @@ Elements* Hexa::disconnectQuad (Quad* quad)
           }
        }
 
-   Quad* new_quad = new Quad (new_node[0], new_node[1], new_node[2], 
+   Quad* new_quad = new Quad (new_node[0], new_node[1], new_node[2],
                                                         new_node[3]);
 
    Quad* new_opp_quad [QUAD4];
@@ -497,7 +581,7 @@ Elements* Hexa::disconnectQuad (Quad* quad)
        new_opp_quad [nro] = NULL;
        if (make_quad[nro])
           {
-          int nro1 = (nro+1) MODULO QUAD4; 
+          int nro1 = (nro+1) MODULO QUAD4;
 
           Edge* n_edge0 = new_quad->getEdge (nro);
           Edge* n_edge1 = new_opp_edge [nro];
@@ -507,9 +591,9 @@ Elements* Hexa::disconnectQuad (Quad* quad)
           int iv3 = n_edge3->inter (n_edge0);
           if (iv1 <0 || iv3 <0)
              return NULL;
-          
+
           Quad* o_face = h_quad [ind_opp_quad [nro]];
-          Edge* edge2  = o_face->findEdge (n_edge1->getVertex (1-iv1), 
+          Edge* edge2  = o_face->findEdge (n_edge1->getVertex (1-iv1),
                                            n_edge3->getVertex (1-iv3));
           if (edge2==NULL)
              return NULL;
@@ -524,18 +608,24 @@ Elements* Hexa::disconnectQuad (Quad* quad)
           }
        }
 
+   replaceQuad (quad, new_quad);
+   for (int nro=0 ; nro<QUAD4 ; nro++)
+       if (make_quad[nro])
+          replaceQuad (old_opp_quad [nro], new_opp_quad [nro]);
+
    for (int nro=0 ; nro<QUAD4 ; nro++)
        {
+       replaceEdge (h_edge[ind_edge[nro]], new_quad->getEdge (nro));
        if (make_edge[nro])
           replaceEdge (old_opp_edge [nro], new_opp_edge [nro]);
+       }
 
-       if (make_quad[nro])
-          replaceQuad (old_opp_quad [nro], new_opp_quad [nro]);
-
-       h_edge   [ind_edge[nro]] = new_quad->getEdge   (nro);
-       h_vertex [ind_node[nro]] = new_quad->getVertex (nro);
+   for (int nro=0 ; nro<QUAD4 ; nro++)
+       {
+       replaceVertex (quad->getVertex(nro), new_node[nro]);
        }
 
+
    h_quad [nface] = new_quad;
    if (debug())
       {
@@ -555,9 +645,10 @@ Elements* Hexa::disconnectQuad (Quad* quad)
        if (make_quad[nro])
           nouveaux->addQuad (new_opp_quad [nro]);
        }
+   nouveaux->moveDisco (this);
    return nouveaux;
 }
-// ========================================================= disconnectEdge 
+// ========================================================= disconnectEdge
 Elements* Hexa::disconnectEdge (Edge* arete)
 {
    int nedge  = findEdge   (arete);
@@ -567,60 +658,109 @@ Elements* Hexa::disconnectEdge (Edge* arete)
    if (nedge==NOTHING || namont==NOTHING || naval==NOTHING)
       return NULL;
 
-   Vertex*   new_amont = new Vertex (arete->getVertex(V_AMONT));
-   Vertex*   new_aval  = new Vertex (arete->getVertex(V_AVAL ));
-   Edge*     new_edge  = new Edge   (new_amont, new_aval);
+   if (debug())
+      {
+      printf (" ... Avant disconnectEdge, arete=");
+      arete->printName ("\n");
+      dumpFull ();
+      }
 
-   h_vertex [namont]   = new_amont;
-   h_vertex [naval]    = new_aval;
-   h_edge   [nedge]    = new_edge;
+   Edge*   n_edge   [HE_MAXI];
+   Quad*   n_quad   [HQ_MAXI];
+   Vertex* n_vertex [HV_MAXI];
 
-   Elements* nouveaux  = new Elements (el_root);
-   nouveaux->addVertex (new_amont);
-   nouveaux->addVertex (new_aval);
-   nouveaux->addEdge   (new_edge);
+   for (int nro=0 ; nro<HQ_MAXI ; nro++) n_quad [nro]   = NULL;
+   for (int nro=0 ; nro<HE_MAXI ; nro++) n_edge [nro]   = NULL;
+   for (int nro=0 ; nro<HV_MAXI ; nro++) n_vertex [nro] = NULL;
+
+   Vertex* old_amont = arete->getVertex (V_AMONT);
+   Vertex* old_aval  = arete->getVertex (V_AVAL );
+   Vertex* new_amont = n_vertex [namont] = new Vertex (old_amont);
+   Vertex* new_aval  = n_vertex [naval]  = new Vertex (old_aval);
+   n_edge [nedge]    = new Edge   (new_amont, new_aval);
+
+   // Un edge non remplace, qui contient un vertex remplace
+   //         commun a plus de 2 faces (donc appartenant a un autre hexa)
+   //         doit etre duplique
 
-                // Trouver les 2 faces contigues a l'arete
-                // et verifier si la face est commune a 2 hexas
-   int nf = 0;
-   for (int nq=0 ; nq<HQ_MAXI && nf < V_TWO; nq++)
+   for (int nro=0 ; nro<HE_MAXI ; nro++)
        {
-       int nro = h_quad[nq]->indexEdge (arete);
-       if (nro>=0)
+       if (   n_edge[nro]==NULL && h_edge[nro] != NULL
+           && h_edge[nro]->getNbrParents()>2)
           {
-          nf ++;
-          if (h_quad[nq]->getNbrParents()>1)
-             {
-             Edge* eoppos = h_quad[nq]->getEdge ((nro+2) MODULO QUAD4);
-             Edge* eleft  = h_quad[nq]->getEdge ((nro+3) MODULO QUAD4);
-             Edge* eright = h_quad[nq]->getEdge ((nro+1) MODULO QUAD4);
-             int nl2, nr2;
-             int nl1 = arete->inter (eleft,  nl2);
-             int nr1 = arete->inter (eright, nr2);
-             if (nl1==NOTHING && nr1==NOTHING)
-                return nouveaux;
-
-             Vertex*  new_vleft  = nl1==V_AMONT ? new_amont : new_aval;
-             Vertex*  new_vright = nr1==V_AMONT ? new_amont : new_aval;
-
-             Edge* new_eleft  = new Edge (new_vleft,  eleft ->getVertex(1-nl2));
-             Edge* new_eright = new Edge (new_vright, eright->getVertex(1-nr2));
-             Quad* new_quad   = new Quad (new_edge, new_eleft, eoppos, 
-                                          new_eright);
-             replaceQuad (h_quad[nq], new_quad);
-             replaceEdge (eleft,      new_eleft);
-             replaceEdge (eright,     new_eright);
-
-             nouveaux->addEdge (new_eleft);
-             nouveaux->addEdge (new_eright);
-             nouveaux->addQuad (new_quad);
-             }
+          Vertex* va =  h_edge[nro]->getVertex (V_AMONT);
+          Vertex* vb =  h_edge[nro]->getVertex (V_AVAL);
+
+          if (va==old_amont)
+             n_edge [nro] = new Edge (new_amont, vb);
+          else if (va==old_aval)
+             n_edge [nro] = new Edge (new_aval,  vb);
+          else if (vb==old_amont)
+             n_edge [nro] = new Edge (va, new_amont);
+          else if (vb==old_aval)
+             n_edge [nro] = new Edge (va, new_aval);
           }
        }
 
+   // Un quad non remplace, qui contient un edge remplace
+   //         commun a plus de 2 Hexas
+   //         doit etre duplique
+
+   Globale* glob = Globale::getInstance();
+   for (int nro=0 ; nro<HQ_MAXI ; nro++)
+       if (   n_quad[nro]==NULL && h_quad[nro] != NULL
+           && h_quad[nro]->getNbrParents()>1)
+          {
+          Edge* qedge[QUAD4];
+          bool  duplic = false;
+          for (int ned=0 ; ned<QUAD4 ; ned++)
+              {
+              int ndup = glob->QuadEdge (nro, (EnumQuad)ned);
+              if (n_edge [ndup] ==NULL)
+                 qedge [ned] = h_edge[ndup];
+              else
+                 {
+                 qedge [ned] = n_edge[ndup];
+                 duplic = true;
+                 }
+              }
+          if (duplic)
+             n_quad[nro] = new Quad (qedge[Q_A], qedge[Q_B],
+                                     qedge[Q_C], qedge[Q_D]);
+          }
+
+   Elements* nouveaux  = new Elements (el_root);
+   for (int nro=0 ; nro<HQ_MAXI ; nro++)
+       if (n_quad[nro]!=NULL)
+          {
+          replaceQuad (h_quad[nro], n_quad[nro]);
+          nouveaux->addQuad  (n_quad[nro]);
+          }
+
+   for (int nro=0 ; nro<HE_MAXI ; nro++)
+       if (n_edge[nro]!=NULL)
+          {
+          replaceEdge (h_edge[nro], n_edge[nro]);
+          nouveaux->addEdge  (n_edge[nro]);
+          }
+
+   for (int nro=0 ; nro<HV_MAXI ; nro++)
+       if (n_vertex[nro]!=NULL)
+          {
+          replaceVertex (h_vertex[nro], n_vertex[nro]);
+          nouveaux->addVertex  (n_vertex[nro]);
+          }
+
+   if (debug())
+      {
+      printf (" ... Apres disconnectEdge\n");
+      dumpFull ();
+      }
+
+   nouveaux->moveDisco (this);
    return nouveaux;
 }
-// ========================================================= disconnectVertex 
+// ========================================================= disconnectVertex
 Elements* Hexa::disconnectVertex (Vertex* noeud)
 {
    if (debug())
@@ -643,7 +783,7 @@ Elements* Hexa::disconnectVertex (Vertex* noeud)
        {
        new_quad [nro] = NULL;
             // Cete face contient le sommet et est commune a 2 hexas
-       if (   h_quad[nro]->indexVertex(noeud) >= 0 
+       if (   h_quad[nro]->indexVertex(noeud) >= 0
            && h_quad[nro]->getNbrParents  ()  >= 2)
            {
            int nbmod = 0;
@@ -654,54 +794,57 @@ Elements* Hexa::disconnectVertex (Vertex* noeud)
                int   indv  = arete->index (noeud);
                if (indv>=0)
                   {
-                  nbmod++;  
+                  nbmod++;
                   int hed = findEdge (arete);
-                 if (hed<0)
+                  if (hed<0)
                      return NULL;
-                 if (new_edge [hed]==NULL)
-                     new_edge [hed] = new Edge (new_node, 
+                  if (new_edge [hed]==NULL)
+                      new_edge [hed] = new Edge (new_node,
                                                  arete->getVertex(1-indv));
                   tedge [qed] = new_edge [hed];
                   }
                }
            if (nbmod!=2)
-              return NULL; 
+              return NULL;
            new_quad [nro] = new Quad (tedge[0], tedge[1], tedge[2], tedge[3]);
            }
        }
 
    Elements* nouveaux  = new Elements (el_root);
-   h_vertex [node] = new_node;
-   nouveaux->addVertex (new_node);
 
-   for (int nro=0 ; nro<HE_MAXI ; nro++) 
-       if (new_edge [nro] != NULL)
+   for (int nro=0 ; nro<HQ_MAXI ; nro++)
+       if (new_quad [nro] != NULL)
           {
-          h_edge [nro] = new_edge [nro];
-          nouveaux->addEdge (new_edge[nro]);
+          replaceQuad (h_quad [nro], new_quad [nro]);
+          nouveaux->addQuad (new_quad[nro]);
           }
 
-   for (int nro=0 ; nro<HQ_MAXI ; nro++) 
-       if (new_quad [nro] != NULL)
+   for (int nro=0 ; nro<HE_MAXI ; nro++)
+       if (new_edge [nro] != NULL)
           {
-          h_quad [nro] = new_quad [nro];
-          nouveaux->addQuad (new_quad[nro]);
+          replaceEdge (h_edge [nro], new_edge [nro]);
+          nouveaux->addEdge (new_edge[nro]);
           }
 
+   replaceVertex (noeud, new_node);
+   nouveaux->addVertex (new_node);
+
+
    if (debug())
       {
-      printf (" ... Apres disconnectVertex");
+      printf (" ... Apres disconnectVertex\n");
       dumpFull ();
       }
 
+   nouveaux->moveDisco (this);
    return nouveaux;
 }
-// ========================================================= getBase 
+// ========================================================= getBase
 int Hexa::getBase (Vertex* orig, Edge* normale)
 {
    for (int nq=0 ; nq<HQ_MAXI ; nq++)
        {
-       if (   h_quad[nq]->indexVertex(orig)    >= 0 
+       if (   h_quad[nq]->indexVertex(orig)    >= 0
            && h_quad[nq]->indexEdge  (normale) < 0)
            return nq;
        }
@@ -712,11 +855,11 @@ void Hexa::replaceQuad (Quad* old, Quad* par)
 {
    for (int nro=0 ; nro<HQ_MAXI ; nro++)
        {
-       if (h_quad[nro]==old) 
+       if (h_quad[nro]==old)
            {
            h_quad[nro] = par;
-          if (debug())
-             {
+           if (debug())
+              {
               printf (" Dans ");
               printName ();
               printf (" [%d], ", nro);
@@ -725,17 +868,18 @@ void Hexa::replaceQuad (Quad* old, Quad* par)
               }
            }
        }
+
 }
 // ======================================================== replaceEdge
 void Hexa::replaceEdge (Edge* old, Edge* par)
 {
    for (int nro=0 ; nro<HE_MAXI ; nro++)
        {
-       if (h_edge[nro]==old) 
+       if (h_edge[nro]==old)
            {
            h_edge[nro] = par;
-          if (debug())
-             {
+           if (debug())
+              {
               printf (" Dans ");
               printName ();
               printf (" [%d], ", nro);
@@ -744,17 +888,22 @@ void Hexa::replaceEdge (Edge* old, Edge* par)
               }
            }
        }
+
+   for (int nro=0 ; nro<HQ_MAXI ; nro++)
+       {
+       h_quad[nro]->replaceEdge (old, par);
+       }
 }
 // ======================================================== replaceVertex
 void Hexa::replaceVertex (Vertex* old, Vertex* par)
 {
    for (int nro=0 ; nro<HV_MAXI ; nro++)
        {
-       if (h_vertex [nro]==old) 
+       if (h_vertex [nro]==old)
            {
            h_vertex [nro] = par;
-          if (debug())
-             {
+           if (debug())
+              {
               printf (" Dans ");
               printName ();
               printf (" [%d], ", nro);
@@ -763,19 +912,31 @@ void Hexa::replaceVertex (Vertex* old, Vertex* par)
               }
            }
        }
+
+   for (int nro=0 ; nro<HE_MAXI ; nro++)
+       {
+       h_edge[nro]->replaceVertex (old, par);
+       }
+
+   for (int nro=0 ; nro<HQ_MAXI ; nro++)
+       {
+       h_quad[nro]->replaceVertex (old, par);
+       }
 }
 // ======================================================== removeConnected
 void Hexa::removeConnected ()
 {
+
    if (el_type == EL_REMOVED)
       return;
 
-   el_type = EL_REMOVED;
+   remove();
 
    for (int nro=0 ; nro<HQ_MAXI ; nro++)
        {
        Quad*  face = h_quad [nro];
        int nbhexas = face->getNbrParents ();
+
        for (int nc=0 ; nc<nbhexas ; nc++)
            {
            Hexa* cell = face->getParent(nc);
@@ -783,6 +944,13 @@ void Hexa::removeConnected ()
               cell->removeConnected ();
            }
        }
+
+   for (int nro=0 ; nro<HQ_MAXI ; nro++)
+       h_quad [nro]->remove();
+   for (int nro=0 ; nro<HE_MAXI ; nro++)
+       h_edge [nro]->remove();
+   for (int nro=0 ; nro<HV_MAXI ; nro++)
+       h_vertex [nro]->remove();
 }
 // ======================================================== findOpposedQuad
 int Hexa::findOpposedQuad (Quad* face, Edge* arete)
@@ -811,10 +979,11 @@ void Hexa::dump ()
    printf (")\n");
 
    printf ("      = (");
+
    for (int nro=0; nro<HE_MAXI ; nro++)
         {
         PrintName (h_edge[nro]);
-        if (nro==3 || nro ==7) 
+        if (nro==3 || nro ==7)
            printf ("\n         ");
         }
    printf (")\n");
@@ -823,6 +992,10 @@ void Hexa::dump ()
    for (int nro=0; nro<HV_MAXI ; nro++)
         PrintName (h_vertex[nro]);
    printf (")\n");
+   Real3 cg;
+   getCenter (cg);
+   printf ("cg    = (%g, %g, %g)\n", cg[0], cg[1], cg[2]);
+
 }
 // ======================================================== dumpPlus
 void Hexa::dumpPlus ()
@@ -883,5 +1056,212 @@ void Hexa::dumpFull ()
            }
        }
    printf ("\n");
+
+   for (int nro=0; nro<HV_MAXI ; nro++)
+       {
+       Vertex* pv = h_vertex[nro];
+       printf (" vertex(%s) = ", glob->namofHexaVertex(nro));
+       if (pv ==NULL)
+           printf (" NULL");
+       else
+           {
+           pv->printName (" = (");
+           printf ("%g, %g, %g)\n", pv->getX(), pv->getY(), pv->getZ());
+           }
+       }
+   printf ("\n");
+}
+// ======================================================== getOpposedQuad
+Quad* Hexa::getOpposedQuad (Quad* face)
+{
+   if      (face == h_quad [Q_A]) return h_quad [Q_B];
+   else if (face == h_quad [Q_B]) return h_quad [Q_A];
+   else if (face == h_quad [Q_C]) return h_quad [Q_D];
+   else if (face == h_quad [Q_D]) return h_quad [Q_C];
+   else if (face == h_quad [Q_E]) return h_quad [Q_F];
+   else if (face == h_quad [Q_F]) return h_quad [Q_F];
+   else                           return NULL;
+}
+// ========================================================= findQuad
+Quad* Hexa::findQuad (Edge* ed1, Edge* ed2)
+{
+   for (int nro=0 ; nro<HQ_MAXI ; nro++)
+       {
+       if (   h_quad[nro]->indexEdge (ed1) >= 0
+           && h_quad[nro]->indexEdge (ed2) >= 0)
+          return h_quad [nro];
+       }
+
+   return NULL;
+}
+// ========================================================= findEdge
+Edge* Hexa::findEdge (Vertex* v1, Vertex* v2)
+{
+   for (int nro=0 ; nro<HE_MAXI ; nro++)
+       {
+       if (   h_edge[nro]->index (v1) >= 0
+           && h_edge[nro]->index (v2) >= 0)
+          return h_edge [nro];
+       }
+
+   return NULL;
+}
+// ====================================================== opposedVertex
+Vertex* Hexa::opposedVertex (Quad* quad, Vertex* vertex)
+{
+   if (quad==NULL || vertex==NULL)
+      return NULL;
+
+   int nv = quad->indexVertex (vertex);
+   int nq = findQuad (quad);
+   if (nv<0 || nq<0)
+      return NULL;
+
+   for (int nro=0 ; nro<HE_MAXI ; nro++)
+       {
+       Edge* edge = h_edge [nro];
+       int   nv   = edge->index (vertex);
+       if (nv>=0 && quad->indexEdge(edge) <0)
+          return edge->getVertex (1-nv);
+       }
+
+   return NULL;
+}
+// ====================================================== perpendicularEdge
+Edge* Hexa::perpendicularEdge (Quad* quad, Vertex* vertex)
+{
+   if (quad==NULL || vertex==NULL)
+      return NULL;
+
+   int nv = quad->indexVertex (vertex);
+   int nq = findQuad (quad);
+   if (nv<0 || nq<0)
+      return NULL;
+
+   for (int nro=0 ; nro<HE_MAXI ; nro++)
+       {
+       if (quad->indexEdge (h_edge[nro])<0 && h_edge[nro]->index(vertex)>=0)
+          return h_edge [nro];
+       }
+
+   return NULL;
+}
+// ====================================================== perpendicularQuad
+Quad* Hexa::perpendicularQuad (Quad* quad, Edge* edge)
+{
+   if (BadElement (quad) || BadElement (edge))
+      return NULL;
+
+   int qed = quad->indexEdge (edge);
+   int ned = findEdge (edge);
+   int nq  = findQuad (quad);
+   if (qed <0 || ned<0 || nq<0)
+      return NULL;
+
+   for (int nro=0 ; nro<HQ_MAXI ; nro++)
+       {
+       if (nro != nq)
+          {   
+          Quad* face = h_quad[nro];
+          if (EltIsValid(face) && face->indexEdge (edge)>=0)
+             return face;
+          }
+       }
+   return NULL;
+}
+// ============================================================  getQuad
+Quad* Hexa::getQuad (int nro)
+{
+   Quad* elt = NULL;
+   if (nro >=0 && nro < HQ_MAXI && el_status == HOK && h_quad [nro]->isValid())
+      elt = h_quad [nro];
+
+   return elt;
+}
+// ============================================================  getEdge
+Edge* Hexa::getEdge (int nro)
+{
+   Edge* elt = NULL;
+   if (nro >=0 && nro < HE_MAXI && el_status == HOK && h_edge [nro]->isValid())
+      elt = h_edge [nro];
+
+   return elt;
+}
+// ============================================================  getVertex
+Vertex* Hexa::getVertex (int nro)
+{
+   Vertex* elt = NULL;
+   if (nro >=0 && nro <  HV_MAXI && el_status == HOK && h_vertex [nro]->isValid())
+      elt = h_vertex [nro];
+
+   return elt;
+}
+// ============================================================  getCenter
+double* Hexa::getCenter (double centre[])
+{
+   centre [dir_x] = centre [dir_y] = centre [dir_z] = 0;
+
+   for (int nv=0 ; nv<HV_MAXI ; nv++)
+       {
+       centre [dir_x] += h_vertex[nv]->getX ();
+       centre [dir_y] += h_vertex[nv]->getY ();
+       centre [dir_z] += h_vertex[nv]->getZ ();
+       }
+
+   centre [dir_x] /= HV_MAXI;
+   centre [dir_y] /= HV_MAXI;
+   centre [dir_z] /= HV_MAXI;
+   return centre;
+}
+// =============================================================== definedBy
+bool Hexa::definedBy  (Vertex* v1, Vertex* v2)
+{
+   for (int n1=0 ; n1< HV_MAXI ; n1++)
+       {
+//              (   Diagonale        )  Dessus
+       int n2 = (n1 + 2) MODULO HV_MAXI + HV_MAXI;
+       if (   (v1 == h_vertex[n1] && v2 == h_vertex[n2])
+           || (v1 == h_vertex[n2] && v2 == h_vertex[n1])) return true;
+       }
+   return false;
+}
+// =============================================================== definedBy
+bool Hexa::definedBy  (Quad* qa, Quad* qb)
+{
+   if (qa==qb || BadElement (qa) || BadElement (qb))
+       return false;
+
+   bool p1 = false, p2 = false;
+   for (int nq=0 ; nq< HQ_MAXI ; nq++)
+       {
+       if (qa == h_quad[nq])
+          p1 = true;
+       else if (qb == h_quad[nq])
+          p2 = true;
+       }
+   return p1 && p2;
+}
+// =============================================================== setColor
+void Hexa::setColor  (double val)
+{
+   for (int nc=0 ; nc< HV_MAXI ; nc++)
+       h_vertex[nc] -> setColor (val);
+}
+// ============================================================== markElements
+void Hexa::markElements  (int marque)
+{
+   for (int nc=0 ; nc< HQ_MAXI ; nc++) h_quad  [nc] -> setMark (marque);
+   for (int nc=0 ; nc< HE_MAXI ; nc++) h_edge  [nc] -> setMark (marque);
+   for (int nc=0 ; nc< HV_MAXI ; nc++) h_vertex[nc] -> setMark (marque);
+}
+// =============================================================== duplicate
+void Hexa::duplicate  ()
+{
+   h_clone = new Hexa (GetClone (h_quad [Q_A]),
+                       GetClone (h_quad [Q_B]),
+                       GetClone (h_quad [Q_C]),
+                       GetClone (h_quad [Q_D]),
+                       GetClone (h_quad [Q_E]),
+                       GetClone (h_quad [Q_F]));
 }
 END_NAMESPACE_HEXA