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