Salome HOME
d51571da1577af21e545a320136d567223f74aec
[modules/hexablock.git] / src / HEXABLOCK / HexHexa.cxx
1
2 // C++ : Gestion des Hexaedres
3
4 // Copyright (C) 2009-2023  CEA, EDF
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 #include "HexHexa.hxx"
23 #include "HexQuad.hxx"
24
25 #include "HexVertex.hxx"
26 #include "HexDocument.hxx"
27 #include "HexEdge.hxx"
28
29 #include "HexGlobale.hxx"
30 #include "HexXmlWriter.hxx"
31 #include "HexDiagnostics.hxx"
32 #include "HexGlobale.hxx"
33 #include "HexMatrix.hxx"
34 #include "HexElements.hxx"
35
36 BEGIN_NAMESPACE_HEXA
37
38 // ======================================================== Constructeur
39 Hexa::Hexa (Vertex* va, Vertex* vb, Vertex* vc, Vertex* vd,
40             Vertex* ve, Vertex* vf, Vertex* vg, Vertex* vh)
41     : EltBase (va->dad(), EL_HEXA)
42 {
43    h_vertex [V_ACE] = va;
44    h_vertex [V_ACF] = vb;   // = vc ; Modif Abu 30/08/2011
45    h_vertex [V_ADE] = vc;   // = vb ; Modif Abu 30/08/2011
46    h_vertex [V_ADF] = vd;
47
48    h_vertex [V_BCE] = ve;
49    h_vertex [V_BCF] = vf;   // = vg ; Modif Abu 30/08/2011
50    h_vertex [V_BDE] = vg;   // = vf ; Modif Abu 30/08/2011
51    h_vertex [V_BDF] = vh;
52
53    h_clone          = NULL;
54
55    controlerSommets ();
56
57    Globale* glob = Globale::getInstance ();
58
59    for (int nro=0 ; nro<HE_MAXI ; nro++)
60        {
61        h_edge[nro] = new Edge (h_vertex[glob->EdgeVertex (nro, V_AMONT)],
62                                h_vertex[glob->EdgeVertex (nro, V_AVAL)]);
63        }
64
65    for (int nro=0 ; nro<HQ_MAXI ; nro++)
66        {
67        h_quad[nro] = new Quad (h_edge [glob->QuadEdge (nro, E_A)],
68                                h_edge [glob->QuadEdge (nro, E_B)],
69                                h_edge [glob->QuadEdge (nro, E_C)],
70                                h_edge [glob->QuadEdge (nro, E_D)]);
71
72        h_quad[nro] -> addParent (this);
73        }
74    majReferences ();
75    if (el_root != NULL && el_status==HOK)
76        el_root->addHexa (this);
77 }
78 // ======================================================== Constructeur 2
79 Hexa::Hexa (Quad* qa, Quad* qb, Quad* qc, Quad* qd, Quad* qe, Quad* qf)
80     : EltBase (qa->dad(), EL_HEXA)
81 {
82    h_quad [Q_A] = qa;
83    h_quad [Q_B] = qb;
84    h_quad [Q_C] = qc;
85    h_quad [Q_D] = qd;
86    h_quad [Q_E] = qe;
87    h_quad [Q_F] = qf;
88    h_clone      = NULL;
89
90    for (int nb=0 ; nb<HE_MAXI ; nb++) h_edge   [nb] = NULL;
91    for (int nb=0 ; nb<HV_MAXI ; nb++) h_vertex [nb] = NULL;
92
93    controlerFaces  ();
94
95    verifierAretes  ();
96    verifierSommets ();
97    majReferences   ();
98
99    if (el_status != HOK)
100       {
101       printf (" +++++++++++++++++++++++++++++++++++++++++++ \n");
102       printf (" +++ Heaedre impossible \n");
103       printf (" +++++++++++++++++++++++++++++++++++++++++++ \n");
104       // el_root->dump ();
105       // printf (" +++++++++++++++++++++++++++++++++++++++++++ \n");
106       dumpFull ();
107       for (int nro=0; nro<HQ_MAXI; nro++) HexDump (h_quad[nro]);
108       for (int nro=0; nro<HE_MAXI; nro++) HexDump (h_edge[nro]);
109       for (int nro=0; nro<HV_MAXI; nro++) HexDump (h_vertex[nro]);
110       printf (" +++++++++++++++++++++++++++++++++++++++++++ \n");
111       // exit (1);
112       }
113    else
114        el_root->addHexa (this);
115 }
116 // =========================================================  Constructeur 3
117 // === a utiliser uniquement pour le clonage
118 Hexa::Hexa (Hexa* other)
119     : EltBase (other->el_root, EL_HEXA)
120 {
121    for (int nro=0 ; nro<HQ_MAXI ; nro++) h_quad   [nro] = NULL;
122    for (int nro=0 ; nro<HE_MAXI ; nro++) h_edge   [nro] = NULL;
123    for (int nro=0 ; nro<HV_MAXI ; nro++) h_vertex [nro] = NULL;
124    h_clone = NULL;
125
126    if (el_root != NULL && el_status==HOK)
127        el_root->addHexa (this);
128 }
129 // ======================================================== majReferences
130 void Hexa::majReferences  ()
131 {
132    for (int nro=0 ; nro<HQ_MAXI ; nro++)
133        h_quad[nro]->addParent (this);
134 }
135 // ======================================================== controlerArete
136 void Hexa::controlerArete  (int arete, int face1, int face2)
137 {
138    h_edge [arete] = h_quad[face1]->commonEdge (h_quad[face2]);
139    if (h_edge [arete]==NULL)
140        {
141        el_root->putError (W_H_BAD_EDGE,
142                           el_root->glob->namofHexaEdge (arete));
143        el_status = 888;
144        }
145 }
146 // ======================================================== controlerSomet
147 void Hexa::controlerSommet  (int node, int ne1, int ne2, int ne3)
148 {
149     if (h_edge[ne1] == NULL || h_edge[ne2] == NULL || h_edge[ne3] == NULL)
150        return;
151
152     Vertex* hv = h_edge[ne1]->commonVertex (h_edge[ne2]);
153     h_vertex [node] = hv;
154     if (hv == NULL)
155        {
156        el_root->putError (W_H_BAD_VERTEX,
157                           el_root->glob->namofHexaVertex(node));
158        el_status = 888;
159        }
160     else if (hv == NULL || h_edge[ne3]->index (hv)<0)
161        {
162        char b[10];
163        el_root->putError (W_H_BAD_VERTEX,
164                           el_root->glob->namofHexaVertex(node));
165        el_status = 888;
166        printf ("%s = %s\n", el_root->glob->namofHexaVertex(node),
167                             hv->getName(b));
168        printf ("%s = %s\n", el_root->glob->namofHexaEdge(ne1),
169                             h_edge[ne1]->getName(b));
170        printf ("%s = %s\n", el_root->glob->namofHexaEdge(ne2),
171                             h_edge[ne2]->getName(b));
172        printf ("%s = %s\n", el_root->glob->namofHexaEdge(ne3),
173                             h_edge[ne3]->getName(b));
174        }
175 }
176 // ======================================================== controlerFaces
177 void Hexa::controlerFaces  ()
178 {
179    for (int n1=0 ; n1<HQ_MAXI ; n1++)
180        {
181        if (BadElement (h_quad [n1]))
182           {
183           el_root->putError (W_H_NULL_QUAD,
184                              el_root->glob->namofHexaQuad (n1));
185           setError (886);
186           return;
187           }
188        for (int n2=n1+1 ; n2<HQ_MAXI ; n2++)
189            if (h_quad [n1] == h_quad[n2])
190               {
191               el_root->putError (W_H_EQ_QUAD,
192                          el_root->glob->namofHexaQuad (n1),
193                          el_root->glob->namofHexaQuad (n2));
194               setError (888);
195               }
196        }
197    for (int dd=0 ; dd<DIM3 ; dd++)
198        {
199        Quad* qa  = h_quad [2*dd];
200        Quad* qb  = h_quad [2*dd+1];
201        Edge* cut = qa->inter (qb);
202        if (cut != NULL)
203           {
204           bool more = true;
205           for (int nc=2*dd+2 ; more && nc<HQ_MAXI ; nc++)
206               {
207               Edge* cut = qa->inter (h_quad[nc]);
208               if (cut==NULL)
209                  {
210                  more = false;
211                  // cout << " ... le quad oppose au quad " << 2*dd
212                       // << " est le " << nc << endl;
213                  qb             = h_quad[nc];
214                  h_quad[nc]     = h_quad [2*dd+1];
215                  h_quad[2*dd+1] = qb;
216                  }
217               }
218           if (more)
219              {
220              char num [10];
221              sprintf (num, "%d", 2*dd+1);
222              el_root->putError ("addHexa : the %sth quad has no opposed quad",
223                                  num);
224              setError (886);
225              return ;
226              }
227           }
228        }
229 }
230 // ======================================================== controlerSommets
231 void Hexa::controlerSommets  ()
232 {
233    for (int n1=0 ; n1<HV_MAXI ; n1++)
234        {
235        if (BadElement (h_vertex [n1]))
236           {
237           el_root->putError (W_H_NULL_QUAD,
238                              el_root->glob->namofHexaVertex (n1));
239           setError (886);
240           return;
241           }
242        for (int n2=n1+1 ; n2<HQ_MAXI ; n2++)
243            if (h_vertex [n1] == h_vertex[n2])
244               {
245               el_root->putError (W_H_EQ_QUAD,
246                          el_root->glob->namofHexaVertex (n1),
247                          el_root->glob->namofHexaVertex (n2));
248               setError (888);
249               }
250        }
251 }
252 // ======================================================== verifierAretes
253 void Hexa::verifierAretes  ()
254 {
255    for (int nro=0 ; nro<HE_MAXI ; nro++) h_edge [nro] = NULL;
256
257    controlerArete ( E_AC, Q_A, Q_C);
258    controlerArete ( E_AF, Q_A, Q_F);
259    controlerArete ( E_AD, Q_A, Q_D);
260    controlerArete ( E_AE, Q_A, Q_E);
261
262    controlerArete ( E_BC, Q_B, Q_C);
263    controlerArete ( E_BF, Q_B, Q_F);
264    controlerArete ( E_BD, Q_B, Q_D);
265    controlerArete ( E_BE, Q_B, Q_E);
266
267    controlerArete ( E_CE, Q_C, Q_E);
268    controlerArete ( E_CF, Q_C, Q_F);
269    controlerArete ( E_DF, Q_D, Q_F);
270    controlerArete ( E_DE, Q_D, Q_E);
271 }
272 // ======================================================== verifierSommets
273 void Hexa::verifierSommets  ()
274 {
275    for (int nro=0 ; nro<HV_MAXI ; nro++) h_vertex [nro] = NULL;
276
277    controlerSommet (V_ACE, E_AC, E_AE, E_CE);
278    controlerSommet (V_ACF, E_AC, E_AF, E_CF);
279    controlerSommet (V_ADF, E_AD, E_AF, E_DF);
280    controlerSommet (V_ADE, E_AD, E_AE, E_DE);
281
282    controlerSommet (V_BCE, E_BC, E_BE, E_CE);
283    controlerSommet (V_BCF, E_BC, E_BF, E_CF);
284    controlerSommet (V_BDF, E_BD, E_BF, E_DF);
285    controlerSommet (V_BDE, E_BD, E_BE, E_DE);
286 }
287 // ======================================================== Inter
288 Quad* Hexa::Inter (Hexa* other)
289 {
290    for (int nf1=0 ; nf1 < HQ_MAXI ; nf1++)
291        for (int nf2=0 ; nf2 < HQ_MAXI ; nf2++)
292            if (h_quad[nf1] == other->h_quad[nf2])
293               return h_quad[nf1];
294
295    return NULL;
296 }
297 // -------------------------------------------------------------------
298 //                         Debug
299 // -------------------------------------------------------------------
300 // ======================================================= razNodes
301 void Hexa::razNodes ()
302 {
303    for (int nb=0 ; nb<HV_MAXI ; nb++)
304        h_vertex[nb]->setMark (NO_COUNTED);
305 }
306 // ======================================================= countNodes
307 int Hexa::countNodes ()
308 {
309    int nombre = 0;
310    for (int nb=0 ; nb<HV_MAXI ; nb++)
311        if (h_vertex[nb]->getMark () == NO_COUNTED)
312           {
313           h_vertex[nb]->setMark (NO_USED);
314           nombre ++;
315           }
316
317    return nombre;
318 }
319 // ======================================================= printNodes
320 void Hexa::printNodes (pfile vtk, int& compteur)
321 {
322    const double minvtk = 1e-30;
323    Real3 koord;
324
325    for (int nb=0 ; nb<HV_MAXI ; nb++)
326        if (h_vertex[nb]->getMark()==NO_USED)
327           {
328           h_vertex[nb]->getPoint (koord);
329           for (int nc=dir_x ; nc<=dir_z ; nc++)
330               if (koord [nc] < minvtk &&  koord [nc] > -minvtk)
331                   koord[nc] = 0.0;
332
333           fprintf (vtk, "%g %g %g\n", koord[dir_x], koord[dir_y], koord[dir_z]);
334           h_vertex[nb]->setMark (compteur);
335           compteur ++;
336           }
337 }
338 // ======================================================= colorNodes
339 void Hexa::colorNodes (pfile vtk)
340 {
341    for (int nb=0 ; nb<HV_MAXI ; nb++)
342        if (h_vertex[nb]->getMark()>=0)
343           {
344           double color = 100*(h_vertex[nb]->getScalar()+1);
345           fprintf (vtk, "%g\n", color);
346           h_vertex[nb]->setMark (NO_COUNTED);
347           }
348 }
349 // ======================================================= moveNodes
350 void Hexa::moveNodes (Matrix* matrice)
351 {
352    for (int nb=0 ; nb<HV_MAXI ; nb++)
353        if (h_vertex[nb]->getMark()!=IS_USED)
354           {
355           matrice->perform (h_vertex[nb]);
356           h_vertex[nb]->setMark (IS_USED);
357           }
358 }
359 // ======================================================= transform
360 void Hexa::transform (Matrix* matrice)
361 {
362    for (int nb=0 ; nb<HV_MAXI ; nb++)
363        matrice->perform (h_vertex[nb]);
364 }
365 // ======================================================= printHexa
366 void Hexa::printHexa  (pfile vtk)
367 {
368    fprintf (vtk, "%d", HV_MAXI);
369
370    fprintf (vtk, " %d", h_vertex[V_ACE]->getMark ());
371    fprintf (vtk, " %d", h_vertex[V_ACF]->getMark ());
372    fprintf (vtk, " %d", h_vertex[V_ADF]->getMark ());
373    fprintf (vtk, " %d", h_vertex[V_ADE]->getMark ());
374
375    fprintf (vtk, " %d", h_vertex[V_BCE]->getMark ());
376    fprintf (vtk, " %d", h_vertex[V_BCF]->getMark ());
377    fprintf (vtk, " %d", h_vertex[V_BDF]->getMark ());
378    fprintf (vtk, " %d", h_vertex[V_BDE]->getMark ());
379
380    fprintf (vtk, "\n");
381 }
382 // ======================================================= printHexaVtk
383 void Hexa::printHexaVtk (pfile vtk)
384 {
385    fprintf (vtk, "%d", HV_MAXI);
386
387    fprintf (vtk, " %d", h_vertex[V_ACE]->getId ());
388    fprintf (vtk, " %d", h_vertex[V_ACF]->getId ());
389    fprintf (vtk, " %d", h_vertex[V_ADF]->getId ());
390    fprintf (vtk, " %d", h_vertex[V_ADE]->getId ());
391
392    fprintf (vtk, " %d", h_vertex[V_BCE]->getId ());
393    fprintf (vtk, " %d", h_vertex[V_BCF]->getId ());
394    fprintf (vtk, " %d", h_vertex[V_BDF]->getId ());
395    fprintf (vtk, " %d", h_vertex[V_BDE]->getId ());
396
397    fprintf (vtk, "\n");
398 }
399 // ======================================================== hasFreEdges
400 bool Hexa::hasFreeEdges ()
401 {
402    if (isDeleted())
403        return false;
404
405    for (int nro=0; nro<HE_MAXI ; nro++)
406        if (h_edge[nro]->getMark()<0)
407           return true;
408
409    return false;
410 }
411 // ======================================================== propager
412 void Hexa::propager (Propagation* prop, int nro)
413 {
414    if (isDeleted())
415        return;
416
417    for (int nro=0; nro<HE_MAXI ; nro++)
418        if (h_edge[nro]->getMark()<0)
419            h_edge[nro]->propager (prop, nro);
420 }
421 // ========================================================= saveXml
422 void Hexa::saveXml (XmlWriter* xml)
423 {
424    char ident[12];
425    std::string quads;
426
427    for (int nro=0 ; nro<HQ_MAXI ; nro++)
428        {
429        if (nro>0) quads += " ";
430        quads += h_quad[nro]->getName(ident);
431        }
432
433    getName (ident);
434    xml->openMark     ("Hexa");
435    xml->addAttribute ("id",    ident);
436    xml->addAttribute ("quads", quads);
437    if (el_name!=ident)
438        xml->addAttribute ("name", el_name);
439    xml->closeMark ();
440 }
441 // ========================================================= findQuad
442 int Hexa::findQuad (Quad* element)
443 {
444    for (int nro=0 ; nro<HQ_MAXI ; nro++)
445        if (h_quad[nro]==element)
446           return nro;
447
448    return NOTHING;
449 }
450 // ========================================================= findEdge
451 int Hexa::findEdge (Edge* element)
452 {
453    for (int nro=0 ; nro<HE_MAXI ; nro++)
454        if (h_edge[nro]==element)
455           return nro;
456
457    return NOTHING;
458 }
459 // ========================================================= findVertex
460 int Hexa::findVertex (Vertex* element)
461 {
462    for (int nro=0 ; nro<HV_MAXI ; nro++)
463        if (h_vertex[nro]==element)
464           return nro;
465
466    return NOTHING;
467 }
468 // ========================================================= disconnectQuad
469 Elements* Hexa::disconnectQuad (Quad* quad)
470 {
471    if (quad==NULL)
472       return NULL;
473
474    if (debug())
475       {
476       printf (" ... Avant disconnectQuad, quad=");
477       quad->printName ("\n");
478       dumpFull ();
479       }
480
481    int nface = findQuad (quad);
482    if (nface==NOTHING)
483       return NULL;
484                                        // Face opposee : replace
485    // int nfopp = (nface MODULO 2==0) ? nface+1 : nface-1;
486
487    int  ind_edge  [QUAD4], ind_opp_quad [QUAD4];
488    bool make_quad [QUAD4], make_edge [QUAD4];
489
490    for (int nro=0 ; nro<QUAD4 ; nro++)
491        make_quad [nro] = make_edge[nro] = false;
492
493    for (int nro=0 ; nro<QUAD4 ; nro++)
494        {
495        int nro1  = (nro+1) MODULO QUAD4;
496        int pedge = findEdge   (quad->getEdge   (nro));
497        int pnode = findVertex (quad->getVertex (nro));
498        int oppq  = findOpposedQuad (quad, quad->getEdge (nro));
499
500        ind_edge [nro]     = pedge;
501        ind_opp_quad [nro] = oppq;
502
503        if (pedge==NOTHING || pnode==NOTHING || oppq==NOTHING)
504           return NULL;
505
506        make_quad [nro]  = h_quad[oppq]->getNbrParents() == 2;
507        make_edge [nro ] = make_edge [nro ] || make_quad [nro];
508        make_edge [nro1] = make_edge [nro1] || make_quad [nro];
509
510        if (debug())
511           {
512           printf (" Sommet nro %d : ", nro);
513           quad->getVertex(nro)->printName (", ");
514           printf (" edge = ");
515           quad->getEdge(nro)->printName (", ");
516           printf (" quad oppose = ");
517           h_quad[oppq]->printName("");
518           if (make_quad [nro])
519              printf (" a dissocier\n");
520           else
521              printf ("\n");
522
523           }
524        }
525
526    Vertex* new_node     [QUAD4];
527    Edge*   new_opp_edge [QUAD4];
528    Edge*   old_opp_edge [QUAD4];
529
530    for (int nro=0 ; nro<QUAD4 ; nro++)
531        {
532        old_opp_edge [nro] = NULL;
533        new_opp_edge [nro] = NULL;
534        Vertex*  o_v0  = quad->getVertex (nro);
535        new_node [nro] = new Vertex (o_v0);
536        if (debug())
537           {
538           printf (" quad.vertex [%d] = ", nro);
539           quad->getVertex (nro)->printName (" --> ");
540           new_node [nro]->printName ("\n");
541           }
542
543        if (make_edge[nro])
544           {
545           Quad*   pface  = h_quad [ind_opp_quad [nro]];
546           int     bid;
547           int     ncut = pface->inter (quad, bid);
548           Edge*   ecut = pface->getEdge ((ncut+1) MODULO QUAD4);
549           Vertex* vopp = ecut->getVertex(V_AMONT);
550           if (vopp==o_v0)
551               vopp = ecut->getVertex (V_AVAL);
552           else if (o_v0 != ecut->getVertex (V_AVAL));
553               {
554               ecut = pface->getEdge ((ncut+3) MODULO QUAD4);
555               vopp = ecut->getVertex(V_AMONT);
556               if (vopp==o_v0)
557                   vopp = ecut->getVertex (V_AVAL);
558               else if (o_v0 != ecut->getVertex (V_AVAL))
559                   return NULL;
560               }
561
562           old_opp_edge [nro] = ecut;
563           new_opp_edge [nro] = new Edge (new_node[nro], vopp);
564           if (debug())
565              {
566              printf (" quad.opp_edge [%d] = ", nro);
567              old_opp_edge [nro]->printName (" --> ");
568              new_opp_edge [nro]->printName ("\n");
569              }
570           }
571        }
572
573    Quad* new_quad = new Quad (new_node[0], new_node[1], new_node[2],
574                                                         new_node[3]);
575
576    Quad* new_opp_quad [QUAD4];
577    Quad* old_opp_quad [QUAD4];
578    for (int nro=0 ; nro<QUAD4 ; nro++)
579        {
580        old_opp_quad [nro] = NULL;
581        new_opp_quad [nro] = NULL;
582        if (make_quad[nro])
583           {
584           int nro1 = (nro+1) MODULO QUAD4;
585
586           Edge* n_edge0 = new_quad->getEdge (nro);
587           Edge* n_edge1 = new_opp_edge [nro];
588           Edge* n_edge3 = new_opp_edge [nro1];
589
590           int iv1 = n_edge1->inter (n_edge0);
591           int iv3 = n_edge3->inter (n_edge0);
592           if (iv1 <0 || iv3 <0)
593              return NULL;
594
595           Quad* o_face = h_quad [ind_opp_quad [nro]];
596           Edge* edge2  = o_face->findEdge (n_edge1->getVertex (1-iv1),
597                                            n_edge3->getVertex (1-iv3));
598           if (edge2==NULL)
599              return NULL;
600           // Edge* o_edge0 = h_edge [ind_edge     [nro]];
601           // int sens = 1;
602           // Edge* edge2   = o_face->getOpposEdge (o_edge0, sens);
603
604           old_opp_quad [nro] = o_face;
605           if (debug())
606              printf (" -------- Quad oppose nro %d\n", nro);
607           new_opp_quad [nro] = new Quad (n_edge0, n_edge1, edge2, n_edge3);
608           }
609        }
610
611    replaceQuad (quad, new_quad);
612    for (int nro=0 ; nro<QUAD4 ; nro++)
613        if (make_quad[nro])
614           replaceQuad (old_opp_quad [nro], new_opp_quad [nro]);
615
616    for (int nro=0 ; nro<QUAD4 ; nro++)
617        {
618        replaceEdge (h_edge[ind_edge[nro]], new_quad->getEdge (nro));
619        if (make_edge[nro])
620           replaceEdge (old_opp_edge [nro], new_opp_edge [nro]);
621        }
622
623    for (int nro=0 ; nro<QUAD4 ; nro++)
624        {
625        replaceVertex (quad->getVertex(nro), new_node[nro]);
626        }
627
628
629    h_quad [nface] = new_quad;
630    if (debug())
631       {
632       printf (" ... Apres disconnectQuad, new_quad=");
633       new_quad->printName ("\n");
634       dumpFull ();
635       }
636
637    Elements* nouveaux  = new Elements (el_root);
638    nouveaux->addQuad   (new_quad);
639    for (int nro=0 ; nro<QUAD4 ; nro++)
640        {
641        nouveaux->addEdge   (new_quad->getEdge   (nro));
642        nouveaux->addVertex (new_quad->getVertex (nro));
643        if (make_edge[nro])
644           nouveaux->addEdge (new_opp_edge [nro]);
645        if (make_quad[nro])
646           nouveaux->addQuad (new_opp_quad [nro]);
647        }
648    nouveaux->moveDisco (this);
649    return nouveaux;
650 }
651 // ========================================================= disconnectEdge
652 Elements* Hexa::disconnectEdge (Edge* arete)
653 {
654    int nedge  = findEdge   (arete);
655    int namont = findVertex (arete->getVertex(V_AMONT));
656    int naval  = findVertex (arete->getVertex(V_AVAL ));
657
658    if (nedge==NOTHING || namont==NOTHING || naval==NOTHING)
659       return NULL;
660
661    if (debug())
662       {
663       printf (" ... Avant disconnectEdge, arete=");
664       arete->printName ("\n");
665       dumpFull ();
666       }
667
668    Edge*   n_edge   [HE_MAXI];
669    Quad*   n_quad   [HQ_MAXI];
670    Vertex* n_vertex [HV_MAXI];
671
672    for (int nro=0 ; nro<HQ_MAXI ; nro++) n_quad [nro]   = NULL;
673    for (int nro=0 ; nro<HE_MAXI ; nro++) n_edge [nro]   = NULL;
674    for (int nro=0 ; nro<HV_MAXI ; nro++) n_vertex [nro] = NULL;
675
676    Vertex* old_amont = arete->getVertex (V_AMONT);
677    Vertex* old_aval  = arete->getVertex (V_AVAL );
678    Vertex* new_amont = n_vertex [namont] = new Vertex (old_amont);
679    Vertex* new_aval  = n_vertex [naval]  = new Vertex (old_aval);
680    n_edge [nedge]    = new Edge   (new_amont, new_aval);
681
682    // Un edge non remplace, qui contient un vertex remplace
683    //         commun a plus de 2 faces (donc appartenant a un autre hexa)
684    //         doit etre duplique
685
686    for (int nro=0 ; nro<HE_MAXI ; nro++)
687        {
688        if (   n_edge[nro]==NULL && h_edge[nro] != NULL
689            && h_edge[nro]->getNbrParents()>2)
690           {
691           Vertex* va =  h_edge[nro]->getVertex (V_AMONT);
692           Vertex* vb =  h_edge[nro]->getVertex (V_AVAL);
693
694           if (va==old_amont)
695              n_edge [nro] = new Edge (new_amont, vb);
696           else if (va==old_aval)
697              n_edge [nro] = new Edge (new_aval,  vb);
698           else if (vb==old_amont)
699              n_edge [nro] = new Edge (va, new_amont);
700           else if (vb==old_aval)
701              n_edge [nro] = new Edge (va, new_aval);
702           }
703        }
704
705    // Un quad non remplace, qui contient un edge remplace
706    //         commun a plus de 2 Hexas
707    //         doit etre duplique
708
709    Globale* glob = Globale::getInstance();
710    for (int nro=0 ; nro<HQ_MAXI ; nro++)
711        if (   n_quad[nro]==NULL && h_quad[nro] != NULL
712            && h_quad[nro]->getNbrParents()>1)
713           {
714           Edge* qedge[QUAD4];
715           bool  duplic = false;
716           for (int ned=0 ; ned<QUAD4 ; ned++)
717               {
718               int ndup = glob->QuadEdge (nro, (EnumQuad)ned);
719               if (n_edge [ndup] ==NULL)
720                  qedge [ned] = h_edge[ndup];
721               else
722                  {
723                  qedge [ned] = n_edge[ndup];
724                  duplic = true;
725                  }
726               }
727           if (duplic)
728              n_quad[nro] = new Quad (qedge[Q_A], qedge[Q_B],
729                                      qedge[Q_C], qedge[Q_D]);
730           }
731
732    Elements* nouveaux  = new Elements (el_root);
733    for (int nro=0 ; nro<HQ_MAXI ; nro++)
734        if (n_quad[nro]!=NULL)
735           {
736           replaceQuad (h_quad[nro], n_quad[nro]);
737           nouveaux->addQuad  (n_quad[nro]);
738           }
739
740    for (int nro=0 ; nro<HE_MAXI ; nro++)
741        if (n_edge[nro]!=NULL)
742           {
743           replaceEdge (h_edge[nro], n_edge[nro]);
744           nouveaux->addEdge  (n_edge[nro]);
745           }
746
747    for (int nro=0 ; nro<HV_MAXI ; nro++)
748        if (n_vertex[nro]!=NULL)
749           {
750           replaceVertex (h_vertex[nro], n_vertex[nro]);
751           nouveaux->addVertex  (n_vertex[nro]);
752           }
753
754    if (debug())
755       {
756       printf (" ... Apres disconnectEdge\n");
757       dumpFull ();
758       }
759
760    nouveaux->moveDisco (this);
761    return nouveaux;
762 }
763 // ========================================================= disconnectVertex
764 Elements* Hexa::disconnectVertex (Vertex* noeud)
765 {
766    if (debug())
767       {
768       printf (" ... Avant disconnectVertex, vertex=");
769       noeud->printName ("\n");
770       dumpFull ();
771       }
772
773    int node = findVertex (noeud);
774    if (node==NOTHING)
775       return NULL;
776
777    Vertex* new_node = new Vertex (noeud);
778    Quad*   new_quad [HQ_MAXI];
779    Edge*   new_edge [HE_MAXI];
780
781    for (int nro=0 ; nro<HE_MAXI ; nro++) new_edge [nro] = NULL;
782    for (int nro=0 ; nro<HQ_MAXI ; nro++)
783        {
784        new_quad [nro] = NULL;
785             // Cete face contient le sommet et est commune a 2 hexas
786        if (   h_quad[nro]->indexVertex(noeud) >= 0
787            && h_quad[nro]->getNbrParents  ()  >= 2)
788            {
789            int nbmod = 0;
790            Edge* tedge [QUAD4];
791            for (int qed=0 ; qed<QUAD4 ; qed++)
792                {
793                Edge* arete = tedge[qed] = h_quad[nro]->getEdge (qed);
794                int   indv  = arete->index (noeud);
795                if (indv>=0)
796                   {
797                   nbmod++;
798                   int hed = findEdge (arete);
799                   if (hed<0)
800                      return NULL;
801                   if (new_edge [hed]==NULL)
802                       new_edge [hed] = new Edge (new_node,
803                                                  arete->getVertex(1-indv));
804                   tedge [qed] = new_edge [hed];
805                   }
806                }
807            if (nbmod!=2)
808               return NULL;
809            new_quad [nro] = new Quad (tedge[0], tedge[1], tedge[2], tedge[3]);
810            }
811        }
812
813    Elements* nouveaux  = new Elements (el_root);
814
815    for (int nro=0 ; nro<HQ_MAXI ; nro++)
816        if (new_quad [nro] != NULL)
817           {
818           replaceQuad (h_quad [nro], new_quad [nro]);
819           nouveaux->addQuad (new_quad[nro]);
820           }
821
822    for (int nro=0 ; nro<HE_MAXI ; nro++)
823        if (new_edge [nro] != NULL)
824           {
825           replaceEdge (h_edge [nro], new_edge [nro]);
826           nouveaux->addEdge (new_edge[nro]);
827           }
828
829    replaceVertex (noeud, new_node);
830    nouveaux->addVertex (new_node);
831
832
833    if (debug())
834       {
835       printf (" ... Apres disconnectVertex\n");
836       dumpFull ();
837       }
838
839    nouveaux->moveDisco (this);
840    return nouveaux;
841 }
842 // ========================================================= getBase
843 int Hexa::getBase (Vertex* orig, Edge* normale)
844 {
845    for (int nq=0 ; nq<HQ_MAXI ; nq++)
846        {
847        if (   h_quad[nq]->indexVertex(orig)    >= 0
848            && h_quad[nq]->indexEdge  (normale) < 0)
849            return nq;
850        }
851    return NOTHING;
852 }
853 // ======================================================== replaceQuad
854 void Hexa::replaceQuad (Quad* old, Quad* par)
855 {
856    for (int nro=0 ; nro<HQ_MAXI ; nro++)
857        {
858        if (h_quad[nro]==old)
859            {
860            h_quad[nro] = par;
861            if (debug())
862               {
863               printf (" Dans ");
864               printName ();
865               printf (" [%d], ", nro);
866               old->printName (" est remplace par ");
867               par->printName ("\n");
868               }
869            }
870        }
871
872 }
873 // ======================================================== replaceEdge
874 void Hexa::replaceEdge (Edge* old, Edge* par)
875 {
876    for (int nro=0 ; nro<HE_MAXI ; nro++)
877        {
878        if (h_edge[nro]==old)
879            {
880            h_edge[nro] = par;
881            if (debug())
882               {
883               printf (" Dans ");
884               printName ();
885               printf (" [%d], ", nro);
886               old->printName (" est remplace par ");
887               par->printName ("\n");
888               }
889            }
890        }
891
892    for (int nro=0 ; nro<HQ_MAXI ; nro++)
893        {
894        h_quad[nro]->replaceEdge (old, par);
895        }
896 }
897 // ======================================================== replaceVertex
898 void Hexa::replaceVertex (Vertex* old, Vertex* par)
899 {
900    for (int nro=0 ; nro<HV_MAXI ; nro++)
901        {
902        if (h_vertex [nro]==old)
903            {
904            h_vertex [nro] = par;
905            if (debug())
906               {
907               printf (" Dans ");
908               printName ();
909               printf (" [%d], ", nro);
910               old->printName (" est remplace par ");
911               par->printName ("\n");
912               }
913            }
914        }
915
916    for (int nro=0 ; nro<HE_MAXI ; nro++)
917        {
918        h_edge[nro]->replaceVertex (old, par);
919        }
920
921    for (int nro=0 ; nro<HQ_MAXI ; nro++)
922        {
923        h_quad[nro]->replaceVertex (old, par);
924        }
925 }
926 // ======================================================== removeConnected
927 void Hexa::removeConnected ()
928 {
929
930    if (el_type == EL_REMOVED)
931       return;
932
933    remove();
934
935    for (int nro=0 ; nro<HQ_MAXI ; nro++)
936        {
937        Quad*  face = h_quad [nro];
938        int nbhexas = face->getNbrParents ();
939
940        for (int nc=0 ; nc<nbhexas ; nc++)
941            {
942            Hexa* cell = face->getParent(nc);
943            if (cell!=NULL && cell->isValid ())
944               cell->removeConnected ();
945            }
946        }
947
948    for (int nro=0 ; nro<HQ_MAXI ; nro++)
949        h_quad [nro]->remove();
950    for (int nro=0 ; nro<HE_MAXI ; nro++)
951        h_edge [nro]->remove();
952    for (int nro=0 ; nro<HV_MAXI ; nro++)
953        h_vertex [nro]->remove();
954 }
955 // ======================================================== findOpposedQuad
956 int Hexa::findOpposedQuad (Quad* face, Edge* arete)
957 {
958    for (int nro=0 ; nro<HQ_MAXI ; nro++)
959        {
960        Quad*  quad = h_quad [nro];
961        if (quad!=face && quad->indexEdge (arete) >=0)
962           return nro;
963        }
964
965    return NOTHING;
966 }
967 // ========================================================= dump
968 void Hexa::dump ()
969 {
970    printName(" = (");
971    if (NOT isHere ())
972       {
973       printf ("*** deleted ***)\n");
974       return;
975       }
976
977    for (int nro=0; nro<HQ_MAXI ; nro++)
978         PrintName (h_quad[nro]);
979    printf (")\n");
980
981    printf ("      = (");
982
983    for (int nro=0; nro<HE_MAXI ; nro++)
984         {
985         PrintName (h_edge[nro]);
986         if (nro==3 || nro ==7)
987            printf ("\n         ");
988         }
989    printf (")\n");
990
991    printf ("      = (");
992    for (int nro=0; nro<HV_MAXI ; nro++)
993         PrintName (h_vertex[nro]);
994    printf (")\n");
995    Real3 cg;
996    getCenter (cg);
997    printf ("cg    = (%g, %g, %g)\n", cg[0], cg[1], cg[2]);
998
999 }
1000 // ======================================================== dumpPlus
1001 void Hexa::dumpPlus ()
1002 {
1003    dump ();
1004    for (int nro=0 ; nro < HV_MAXI ; nro++)
1005        {
1006        Vertex* pv = h_vertex[nro];
1007        printf ( "    ");
1008        if (pv!=NULL)
1009           {
1010           pv->printName ("");
1011           printf ( " (%g, %g, %g)\n", pv->getX(),  pv->getY(),  pv->getZ());
1012           }
1013        else
1014           {
1015           printf ( "NULL\n");
1016           }
1017        }
1018 }
1019 // ======================================================== dumpFull
1020 void Hexa::dumpFull ()
1021 {
1022    dump ();
1023    Globale* glob = Globale::getInstance ();
1024
1025    printf ("\n");
1026    for (int nro=0; nro<HQ_MAXI ; nro++)
1027        {
1028        printf (" quad(%s) = ", glob->namofHexaQuad(nro));
1029        if (h_quad[nro] ==NULL)
1030            printf (" NULL\n");
1031        else
1032            {
1033            h_quad[nro]->printName (" = (");
1034            for (int nc=0; nc<QUAD4 ; nc++)
1035                 h_quad[nro]->getEdge(nc)->printName ();
1036            printf (")\n");
1037            printf ("                   = (");
1038            for (int nc=0; nc<QUAD4 ; nc++)
1039                 h_quad[nro]->getVertex(nc)->printName ();
1040            printf (")\n");
1041            }
1042        }
1043
1044    printf ("\n");
1045    for (int nro=0; nro<HE_MAXI ; nro++)
1046        {
1047        printf (" edge(%s) = ", glob->namofHexaEdge(nro));
1048        if (h_edge[nro] ==NULL)
1049            printf (" NULL\n");
1050        else
1051            {
1052            h_edge[nro]->printName (" = (");
1053            for (int nc=0; nc<V_TWO ; nc++)
1054                 h_edge[nro]->getVertex(nc)->printName ();
1055            printf (")\n");
1056            }
1057        }
1058    printf ("\n");
1059
1060    for (int nro=0; nro<HV_MAXI ; nro++)
1061        {
1062        Vertex* pv = h_vertex[nro];
1063        printf (" vertex(%s) = ", glob->namofHexaVertex(nro));
1064        if (pv ==NULL)
1065            printf (" NULL");
1066        else
1067            {
1068            pv->printName (" = (");
1069            printf ("%g, %g, %g)\n", pv->getX(), pv->getY(), pv->getZ());
1070            }
1071        }
1072    printf ("\n");
1073 }
1074 // ======================================================== getOpposedQuad
1075 Quad* Hexa::getOpposedQuad (Quad* face)
1076 {
1077    if      (face == h_quad [Q_A]) return h_quad [Q_B];
1078    else if (face == h_quad [Q_B]) return h_quad [Q_A];
1079    else if (face == h_quad [Q_C]) return h_quad [Q_D];
1080    else if (face == h_quad [Q_D]) return h_quad [Q_C];
1081    else if (face == h_quad [Q_E]) return h_quad [Q_F];
1082    else if (face == h_quad [Q_F]) return h_quad [Q_F];
1083    else                           return NULL;
1084 }
1085 // ========================================================= findQuad
1086 Quad* Hexa::findQuad (Edge* ed1, Edge* ed2)
1087 {
1088    for (int nro=0 ; nro<HQ_MAXI ; nro++)
1089        {
1090        if (   h_quad[nro]->indexEdge (ed1) >= 0
1091            && h_quad[nro]->indexEdge (ed2) >= 0)
1092           return h_quad [nro];
1093        }
1094
1095    return NULL;
1096 }
1097 // ========================================================= findEdge
1098 Edge* Hexa::findEdge (Vertex* v1, Vertex* v2)
1099 {
1100    for (int nro=0 ; nro<HE_MAXI ; nro++)
1101        {
1102        if (   h_edge[nro]->index (v1) >= 0
1103            && h_edge[nro]->index (v2) >= 0)
1104           return h_edge [nro];
1105        }
1106
1107    return NULL;
1108 }
1109 // ====================================================== opposedVertex
1110 Vertex* Hexa::opposedVertex (Quad* quad, Vertex* vertex)
1111 {
1112    if (quad==NULL || vertex==NULL)
1113       return NULL;
1114
1115    int nv = quad->indexVertex (vertex);
1116    int nq = findQuad (quad);
1117    if (nv<0 || nq<0)
1118       return NULL;
1119
1120    for (int nro=0 ; nro<HE_MAXI ; nro++)
1121        {
1122        Edge* edge = h_edge [nro];
1123        int   nv   = edge->index (vertex);
1124        if (nv>=0 && quad->indexEdge(edge) <0)
1125           return edge->getVertex (1-nv);
1126        }
1127
1128    return NULL;
1129 }
1130 // ====================================================== perpendicularEdge
1131 Edge* Hexa::perpendicularEdge (Quad* quad, Vertex* vertex)
1132 {
1133    if (quad==NULL || vertex==NULL)
1134       return NULL;
1135
1136    int nv = quad->indexVertex (vertex);
1137    int nq = findQuad (quad);
1138    if (nv<0 || nq<0)
1139       return NULL;
1140
1141    for (int nro=0 ; nro<HE_MAXI ; nro++)
1142        {
1143        if (quad->indexEdge (h_edge[nro])<0 && h_edge[nro]->index(vertex)>=0)
1144           return h_edge [nro];
1145        }
1146
1147    return NULL;
1148 }
1149 // ====================================================== perpendicularQuad
1150 Quad* Hexa::perpendicularQuad (Quad* quad, Edge* edge)
1151 {
1152    if (BadElement (quad) || BadElement (edge))
1153       return NULL;
1154
1155    int qed = quad->indexEdge (edge);
1156    int ned = findEdge (edge);
1157    int nq  = findQuad (quad);
1158    if (qed <0 || ned<0 || nq<0)
1159       return NULL;
1160
1161    for (int nro=0 ; nro<HQ_MAXI ; nro++)
1162        {
1163        if (nro != nq)
1164           {   
1165           Quad* face = h_quad[nro];
1166           if (EltIsValid(face) && face->indexEdge (edge)>=0)
1167              return face;
1168           }
1169        }
1170    return NULL;
1171 }
1172 // ============================================================  getQuad
1173 Quad* Hexa::getQuad (int nro)
1174 {
1175    Quad* elt = NULL;
1176    if (nro >=0 && nro < HQ_MAXI && el_status == HOK && h_quad [nro]->isValid())
1177       elt = h_quad [nro];
1178
1179    return elt;
1180 }
1181 // ============================================================  getEdge
1182 Edge* Hexa::getEdge (int nro)
1183 {
1184    Edge* elt = NULL;
1185    if (nro >=0 && nro < HE_MAXI && el_status == HOK && h_edge [nro]->isValid())
1186       elt = h_edge [nro];
1187
1188    return elt;
1189 }
1190 // ============================================================  getVertex
1191 Vertex* Hexa::getVertex (int nro)
1192 {
1193    Vertex* elt = NULL;
1194    if (nro >=0 && nro <  HV_MAXI && el_status == HOK && h_vertex [nro]->isValid())
1195       elt = h_vertex [nro];
1196
1197    return elt;
1198 }
1199 // ============================================================  getCenter
1200 double* Hexa::getCenter (double centre[])
1201 {
1202    centre [dir_x] = centre [dir_y] = centre [dir_z] = 0;
1203
1204    for (int nv=0 ; nv<HV_MAXI ; nv++)
1205        {
1206        centre [dir_x] += h_vertex[nv]->getX ();
1207        centre [dir_y] += h_vertex[nv]->getY ();
1208        centre [dir_z] += h_vertex[nv]->getZ ();
1209        }
1210
1211    centre [dir_x] /= HV_MAXI;
1212    centre [dir_y] /= HV_MAXI;
1213    centre [dir_z] /= HV_MAXI;
1214    return centre;
1215 }
1216 // =============================================================== definedBy
1217 bool Hexa::definedBy  (Vertex* v1, Vertex* v2)
1218 {
1219    for (int n1=0 ; n1< HV_MAXI ; n1++)
1220        {
1221 //              (   Diagonale        )  Dessus
1222        int n2 = (n1 + 2) MODULO HV_MAXI + HV_MAXI;
1223        if (   (v1 == h_vertex[n1] && v2 == h_vertex[n2])
1224            || (v1 == h_vertex[n2] && v2 == h_vertex[n1])) return true;
1225        }
1226    return false;
1227 }
1228 // =============================================================== definedBy
1229 bool Hexa::definedBy  (Quad* qa, Quad* qb)
1230 {
1231    if (qa==qb || BadElement (qa) || BadElement (qb))
1232        return false;
1233
1234    bool p1 = false, p2 = false;
1235    for (int nq=0 ; nq< HQ_MAXI ; nq++)
1236        {
1237        if (qa == h_quad[nq])
1238           p1 = true;
1239        else if (qb == h_quad[nq])
1240           p2 = true;
1241        }
1242    return p1 && p2;
1243 }
1244 // =============================================================== setColor
1245 void Hexa::setColor  (double val)
1246 {
1247    for (int nc=0 ; nc< HV_MAXI ; nc++)
1248        h_vertex[nc] -> setColor (val);
1249 }
1250 // ============================================================== markElements
1251 void Hexa::markElements  (int marque)
1252 {
1253    for (int nc=0 ; nc< HQ_MAXI ; nc++) h_quad  [nc] -> setMark (marque);
1254    for (int nc=0 ; nc< HE_MAXI ; nc++) h_edge  [nc] -> setMark (marque);
1255    for (int nc=0 ; nc< HV_MAXI ; nc++) h_vertex[nc] -> setMark (marque);
1256 }
1257 // =============================================================== duplicate
1258 void Hexa::duplicate  ()
1259 {
1260    h_clone = new Hexa (GetClone (h_quad [Q_A]),
1261                        GetClone (h_quad [Q_B]),
1262                        GetClone (h_quad [Q_C]),
1263                        GetClone (h_quad [Q_D]),
1264                        GetClone (h_quad [Q_E]),
1265                        GetClone (h_quad [Q_F]));
1266 }
1267 END_NAMESPACE_HEXA