PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/branches/KFEM/kfem/freefemplus/NDBI2/BamgFreeFem.cpp

#
C++ | 585 lines | 320 code | 27 blank | 238 comment | 86 complexity | 12ee4e347b3a040b73f347024b10f462 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. // ********** DO NOT REMOVE THIS BANNER **********
  2. //
  3. // SUMMARY: Bamg: Bidimensional Anisotrope Mesh Generator
  4. // RELEASE: 0
  5. // USAGE : You may copy freely these files and use it for
  6. // teaching or research. These or part of these may
  7. // not be sold or used for a commercial purpose with-
  8. // out our consent : fax (33) 1 39 63 55 14
  9. //
  10. // AUTHOR: F. Hecht,
  11. // ORG : INRIA
  12. // E-MAIL : Frederic.Hecht@Inria.fr
  13. //
  14. // ORIG-DATE: Dec 97
  15. // #define TRACETRIANGLE 3
  16. #undef NDEBUG
  17. extern int verbosity ;
  18. //#define strcasecmp strcmp
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <math.h>
  22. #include <time.h>
  23. #include "Meshio.h"
  24. #include "Mesh2.h"
  25. #include "QuadTree.h"
  26. #include "SetOfE4.h"
  27. #include "vect.h"
  28. #include "BamgFreeFem.h"
  29. /*
  30. void Grid::MakeTriangles()
  31. {
  32. cerr << "&#x203A; faire / to do" << endl;
  33. exit(3);
  34. }
  35. */
  36. /*
  37. Int4 i,j,k;
  38. Int4 nbv = nv;
  39. Int4 nbt = nt;
  40. Int4 nbe = 0;
  41. assert(!Th);
  42. assert(!Gh);
  43. // generation of the Geometry
  44. // Construction of the edges
  45. Gh = new Geometry();
  46. Th = new Triangles(nbv,&Gh);
  47. Triangles &T(*Th);
  48. Geometry &G(*Gh);
  49. assert(nbt<=T.nbtx);
  50. assert(nbv<=T.nbvx);
  51. T.nbt=nbt;
  52. T.nbv=nbv;
  53. for (i=0;i<nv;i++)
  54. {
  55. T.vertices[i].r.x = v[i].x;
  56. T.vertices[i].r.y = v[i].y;
  57. T.vertices[i].ref = v[i].where;
  58. }
  59. for (i=0;i<nt;i++)
  60. for (j=0;j<3;j++)
  61. {
  62. T[i]=trianglesTriangle(this, no(t[i][0]),no(t[i][1]),no(t[i][2]));
  63. T[i].color = t[i].where;
  64. }
  65. // generation of the adjacence of the triangles
  66. Triangle * triangles = T.triangles;
  67. Vertex * vertices = T.vertices;
  68. SetOfEdges4 * edge4= new SetOfEdges4(nbt*3,nbv);
  69. Int4 * st = new Int4[nbt*3];
  70. for (i=0;i<nbt*3;i++)
  71. st[i]=-1;
  72. Int4 kk =0;
  73. nbe =0;
  74. Int4 nbei =0;
  75. for (i=0;i<nv;i++)
  76. vetices[i].color=0;
  77. for (i=0;i<nbt;i++)
  78. for (int j=0;j<3;j++)
  79. {
  80. // Int4 i0,i1;
  81. Int4 i0 =T.Number(triangles[i][VerticesOfTriangularEdge[j][0]]);
  82. Int4 i1 = T.Number(triangles[i][VerticesOfTriangularEdge[j][1]]);
  83. Int4 k =edge4->addtrie(i0,i1);,
  84. Int4 invisible = triangles[i].Hidden(j);
  85. if(st[k]==-1)
  86. st[k]=3*i+j;
  87. else if(st[k]>=0)
  88. {
  89. nbei++;
  90. Int4 ii = st[k] / 3;
  91. int jj = (int) (st[k]%3);
  92. assert( ! triangles[i].TriangleAdj(j) &&
  93. !triangles[st[k] / 3].TriangleAdj((int) (st[k]%3)));
  94. triangles[i].SetAdj2(j,triangles + ii,jj);
  95. if (triangles[i].color != triangles[ii].color)
  96. {
  97. triangles[i].SetLocked(j);
  98. vertices[i0].color=1;
  99. vertices[i1].color=1;
  100. nbe++;
  101. }
  102. if (invisible) triangles[i].SetHidden(j);
  103. st[k]=-2-st[k];
  104. }
  105. else
  106. {
  107. cerr << " The edge ("
  108. << T.Number(triangles[i][VerticesOfTriangularEdge[j][0]])
  109. << " , "
  110. << T.Number(triangles[i][VerticesOfTriangularEdge[j][1]])
  111. << " ) is in more than 2 triangles " <<k <<endl;
  112. cerr << " Edge " << j << " Of Triangle " << i << endl;
  113. cerr << " Edge " << (-st[k]+2)%3 << " Of Triangle " << (-st[k]+2)/3 << endl;
  114. cerr << " Edge " << triangles[(-st[k]+2)/3].NuEdgeTriangleAdj((int)((-st[k]+2)%3))
  115. << " Of Triangle "
  116. << T.Number(triangles[(-st[k]+2)/3].TriangleAdj((int)((-st[k]+2)%3))) << endl;
  117. MeshError(9999);}
  118. }
  119. // NbOfEdge
  120. nbe += edge4->NbOfEdges-nbei;
  121. // ---
  122. kk =0;
  123. for (i=0;i<nbt;i++)
  124. for (int j=0;j<3;j++)
  125. {
  126. Int4 i0 =T.Number(triangles[i][VerticesOfTriangularEdge[j][0]]);
  127. Int4 i1 = T.Number(triangles[i][VerticesOfTriangularEdge[j][1]]);
  128. Int4 k =edge4->addtrie(i0,i1);
  129. Int4 ii = st[k] / 3;
  130. if(st[k]>=0 || (i<ii && triangles[i].Locked(j)) )
  131. {
  132. kk++;
  133. vertices[i0].color=1;
  134. vertices[i1].color=1;
  135. }
  136. }
  137. assert(kk== nbe);
  138. // compuation of the geom vertices
  139. Gh.nbv =0;
  140. for (i=0;i<nbv;i++)
  141. if(vertices[i0].color)
  142. vertices[i0].color= Gh.nbv++;
  143. else
  144. vertices[i0].color=-1;
  145. Gh.vertices = new GeometricalVertex[Gh.nbv];
  146. Gh->nbe = nbe;
  147. Gh->edges = new GeometricalEdges[nbe];
  148. kk =0;
  149. Real4 *len = new Real4[ Gh->nbv];
  150. for (i=0;i<nbv;i++)
  151. if(vertices[i0].color)
  152. {
  153. Gh.vertices[kk].r = vertices[i0];
  154. Gh.vertices[kk].color=0;
  155. len[kk]=0;
  156. kk++;
  157. }
  158. assert(kk==Gh.nbv);
  159. kk =0;
  160. Real8 Hmin = HUGE_VAL;// the infinie value
  161. R2 zero2(0,0);
  162. for (i=0;i<nbt;i++)
  163. for (int j=0;j<3;j++)
  164. {
  165. Int4 i0 =T.Number(triangles[i][VerticesOfTriangularEdge[j][0]]);
  166. Int4 i1 = T.Number(triangles[i][VerticesOfTriangularEdge[j][1]]);
  167. Int4 k =edge4->addtrie(i0,i1);
  168. Int4 ii = st[k] / 3;
  169. if(st[k]>=0 || (i<ii && triangles[i].Locked(j)) )
  170. {
  171. i0 = vertices[i0].color;
  172. i1 = vertices[i1].color;
  173. G.edges[kk].v[0]= G.vertices + i0;
  174. G.edges[kk].v[1]= G.vertices + i1;
  175. G.edges[kk].tg[0]=zero2;
  176. G.edges[kk].tg[1]=zero2;
  177. G.edges[kk].SensAdj[0] = G.edges[i].SensAdj[1] = -1;
  178. G.edges[kk].Adj[0] = G.edges[i].Adj[1] = 0;
  179. G.edges[kk].flag = 0;
  180. G.vertices[i0].color++;
  181. G.vertices[i2].color++;
  182. R2 x12 = G.vertices[i0].r-G.vertices[i1].r;
  183. Real8 l12=sqrt(x12*x12);
  184. len[i1] += l12;
  185. len[i2] += l12;
  186. Hmin = Min(Hmin,l12);
  187. kk++;
  188. }
  189. }
  190. assert(kk== nbe);
  191. for (i=0;i<G.nbv;i++)
  192. if (G.vertices[i].color > 0)
  193. G.vertices[i].m= Metric(len[i] /(Real4) vertices[i].color);
  194. else
  195. G.vertices[i].m= Metric(Hmin);
  196. delete [] len;
  197. // find sub domaine --
  198. for (i=0;i<nbt;i++)
  199. triangles[i].color=-1;
  200. Int4 nbsd =0;
  201. for (i=0;i<nbt;i++)
  202. if ( triangles[i].color==-1)
  203. {
  204. triangles[i].color=nbsd++;
  205. Int4 k=0;
  206. st[k++]=i;
  207. st[k]=0;
  208. while(1)
  209. if((j=st[k]++)<3 && !triangles[st[k-1]].Locked(j))
  210. {
  211. Triangle * tt = triangles[st[k-1]].TriangleAdj(j);
  212. }
  213. else
  214. {
  215. k -= 2;
  216. if (k<0) break;
  217. Triangle *t = triangles + st[k-1];
  218. }
  219. }
  220. delete edge4;
  221. delete st;
  222. } */
  223. void Grid::th2t(Triangles* tTh)
  224. {
  225. tTh->ReNumberingTheTriangleBySubDomain();
  226. //tTh->NbRef++;
  227. Int4 i,j,k=0;
  228. nv = tTh->nbv;
  229. nt = tTh->nbt - tTh->NbOutT;
  230. v.init(nv);
  231. t.init(nt);
  232. // construction of the edges --
  233. SetOfEdges4 * edge4= new SetOfEdges4(nt*3,nv);
  234. // 1 compuation of the nb of edges
  235. for (i=0;i<tTh->nbe;i++)
  236. edge4->addtrie(tTh->Number(tTh->edges[i][0]),tTh->Number(tTh->edges[i][1]));
  237. for (i=0;i<nt;i++)
  238. for (j=0;j<3;j++)
  239. {
  240. Int4 i0 =tTh->Number(tTh->triangles[i][VerticesOfTriangularEdge[j][0]]);
  241. Int4 i1 = tTh->Number(tTh->triangles[i][VerticesOfTriangularEdge[j][1]]);
  242. Int4 k =edge4->addtrie(i0,i1);
  243. }
  244. ne = edge4->nb();
  245. delete edge4;
  246. if(verbosity>1)
  247. cout <<"\t\t" << " ne = " << ne << " nv + nt - ne = " << nv + nt - ne
  248. << " == Nb of hole " << endl;
  249. e.init(ne);
  250. for (i=0;i<ne;i++)
  251. {
  252. e[i].left=e[i].right=0;
  253. e[i].where=0;
  254. }
  255. // now
  256. edge4= new SetOfEdges4(ne,nv);
  257. for (i=0;i<tTh->nbe;i++)
  258. {
  259. Int4 k =edge4->addtrie(tTh->Number(tTh->edges[i][0]),tTh->Number(tTh->edges[i][1]));
  260. e[k].where=tTh->edges[i].ref;
  261. }
  262. for (i=0;i<nt;i++)
  263. for (j=0;j<3;j++)
  264. {
  265. Int4 i0 = tTh->Number(tTh->triangles[i][VerticesOfTriangularEdge[j][0]]);
  266. Int4 i1 = tTh->Number(tTh->triangles[i][VerticesOfTriangularEdge[j][1]]);
  267. Int4 k = edge4->addtrie(i0,i1);
  268. Int4 ii = edge4->i(k);
  269. Int4 jj = edge4->j(k);
  270. e[k].in = v.cc + ii;
  271. e[k].out = v.cc + jj;
  272. t[i].e[j]=e.cc+k;
  273. if ( i0 == ii)
  274. assert( !e[k].left), e[k].left = t.cc+i;
  275. else
  276. assert( !e[k].right), e[k].right= t.cc+i;
  277. }
  278. assert( ne == edge4->nb());
  279. delete edge4;
  280. for( i=0;i<tTh->nbv;i++)
  281. {
  282. v[i].x = tTh->vertices[i].r.x;
  283. v[i].y = tTh->vertices[i].r.y;
  284. v[i].where = tTh->vertices[i].ref;
  285. }
  286. Int4 *reft = new Int4[tTh->nbt];
  287. Int4 nbref = tTh->ConsRefTriangle(reft);
  288. for( i=0,k=0;i<tTh->nbt;i++)
  289. if(tTh->triangles[i].link)
  290. {
  291. t[k].where = reft[i]; // a faire
  292. for(int j=0;j<3;j++)
  293. t[k].v[j]= &v[tTh->Number(tTh->triangles[i][j])];
  294. //renu[i]=k;
  295. assert(k == i);
  296. k++;
  297. }
  298. //else renu[i]=-1;
  299. delete [] reft;
  300. assert ( nt == k);
  301. tTh->ReMakeTriangleContainingTheVertex();
  302. // some verification
  303. for (k=0;k<ne;k++)
  304. {
  305. assert( e[k].left || e[k].right);
  306. if (e[k].left)
  307. {
  308. bTriangle & tt= *e[k].left;
  309. // cout <<k << no(e[k].in) << " " << no(e[k].out) << " "
  310. // << no(tt.v[0]) << " "
  311. // << no(tt.v[1]) << " " << no(tt.v[2]) << " " << endl;
  312. assert((tt.e[0] == &e[k]) ||(tt.e[1] == &e[k]) ||(tt.e[2] == &e[k]) );
  313. assert((tt.v[0] == e[k].in) ||(tt.v[1] == e[k].in) ||(tt.v[2] == e[k].in));
  314. assert((tt.v[0] == e[k].out) ||(tt.v[1] == e[k].out) ||(tt.v[2] == e[k].out));
  315. }
  316. if (e[k].right)
  317. {
  318. bTriangle & tt= *e[k].right;
  319. assert((tt.e[0] == &e[k]) ||(tt.e[1] == &e[k]) ||(tt.e[2] == &e[k]) );
  320. assert((tt.v[0] == e[k].in) ||(tt.v[1] == e[k].in) ||(tt.v[2] == e[k].in));
  321. assert((tt.v[0] == e[k].out) ||(tt.v[1] == e[k].out) ||(tt.v[2] == e[k].out));
  322. }
  323. }
  324. Th = tTh;
  325. Gh = &tTh->Gh;
  326. cout << " th2t " << Th->NbRef<< " " << Gh->NbRef << endl;
  327. }
  328. Geometry * frontiere2Geometry(const frontiere & fr)
  329. {
  330. Geometry * Gh = new Geometry;
  331. if(verbosity>2)
  332. cout <<"\t\t" << " Begin: ConstGeometry from frontiere" << endl;
  333. //assert(empty());
  334. const char * filename = "FREEFEM.gh";
  335. Gh->name=new char [strlen(filename)+1];
  336. strcpy(Gh->name,filename);
  337. Real8 Hmin = HUGE_VAL;// the infinie value
  338. Int4 hvertices =0;
  339. Int4 i;
  340. Int4 Version,dim=0;
  341. Gh->MaximalAngleOfCorner =30.00*Pi/180.0;
  342. Gh->nbv = fr.nbp;
  343. Gh->nbvx = Gh->nbv;
  344. Gh->vertices = new GeometricalVertex[Gh->nbvx];
  345. assert(Gh->nbvx >= Gh->nbv);
  346. Gh->nbiv = Gh->nbv;
  347. Int4 k=0;
  348. for (i=0;i<Gh->nbv;i++)
  349. {
  350. Gh->vertices[i].r.x = fr.xy[k++];
  351. Gh->vertices[i].r.y = fr.xy[k++];
  352. Gh->vertices[i].ref = fr.ng[i];
  353. Gh->vertices[i].color =0;
  354. Gh->vertices[i].Set();
  355. // vertices[i].SetCorner();
  356. // vertices[i].SetRequired();
  357. }
  358. Gh->pmin = Gh->vertices[0].r;
  359. Gh->pmax = Gh->vertices[0].r;
  360. // recherche des extrema des vertices pmin,pmax
  361. for (i=0;i<Gh->nbv;i++)
  362. {
  363. Gh->pmin.x = Min(Gh->pmin.x,Gh->vertices[i].r.x);
  364. Gh->pmin.y = Min(Gh->pmin.y,Gh->vertices[i].r.y);
  365. Gh->pmax.x = Max(Gh->pmax.x,Gh->vertices[i].r.x);
  366. Gh->pmax.y = Max(Gh->pmax.y,Gh->vertices[i].r.y);
  367. }
  368. Gh->coefIcoor= (MaxICoor)/(Max(Gh->pmax.x-Gh->pmin.x,Gh->pmax.y-Gh->pmin.y));
  369. assert(Gh->coefIcoor >0);
  370. if (verbosity>2)
  371. {
  372. cout <<"\t\t" << " Geom: min="<< Gh->pmin << "max ="<< Gh->pmax
  373. << " hmin = " << Gh->MinimalHmin() << endl;
  374. }
  375. R2 zero2(0,0);
  376. Gh->nbe = fr.nbs;
  377. Gh->edges = new GeometricalEdge[Gh->nbe];
  378. if(verbosity>5)
  379. cout <<"\t\t" << " Record Edges: Nb of Edge " << Gh->nbe <<endl;
  380. assert(Gh->edges);
  381. assert (Gh->nbv >0);
  382. Real4 *len =0;
  383. if (!hvertices)
  384. {
  385. len = new Real4[Gh->nbv];
  386. for(i=0;i<Gh->nbv;i++)
  387. len[i]=0;
  388. }
  389. k=0;
  390. for (i=0;i<Gh->nbe;i++)
  391. {
  392. Int4 i1 = fr.s[k++], i2 = fr.s[k++];
  393. Gh->edges[i].ref = fr.ngf[i];
  394. Gh->edges[i].v[0]= Gh->vertices + i1;
  395. Gh->edges[i].v[1]= Gh->vertices + i2;
  396. R2 x12 = Gh->vertices[i2].r-Gh->vertices[i1].r;
  397. Real8 l12=sqrt(x12*x12);
  398. Gh->edges[i].tg[0]=zero2;
  399. Gh->edges[i].tg[1]=zero2;
  400. Gh->edges[i].SensAdj[0] = Gh->edges[i].SensAdj[1] = -1;
  401. Gh->edges[i].Adj[0] = Gh->edges[i].Adj[1] = 0;
  402. Gh->edges[i].flag = 0;
  403. if (!hvertices)
  404. {
  405. Gh->vertices[i1].color++;
  406. Gh->vertices[i2].color++;
  407. len[i1] += l12;
  408. len[i2] += l12;
  409. }
  410. Hmin = Min(Hmin,l12);
  411. }
  412. // definition the default of the given mesh size
  413. if (!hvertices)
  414. {
  415. for (i=0;i<Gh->nbv;i++)
  416. if (Gh->vertices[i].color > 0)
  417. Gh->vertices[i].m= Metric(len[i] /(Real4) Gh->vertices[i].color);
  418. else
  419. Gh->vertices[i].m= Metric(Hmin);
  420. delete [] len;
  421. if(verbosity>3)
  422. cout <<"\t\t" << " Geom Hmin " << Hmin << endl;
  423. }
  424. Gh->NbSubDomains=fr.nbsd;
  425. if (Gh->NbSubDomains>0)
  426. {
  427. Gh->subdomains = new GeometricalSubDomain[ Gh->NbSubDomains];
  428. Int4 i0,i1,i2,i3;
  429. for (i=0;i<Gh->NbSubDomains;i++)
  430. {
  431. i1 = fr.sd[2*i];
  432. Gh->subdomains[i].sens = 1;
  433. if(i1<0){i1=-i1; Gh->subdomains[i].sens = -1;}
  434. assert(i1<Gh->nbe && i1>=0);
  435. Gh->subdomains[i].edge=Gh->edges + (i1);
  436. Gh->subdomains[i].ref = i+1;
  437. }
  438. }
  439. Gh->AfterRead();
  440. return Gh;
  441. }
  442. Int4 FindTriangle(Triangles &Th, Real8 x, Real8 y, double* a)
  443. {
  444. CurrentTh=&Th;
  445. assert(&Th);
  446. I2 I = Th.toI2(R2(Min(Max(Th.pmin.x,x),Th.pmax.x),Min(Max(Th.pmin.y,y),Th.pmax.y)));
  447. Icoor2 dete[3];
  448. Triangle & tb = *Th.FindTriangleContening(I,dete);
  449. if (tb.link)
  450. { // internal point in a true triangles
  451. a[0]= (Real8) dete[0]/ tb.det;
  452. a[1]= (Real8) dete[1] / tb.det;
  453. a[2] = (Real8) dete[2] / tb.det;
  454. return Th.Number(tb);
  455. }
  456. else return -1;
  457. }
  458. Triangles::Triangles(const Triangles & Tho,const int *flag ,const int *bb)
  459. : Gh(*(new Geometry())), BTh(*this)
  460. { // truncature
  461. //
  462. char cname[] = "trunc";
  463. int i,j,k,itadj;
  464. int kt=0;
  465. int * kk = new int [Tho.nbv];
  466. Int4 * reft = new Int4[Tho.nbt];
  467. Int4 nbInT = Tho.ConsRefTriangle(reft);
  468. Int4 * refv = new Int4[Tho.nbv];
  469. for (i=0;i<Tho.nbv;i++)
  470. kk[i]=-1;
  471. for (i=0;i<Tho.nbv;i++)
  472. refv[i]=0;
  473. int nbNewBedge =0;
  474. int nbOldBedge =0;
  475. for (i=0;i<Tho.nbt;i++)
  476. if( reft[i] >=0 && flag[i])
  477. {
  478. const Triangle & t = Tho.triangles[i];
  479. kt++;
  480. kk[Tho.Number(t[0])]=1;
  481. kk[Tho.Number(t[1])]=1;
  482. kk[Tho.Number(t[2])]=1;
  483. itadj=Tho.Number(t.TriangleAdj(0));
  484. if ( reft[itadj] >=0 && !flag[itadj])
  485. { nbNewBedge++;
  486. refv[Tho.Number(t[VerticesOfTriangularEdge[0][0]])]=bb[i];
  487. refv[Tho.Number(t[VerticesOfTriangularEdge[0][1]])]=bb[i];
  488. }
  489. itadj=Tho.Number(t.TriangleAdj(1));
  490. if ( reft[itadj] >=0 && !flag[itadj])
  491. { nbNewBedge++;
  492. refv[Tho.Number(t[VerticesOfTriangularEdge[1][0]])]=bb[i];
  493. refv[Tho.Number(t[VerticesOfTriangularEdge[1][1]])]=bb[i];}
  494. itadj=Tho.Number(t.TriangleAdj(2));
  495. if ( reft[itadj] >=0 && !flag[itadj])
  496. { nbNewBedge++;
  497. refv[Tho.Number(t[VerticesOfTriangularEdge[2][0]])]=bb[i];
  498. refv[Tho.Number(t[VerticesOfTriangularEdge[2][1]])]=bb[i];}
  499. }
  500. k=0;
  501. for (i=0;i<Tho.nbv;i++)
  502. if (kk[i]>=0)
  503. kk[i]=k++;
  504. cout << " number of vertices " << k << " remove = " << Tho.nbv - k << endl;
  505. cout << " number of triangles " << kt << " remove = " << nbInT-kt << endl;
  506. cout << " number of New boundary edge " << nbNewBedge << endl;
  507. Int4 inbvx =k;
  508. PreInit(inbvx,cname);
  509. for (i=0;i<Tho.nbv;i++)
  510. if (kk[i]>=0)
  511. {
  512. vertices[nbv] = Tho.vertices[i];
  513. if (!vertices[nbv].ref)
  514. vertices[nbv].ref = refv[i];
  515. nbv++;
  516. }
  517. assert(inbvx == nbv);
  518. for (i=0;i<Tho.nbt;i++)
  519. if( reft[i] >=0 && flag[i])
  520. {
  521. const Triangle & t = Tho.triangles[i];
  522. int i0 = Tho.Number(t[0]);
  523. int i1 = Tho.Number(t[1]);
  524. int i2 = Tho.Number(t[2]);
  525. assert(i0>=0 && i1 >= 0 && i2 >= 0);
  526. assert(i0<Tho.nbv && i1 <Tho.nbv && i2 <Tho.nbv);
  527. // cout <<i<< " F" << flag[i] << " T " << nbt << " = " << kk[i0] << " " << kk[i1] << " " << kk[i2] ;
  528. // cout << " OT " << i0 << " " << i1 << " " << i2 << " " << reft[i] << endl;
  529. triangles[nbt] = Triangle(this,kk[i0],kk[i1],kk[i2]);
  530. triangles[nbt].color = Tho.subdomains[reft[i]].ref;
  531. nbt++;
  532. }
  533. assert(kt==nbt);
  534. if (nbt ==0 && nbv ==0) {
  535. cout << "Error all triangles was remove " << endl;
  536. MeshError(999);
  537. }
  538. delete [] kk;
  539. delete [] reft;
  540. delete [] refv;
  541. double cutoffradian = 10.0/180.0*Pi;
  542. ConsGeometry(cutoffradian);
  543. Gh.AfterRead();
  544. SetIntCoor();
  545. FillHoleInMesh();
  546. assert(NbSubDomains);
  547. assert(subdomains[0].head && subdomains[0].head->link);
  548. }