1 // -*- Mode : c++ -*-
2 //
3 // SUMMARY  :
4 // USAGE    :
5 // ORG      :
6 // AUTHOR   : Frederic Hecht
7 // E-MAIL   : hecht@ann.jussieu.fr
8 //
9 
10 /*
11 
12  This file is part of Freefem++
13 
14  Freefem++ is free software; you can redistribute it and/or modify
15  it under the terms of the GNU Lesser General Public License as published by
16  the Free Software Foundation; either version 2.1 of the License, or
17  (at your option) any later version.
18 
19  Freefem++  is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  GNU Lesser General Public License for more details.
23 
24  You should have received a copy of the GNU Lesser General Public License
25  along with Freefem++; if not, write to the Free Software
26  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
27  */
28 #include <cstdio>
29 #include <cstring>
30 #include <cmath>
31 #include <ctime>
32 
33 #include "Meshio.h"
34 #include "Mesh2.h"
35 #include "QuadTree.h"
36 #include "SetOfE4.h"
37 #ifdef __MWERKS__
38 #pragma optimization_level 2
39 //#pragma inline_depth 1
40 #endif
41 
42 #ifdef DRAWING1
43 extern bool withrgraphique;
44 #endif
45 
46 namespace bamg {
47 
48   static const Direction NoDirOfSearch = Direction( );
49 
Read(MeshIstream & f_in,int Version,Real8 cutoffradian)50   void Triangles::Read(MeshIstream& f_in, int Version, Real8 cutoffradian) {
51     Real8 hmin = HUGE_VAL;    // the infinie value
52     //  Real8 MaximalAngleOfCorner = 10*Pi/180;//
53     Int4 i;
54     Int4 dim = 0;
55     Int4 hvertices = 0;
56     Int4 ifgeom = 0;
57     Metric M1(1);
58     if (verbosity > 1)
59       cout << "  -- ReadMesh " << f_in.CurrentFile << " Version = " << Version << endl;
60     int field = 0;
61     int showfield = 0;
62     while (f_in.cm( )) {
63       field = 0;
64       char fieldname[256];
65       if (f_in.eof( )) break;
66       f_in.cm( ) >> fieldname;
67       ;
68       if (f_in.eof( )) break;
69       f_in.err( );
70       if (verbosity > 9) cout << "    " << fieldname << endl;
71       if (!strcmp(fieldname, "MeshVersionFormatted"))
72         f_in >> Version;
73       else if (!strcmp(fieldname, "End"))
74         break;
75       else if (!strcmp(fieldname, "Dimension")) {
76         f_in >> dim;
77         assert(dim == 2);
78       } else if (!strcmp(fieldname, "Geometry")) {
79         string dir = "", str = f_in.CurrentFile;
80         std::size_t found = str.find_last_of("/\\");
81         if (found != string::npos) dir = str.substr(0, found + 1);
82         char* fgeom;
83         f_in >> fgeom;
84         //	  if (cutoffradian>=0) => bug if change edit the file geometry
85         //  Gh.MaximalAngleOfCorner = cutoffradian;
86         if (strlen(fgeom)) {
87           string fg = fgeom;
88           found = fg.find_last_of("/\\");
89           if (found != string::npos)    // seaprateur
90             fg = dir + fg.substr(found + 1);
91           if (verbosity > 4)
92             cout << " -- read geometry in " << fg << " not in  " << fgeom << " " << endl;
93           Gh.ReadGeometry(fg.c_str( ));
94         } else {
95           // include geometry
96           f_in.cm( );
97           Gh.ReadGeometry(f_in, fgeom);
98         }
99 
100         Gh.AfterRead( );
101         ifgeom = 1;
102         delete[] fgeom;
103       } else if (!strcmp(fieldname, "Identifier")) {
104         if (identity) delete[] identity;
105         f_in >> identity;
106       } else if (!strcmp(fieldname, "hVertices")) {
107         hvertices = 1;
108         Real4 h;
109         for (i = 0; i < nbv; i++) {
110           f_in >> h;
111           vertices[i].m = Metric(h);
112         }
113       } else if (!strcmp(fieldname, "Vertices")) {
114         assert(dim == 2);
115         f_in >> nbv;
116         if (verbosity > 3) cout << "   Nb of Vertices = " << nbv << endl;
117         nbvx = nbv;
118         vertices = new Vertex[nbvx];
119         assert(vertices);
120         ordre = new Vertex*[nbvx];
121         assert(ordre);
122 
123         nbiv = nbv;
124         for (i = 0; i < nbv; i++) {
125           ordre[i] = 0;
126           f_in >> vertices[i].r.x >> vertices[i].r.y >> vertices[i].ReferenceNumber;
127           vertices[i].DirOfSearch = NoDirOfSearch;
128           vertices[i].m = M1;
129           vertices[i].color = 0;
130         }
131         nbtx = 2 * nbv - 2;    // for filling The Holes and quadrilaterals
132         triangles = new Triangle[nbtx];
133         assert(triangles);
134         nbt = 0;
135       } else if (!strcmp(fieldname, "Triangles")) {
136         if (dim != 2) cerr << "ReadMesh: Dimension <> 2" << endl, f_in.ShowIoErr(0);
137         if (!vertices || !triangles || !nbv)
138           cerr << "ReadMesh:Triangles before Vertices" << endl, f_in.ShowIoErr(0);
139         int NbOfTria;
140         f_in >> NbOfTria;
141         if (verbosity > 3) cout << "   NbOfTria = " << NbOfTria << endl;
142         if (nbt + NbOfTria >= nbtx)
143           cerr << "ReadMesh: We must have 2*NbOfQuad + NbOfTria  = " << nbt + NbOfTria
144                << "  < 2*nbv-2 =" << nbtx << endl,
145             f_in.ShowIoErr(0);
146         //	  begintria = nbt;
147         for (i = 0; i < NbOfTria; i++) {
148           Int4 i1, i2, i3, iref;
149           Triangle& t = triangles[nbt++];
150           f_in >> i1 >> i2 >> i3 >> iref;
151           ordre[i1 - 1]++;
152           ordre[i2 - 1]++;
153           ordre[i3 - 1]++;
154 
155           t = Triangle(this, i1 - 1, i2 - 1, i3 - 1);
156           t.color = iref;
157         }
158         // verif
159         {
160           int err = 0;
161           for (int i = 0; i < nbv; ++i) {
162             if (ordre[i] == 0) {
163               cerr << " Err mesh vertices " << i + 1 << " is not in a  triangle " << endl;
164               err++;
165             }
166           }
167           if (err) {
168             cerr << " Fatal error read mesh  some vertices are in no traingle " << err << endl;
169             MeshError(6666);
170           }
171         }
172         // endtria=nbt;
173       } else if (!strcmp(fieldname, "Quadrilaterals")) {
174 
175         if (dim != 2) cerr << "ReadMesh: Dimension <> 2" << endl, f_in.ShowIoErr(0);
176         if (!vertices || !triangles || !nbv)
177           cerr << "ReadMesh:Quadrilaterals before Vertices" << endl, f_in.ShowIoErr(0);
178         f_in >> NbOfQuad;
179         if (verbosity > 3) cout << "   NbOfQuad= " << NbOfQuad << endl;
180         if (nbt + 2 * NbOfQuad >= nbtx)
181           cerr << "ReadMesh: We must have 2*NbOfQuad + NbOfTria  = " << nbt + 2 * NbOfQuad
182                << "  < 2*nbv-2 =" << nbtx << endl,
183             f_in.ShowIoErr(0);
184         //  beginquad=nbt;
185         for (i = 0; i < NbOfQuad; i++) {
186           Int4 i1, i2, i3, i4, iref;
187           Triangle& t1 = triangles[nbt++];
188           Triangle& t2 = triangles[nbt++];
189           f_in >> i1 >> i2 >> i3 >> i4 >> iref;
190           t1 = Triangle(this, i1 - 1, i2 - 1, i3 - 1);
191           t1.color = iref;
192           t2 = Triangle(this, i3 - 1, i4 - 1, i1 - 1);
193           t2.color = iref;
194           t1.SetHidden(OppositeEdge[1]);    // two time  because the adj was not created
195           t2.SetHidden(OppositeEdge[1]);
196         }
197         // endquad=nbt;
198       } else if (!strcmp(fieldname, "VertexOnGeometricVertex")) {
199         f_in >> NbVerticesOnGeomVertex;
200         if (verbosity > 5)
201           cout << "   NbVerticesOnGeomVertex = " << NbVerticesOnGeomVertex << endl
202                << " Gh.vertices " << Gh.vertices << endl;
203         if (NbVerticesOnGeomVertex) {
204           VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];
205           if (verbosity > 7)
206             cout << "   VerticesOnGeomVertex = " << VerticesOnGeomVertex << endl
207                  << "   Gh.vertices " << Gh.vertices << endl;
208           assert(VerticesOnGeomVertex);
209           for (Int4 i0 = 0; i0 < NbVerticesOnGeomVertex; i0++) {
210             Int4 i1, i2;
211             // VertexOnGeom & v =VerticesOnGeomVertex[i0];
212             f_in >> i1 >> i2;
213             VerticesOnGeomVertex[i0] = VertexOnGeom(vertices[i1 - 1], Gh.vertices[i2 - 1]);
214           }
215         }
216       } else if (!strcmp(fieldname, "VertexOnGeometricEdge")) {
217         f_in >> NbVerticesOnGeomEdge;
218         if (verbosity > 3) cout << "   NbVerticesOnGeomEdge = " << NbVerticesOnGeomEdge << endl;
219         if (NbVerticesOnGeomEdge) {
220           VerticesOnGeomEdge = new VertexOnGeom[NbVerticesOnGeomEdge];
221           assert(VerticesOnGeomEdge);
222           for (Int4 i0 = 0; i0 < NbVerticesOnGeomEdge; i0++) {
223             Int4 i1, i2;
224             Real8 s;
225             // VertexOnGeom & v =VerticesOnGeomVertex[i0];
226             f_in >> i1 >> i2 >> s;
227             VerticesOnGeomEdge[i0] = VertexOnGeom(vertices[i1 - 1], Gh.edges[i2 - 1], s);
228           }
229         }
230       } else if (!strcmp(fieldname, "Edges")) {
231         Int4 i, j, i1, i2;
232         f_in >> nbe;
233         edges = new Edge[nbe];
234         if (verbosity > 5)
235           cout << "     Record Edges: Nb of Edge " << nbe << " edges " << edges << endl;
236         assert(edges);
237         Real4* len = 0;
238         if (!hvertices) {
239           len = new Real4[nbv];
240           for (i = 0; i < nbv; i++) len[i] = 0;
241         }
242         for (i = 0; i < nbe; i++) {
243           f_in >> i1 >> i2 >> edges[i].ref;
244 
245           assert(i1 > 0 && i2 > 0);
246           assert(i1 <= nbv && i2 <= nbv);
247           i1--;
248           i2--;
249           edges[i].v[0] = vertices + i1;
250           edges[i].v[1] = vertices + i2;
251           edges[i].adj[0] = 0;
252           edges[i].adj[1] = 0;
253 
254           R2 x12 = vertices[i2].r - vertices[i1].r;
255           Real8 l12 = sqrt((x12, x12));
256           if (!hvertices) {
257             vertices[i1].color++;
258             vertices[i2].color++;
259             len[i1] += l12;
260             len[i2] += l12;
261           }
262           hmin = Min(hmin, l12);
263         }
264         // definition  the default of the given mesh size
265         if (!hvertices) {
266           for (i = 0; i < nbv; i++)
267             if (vertices[i].color > 0)
268               vertices[i].m = Metric(len[i] / (Real4)vertices[i].color);
269             else
270               vertices[i].m = Metric(hmin);
271           delete[] len;
272         }
273         if (verbosity > 5) cout << "     hmin " << hmin << endl;
274         // construction of edges[].adj
275         for (i = 0; i < nbv; i++) vertices[i].color = (vertices[i].color == 2) ? -1 : -2;
276         for (i = 0; i < nbe; i++)
277           for (j = 0; j < 2; j++) {
278             Vertex* v = edges[i].v[j];
279             Int4 i0 = v->color, j0;
280             if (i0 == -1)
281               v->color = i * 2 + j;
282             else if (i0 >= 0) {    // i and i0 edge are adjacent by the vertex v
283               j0 = i0 % 2;
284               i0 = i0 / 2;
285               assert(v == edges[i0].v[j0]);
286               edges[i].adj[j] = edges + i0;
287               edges[i0].adj[j0] = edges + i;
288               assert(edges[i0].v[j0] == v);
289               //	    if(verbosity>8)
290               //  cout << " edges adj " << i0 << " "<< j0 << " <-->  "  << i << " " << j << endl;
291               v->color = -3;
292             }
293           }
294 
295       }
296 
297       /*   ne peut pas marche car il n'y a pas de flag dans les aretes du maillages
298              else if (!strcmp(fieldname,"RequiredEdges"))
299               {
300                 int i,j,n;
301                 f_in  >> n ;
302 
303                 for (i=0;i<n;i++) {
304                   f_in  >>  j ;
305                   assert( j <= nbe );
306                   assert( j > 0 );
307                   j--;
308                   edges[j].SetRequired();  }
309             }
310       */
311       else if (!strcmp(fieldname, "EdgeOnGeometricEdge")) {
312         assert(edges);
313         int i1, i2, i, j;
314         f_in >> i2;
315         if (verbosity > 3) cout << "     Record EdgeOnGeometricEdge: Nb " << i2 << endl;
316         for (i1 = 0; i1 < i2; i1++) {
317           f_in >> i >> j;
318           if (!(i > 0 && j > 0 && i <= nbe && j <= Gh.nbe)) {
319             cerr << "      Record EdgeOnGeometricEdge i=" << i << " j = " << j;
320             cerr << " nbe = " << nbe << " Gh.nbe = " << Gh.nbe << endl;
321             cerr << " We must have : (i>0 && j >0 && i <= nbe && j <= Gh.nbe) ";
322             cerr << " Fatal error in file " << name << " line " << f_in.LineNumber << endl;
323             MeshError(1);
324           }
325 
326           edges[i - 1].on = Gh.edges + j - 1;
327         }
328         //	  cout << "end EdgeOnGeometricEdge" << endl;
329       } else if (!strcmp(fieldname, "SubDomain") || !strcmp(fieldname, "SubDomainFromMesh")) {
330 
331         f_in >> NbSubDomains;
332         subdomains = new SubDomain[NbSubDomains];
333         for (i = 0; i < NbSubDomains; i++) {
334           Int4 i3, head, sens;
335           f_in >> i3 >> head >> sens >> subdomains[i].ref;
336           assert(i3 == 3);
337           head--;
338           assert(head < nbt && head >= 0);
339           subdomains[i].head = triangles + head;
340         }
341       } else {    // unkown field
342         field = ++showfield;
343         if (showfield == 1)    // just to show one time
344           if (verbosity > 5)
345             cout << "     Warning we skip the field " << fieldname << " at line " << f_in.LineNumber
346                  << endl;
347       }
348       showfield = field;    // just to show one time
349     }
350 
351     if (ifgeom == 0) {
352       if (verbosity)
353         cout << " ## Warning: Mesh without geometry we construct a geometry (theta ="
354              << cutoffradian * 180 / Pi << " degres )" << endl;
355       ConsGeometry(cutoffradian);
356       Gh.AfterRead( );
357     }
358   }
359 
Read_am_fmt(MeshIstream & f_in)360   void Triangles::Read_am_fmt(MeshIstream& f_in) {
361     Metric M1(1);
362 
363     if (verbosity > 1) cout << "  -- ReadMesh .am_fmt file " << f_in.CurrentFile << endl;
364 
365     Int4 i;
366     f_in.cm( ) >> nbv >> nbt;
367     if (verbosity > 3) cout << "    nbv = " << nbv << " nbt = " << nbt << endl;
368     f_in.eol( );    //
369     nbvx = nbv;
370     nbtx = 2 * nbv - 2;    // for filling The Holes and quadrilaterals
371     triangles = new Triangle[nbtx];
372     assert(triangles);
373     vertices = new Vertex[nbvx];
374     ordre = new Vertex*[nbvx];
375 
376     for (i = 0; i < nbt; i++) {
377       Int4 i1, i2, i3;
378       f_in >> i1 >> i2 >> i3;
379       triangles[i] = Triangle(this, i1 - 1, i2 - 1, i3 - 1);
380     }
381     f_in.eol( );    //
382 
383     for (i = 0; i < nbv; i++)
384       f_in >> vertices[i].r.x >> vertices[i].r.y, vertices[i].m = M1,
385                                                   vertices[i].DirOfSearch = NoDirOfSearch;
386 
387     f_in.eol( );    //
388 
389     for (i = 0; i < nbt; i++) f_in >> triangles[i].color;
390     f_in.eol( );    //
391 
392     for (i = 0; i < nbv; i++) f_in >> vertices[i].ReferenceNumber;
393   }
394 
395   ////////////////////////
396 
Read_am(MeshIstream & ff)397   void Triangles::Read_am(MeshIstream& ff) {
398     if (verbosity > 1) cout << "  -- ReadMesh .am_fmt file " << ff.CurrentFile << endl;
399     Metric M1(1);
400 
401     IFortranUnFormattedFile f_in(ff);
402 
403     Int4 l = f_in.Record( );
404     assert(l == 2 * sizeof(Int4));
405     f_in >> nbv >> nbt;
406     l = f_in.Record( );
407     assert((size_t)l == nbt * sizeof(long) * 4 + nbv * (2 * sizeof(float) + sizeof(long)));
408     if (verbosity > 3) cout << "    nbv = " << nbv << " nbt = " << nbt << endl;
409 
410     nbvx = nbv;
411     nbtx = 2 * nbv - 2;    // for filling The Holes and quadrilaterals
412     triangles = new Triangle[nbtx];
413     assert(triangles);
414     vertices = new Vertex[nbvx];
415     ordre = new Vertex*[nbvx];
416 
417     Int4 i;
418     for (i = 0; i < nbt; i++) {
419       long i1, i2, i3;
420       f_in >> i1 >> i2 >> i3;
421       triangles[i] = Triangle(this, i1 - 1, i2 - 1, i3 - 1);
422     }
423 
424     for (i = 0; i < nbv; i++) {
425       float x, y;
426       f_in >> x >> y;
427       vertices[i].r.x = x;
428       vertices[i].r.y = y;
429       vertices[i].m = M1;
430     }
431 
432     for (i = 0; i < nbt; i++) {
433       long i;
434       f_in >> i;
435       triangles[i].color = i;
436     }
437 
438     for (i = 0; i < nbv; i++) {
439       long i;
440       f_in >> i;
441       vertices[i].ReferenceNumber = i;
442     }
443   }
444 
445   //////////////////////////////////
446 
Read_nopo(MeshIstream & ff)447   void Triangles::Read_nopo(MeshIstream& ff) {
448 
449     if (verbosity > 1) cout << "  -- ReadMesh .nopo file " << ff.CurrentFile << endl;
450     IFortranUnFormattedFile f_in(ff);
451 
452     Int4 l, i, j;
453     l = f_in.Record( );
454     l = f_in.Record( );
455     f_in >> i;
456     assert(i == 32);
457     Int4 niveau, netat, ntacm;
458 
459     char titre[80 + 1], date[2 * 4 + 1], nomcre[6 * 4 + 1], typesd[5];
460     f_in.read4(titre, 20);
461     f_in.read4(date, 2);
462     f_in.read4(nomcre, 6);
463     f_in.read4(typesd, 1);
464 
465     f_in >> niveau >> netat >> ntacm;
466     if (strcmp("NOPO", typesd)) {
467       cout << " where in record  " << f_in.where( ) << " " << strcmp("NOPO", typesd) << endl;
468       cerr << " not a  nopo file but `" << typesd << "`"
469            << " len = " << strlen(typesd) << endl;
470       cerr << (int)typesd[0] << (int)typesd[1] << (int)typesd[2] << (int)typesd[3] << (int)typesd[4]
471            << endl;
472       cout << " nomcre :" << nomcre << endl;
473       cout << " date   :" << date << endl;
474       cout << " titre  :" << titre << endl;
475       MeshError(112);
476     }
477     if (verbosity > 2)
478       cout << "    nb de tableau associe : " << ntacm << " niveau =" << niveau << endl;
479 
480     for (i = 0; i < ntacm; i++) f_in.Record( );
481 
482     f_in.Record( );
483     f_in >> l;
484     assert(l == 27);
485     Int4 nop2[27];
486     for (i = 0; i < 27; i++) f_in >> nop2[i];
487     Int4 ndim = nop2[0];
488     Int4 ncopnp = nop2[3];
489     Int4 ne = nop2[4];
490     Int4 ntria = nop2[7];
491     Int4 nquad = nop2[8];
492     Int4 np = nop2[21];
493     // Int4 nef = nop2[13];
494     Metric M1(1);
495     if (verbosity > 2)
496       cout << "    ndim = " << ndim << " ncopnp= " << ncopnp << " ne = " << ne
497            << "    ntri = " << ntria << " nquad = " << nquad << " np = " << np << endl;
498     nbv = np;
499     nbt = 2 * nquad + ntria;
500     if (ne != nquad + ntria || ndim != 2 || ncopnp != 1) {
501       cerr << " not only tria & quad in nopo mesh on dim != 2 ou ncopnp != 1 " << endl;
502       MeshError(113);
503     }
504     if (nop2[24] >= 0) f_in.Record( );
505     NbOfQuad = nquad;
506     nbvx = nbv;
507     nbtx = 2 * nbv - 2;    // for filling The Holes and quadrilaterals
508     triangles = new Triangle[nbtx];
509     assert(triangles);
510     vertices = new Vertex[nbvx];
511     ordre = new Vertex*[nbvx];
512 
513     f_in >> l;
514 
515     if (verbosity > 9) cout << " Read cnop4 nb of float  " << l << endl;
516 
517     assert(l == 2 * np);
518     for (i = 0; i < np; i++) {
519       float x, y;
520       f_in >> x >> y;
521       vertices[i].r.x = x;
522       vertices[i].r.y = y;
523       vertices[i].m = M1;
524       vertices[i].DirOfSearch = NoDirOfSearch;
525     }
526     f_in.Record( );
527     // lecture de nop5 bonjour les degats
528     f_in >> l;
529     if (verbosity > 9) cout << " Read nop5  nb of int4 " << l << endl;
530     Int4 k = 0;
531     Int4 nbe4 = 3 * ntria + 4 * nquad;
532     // cout << " nbv = " << nbv << " nbe4 " << nbe4 << endl;
533     SetOfEdges4* edge4 = new SetOfEdges4(nbe4, nbv);
534     Int4* refe = new Int4[nbe4];
535     Int4 kr = 0;
536     for (i = 0; i < ne; i++) {
537       // Int4 ng[4]={0,0,0,0};
538       Int4 np[4], rv[4], re[4];
539       Int4 ncge, nmae, ndsde, npo;
540       f_in >> ncge >> nmae >> ndsde >> npo;
541       // cout << " element " << i << " " << ncge << " "
542       // << nmae <<" " <<  npo << endl;
543       if (ncge != 3 && ncge != 4) {
544         cerr << " read nopo type element[" << i << "] =" << ncge << " not 3 or 4 " << endl;
545         MeshError(115);
546       }
547       if (npo != 3 && npo != 4) {
548         cerr << " read nopo element[" << i << "] npo = " << npo << " not 3 or 4 " << endl;
549         MeshError(115);
550       }
551 
552       for (j = 0; j < npo; j++) {
553         f_in >> np[j];
554         np[j]--;
555       }
556 
557       if (ncopnp != 1) {
558         f_in >> npo;
559         if (npo != 3 || npo != 4) {
560           cerr << " read nopo type element[" << i << "]= " << ncge << " not 3 or 4 " << endl;
561           MeshError(115);
562         }
563 
564         for (j = 0; j < npo; j++) {
565           f_in >> np[j];
566           np[j]--;
567         }
568       }
569       if (nmae > 0) {
570         Int4 ining;    // no ref
571 
572         f_in >> ining;
573         if (ining == 1) MeshError(116);
574         if (ining == 2)
575           for (j = 0; j < npo; j++) f_in >> re[j];
576         for (j = 0; j < npo; j++) f_in >> rv[j];
577 
578         // set the ref on vertex and the shift np of -1 to start at 0
579         for (j = 0; j < npo; j++) vertices[np[j]].ReferenceNumber = rv[j];
580 
581         if (ining == 2)
582           for (j = 0; j < npo; j++)
583             if (re[j]) {
584               kr++;
585               Int4 i0 = np[j];
586               Int4 i1 = np[(j + 1) % npo];
587               // cout << kr << " ref  edge " << i0 << " " << i1 << " " << re[j] << endl;
588               refe[edge4->addtrie(i0, i1)] = re[j];
589             }
590       }
591 
592       if (npo == 3) {    // triangles
593         triangles[k] = Triangle(this, np[0], np[1], np[2]);
594         triangles[k].color = ndsde;
595         k++;
596       } else if (npo == 4) {    // quad
597         Triangle& t1 = triangles[k++];
598         Triangle& t2 = triangles[k++];
599         t1 = Triangle(this, np[0], np[1], np[2]);
600         t2 = Triangle(this, np[2], np[3], np[0]);
601         t1.SetHidden(OppositeEdge[1]);    // two time  because the adj was not created
602         t2.SetHidden(OppositeEdge[1]);
603         t1.color = ndsde;
604         t2.color = ndsde;
605       } else {
606         cerr << " read nopo type element =" << npo << " not 3 or 4 " << endl;
607         MeshError(114);
608       }
609     }
610     // cout << k << " == " << nbt << endl;
611     assert(k == nbt);
612 
613     nbe = edge4->nb( );
614     if (nbe) {
615       if (verbosity > 7) cout << " Nb of ref edges = " << nbe << endl;
616       if (edges) delete[] edges;
617       edges = new Edge[nbe];
618       for (i = 0; i < nbe; i++) {
619         edges[i].v[0] = vertices + edge4->i(i);
620         edges[i].v[1] = vertices + edge4->j(i);
621         edges[i].ref = refe[i];
622         //	 cout << i << " " <<  edge4->i(i) << " " <<  edge4->j(i) << endl;
623       }
624       if (verbosity > 7) cout << " Number of reference edge in the  mesh = " << nbe << endl;
625     }
626     delete[] refe;
627     delete edge4;
628   }
Read_ftq(MeshIstream & f_in)629   void Triangles::Read_ftq(MeshIstream& f_in) {
630     //
631     if (verbosity > 1) cout << "  -- ReadMesh .ftq file " << f_in.CurrentFile << endl;
632 
633     Int4 i, ne, nt, nq;
634     f_in.cm( ) >> nbv >> ne >> nt >> nq;
635     if (verbosity > 3)
636       cout << "    nbv = " << nbv << " nbtra = " << nt << " nbquad = " << nq << endl;
637     nbt = nt + 2 * nq;
638 
639     nbvx = nbv;
640     nbtx = 2 * nbv - 2;    // for filling The Holes and quadrilaterals
641     triangles = new Triangle[nbtx];
642     assert(triangles);
643     vertices = new Vertex[nbvx];
644     ordre = new Vertex*[nbvx];
645     Int4 k = 0;
646 
647     for (i = 0; i < ne; i++) {
648       long ii, i1, i2, i3, i4, ref;
649       f_in >> ii;
650       if (ii == 3) {    // triangles
651         f_in >> i1 >> i2 >> i3 >> ref;
652         triangles[k] = Triangle(this, i1 - 1, i2 - 1, i3 - 1);
653         triangles[k++].color = ref;
654       } else if (ii == 4) {    // quad
655         f_in >> i1 >> i2 >> i3 >> i4 >> ref;
656         Triangle& t1 = triangles[k++];
657         Triangle& t2 = triangles[k++];
658         t1 = Triangle(this, i1 - 1, i2 - 1, i3 - 1);
659         t1.color = ref;
660         t2 = Triangle(this, i3 - 1, i4 - 1, i1 - 1);
661         t2.color = ref;
662         t1.SetHidden(OppositeEdge[1]);    // two time  because the adj was not created
663         t2.SetHidden(OppositeEdge[1]);
664       } else {
665         cout << " read ftq type element =" << ii << " not 3 or 4 " << endl;
666         MeshError(111);
667       }
668     }
669     assert(k == nbt);
670     Metric M1(1);
671     for (i = 0; i < nbv; i++) {
672       f_in >> vertices[i].r.x >> vertices[i].r.y >> vertices[i].ReferenceNumber;
673       vertices[i].DirOfSearch = NoDirOfSearch;
674       vertices[i].m = M1;
675     }
676   }
677 
678   ///////////////////////////////////////////////
679 
Read_msh(MeshIstream & f_in)680   void Triangles::Read_msh(MeshIstream& f_in) {
681     Metric M1(1.);
682     if (verbosity > 1) cout << "  -- ReadMesh .msh file " << f_in.CurrentFile << endl;
683 
684     Int4 i;
685     f_in.cm( ) >> nbv >> nbt;
686     while (f_in.in.peek( ) == ' ') f_in.in.get( );
687     if (isdigit(f_in.in.peek( ))) f_in >> nbe;
688     if (verbosity > 3) cout << "    nbv = " << nbv << " nbt = " << nbt << " nbe = " << nbe << endl;
689     nbvx = nbv;
690     nbtx = 2 * nbv - 2;    // for filling The Holes and quadrilaterals
691     triangles = new Triangle[nbtx];
692     assert(triangles);
693     vertices = new Vertex[nbvx];
694     ordre = new Vertex*[nbvx];
695     edges = new Edge[nbe];
696     for (i = 0; i < nbv; i++) {
697       f_in >> vertices[i].r.x >> vertices[i].r.y >> vertices[i].ReferenceNumber;
698       vertices[i].on = 0;
699       vertices[i].m = M1;
700       // if(vertices[i].ReferenceNumber>NbRef)	NbRef=vertices[i].ReferenceNumber;
701     }
702     for (i = 0; i < nbt; i++) {
703       Int4 i1, i2, i3, r;
704       f_in >> i1 >> i2 >> i3 >> r;
705       triangles[i] = Triangle(this, i1 - 1, i2 - 1, i3 - 1);
706       triangles[i].color = r;
707     }
708     for (i = 0; i < nbe; i++) {
709       Int4 i1, i2, r;
710       f_in >> i1 >> i2 >> r;
711       edges[i].v[0] = vertices + i1 - 1;
712       edges[i].v[1] = vertices + i2 - 1;
713       edges[i].adj[0] = 0;
714       edges[i].adj[1] = 0;
715       edges[i].ref = r;
716       edges[i].on = 0;
717     }
718   }
719 
720   //////////////////////////////////////////////////
721 
Read_amdba(MeshIstream & f_in)722   void Triangles::Read_amdba(MeshIstream& f_in) {
723     Metric M1(1);
724     if (verbosity > 1) cout << "  -- ReadMesh .amdba file " << f_in.CurrentFile << endl;
725 
726     Int4 i;
727     f_in.cm( ) >> nbv >> nbt;
728     //    if (verbosity>3)
729     cout << "    nbv = " << nbv << " nbt = " << nbt << endl;
730     f_in.eol( );    //
731     nbvx = nbv;
732     nbtx = 2 * nbv - 2;    // for filling The Holes and quadrilaterals
733     triangles = new Triangle[nbtx];
734     assert(triangles);
735     vertices = new Vertex[nbvx];
736     ordre = new Vertex*[nbvx];
737     Int4 j;
738     for (i = 0; i < nbv; i++) {
739       f_in >> j;
740       assert(j > 0 && j <= nbv);
741       j--;
742       f_in >> vertices[j].r.x >> vertices[j].r.y >> vertices[j].ReferenceNumber;
743       vertices[j].m = M1;
744       vertices[j].DirOfSearch = NoDirOfSearch;
745     }
746 
747     for (i = 0; i < nbt; i++) {
748       Int4 i1, i2, i3, ref;
749       f_in >> j;
750       assert(j > 0 && j <= nbt);
751       j--;
752       f_in >> i1 >> i2 >> i3 >> ref;
753       triangles[j] = Triangle(this, i1 - 1, i2 - 1, i3 - 1);
754       triangles[j].color = ref;
755     }
756     f_in.eol( );    //
757 
758     // cerr << " a faire " << endl;
759     // MeshError(888);
760   }
761 
Triangles(const char * filename,Real8 cutoffradian)762   Triangles::Triangles(const char* filename, Real8 cutoffradian)
763     : Gh(*(new Geometry( ))), BTh(*this) {
764 #ifdef DRAWING1
765     if (!withrgraphique) {
766       initgraphique( );
767       withrgraphique = true;
768     }
769 #endif
770 
771     //  Int4 beginquad=0,begintria=0;
772     // Int4 endquad=0;endtria=0;
773     // int type_file=0;
774 
775     int lll = strlen(filename);
776     int am_fmt = !strcmp(filename + lll - 7, ".am_fmt");
777     int amdba = !strcmp(filename + lll - 6, ".amdba");
778     int am = !strcmp(filename + lll - 3, ".am");
779     int nopo = !strcmp(filename + lll - 5, ".nopo");
780     int msh = !strcmp(filename + lll - 4, ".msh");
781     int ftq = !strcmp(filename + lll - 4, ".ftq");
782 
783     // cout << " Lecture type  :" << filename + lll - 7 <<":" <<am_fmt<<  endl;
784 
785     char* cname = new char[lll + 1];
786     strcpy(cname, filename);
787     Int4 inbvx = 0;
788     PreInit(inbvx, cname);
789     OnDisk = 1;
790     //  allocGeometry = &Gh; // after Preinit ;
791 
792     MeshIstream f_in(filename);
793 
794     if (f_in.IsString("MeshVersionFormatted")) {
795       int version;
796       f_in >> version;
797       Read(f_in, version, cutoffradian);
798     } else {
799       if (am_fmt)
800         Read_am_fmt(f_in);
801       else if (am)
802         Read_am(f_in);
803       else if (amdba)
804         Read_amdba(f_in);
805       else if (msh)
806         Read_msh(f_in);
807       else if (nopo)
808         Read_nopo(f_in);
809       else if (ftq)
810         Read_ftq(f_in);
811       else {
812         cerr << " Unkown type mesh " << filename << endl;
813         MeshError(2);
814       }
815       ConsGeometry(cutoffradian);
816       Gh.AfterRead( );
817     }
818 
819     SetIntCoor( );
820     FillHoleInMesh( );
821     // Make the quad ---
822   }
823 
ReadGeometry(const char * filename)824   void Geometry::ReadGeometry(const char* filename) {
825     OnDisk = 1;
826     if (verbosity > 1) cout << "  -- ReadGeometry " << filename << endl;
827     MeshIstream f_in(filename);
828     ReadGeometry(f_in, filename);
829   }
830 
ReadGeometry(MeshIstream & f_in,const char * filename)831   void Geometry::ReadGeometry(MeshIstream& f_in, const char* filename) {
832     if (verbosity > 1) cout << "  -- ReadGeometry " << filename << endl;
833     assert(empty( ));
834     nbiv = nbv = nbvx = 0;
835     nbe = nbt = nbtx = 0;
836     NbOfCurves = 0;
837     // BeginOfCurve=0;
838     name = new char[strlen(filename) + 1];
839     strcpy(name, filename);
840     Real8 Hmin = HUGE_VAL;    // the infinie value
841                               //  Real8 MaximalAngleOfCorner = 10*Pi/180; ;
842     Int4 hvertices = 0;
843     Int4 i;
844     Int4 Version, dim = 0;
845     int field = 0;
846     int showfield = 0;
847     int NbErr = 0;
848 
849     while (f_in.cm( )) {
850       field = 0;
851       // warning ruse for on allocate fiedname at each time
852       char fieldname[256];
853       f_in.cm( ) >> fieldname;
854       f_in.err( );
855       if (f_in.eof( )) break;
856       //      cout <<  fieldname <<  " line " << LineNumber  <<endl;
857       if (!strcmp(fieldname, "MeshVersionFormatted"))
858         f_in >> Version;
859       else if (!strcmp(fieldname, "End"))
860         break;
861       else if (!strcmp(fieldname, "end"))
862         break;
863       else if (!strcmp(fieldname, "Dimension")) {
864         f_in >> dim;
865         if (verbosity > 5) cout << "     Geom Record Dimension dim = " << dim << endl;
866         assert(dim == 2);
867       } else if (!strcmp(fieldname, "hVertices")) {
868         if (nbv <= 0) {
869           cerr << "Error: the field Vertex is not found before hVertices " << filename << endl;
870           NbErr++;
871         }
872         if (verbosity > 5) cout << "     Geom Record hVertices nbv=" << nbv << endl;
873         hvertices = 1;
874         for (i = 0; i < nbv; i++) {
875           Real4 h;
876           f_in >> h;
877           vertices[i].m = Metric(h);
878         }
879       } else if (!strcmp(fieldname, "MetricVertices")) {
880         hvertices = 1;
881         if (nbv <= 0) {
882           cerr << "Error: the field Vertex is not found before MetricVertices " << filename << endl;
883           NbErr++;
884         }
885         if (verbosity > 5) cout << "     Geom Record MetricVertices nbv =" << nbv << endl;
886         for (i = 0; i < nbv; i++) {
887           Real4 a11, a21, a22;
888           f_in >> a11 >> a21 >> a22;
889           vertices[i].m = Metric(a11, a21, a22);
890         }
891       } else if (!strcmp(fieldname, "h1h2VpVertices")) {
892         hvertices = 1;
893         if (nbv <= 0) {
894           cerr << "Error: the field Vertex is not found before h1h2VpVertices " << filename << endl;
895           NbErr++;
896         }
897         if (verbosity > 5) cout << "     Geom Record h1h2VpVertices nbv=" << nbv << endl;
898 
899         for (i = 0; i < nbv; i++) {
900           Real4 h1, h2, v1, v2;
901           f_in >> h1 >> h2 >> v1 >> v2;
902           vertices[i].m = Metric(MatVVP2x2(1 / (h1 * h1), 1 / (h2 * h2), D2(v1, v2)));
903         }
904       } else if (!strcmp(fieldname, "Vertices")) {
905         assert(dim == 2);
906         f_in >> nbv;
907         //          if(LineError) break;
908         nbvx = nbv;
909 
910         vertices = new GeometricalVertex[nbvx];
911         if (verbosity > 5)
912           cout << "     Geom Record Vertices nbv = " << nbv << "vertices = " << vertices << endl;
913         assert(nbvx >= nbv);
914         nbiv = nbv;
915         for (i = 0; i < nbv; i++) {
916           f_in >> vertices[i].r.x;
917           // if(LineError) break;
918           f_in >> vertices[i].r.y;
919           // if(LineError) break;
920           f_in >> vertices[i].ReferenceNumber;
921           vertices[i].DirOfSearch = NoDirOfSearch;
922           //            vertices[i].m.h = 0;
923           vertices[i].color = 0;
924           vertices[i].Set( );
925         }
926         // if(LineError) break;
927         pmin = vertices[0].r;
928         pmax = vertices[0].r;
929         // recherche des extrema des vertices pmin,pmax
930         for (i = 0; i < nbv; i++) {
931           pmin.x = Min(pmin.x, vertices[i].r.x);
932           pmin.y = Min(pmin.y, vertices[i].r.y);
933           pmax.x = Max(pmax.x, vertices[i].r.x);
934           pmax.y = Max(pmax.y, vertices[i].r.y);
935         }
936 
937         R2 DD05 = (pmax - pmin) * 0.05;
938         pmin -= DD05;
939         pmax += DD05;
940 
941         coefIcoor = (MaxICoor) / (Max(pmax.x - pmin.x, pmax.y - pmin.y));
942         assert(coefIcoor > 0);
943         if (verbosity > 5) {
944           cout << "     Geom: min=" << pmin << "max =" << pmax << " hmin = " << MinimalHmin( )
945                << endl;
946         }
947       } else if (!strcmp(fieldname, "MaximalAngleOfCorner") ||
948                  !strcmp(fieldname, "AngleOfCornerBound")) {
949         f_in >> MaximalAngleOfCorner;
950 
951         if (verbosity > 5)
952           cout << "     Geom Record MaximalAngleOfCorner " << MaximalAngleOfCorner << endl;
953         MaximalAngleOfCorner *= Pi / 180;
954       } else if (!strcmp(fieldname, "Edges")) {
955         if (nbv <= 0) {
956           cerr << "Error: the field edges is not found before MetricVertices " << filename << endl;
957           NbErr++;
958         } else {
959           int i1, i2;
960           R2 zero2(0, 0);
961           f_in >> nbe;
962 
963           edges = new GeometricalEdge[nbe];
964           if (verbosity > 5) cout << "     Record Edges: Nb of Edge " << nbe << endl;
965           assert(edges);
966           assert(nbv > 0);
967           Real4* len = 0;
968           if (!hvertices) {
969             len = new Real4[nbv];
970             for (i = 0; i < nbv; i++) len[i] = 0;
971           }
972 
973           for (i = 0; i < nbe; i++) {
974             f_in >> i1 >> i2 >> edges[i].ref;
975 
976             i1--;
977             i2--;    // for C index
978             edges[i].v[0] = vertices + i1;
979             edges[i].v[1] = vertices + i2;
980             R2 x12 = vertices[i2].r - vertices[i1].r;
981             Real8 l12 = sqrt((x12, x12));
982             edges[i].tg[0] = zero2;
983             edges[i].tg[1] = zero2;
984             edges[i].SensAdj[0] = edges[i].SensAdj[1] = -1;
985             edges[i].Adj[0] = edges[i].Adj[1] = 0;
986             edges[i].flag = 0;
987             if (!hvertices) {
988               vertices[i1].color++;
989               vertices[i2].color++;
990               len[i1] += l12;
991               len[i2] += l12;
992             }
993 
994             Hmin = Min(Hmin, l12);
995           }
996           // definition  the default of the given mesh size
997           if (!hvertices) {
998             for (i = 0; i < nbv; i++)
999               if (vertices[i].color > 0)
1000                 vertices[i].m = Metric(len[i] / (Real4)vertices[i].color);
1001               else
1002                 vertices[i].m = Metric(Hmin);
1003             delete[] len;
1004 
1005             if (verbosity > 3) cout << "     Geom Hmin " << Hmin << endl;
1006           }
1007         }
1008       } else if (!strcmp(fieldname, "EdgesTangence") || !strcmp(fieldname, "TangentAtEdges")) {
1009         int n, i, j, k;
1010         R2 tg;
1011         f_in >> n;
1012 
1013         if (verbosity > 5) cout << "     Record TangentAtEdges: Nb of Edge " << n << endl;
1014 
1015         for (k = 0; k < n; k++) {
1016           f_in >> i >> j;
1017           f_in >> tg.x >> tg.y;
1018           assert(i <= nbe);
1019           assert(i > 0);
1020           assert(j == 1 || j == 2);
1021           i--;
1022           j--;    // for C index
1023           edges[i].tg[j] = tg;
1024         }
1025       } else if (!strcmp(fieldname, "Corners")) {
1026         int i, j, n;
1027         f_in >> n;
1028         if (verbosity > 5) cout << "     Record Corner: Nb of Corner " << n << endl;
1029 
1030         for (i = 0; i < n; i++) {
1031           f_in >> j;
1032           assert(j <= nbv);
1033           assert(j > 0);
1034           j--;
1035           vertices[j].SetCorner( );
1036           vertices[j].SetRequired( );
1037         }
1038       } else if (!strcmp(fieldname, "RequiredVertices")) {
1039         int i, j, n;
1040         f_in >> n;
1041 
1042         for (i = 0; i < n; i++) {
1043           f_in >> j;
1044           assert(j <= nbv);
1045           assert(j > 0);
1046           j--;
1047           vertices[j].SetRequired( );
1048         }
1049       } else if (!strcmp(fieldname, "RequiredEdges")) {
1050         int i, j, n;
1051         f_in >> n;
1052 
1053         for (i = 0; i < n; i++) {
1054           f_in >> j;
1055           assert(j <= nbe);
1056           assert(j > 0);
1057           j--;
1058           edges[j].SetRequired( );
1059         }
1060       } else if (!strcmp(fieldname, "SubDomain") || !strcmp(fieldname, "SubDomainFromGeom")) {
1061         f_in >> NbSubDomains;
1062         if (NbSubDomains > 0) {
1063           subdomains = new GeometricalSubDomain[NbSubDomains];
1064           Int4 i0, i1, i2, i3;
1065           for (i = 0; i < NbSubDomains; i++) {
1066             f_in >> i0 >> i1 >> i2 >> i3;
1067 
1068             assert(i0 == 2);
1069             assert(i1 <= nbe && i1 > 0);
1070             subdomains[i].edge = edges + (i1 - 1);
1071             subdomains[i].sens = (int)i2;
1072             subdomains[i].ref = i3;
1073           }
1074         }
1075       } else {    // unkown field
1076         field = ++showfield;
1077         if (showfield == 1)    // just to show one time
1078           if (verbosity > 3)
1079             cout << "    Warning we skip the field " << fieldname << " at line " << f_in.LineNumber
1080                  << endl;
1081       }
1082       showfield = field;    // just to show one time
1083     }                       // while !eof()
1084     // generation  de la geometrie
1085     // 1 construction des aretes
1086     // construire des aretes en chaque sommets
1087 
1088     if (nbv <= 0) {
1089       cerr << "Error: the field Vertex is not found in " << filename << endl;
1090       NbErr++;
1091     }
1092     if (nbe <= 0) {
1093       cerr << "Error: the field Edges is not found in " << filename << endl;
1094       NbErr++;
1095     }
1096     if (NbErr) MeshError(1);
1097   }
1098 
1099 }    // end of namespace bamg
1100