Salome HOME
Hexa6 : Mise ajour des sources
[modules/hexablock.git] / src / HEXABLOCK / HexDocument_Xml.cxx
1
2 // C++ : Classe Document : methodes internes
3
4 // Copyright (C) 2009-2013  CEA/DEN, EDF R&D
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.
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 "HexDocument.hxx"
23 #include <libgen.h>               // Pour basename
24 #include <cstdlib>               // Pour atoi et atof
25
26 #include "Hex.hxx"
27 #include "HexVertex.hxx"
28 #include "HexEdge.hxx"
29 #include "HexQuad.hxx"
30 #include "HexHexa.hxx"
31
32 #include "HexElements.hxx"
33
34 #include "HexVector.hxx"
35 #include "HexCylinder.hxx"
36 #include "HexPipe.hxx"
37 #include "HexMatrix.hxx"
38 #include "HexCloner.hxx"
39 #include "HexPropagation.hxx"
40 #include "HexLaw.hxx"
41 #include "HexGroup.hxx"
42
43 #include "HexNewShape.hxx"
44 #include "HexVertexShape.hxx"
45 #include "HexEdgeShape.hxx"
46 #include "HexFaceShape.hxx"
47
48 #include "HexXmlWriter.hxx"
49 #include "HexXmlTree.hxx"
50 #include "HexGlobale.hxx"
51
52 BEGIN_NAMESPACE_HEXA
53
54 // ======================================================== get_coords
55 int get_coords (const string& chaine, double& x, double& y, double& z)
56 {
57    // int nv = sscanf (chaine.c_str (), "%lg %lg %lg", &x, &y, &z);
58    cpchar buffer = chaine.c_str ();
59    int nv = sscanf (buffer, "%lg %lg %lg", &x, &y, &z);
60    if (nv!=3) return HERR;
61    return HOK;
62 }
63 // ======================================================== get_coords
64 int get_coords (const string& chaine, double& x, double& y)
65 {
66    cpchar buffer = chaine.c_str ();
67    int nv = sscanf (buffer, "%lg %lg", &x, &y);
68    if (nv!=2) return HERR;
69    return HOK;
70 }
71 // ======================================================== parse_name
72 int parse_name (XmlTree* node, const string& nom, EltBase* elt)
73 {
74    int lg    = nom.size();
75    int nroid = 0;
76    for (int nc=1 ; nc<lg ; nc++)
77        nroid = 10*nroid + nom[nc] - '0';
78
79    elt->setId (nroid);
80
81    const  string& name = node->findValue ("name");
82    if (name=="")
83       return HERR;
84
85    elt->setName (name);
86    return HOK;
87 }
88 // ======================================================== get_names
89 void get_names (const string& chaine, int size, vector<string>& table)
90 {
91    table.clear ();
92    int    lg    = chaine.size();
93    string mot   = "";
94    bool encours = false;
95
96    for (int nc=0 ; nc<lg ; nc++)
97        {
98        char car  = chaine[nc];
99        if (isalnum (car))
100           {
101           mot += car;
102           encours = true;
103           }
104        else if (encours)
105           {
106           table.push_back (mot);
107           encours = false;
108           mot     = "";
109           }
110        }
111
112    if (encours)
113       table.push_back (mot);
114 }
115 // ======================================================== count_children
116 int count_children (XmlTree* dad)
117 {
118    int    nbre = dad==NULL ? 0 : dad->getNbrChildren ();
119    return nbre;
120 }
121 // ======================================================== loadXml
122 int Document::loadXml (cpchar ficname)
123 {
124    XmlTree xml("");
125    string filename = ficname;
126    el_name         = basename ((pchar)ficname);
127
128    static const int NbExt = 3;
129    static cpchar t_ext [NbExt] = { ".xml", ".XML", ".Xml" };
130    size_t ici   = 0;
131    bool   noext = true;
132    for (int nx = 0; nx < NbExt && noext ; nx++)
133        {
134        ici   = el_name.rfind (t_ext[nx]);
135        noext = ici < 0 || ici > el_name.size();
136        }
137
138    if (noext)
139       filename += ".xml";
140    else
141       el_name.erase (ici, 4);
142
143    int ier = xml.parseFile (filename);
144    if (ier!=HOK)
145       return ier;
146
147    ier = parseXml (xml);
148    return ier;
149 }
150 // ======================================================== setXml
151 int Document::setXml (cpchar flux)
152 {
153    int posit = 0;
154    int ier   = setXml (flux, posit);
155    return ier;
156 }
157 // ======================================================== setXml
158 int Document::setXml (cpchar flux, int& posit)
159 {
160    XmlTree xml("");
161
162    int ier = xml.parseStream (flux, posit);
163    if (ier!=HOK)
164       return ier;
165
166    ier = parseXml (xml);
167    if (ier==HOK)
168       doc_saved = true;
169
170    return ier;
171 }
172 // ======================================================== parseXml
173 int Document::parseXml (XmlTree& xml)
174 {
175    // xml.dump ();
176
177    map <std::string, Vertex*> t_vertex;
178    map <std::string, Edge*>   t_edge;
179    map <std::string, Quad*>   t_quad;
180    map <std::string, Hexa*>   t_hexa;
181    map <std::string, Vector*> t_vector;
182    vector <string> tname;
183
184    const  string& version = xml.findValue ("version");
185    if (version == "")
186        {
187        cout << " **** Format du fichier XML perime"
188             << endl;
189        return HERR;
190        }
191    const  string& name = xml.findValue ("name");
192    if (name != el_name)
193        setName (name.c_str());
194
195    parseShapes (xml);
196
197    XmlTree* rubrique = xml.findChild ("ListVertices");
198    int nbrelts       = count_children (rubrique);
199
200    Vertex* vertex = NULL;
201    for (int nro=0 ; nro < nbrelts ; nro++)
202        {
203        XmlTree* node = rubrique->getChild (nro);
204        const string& type = node->getName();
205        double px, py, pz;
206        if (type=="Vertex")
207           {
208           const  string& nom    = node->findValue ("id");
209           const  string& coords = node->findValue ("coord");
210           get_coords (coords, px, py, pz);
211
212           vertex = addVertex (px, py, pz);
213           parse_name (node, nom, vertex);
214           t_vertex [nom] = vertex;
215           }
216        else if (type=="Asso")
217           {
218           parseAssociation (node, vertex);
219           }
220        }
221
222    rubrique = xml.findChild ("ListEdges");
223    nbrelts  = count_children (rubrique);
224    Edge* edge = NULL;
225
226    for (int nro=0 ; nro < nbrelts ; nro++)
227        {
228        XmlTree*      node = rubrique->getChild (nro);
229        const string& type = node->getName();
230        if (type=="Edge")
231           {
232           const  string& nom      = node->findValue ("id");
233           const  string& vertices = node->findValue ("vertices");
234           get_names (vertices, V_TWO, tname);
235           edge = new Edge (t_vertex [tname[0]], t_vertex [tname[1]]);
236           t_edge [nom] = edge;
237           parse_name (node, nom, edge);
238           }
239        else if (type=="Asso")
240           {
241           parseAssociation (node, edge);
242           }
243        }
244
245    rubrique = xml.findChild ("ListQuads");
246    nbrelts  = count_children (rubrique);
247    Quad* quad = NULL;
248
249    for (int nro=0 ; nro < nbrelts ; nro++)
250        {
251        XmlTree*      node = rubrique->getChild (nro);
252        const string& type = node->getName();
253        if (type=="Quad")
254           {
255           const string& nom   = node->findValue ("id");
256           const string& edges = node->findValue ("edges");
257           get_names (edges, V_TWO, tname);
258
259           quad = new Quad (t_edge [tname[0]], t_edge [tname[1]],
260                            t_edge [tname[2]], t_edge [tname[3]]);
261           t_quad [nom] = quad;
262           parse_name (node, nom, quad);
263           }
264        else if (type=="Asso")
265           {
266           parseAssociation (node, quad);
267           }
268        }
269
270    rubrique = xml.findChild ("ListHexas");
271    nbrelts  = count_children (rubrique);
272
273    for (int nro=0 ; nro < nbrelts ; nro++)
274        {
275        XmlTree* node = rubrique->getChild (nro);
276        const  string& nom   = node->findValue ("id");
277        const  string& quads = node->findValue ("quads");
278        get_names (quads, V_TWO, tname);
279
280        Hexa* hexa =  new Hexa (t_quad [tname[0]], t_quad [tname[1]],
281                                 t_quad [tname[2]], t_quad [tname[3]],
282                                 t_quad [tname[4]], t_quad [tname[5]]);
283        t_hexa [nom] = hexa;
284        parse_name (node, nom, hexa);
285        }
286
287    rubrique = xml.findChild ("ListVectors");
288    nbrelts  = count_children (rubrique);
289
290    for (int nro=0 ; nro < nbrelts ; nro++)
291        {
292        XmlTree* node = rubrique->getChild (nro);
293        double px, py, pz;
294        const  string& nom    = node->findValue ("id");
295        const  string& coords = node->findValue ("coord");
296        get_coords (coords, px, py, pz);
297
298        Vector* vector = addVector (px, py, pz);
299        t_vector [nom] = vector;
300        parse_name (node, nom, vector);
301        }
302
303    rubrique = xml.findChild ("ListDicretizationLaws");
304    nbrelts  = count_children (rubrique);
305
306    for (int nro=0 ; nro < nbrelts ; nro++)
307        {
308        XmlTree* node = rubrique->getChild (nro);
309        const  string& id    = node->findValue ("id");
310        const  string& kind  = node->findValue ("kind");
311        const  string& nodes = node->findValue ("nodes");
312        const  string& coeff = node->findValue ("coeff");
313
314        int    nbnodes = atoi (nodes.c_str());
315        double koeff   = atof (coeff.c_str());
316        if (id != "DefaultLaw")
317           {
318           Law*   law  = addLaw (id.c_str(), nbnodes);
319           law->setCoefficient (koeff);
320           law->setKind (kind.c_str());
321           }
322        }
323
324    rubrique = xml.findChild ("ListPropagations");
325    nbrelts  = count_children (rubrique);
326
327    for (int nro=0 ; nro < nbrelts ; nro++)
328        {
329        XmlTree* node = rubrique->getChild (nro);
330        const  string& nmedge  = node->findValue ("edge");
331        const  string& nmlaw   = node->findValue ("law");
332        //  const  string& nmway   = node->findValue ("way");
333
334        edge     = t_edge [nmedge];
335        Law* law = findLaw (nmlaw.c_str());
336        //  bool way = nmway == "true";
337
338        if (edge != NULL)
339            edge->setLaw (law);
340        }
341
342    for (int pipe=0 ; pipe<2 ; pipe++)
343        {
344        rubrique = pipe ? xml.findChild ("ListPipes")
345                        : xml.findChild ("ListCylinders");
346
347        nbrelts  = count_children (rubrique);
348
349        for (int nro=0 ; nro < nbrelts ; nro++)
350            {
351            XmlTree* node = rubrique->getChild (nro);
352            const  string& cbase   = node->findValue ("c_base"  );
353            const  string& cdir    = node->findValue ("c_dir"   );
354            const  string& cradius = node->findValue ("c_radius");
355            const  string& cheight = node->findValue ("c_height");
356
357            Vertex* base    = t_vertex [cbase];
358            Vector* dir     = t_vector [cdir];
359            double radius  = atof (cradius.c_str());
360            double height  = atof (cheight.c_str());
361
362            if (pipe)
363               {
364               const string& cradius1  = node->findValue ("c_int_radius");
365               double radius1  = atof (cradius1.c_str());
366               addPipe (base, dir, radius1, radius, height);
367               }
368            else
369               {
370               addCylinder (base, dir, radius, height);
371               }
372            }
373        }
374
375    rubrique = xml.findChild ("ListGroups");
376    int nbrgroups  = count_children (rubrique);
377
378    for (int nro=0 ; nro < nbrgroups ; nro++)
379        {
380        XmlTree*  ndgroup = rubrique->getChild (nro);
381        XmlTree*  node    = ndgroup ->getChild (0);
382        const  string& nom   = node->findValue ("name");
383        const  string& ckind = node->findValue ("kind");
384
385        EnumGroup kind   = Group::getKind (ckind);
386        Group*    groupe = addGroup (nom.c_str(), kind);
387        EnumElt   type   = groupe->getTypeElt ();
388
389        nbrelts = count_children (ndgroup);
390        for (int nelt=1 ; nelt < nbrelts ; nelt++)
391            {
392            node = ndgroup ->getChild (nelt);
393            const string& id = node->findValue ("id");
394            switch (type)
395               {
396               case EL_HEXA : groupe->addElement (t_hexa [id]);
397                    break;
398               case EL_QUAD : groupe->addElement (t_quad [id]);
399                    break;
400               case EL_EDGE : groupe->addElement (t_edge [id]);
401                    break;
402               case EL_VERTEX :
403               default      : groupe->addElement (t_vertex [id]);
404                    break;
405               }
406            }
407        }
408
409
410    return HOK;
411 }
412 // ======================================================== save
413 int Document::save (const char* ficxml)
414 {
415    DumpStart ("save", ficxml);
416
417    if (doc_xml==NULL)
418        doc_xml = new XmlWriter ();
419
420    int ier  = doc_xml->setFileName (ficxml);
421    if (ier == HOK)
422        ier =  genXml ();
423
424    DumpReturn (ier);
425    return ier;
426 }
427 // ======================================================== appendXml
428 int Document::appendXml (pfile fstudy)
429 {
430    if (doc_xml==NULL)
431        doc_xml = new XmlWriter ();
432
433    doc_xml->setFile (fstudy);
434
435    int    ier = genXml ();
436    return ier;
437 }
438 // ======================================================== getXml
439 cpchar Document::getXml ()
440 {
441    if (doc_xml==NULL)
442        doc_xml = new XmlWriter ();
443
444    doc_xml->setStream ();
445    int ier = genXml ();
446    if (ier!=HOK)
447       return NULL;
448
449    return doc_xml->getXml ();
450 }
451 // ======================================================== genXml
452 int Document::genXml ()
453 {
454    const int HexVersion = 1;
455                                        // -- 1) Raz numerotation precedente
456    markAll (NO_COUNTED);
457    if (maj_propagation)
458        majPropagation ();
459
460    if (doc_xml==NULL)
461        doc_xml = new XmlWriter ();
462
463    doc_xml->startXml ();
464    doc_xml->openMark ("Document");
465    doc_xml->addAttribute ("name",    el_name);
466    doc_xml->addAttribute ("version", HexVersion);
467    doc_xml->endMark ();
468
469    cpchar balise [] = {"ListXXXX",
470           "ListVertices", "ListEdges", "ListQuads", "ListHexas", "ListVectors",
471           "ListXXXX" };
472
473    for (int type=EL_VERTEX ; type <= EL_VECTOR ; type++)
474        {
475        doc_xml->addMark (balise [type]);
476        for (EltBase* elt = doc_first_elt[type]->next (); elt!=NULL;
477                      elt = elt->next())
478            {
479            if (elt !=NULL && elt->isHere())
480               elt->saveXml (doc_xml);
481            }
482        doc_xml->closeMark (true);
483        }
484
485    doc_xml->addMark ("ListDicretizationLaws");
486    for (int nro=0 ; nro<nbr_laws ; nro++)
487        doc_laws [nro]->saveXml (doc_xml);
488    doc_xml->closeMark (true);
489
490    doc_xml->addMark ("ListPropagations");
491    for (int nro=0 ; nro<nbr_propagations ; nro++)
492        doc_propagation[nro]->saveXml (doc_xml);
493    doc_xml->closeMark (true);
494
495    int nombre = countCylinder();
496    doc_xml->addMark ("ListCylinders");
497    for (int nro=0 ; nro<nombre ; nro++)
498        doc_cylinder[nro]->saveXml (doc_xml);
499    doc_xml->closeMark (true);
500
501    nombre = countPipe();
502    doc_xml->addMark ("ListPipes");
503    for (int nro=0 ; nro<nombre ; nro++)
504        doc_pipe[nro]->saveXml (doc_xml);
505    doc_xml->closeMark (true);
506
507    nombre = countGroup();
508    doc_xml->addMark ("ListGroups");
509    for (int nro=0 ; nro<nombre ; nro++)
510        doc_group[nro]->saveXml (doc_xml);
511    doc_xml->closeMark (true);
512
513    nombre = countShape ();
514    doc_xml->addMark ("ListShapes");
515    for (int nro=0 ; nro<nombre ; nro++)
516        doc_tab_shape[nro]->saveXml (doc_xml);
517    doc_xml->closeMark ();
518
519    doc_xml->closeMark ();
520    doc_xml->closeXml  ();
521    doc_saved = true;
522    return  HOK;
523 }
524 // ======================================================== markAll
525 void Document::markAll (int marque, int type)
526 {
527    int debut = EL_VERTEX;
528    int fin   = EL_HEXA;
529    if (type>=0 && type<EL_MAXI)
530       debut = fin = type;
531
532    for (int type=debut ; type <= fin ; type++)
533        {
534        for (EltBase* elt = doc_first_elt[type]->next (); elt!=NULL;
535                      elt = elt->next())
536            elt->setMark (marque);
537        }
538 }
539 // ====================================================== saveVtk
540 int Document::saveVtk0 (cpchar nomfic)
541 {
542                                            // -- 1) Raz numerotation precedente
543    markAll (NO_COUNTED, EL_VERTEX);
544
545    int nbnodes = 0;
546    int nbcells = 0;
547
548    for (EltBase* elt = doc_first_elt[EL_HEXA]->next (); elt!=NULL;
549                  elt = elt->next())
550        {
551        Hexa* cell = static_cast <Hexa*> (elt);
552        if (cell!=NULL && cell->isHere())
553           {
554           nbcells ++;
555           nbnodes += cell->countNodes ();
556           }
557        }
558
559    pfile vtk = fopen (nomfic, "w");
560    if (vtk==NULL)
561       {
562       cout << " ****" << endl;
563       cout << " **** Document::saveVtk : " << endl;
564       cout << " **** Can't open file "     << endl;
565       cout << " ****" << endl;
566
567       }
568    fprintf (vtk, "# vtk DataFile Version 3.1\n");
569    fprintf (vtk, "%s \n", nomfic);
570    fprintf (vtk, "ASCII\n");
571    fprintf (vtk, "DATASET UNSTRUCTURED_GRID\n");
572    fprintf (vtk, "POINTS %d float\n", nbnodes);
573
574                                            // -- 2) Les noeuds
575    int nronode = 0;
576    for (EltBase* elt = doc_first_elt[EL_HEXA]->next (); elt!=NULL;
577                  elt = elt->next())
578        {
579        Hexa* cell = static_cast <Hexa*> (elt);
580        if (cell!=NULL && cell->isHere())
581           cell->printNodes (vtk, nronode);
582        }
583                                            // -- 2) Les hexas
584
585    fprintf (vtk, "CELLS %d %d\n", nbcells, nbcells*(HV_MAXI+1));
586
587    for (EltBase* elt = doc_first_elt[EL_HEXA]->next (); elt!=NULL;
588                  elt = elt->next())
589        {
590        Hexa* cell = static_cast <Hexa*> (elt);
591        if (cell!=NULL && cell->isHere())
592           cell->printHexa (vtk);
593        }
594
595    fprintf (vtk, "CELL_TYPES %d\n", nbcells);
596    for (int nro=0 ; nro<nbcells ; nro++)
597        fprintf (vtk, "%d\n", HE_MAXI);
598
599    fprintf (vtk, "POINT_DATA %d \n", nbnodes);
600    fprintf (vtk, "SCALARS A float\n");
601    fprintf (vtk, "LOOKUP_TABLE default\n");
602
603    for (EltBase* elt = doc_first_elt[EL_HEXA]->next (); elt!=NULL;
604                  elt = elt->next())
605        {
606        Hexa* cell = static_cast <Hexa*> (elt);
607        if (cell!=NULL && cell->isHere())
608           cell->colorNodes (vtk);
609        }
610
611    fclose (vtk);
612    return HOK;
613 }
614
615 // ====================================================== saveVtk
616 // ==== Nouvelle formule qui conserve les numeros de vertex
617 int Document::saveVtk (cpchar nomfic)
618 {
619    DumpStart ("saveVtk", nomfic);
620    int nbnodes = doc_nbr_elt [EL_VERTEX];
621    int nbcells = countHexa ();
622
623    pfile vtk = fopen (nomfic, "w");
624    if (vtk==NULL)
625       {
626       cout << " ****" << endl;
627       cout << " **** Document::saveVtk : " << endl;
628       cout << " **** Can't open file "     << endl;
629       cout << " ****" << endl;
630
631       }
632    fprintf (vtk, "# vtk DataFile Version 3.1\n");
633    fprintf (vtk, "%s \n", nomfic);
634    fprintf (vtk, "ASCII\n");
635    fprintf (vtk, "DATASET UNSTRUCTURED_GRID\n");
636    fprintf (vtk, "POINTS %d float\n", nbnodes);
637
638                                            // -- 1) Les noeuds
639    Real3 koord;
640    static const double minvtk = 1e-30;
641 #define Koord(p) koord[p]<minvtk && koord[p]>-minvtk ? 0 : koord[p]
642
643    for (EltBase* elt = doc_first_elt[EL_VERTEX]->next (); elt!=NULL;
644                  elt = elt->next())
645        {
646        Vertex* node = static_cast <Vertex*> (elt);
647        if (node->isHere())
648           {
649           node->getPoint (koord);
650           fprintf (vtk, "%g %g %g\n", Koord(dir_x), Koord(dir_y), Koord(dir_z));
651           }
652        else
653           fprintf (vtk, "0 0 0\n");
654        }
655                                            // -- 2) Les hexas
656
657    fprintf (vtk, "CELLS %d %d\n", nbcells, nbcells*(HV_MAXI+1));
658
659    for (EltBase* elt = doc_first_elt[EL_HEXA]->next (); elt!=NULL;
660                  elt = elt->next())
661        {
662        Hexa* cell = static_cast <Hexa*> (elt);
663        if (cell!=NULL && cell->isHere())
664           cell->printHexaVtk (vtk);
665        }
666
667    fprintf (vtk, "CELL_TYPES %d\n", nbcells);
668    for (int nro=0 ; nro<nbcells ; nro++)
669        fprintf (vtk, "%d\n", HE_MAXI);
670
671    fprintf (vtk, "POINT_DATA %d \n", nbnodes);
672    fprintf (vtk, "SCALARS A float\n");
673    fprintf (vtk, "LOOKUP_TABLE default\n");
674    for (EltBase* elt = doc_first_elt[EL_VERTEX]->next (); elt!=NULL;
675                  elt = elt->next())
676        {
677        Vertex* node = static_cast <Vertex*> (elt);
678        if (node->isHere())
679           {
680           double color = 100*(node->getScalar()+1);
681           fprintf (vtk, "%g\n", color);
682           }
683        else 
684           fprintf (vtk, "100\n");
685        }
686
687    fclose (vtk);
688    DumpReturn (HOK);
689    return HOK;
690 }
691 // ====================================================== purge
692 void Document::purge ()
693 {
694    purge_elements = false;
695                        // ------------------- Raz marques
696    markAll (NO_USED);
697
698                        // ------------------- Marquage elements utilises
699    for (EltBase* elt = doc_first_elt[EL_HEXA]->next (); elt!=NULL;
700                  elt = elt->next())
701        {
702        Hexa* cell = static_cast <Hexa*> (elt);
703        if (cell!=NULL && cell->isHere())
704           cell->markElements (IS_USED);
705        }
706                        // ------------------- Elimination elements inutilises
707    for (int type=EL_VERTEX ; type <= EL_QUAD ; type++)
708        {
709        for (EltBase* elt = doc_first_elt[type]->next (); elt!=NULL;
710                      elt = elt->next())
711            {
712            if (elt->getMark  () == NO_USED)
713                elt->suppress ();
714            }
715        }
716                        // ------------------- Sortie elements inutilises
717
718 /* ****************************************************************
719    EltBase* trash = doc_last_elt [EL_REMOVED];
720
721    for (int type=EL_VERTEX ; type <= EL_HEXA ; type++)
722        {
723        doc_nbr_elt [type] = 0;
724        EltBase* last = doc_first_elt [type];
725        for (EltBase* elt = last->next (); elt!=NULL; elt = last->next())
726            {
727            if (elt->isHere  ())
728                {
729                doc_nbr_elt  [type] ++;
730                last = elt;
731                }
732            else
733                {
734                last  -> setNext (elt -> next());
735                trash -> setNext (elt);
736                trash = elt;
737                trash -> setNext (NULL);
738                }
739            }
740        doc_last_elt [type] = last;
741        }
742
743    doc_last_elt [EL_REMOVED] = trash;
744    **************************************************************** */
745    update ();
746 }
747 // ======================================================== majReferences
748 void Document::majReferences ()
749 {
750    maj_connection = false;
751
752    for (int type=EL_VERTEX ; type <= EL_QUAD ; type++)
753        {
754        for (EltBase* elt = doc_first_elt[type]->next (); elt!=NULL;
755                      elt = elt->next())
756            {
757            elt->razReferences ();
758            }
759        }
760
761    for (int type=EL_EDGE ; type <= EL_HEXA ; type++)
762        {
763        for (EltBase* elt = doc_first_elt[type]->next (); elt!=NULL;
764                      elt = elt->next())
765            {
766            if (elt->isHere ())
767                elt->majReferences ();
768            }
769        }
770 }
771 // ======================================================== dump
772 void Document::dump ()
773 {
774    cpchar nom_type [] = { "Elments non classes",
775           "Sommets", "Aretes", "Faces", "Hexaedres", "Elements detruits" };
776
777    for (int type=EL_VERTEX ; type <= EL_HEXA ; type++)
778        {
779        printf ("\n");
780        printf (" ++++ Liste des %s\n", nom_type[type]);
781        printf ("\n");
782
783        for (EltBase* elt = doc_first_elt[type]->next (); elt!=NULL;
784                      elt = elt->next())
785            {
786            if (elt->isHere())
787                elt->dump ();
788            }
789        }
790
791    printf (" ++++ End od dump\n");
792 }
793 // ======================================================== putError
794 void Document::putError (cpchar mess, cpchar info1, cpchar info2)
795 {
796      nbr_errors ++;
797      printf (" ********************************************************** \n");
798      printf (" ****  HexaBlocks Error nro %d :\n", nbr_errors);
799      printf (" **** ");
800      printf (mess, info1, info2);
801      printf ("\n");
802      printf (" **** \n");
803      printf (" ********************************************************** \n");
804 }
805 // ======================================================== hputError
806 void Document::hputError (cpchar mess, EltBase* e1, EltBase* e2)
807 {
808    char name1 [32] = { 0 };
809    char name2 [32] = { 0 };
810
811    if (e1!=NULL) e1->getName (name1);
812    if (e2!=NULL) e2->getName (name2);
813
814    putError (mess, name1, name2);
815 }
816 // ======================================================== parseSubShape
817 SubShape* Document::parseSubShape (XmlTree* node)
818 {
819    const string& name  = node->findValue   ("shape");
820    int           subid = node->findInteger ("subid");
821    NewShape*     shape = findShape (name);
822    if (shape==NULL)
823        return NULL;
824
825    SubShape* sub_shape = shape->findSubShape (subid);
826    return    sub_shape;
827 }
828 // ======================================================== parseAssociation (v)
829 void Document::parseAssociation (XmlTree* node, Vertex* vertex)
830 {
831    SubShape* shape = parseSubShape (node);
832    if (shape==NULL || vertex==NULL)
833        return;
834
835    if (shape->getDim()!=0)
836       return;
837    VertexShape* vshape = static_cast <VertexShape*> (shape);
838    vertex->setAssociation (vshape);
839 }
840 // ======================================================== parseAssociation (e)
841 void Document::parseAssociation (XmlTree* node, Edge* edge)
842 {
843    SubShape* shape = parseSubShape (node);
844    if (shape==NULL || edge==NULL)
845        return;
846
847    if (shape->getDim()!=1)
848       return;
849
850    const  string& inter = node->findValue ("interval");
851    double pdeb, pfin;
852    get_coords (inter, pdeb, pfin);
853
854    EdgeShape* line = static_cast <EdgeShape*> (shape);
855    edge->addAssociation (line, pdeb, pfin);
856 }
857 // ======================================================== parseAssociation (q)
858 void Document::parseAssociation (XmlTree* node, Quad* quad)
859 {
860    SubShape* shape = parseSubShape (node);
861    if (shape==NULL || quad==NULL)
862        return;
863
864    if (shape->getDim()!=2)
865       return;
866    FaceShape* face = static_cast <FaceShape*> (shape);
867    quad->addAssociation (face);
868 }
869 // ======================================================== parseShapes
870 void Document::parseShapes (XmlTree& root)
871 {
872    XmlTree* rubrique = root.findChild ("ListShapes");
873    int nbrelts       = count_children (rubrique);
874
875    for (int nro=0 ; nro < nbrelts ; nro++)
876        {
877        XmlTree*      node = rubrique->getChild (nro);
878        const string& type = node->getName();
879        if (type=="Shape")
880           {
881           const string& nom   = node->findValue   ("id"  );
882           int           orig  = node->findInteger ("type");
883           const string& brep  = node->findValue   ("brep");
884           NewShape*     shape = new NewShape (this, (EnumShape)orig);
885
886           parse_name (node, nom, shape);
887           shape->setBrep (brep);
888           doc_tab_shape.push_back (shape);
889           }
890        else if (type=="Cloud")
891           {
892           int nbvert = count_children (node);
893           for (int nv=0 ; nv < nbvert ; nv++)
894               {
895               Real3    point;
896               XmlTree* sommet = node->getChild (nv);
897               const  string& coords = sommet->findValue ("coord");
898               get_coords (coords, point[dir_x], point[dir_y], point[dir_z]);
899               doc_cloud->addPoint (point);
900               }
901           }
902        }
903 }
904 END_NAMESPACE_HEXA