source: issm/branches/trunk-larour-NatGeoScience2016/src/c/bamg/Mesh.cpp@ 21759

Last change on this file since 21759 was 21759, checked in by Eric.Larour, 8 years ago

CHG: merged branch back to trunk-jpl 21754.

File size: 149.1 KB
Line 
1#include <cstdio>
2#include <cstring>
3#include <cmath>
4#include <ctime>
5
6#include "../shared/shared.h"
7#include "./bamgobjects.h"
8#include "./det.h"
9
10namespace bamg {
11
12 /*Constructors/Destructors*/
13 Mesh::Mesh(BamgGeom* bamggeom,BamgMesh* bamgmesh, BamgOpts* bamgopts):Gh(*(new Geometry())),BTh(*this){ /*{{{*/
14
15 /*Initialize fields*/
16 Init(0);
17
18 /*Read Geometry if provided*/
19 if(bamggeom->Edges) {
20 Gh.ReadGeometry(bamggeom,bamgopts);
21 Gh.PostRead();
22 }
23
24 /*Read background mesh*/
25 ReadMesh(bamgmesh,bamgopts);
26
27 /*Build Geometry if not provided*/
28 if(bamggeom->Edges==NULL) {
29 /*Recreate geometry if needed*/
30 _printf_("WARNING: mesh present but no geometry found. Reconstructing...\n");
31 BuildGeometryFromMesh(bamgopts);
32 Gh.PostRead();
33 }
34
35 /*Set integer coordinates*/
36 SetIntCoor();
37
38 /*Fill holes and generate mesh properties*/
39 ReconstructExistingMesh();
40 }
41 /*}}}*/
42 Mesh::Mesh(int* index,double* x,double* y,int nods,int nels):Gh(*(new Geometry())),BTh(*this){/*{{{*/
43
44 Init(0);
45 ReadMesh(index,x,y,nods,nels);
46 SetIntCoor();
47 ReconstructExistingMesh();
48 }
49 /*}}}*/
50 Mesh::Mesh(double* x,double* y,int nods):Gh(*(new Geometry())),BTh(*this){/*{{{*/
51 Triangulate(x,y,nods);
52 }
53 /*}}}*/
54 Mesh::Mesh(const Mesh & Tho,const int *flag ,const int *bb,BamgOpts* bamgopts) : Gh(*(new Geometry())), BTh(*this) {/*{{{*/
55 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Triangles)*/
56
57 int i,k,itadj;
58 int kt=0;
59 int * kk = new int [Tho.nbv];
60 long * reft = new long[Tho.nbt];
61 long nbInT = Tho.TriangleReferenceList(reft);
62 long * refv = new long[Tho.nbv];
63
64 for (i=0;i<Tho.nbv;i++)
65 kk[i]=-1;
66 for (i=0;i<Tho.nbv;i++)
67 refv[i]=0;
68 int nbNewBedge =0;
69 // int nbOldBedge =0;
70 for (i=0;i<Tho.nbt;i++)
71 if( reft[i] >=0 && flag[i])
72 {
73 const Triangle & t = Tho.triangles[i];
74 kt++;
75 kk[Tho.GetId(t[0])]=1;
76 kk[Tho.GetId(t[1])]=1;
77 kk[Tho.GetId(t[2])]=1;
78 itadj=Tho.GetId(t.TriangleAdj(0));
79 if ( reft[itadj] >=0 && !flag[itadj])
80 { nbNewBedge++;
81 refv[Tho.GetId(t[VerticesOfTriangularEdge[0][0]])]=bb[i];
82 refv[Tho.GetId(t[VerticesOfTriangularEdge[0][1]])]=bb[i];
83 }
84 itadj=Tho.GetId(t.TriangleAdj(1));
85 if ( reft[itadj] >=0 && !flag[itadj])
86 { nbNewBedge++;
87 refv[Tho.GetId(t[VerticesOfTriangularEdge[1][0]])]=bb[i];
88 refv[Tho.GetId(t[VerticesOfTriangularEdge[1][1]])]=bb[i];}
89 itadj=Tho.GetId(t.TriangleAdj(2));
90 if ( reft[itadj] >=0 && !flag[itadj])
91 { nbNewBedge++;
92 refv[Tho.GetId(t[VerticesOfTriangularEdge[2][0]])]=bb[i];
93 refv[Tho.GetId(t[VerticesOfTriangularEdge[2][1]])]=bb[i];}
94 }
95 k=0;
96 for (i=0;i<Tho.nbv;i++){
97 if (kk[i]>=0) kk[i]=k++;
98 }
99 _printf_(" number of vertices " << k << ", remove = " << Tho.nbv - k << "\n");
100 _printf_(" number of triangles " << kt << ", remove = " << nbInT-kt << "\n");
101 _printf_(" number of New boundary edge " << nbNewBedge << "\n");
102 long imaxnbv =k;
103 Init(imaxnbv);
104 for (i=0;i<Tho.nbv;i++)
105 if (kk[i]>=0)
106 {
107 vertices[nbv] = Tho.vertices[i];
108 if (!vertices[nbv].GetReferenceNumber())
109 vertices[nbv].ReferenceNumber = refv[i];
110 nbv++;
111 }
112 if (imaxnbv != nbv){
113 delete [] kk;
114 delete [] refv;
115 _error_("imaxnbv != nbv");
116 }
117 for (i=0;i<Tho.nbt;i++)
118 if(reft[i] >=0 && flag[i]){
119 const Triangle & t = Tho.triangles[i];
120 int i0 = Tho.GetId(t[0]);
121 int i1 = Tho.GetId(t[1]);
122 int i2 = Tho.GetId(t[2]);
123 if(i0<0 || i1<0 || i2<0){
124 delete [] refv;
125 _error_("i0<0 || i1<0 || i2< 0");
126 }
127 if(i0>=Tho.nbv || i1>=Tho.nbv || i2>=Tho.nbv){
128 delete [] refv;
129 _error_("i0>=Tho.nbv || i1>=Tho.nbv || i2>=Tho.nbv");
130 }
131 triangles[nbt] = Triangle(this,kk[i0],kk[i1],kk[i2]);
132 triangles[nbt].color = Tho.subdomains[reft[i]].ReferenceNumber;
133 nbt++;
134 }
135 if (nbt==0 && nbv==0) {
136 _error_("All triangles have been removed");
137 }
138 delete [] kk;
139 delete [] reft;
140 delete [] refv;
141 BuildGeometryFromMesh(bamgopts);
142 Gh.PostRead();
143 SetIntCoor();
144 ReconstructExistingMesh();
145
146 /*Final checks*/
147 _assert_(kt==nbt);
148 _assert_(nbsubdomains);
149 _assert_(subdomains[0].head && subdomains[0].head->link);
150 }
151 /*}}}*/
152 Mesh::Mesh(Mesh & Th,Geometry * pGh,Mesh * pBth,long maxnbv_in)/*{{{*/
153 : Gh(*(pGh?pGh:&Th.Gh)), BTh(*(pBth?pBth:this)) {
154 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Triangles)*/
155 Gh.NbRef++;
156 maxnbv_in = Max(maxnbv_in,Th.nbv);
157 long i;
158 // do all the allocation to be sure all the pointer existe
159
160 Init(maxnbv_in);// to make the allocation
161 // copy of triangles
162 nbv = Th.nbv;
163 nbt = Th.nbt;
164 nbe = Th.nbe;
165 nbsubdomains = Th.nbsubdomains;
166 nbtout = Th.nbtout;
167 NbVerticesOnGeomVertex = Th.NbVerticesOnGeomVertex;
168 if(NbVerticesOnGeomVertex)
169 VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];
170 NbVerticesOnGeomEdge = Th.NbVerticesOnGeomEdge;
171 if (NbVerticesOnGeomEdge)
172 VerticesOnGeomEdge = new VertexOnGeom[NbVerticesOnGeomEdge] ;
173 if (& BTh == & Th.BTh){ // same background
174 BTh.NbRef++;
175 NbVertexOnBThVertex = Th.NbVertexOnBThVertex;
176 if(NbVertexOnBThVertex)
177 VertexOnBThVertex = new VertexOnVertex[NbVertexOnBThVertex];
178 NbVertexOnBThEdge = Th.NbVertexOnBThEdge;
179 if(NbVertexOnBThEdge)
180 VertexOnBThEdge = new VertexOnEdge[NbVertexOnBThEdge];
181 }
182 else { // no add on background mesh
183 BTh.NbRef++;
184 NbVertexOnBThVertex=0;
185 VertexOnBThVertex=0;
186 NbVertexOnBThEdge=0;
187 VertexOnBThEdge=0;
188 }
189
190 if(nbe)
191 edges = new Edge[nbe];
192 if(nbsubdomains)
193 subdomains = new SubDomain[nbsubdomains];
194 pmin = Th.pmin;
195 pmax = Th.pmax;
196 coefIcoor = Th.coefIcoor;
197 for(i=0;i<nbt;i++)
198 triangles[i].Set(Th.triangles[i],Th,*this);
199 for(i=0;i<nbe;i++)
200 edges[i].Set(Th,i,*this);
201 for(i=0;i<nbv;i++)
202 vertices[i].Set(Th.vertices[i],Th,*this);
203 for(i=0;i<nbsubdomains;i++)
204 subdomains[i].Set(Th,i,*this);
205 for (i=0;i<NbVerticesOnGeomVertex;i++)
206 VerticesOnGeomVertex[i].Set(Th.VerticesOnGeomVertex[i],Th,*this);
207 for (i=0;i<NbVerticesOnGeomEdge;i++)
208 VerticesOnGeomEdge[i].Set(Th.VerticesOnGeomEdge[i],Th,*this);
209 quadtree=0;
210
211 }
212 /*}}}*/
213 Mesh::Mesh(long imaxnbv,Mesh & BT,BamgOpts* bamgopts,int keepBackVertices) :Gh(BT.Gh),BTh(BT) {/*{{{*/
214 this->Init(imaxnbv);
215 TriangulateFromGeom1(bamgopts,keepBackVertices);
216 }
217 /*}}}*/
218 Mesh::Mesh(long imaxnbv,Geometry & G,BamgOpts* bamgopts):Gh(G),BTh(*this){/*{{{*/
219 Init(imaxnbv);
220 TriangulateFromGeom0(bamgopts);
221 }
222 /*}}}*/
223 Mesh::~Mesh() {/*{{{*/
224 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Triangles)*/
225
226 if(vertices) delete [] vertices;
227 if(edges) delete [] edges;
228 if(triangles) delete [] triangles;
229 if(quadtree) delete quadtree;
230 if(orderedvertices) delete [] orderedvertices;
231 if(subdomains) delete [] subdomains;
232 if(VerticesOnGeomEdge) delete [] VerticesOnGeomEdge;
233 if(VerticesOnGeomVertex) delete [] VerticesOnGeomVertex;
234 if(VertexOnBThVertex) delete [] VertexOnBThVertex;
235 if(VertexOnBThEdge) delete [] VertexOnBThEdge;
236
237 if (Gh.NbRef>0) Gh.NbRef--;
238 else if (Gh.NbRef==0) delete &Gh;
239 if(&BTh != this){
240 if (BTh.NbRef>0) BTh.NbRef--;
241 else if (BTh.NbRef==0) delete &BTh;
242 }
243 Init(0); // set all to zero
244 }
245 /*}}}*/
246
247 /*IO*/
248 void Mesh::ReadMesh(int* index,double* x,double* y,int nods,int nels){/*{{{*/
249
250 long i1,i2,i3;
251 long i;
252 Metric M1(1);
253 int verbose=0;
254 bool* nodeflags=NULL;
255
256 nbv=nods;
257 maxnbv=nbv;
258 nbt=nels;
259
260 //Vertices
261 if (verbose) _printf_("Reading vertices (" << nbv << ")\n");
262 vertices=xNew<BamgVertex>(nbv);
263 orderedvertices=xNew<BamgVertex*>(nbv);
264 for (i=0;i<nbv;i++){
265 vertices[i].r.x=x[i];
266 vertices[i].r.y=y[i];
267 vertices[i].ReferenceNumber=1;
268 vertices[i].m=M1;
269 vertices[i].color=0;
270 }
271 maxnbt=2*maxnbv-2; // for filling The Holes and quadrilaterals
272
273 //Triangles
274 if (verbose) _printf_("Reading triangles (" << nbt << ")\n");
275 triangles =new Triangle[maxnbt]; //we cannot allocate only nbt triangles since
276 nodeflags=xNew<bool>(nbv);
277 for(i=0;i<nbv;i++) nodeflags[i]=false;
278 //other triangles will be added for each edge
279 for (i=0;i<nbt;i++){
280 Triangle & t = triangles[i];
281 i1=(long)index[i*3+0]-1; //for C indexing
282 i2=(long)index[i*3+1]-1; //for C indexing
283 i3=(long)index[i*3+2]-1; //for C indexing
284 t=Triangle(this,i1,i2,i3);
285 t.color=1;
286 nodeflags[i1]=nodeflags[i2]=nodeflags[i3]=true;
287 }
288
289 /*Recreate geometry: */
290 if (verbose) _printf_("Building Geometry\n");
291 BuildGeometryFromMesh();
292 if (verbose) _printf_("Completing geometry\n");
293 Gh.PostRead();
294
295 /*Check that there is no orphan*/
296 bool isorphan=false;
297 for(i=0;i<nbv;i++){
298 if(!nodeflags[i]){
299 _printf_("Vertex " << i+1 << " does not belong to any element\n");
300 isorphan=true;
301 }
302 }
303 if(isorphan) _error_("Orphan found in mesh, see ids above");
304
305 /*Clean up*/
306 xDelete<bool>(nodeflags);
307 }
308 /*}}}*/
309 void Mesh::ReadMesh(BamgMesh* bamgmesh, BamgOpts* bamgopts){/*{{{*/
310
311 int verbose;
312 double Hmin = HUGE_VAL; // the infinie value
313 long i1,i2,i3;
314 long i,j;
315 Metric M1(1);
316
317 verbose=bamgopts->verbose;
318
319 nbv=bamgmesh->VerticesSize[0];
320 maxnbv=nbv;
321 nbt=bamgmesh->TrianglesSize[0];
322
323 //Vertices
324 if(bamgmesh->Vertices){
325 if(verbose>5) _printf_(" processing Vertices\n");
326
327 vertices=xNew<BamgVertex>(nbv);
328 orderedvertices=xNew<BamgVertex*>(nbv);
329
330 for (i=0;i<nbv;i++){
331 vertices[i].r.x=bamgmesh->Vertices[i*3+0];
332 vertices[i].r.y=bamgmesh->Vertices[i*3+1];
333 vertices[i].ReferenceNumber=(long)bamgmesh->Vertices[i*3+2];
334 vertices[i].m=M1;
335 vertices[i].color=0;
336 }
337 maxnbt=2*maxnbv-2; // for filling The Holes and quadrilaterals
338 }
339 else{
340 if(verbose>5) _error_("no Vertices found in the initial mesh");
341 }
342
343 //Triangles
344 if(bamgmesh->Triangles){
345 if(verbose>5) _printf_(" processing Triangles\n");
346 triangles =new Triangle[maxnbt]; //we cannot allocate only nbt triangles since
347 //other triangles will be added for each edge
348 for (i=0;i<nbt;i++){
349 Triangle &t=triangles[i];
350 i1=(long)bamgmesh->Triangles[i*4+0]-1; //for C indexing
351 i2=(long)bamgmesh->Triangles[i*4+1]-1; //for C indexing
352 i3=(long)bamgmesh->Triangles[i*4+2]-1; //for C indexing
353 t=Triangle(this,i1,i2,i3);
354 t.color=(long)bamgmesh->Triangles[i*4+3];
355 }
356 }
357 else{
358 if(verbose>5) _error_("no Triangles found in the initial mesh");
359 }
360
361 //VerticesOnGeomEdge
362 if(bamgmesh->VerticesOnGeomEdge){
363 if(verbose>5) _printf_(" processing VerticesOnGeomEdge\n");
364 NbVerticesOnGeomEdge=bamgmesh->VerticesOnGeomEdgeSize[0];
365 VerticesOnGeomEdge= new VertexOnGeom[NbVerticesOnGeomEdge] ;
366 for (i=0;i<NbVerticesOnGeomEdge;i++){
367 long i1,i2;
368 double s;
369 i1=(long) bamgmesh->VerticesOnGeomEdge[i*3+0]-1; //for C indexing
370 i2=(long) bamgmesh->VerticesOnGeomEdge[i*3+1]-1; //for C indexing
371 s =(double)bamgmesh->VerticesOnGeomEdge[i*3+2];
372 VerticesOnGeomEdge[i]=VertexOnGeom(vertices[i1],Gh.edges[i2],s);
373 }
374 }
375
376 //VerticesOnGeomVertex
377 if(bamgmesh->VerticesOnGeomVertexSize[0]){
378 if(verbose>5) _printf_(" processing VerticesOnGeomVertex\n");
379 NbVerticesOnGeomVertex=bamgmesh->VerticesOnGeomVertexSize[0];
380 VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex] ;
381 for (i=0;i<NbVerticesOnGeomVertex;i++){
382 long i1,i2;
383 i1=(long)bamgmesh->VerticesOnGeomVertex[i*2+0]-1; //for C indexing
384 i2=(long)bamgmesh->VerticesOnGeomVertex[i*2+1]-1; //for C indexing
385 VerticesOnGeomVertex[i]=VertexOnGeom(vertices[i1],Gh.vertices[i2]);
386 }
387 }
388
389 //Edges
390 if (bamgmesh->Edges){
391 int i1,i2;
392 double* len=NULL;
393
394 if(verbose>5) _printf_(" processing Edges\n");
395 nbe=bamgmesh->EdgesSize[0];
396 edges= new Edge[nbe];
397 //initialize length of each edge (used to provided metric)
398 len= new double[nbv];
399 for(i=0;i<nbv;i++) len[i]=0;
400
401 for (i=0;i<nbe;i++){
402 i1=(int)bamgmesh->Edges[i*3+0]-1; //-1 for C indexing
403 i2=(int)bamgmesh->Edges[i*3+1]-1; //-1 for C indexing
404 edges[i].ReferenceNumber=(long)bamgmesh->Edges[i*3+2];
405 edges[i].v[0]= vertices +i1;
406 edges[i].v[1]= vertices +i2;
407 edges[i].adj[0]=NULL;
408 edges[i].adj[1]=NULL;
409 R2 x12=vertices[i2].r-vertices[i1].r;
410 double l12=sqrt((x12,x12));
411
412 //prepare metric
413 vertices[i1].color++;
414 vertices[i2].color++;
415 len[i1]+=l12;
416 len[i2]+=l12;
417 Hmin = Min(Hmin,l12);
418 }
419
420 // definition the default of the given mesh size
421 for (i=0;i<nbv;i++){
422 if (vertices[i].color>0)
423 vertices[i].m=Metric(len[i]/(double)vertices[i].color);
424 else
425 vertices[i].m=Metric(Hmin);
426 }
427 delete [] len;
428
429 // construction of edges[].adj
430 for (i=0;i<nbv;i++){
431 vertices[i].color=(vertices[i].color ==2) ?-1:-2;
432 }
433 for (i=0;i<nbe;i++){
434 for (j=0;j<2;j++) {
435 BamgVertex *v=edges[i].v[j];
436 long i0=v->color,j0;
437 if(i0==-1){
438 v->color=i*2+j;
439 }
440 else if (i0>=0) {// i and i0 edge are adjacent by the vertex v
441 j0 = i0%2;
442 i0 = i0/2;
443 _assert_(v==edges[i0 ].v[j0]);
444 edges[i ].adj[j ] =edges +i0;
445 edges[i0].adj[j0] =edges +i ;
446 v->color = -3;
447 }
448 }
449 }
450 }
451
452 //EdgeOnGeomEdge
453 if(bamgmesh->EdgesOnGeomEdge){
454 if(verbose>5) _printf_(" processing EdgesOnGeomEdge\n");
455 int i1,i2,i,j;
456 i2=bamgmesh->EdgesOnGeomEdgeSize[0];
457 for (i1=0;i1<i2;i1++) {
458 i=(int)bamgmesh->EdgesOnGeomEdge[i1*2+0]-1; //C indexing
459 j=(int)bamgmesh->EdgesOnGeomEdge[i1*2+1]-1; //C indexing
460 //Check value
461 if(!(i>=0 && j>=0 && i<nbe && j<Gh.nbe)) {
462 _error_("ReadMesh error: EdgesOnGeomEdge edge provided (line " << i1+1 << ": [" << i+1 << " " << j+1 << "]) is incorrect (must be positive, [0<i<nbe=" << nbe << " 0<j<Gh.nbe=" << Gh.nbe << "]");
463 }
464 edges[i].GeomEdgeHook=Gh.edges+j;
465 }
466 }
467
468 //SubDomain
469 if(bamgmesh->SubDomains){
470 long i3,head,direction;
471 if(verbose>5) _printf_(" processing SubDomains\n");
472 nbsubdomains=bamgmesh->SubDomainsSize[0];
473 subdomains = new SubDomain [ nbsubdomains ];
474 for (i=0;i<nbsubdomains;i++) {
475 i3 =(int)bamgmesh->SubDomains[i*4+0];
476 head=(int)bamgmesh->SubDomains[i*4+1]-1;//C indexing
477 direction=(int)bamgmesh->SubDomains[i*4+2];
478 if (i3!=3) _error_("Bad Subdomain definition: first number should be 3");
479 if (head<0 || head>=nbt) _error_("Bad Subdomain definition: head should in [1 " << nbt << "] (triangle number)");
480 subdomains[i].head = triangles+head;
481 subdomains[i].direction = direction;
482 subdomains[i].ReferenceNumber = i3;
483 }
484 }
485
486 }
487 /*}}}*/
488 void Mesh::WriteMesh(BamgMesh* bamgmesh,BamgOpts* bamgopts){/*{{{*/
489
490 /*Intermediary*/
491 int i,j,k,num,i1,i2;
492 long n;
493 int* head_1=NULL;
494 int* next_1=NULL;
495 int* connectivitysize_1=NULL;
496 int connectivitymax_1=0;
497
498 /*Get options*/
499 int verbose=bamgopts->verbose;
500
501 /*Build reft that holds the number the subdomain number of each triangle, and the real numbering of the elements*/
502 long* reft = new long[nbt];
503 long* numt = new long[nbt];
504 long nbInT = TriangleReferenceList(reft);
505 TriangleIntNumbering(numt);
506
507 /*Chaining algorithm used to generate connectivity tables and other outputs*/
508
509 //Memory Allocation
510 head_1=xNew<int>(nbv);
511 next_1=xNew<int>(3*nbt);
512 connectivitysize_1=xNew<int>(nbv);
513
514 //Initialization
515 for (i=0;i<nbv;i++) head_1[i]=-1;
516 for (i=0;i<nbv;i++) connectivitysize_1[i]=0;
517 k=0;
518 //Chains generation
519 for (i=0;i<nbt;i++) {
520 //Do not take into account outside triangles (reft<0)
521 if (reft[i]>=0){
522 for (j=0;j<3;j++){
523 int v=GetId(triangles[i][j]); //jth vertex of the ith triangle
524 if (k>3*nbt-1 || k<0) _error_("k = " << k << ", nbt = " << nbt);
525 next_1[k]=head_1[v];
526 if (v>nbv-1 || v<0) _error_("v = " << v << ", nbv = " << nbv);
527 head_1[v]=k++;
528 connectivitysize_1[v]+=1;
529 }
530 }
531 }
532 //Get maximum connectivity
533 connectivitymax_1=0;
534 for (i=0;i<nbv;i++){
535 if (connectivitysize_1[i]>connectivitymax_1) connectivitymax_1=connectivitysize_1[i];
536 }
537
538 /*OK, now build outputs*/
539
540 /*Vertices*/
541 if(verbose>5) _printf_(" writing Vertices\n");
542 bamgmesh->VerticesSize[0]=nbv;
543 bamgmesh->VerticesSize[1]=3;
544 if(nbv){
545 bamgmesh->Vertices=xNew<double>(3*nbv);
546 bamgmesh->PreviousNumbering=xNew<double>(nbv);
547 for (i=0;i<nbv;i++){
548 bamgmesh->Vertices[i*3+0]=vertices[i].r.x;
549 bamgmesh->Vertices[i*3+1]=vertices[i].r.y;
550 bamgmesh->Vertices[i*3+2]=vertices[i].GetReferenceNumber();
551 bamgmesh->PreviousNumbering[i]=vertices[i].PreviousNumber;
552 }
553 }
554
555 /*Edges*/
556 if(verbose>5) _printf_(" writing Edges\n");
557 bamgmesh->EdgesSize[0]=nbe;
558 bamgmesh->EdgesSize[1]=3;
559 int NumIssmSegments=0;
560 if (nbe){
561 bamgmesh->Edges=xNew<double>(3*nbe);
562 for (i=0;i<nbe;i++){
563 bamgmesh->Edges[i*3+0]=GetId(edges[i][0])+1; //back to M indexing
564 bamgmesh->Edges[i*3+1]=GetId(edges[i][1])+1; //back to M indexing
565 bamgmesh->Edges[i*3+2]=edges[i].ReferenceNumber;
566 if(edges[i].GeomEdgeHook){
567 NumIssmSegments++;
568 }
569 }
570 }
571
572 /*Element edges*/
573 if(verbose>5) _printf_(" writing element edges\n");
574 SetOfEdges4* edge4=new SetOfEdges4(nbt*3,nbv);
575 double* elemedge=NULL;
576 elemedge=xNew<double>(3*nbt);
577 for (i=0;i<3*nbt;i++) elemedge[i]=-2.;//will become -1
578 k=0;
579 for (i=0;i<nbt;i++){
580 //Do not take into account outside triangles (reft<0)
581 if (reft[i]>=0){
582 for (j=0;j<3;j++) {
583 i1=GetId(triangles[i][VerticesOfTriangularEdge[j][0]]);
584 i2=GetId(triangles[i][VerticesOfTriangularEdge[j][1]]);
585 n =edge4->SortAndFind(i1,i2);
586 if (n==-1){
587 //first time
588 n=edge4->SortAndAdd(i1,i2);
589 elemedge[n*2+0]=double(k);
590 }
591 else{
592 //second time
593 elemedge[n*2+1]=double(k);
594 }
595 }
596 k++;
597 }
598 }
599 bamgmesh->IssmEdgesSize[0]=edge4->nb();
600 bamgmesh->IssmEdgesSize[1]=4;
601 bamgmesh->IssmEdges=xNew<double>(4*edge4->nb());
602 for (i=0;i<edge4->nb();i++){
603 /*Invert first two vertices if necessary*/
604 bool found=false;
605 for (j=0;j<3;j++){
606 if (triangles[(int)elemedge[2*i+0]](j)==vertices+edge4->i(i)){
607 if (triangles[(int)elemedge[2*i+0]]((j+1)%3)==vertices+edge4->j(i)){
608 //trigonometric direction
609 bamgmesh->IssmEdges[i*4+0]=edge4->i(i)+1;// back to M indexing
610 bamgmesh->IssmEdges[i*4+1]=edge4->j(i)+1;// back to M indexing
611 }
612 else{
613 bamgmesh->IssmEdges[i*4+0]=edge4->j(i)+1;// back to M indexing
614 bamgmesh->IssmEdges[i*4+1]=edge4->i(i)+1;// back to M indexing
615 }
616 found=true;
617 break;
618 }
619 }
620 _assert_(found);
621 bamgmesh->IssmEdges[i*4+2]=elemedge[2*i+0]+1; // back to M indexing
622 bamgmesh->IssmEdges[i*4+3]=elemedge[2*i+1]+1; // back to M indexing
623 }
624 //clean up
625 delete edge4;
626 xDelete<double>(elemedge);
627
628 /*IssmSegments*/
629 if(verbose>5) _printf_(" writing IssmSegments\n");
630 bamgmesh->IssmSegmentsSize[0]=NumIssmSegments;
631 bamgmesh->IssmSegmentsSize[1]=4;
632 bamgmesh->IssmSegments=xNew<double>(4*NumIssmSegments);
633 num=0;
634 for (i=0;i<nbe;i++){
635 if(edges[i].GeomEdgeHook){
636 //build segment
637 int i1=GetId(edges[i][0]);
638 int i2=GetId(edges[i][1]);
639 bool stop=false;
640 for(j=head_1[i1];j!=-1;j=next_1[j]){
641 for(k=0;k<3;k++){
642 if (GetId(triangles[(int)j/3][k])==i1){
643 if (GetId(triangles[(int)j/3][(int)((k+1)%3)])==i2){
644 bamgmesh->IssmSegments[num*4+0]=GetId(edges[i][0])+1; //back to M indexing
645 bamgmesh->IssmSegments[num*4+1]=GetId(edges[i][1])+1; //back to M indexing
646 bamgmesh->IssmSegments[num*4+2]=(int)j/3+1; //back to M indexing
647 bamgmesh->IssmSegments[num*4+3]=edges[i].ReferenceNumber;
648 num+=1;
649 stop=true;
650 break;
651 }
652 if (GetId(triangles[(int)j/3][(int)((k+2)%3)])==i2){
653 bamgmesh->IssmSegments[num*4+0]=GetId(edges[i][1])+1; //back to M indexing
654 bamgmesh->IssmSegments[num*4+1]=GetId(edges[i][0])+1; //back to M indexing
655 bamgmesh->IssmSegments[num*4+2]=(int)j/3+1; //back to M indexing
656 bamgmesh->IssmSegments[num*4+3]=edges[i].ReferenceNumber;
657 num+=1;
658 stop=true;
659 break;
660 }
661 }
662 }
663 if(stop) break;
664 }
665 if (!stop){
666 _error_("Element holding segment [" << i1+1 << " " << i2+1 << "] not found...");
667 }
668 }
669 }
670
671 /*Triangles*/
672 if(verbose>5) _printf_(" writing Triangles\n");
673 k=nbInT;
674 num=0;
675 bamgmesh->TrianglesSize[0]=k;
676 bamgmesh->TrianglesSize[1]=4;
677 if (k){
678 bamgmesh->Triangles=xNew<double>(4*k);
679 for (i=0;i<nbt;i++){
680 Triangle &t=triangles[i];
681 //reft[i]=-1 for outside triangle
682 if (reft[i]>=0 && !( t.Hidden(0) || t.Hidden(1) || t.Hidden(2) )){
683 bamgmesh->Triangles[num*4+0]=GetId(t[0])+1; //back to M indexing
684 bamgmesh->Triangles[num*4+1]=GetId(t[1])+1; //back to M indexing
685 bamgmesh->Triangles[num*4+2]=GetId(t[2])+1; //back to M indexing
686 bamgmesh->Triangles[num*4+3]=subdomains[reft[i]].ReferenceNumber;
687 num=num+1;
688 }
689 }
690 }
691
692 /*SubDomains*/
693 if(verbose>5) _printf_(" writing SubDomains\n");
694 bamgmesh->SubDomainsSize[0]=nbsubdomains;
695 bamgmesh->SubDomainsSize[1]=4;
696 if (nbsubdomains){
697 bamgmesh->SubDomains=xNew<double>(4*nbsubdomains);
698 for (i=0;i<nbsubdomains;i++){
699 bamgmesh->SubDomains[i*4+0]=3;
700 bamgmesh->SubDomains[i*4+1]=reft[GetId(subdomains[i].head)];
701 bamgmesh->SubDomains[i*4+2]=1;
702 bamgmesh->SubDomains[i*4+3]=subdomains[i].ReferenceNumber;
703 }
704 }
705
706 /*SubDomainsFromGeom*/
707 if(verbose>5) _printf_(" writing SubDomainsFromGeom\n");
708 bamgmesh->SubDomainsFromGeomSize[0]=Gh.nbsubdomains;
709 bamgmesh->SubDomainsFromGeomSize[1]=4;
710 if (Gh.nbsubdomains){
711 bamgmesh->SubDomainsFromGeom=xNew<double>(4*Gh.nbsubdomains);
712 for (i=0;i<Gh.nbsubdomains;i++){
713 bamgmesh->SubDomainsFromGeom[i*4+0]=2;
714 bamgmesh->SubDomainsFromGeom[i*4+1]=GetId(subdomains[i].edge)+1; //back to Matlab indexing
715 bamgmesh->SubDomainsFromGeom[i*4+2]=subdomains[i].direction;
716 bamgmesh->SubDomainsFromGeom[i*4+3]=Gh.subdomains[i].ReferenceNumber;
717 }
718 }
719
720 /*VerticesOnGeomVertex*/
721 if(verbose>5) _printf_(" writing VerticesOnGeomVertex\n");
722 bamgmesh->VerticesOnGeomVertexSize[0]=NbVerticesOnGeomVertex;
723 bamgmesh->VerticesOnGeomVertexSize[1]=2;
724 if (NbVerticesOnGeomVertex){
725 bamgmesh->VerticesOnGeomVertex=xNew<double>(2*NbVerticesOnGeomVertex);
726 for (i=0;i<NbVerticesOnGeomVertex;i++){
727 VertexOnGeom &v=VerticesOnGeomVertex[i];
728 _assert_(v.OnGeomVertex());
729 bamgmesh->VerticesOnGeomVertex[i*2+0]=GetId((BamgVertex*)v)+1; //back to Matlab indexing
730 bamgmesh->VerticesOnGeomVertex[i*2+1]=Gh.GetId((GeomVertex*)v)+1; //back to Matlab indexing
731 }
732 }
733
734 /*VertexOnGeomEdge*/
735 if(verbose>5) _printf_(" writing VerticesOnGeomEdge\n");
736 bamgmesh->VerticesOnGeomEdgeSize[0]=NbVerticesOnGeomEdge;
737 bamgmesh->VerticesOnGeomEdgeSize[1]=3;
738 if (NbVerticesOnGeomEdge){
739 bamgmesh->VerticesOnGeomEdge=xNew<double>(3*NbVerticesOnGeomEdge);
740 for (i=0;i<NbVerticesOnGeomEdge;i++){
741 const VertexOnGeom &v=VerticesOnGeomEdge[i];
742 if (!v.OnGeomEdge()){
743 _error_("A vertices supposed to be OnGeomEdge is actually not");
744 }
745 bamgmesh->VerticesOnGeomEdge[i*3+0]=GetId((BamgVertex*)v)+1; //back to Matlab indexing
746 bamgmesh->VerticesOnGeomEdge[i*3+1]=Gh.GetId((const GeomEdge*)v)+1; //back to Matlab indexing
747 bamgmesh->VerticesOnGeomEdge[i*3+2]=(double)v; //absisce
748 }
749 }
750
751 /*EdgesOnGeomEdge*/
752 if(verbose>5) _printf_(" writing EdgesOnGeomEdge\n");
753 k=0;
754 for (i=0;i<nbe;i++){
755 if (edges[i].GeomEdgeHook) k=k+1;
756 }
757 bamgmesh->EdgesOnGeomEdgeSize[0]=k;
758 bamgmesh->EdgesOnGeomEdgeSize[1]=2;
759 if (k){
760 bamgmesh->EdgesOnGeomEdge=xNew<double>(2*(int)k);
761 int count=0;
762 for (i=0;i<nbe;i++){
763 if (edges[i].GeomEdgeHook){
764 bamgmesh->EdgesOnGeomEdge[count*2+0]=(double)i+1; //back to Matlab indexing
765 bamgmesh->EdgesOnGeomEdge[count*2+1]=(double)Gh.GetId(edges[i].GeomEdgeHook)+1; //back to Matlab indexing
766 count=count+1;
767 }
768 }
769 }
770
771 /*Element Connectivity*/
772 if(verbose>5) _printf_(" writing Element connectivity\n");
773 bamgmesh->ElementConnectivitySize[0]=nbt-nbtout;
774 bamgmesh->ElementConnectivitySize[1]=3;
775 bamgmesh->ElementConnectivity=xNew<double>(3*(nbt-nbtout));
776 for (i=0;i<3*(nbt-nbtout);i++) bamgmesh->ElementConnectivity[i]=NAN;
777 num=0;
778 for (i=0;i<nbt;i++){
779 if (reft[i]>=0){
780 for (j=0;j<3;j++){
781 k=GetId(triangles[i].TriangleAdj(j));
782 if (reft[k]>=0){
783 _assert_(3*num+j<3*(nbt-nbtout));
784 bamgmesh->ElementConnectivity[3*num+j]=k+1; // back to Matlab indexing
785 }
786 }
787 num+=1;
788 }
789 }
790
791 /*ElementNodal Connectivity*/
792 if(verbose>5) _printf_(" writing Nodal element connectivity\n");
793 bamgmesh->NodalElementConnectivitySize[0]=nbv;
794 bamgmesh->NodalElementConnectivitySize[1]=connectivitymax_1;
795 bamgmesh->NodalElementConnectivity=xNew<double>(connectivitymax_1*nbv);
796 for (i=0;i<connectivitymax_1*nbv;i++) bamgmesh->NodalElementConnectivity[i]=NAN;
797 for (i=0;i<nbv;i++){
798 k=0;
799 for(j=head_1[i];j!=-1;j=next_1[j]){
800 _assert_(connectivitymax_1*i+k < connectivitymax_1*nbv);
801 bamgmesh->NodalElementConnectivity[connectivitymax_1*i+k]=floor((double)j/3)+1;
802 k++;
803 }
804 }
805
806 /*Nodal Connectivity*/
807 if(verbose>5) _printf_(" writing Nodal connectivity\n");
808 //chaining algorithm (again...)
809 int* head_2=NULL;
810 int* next_2=NULL;
811 int* connectivitysize_2=NULL;
812 int connectivitymax_2=0;
813 i1=bamgmesh->IssmEdgesSize[0];
814 i2=bamgmesh->IssmEdgesSize[1];
815 head_2=xNew<int>(nbv);
816 next_2=xNew<int>(2*i1);
817 connectivitysize_2=xNew<int>(nbv);
818 //Initialization
819 for (i=0;i<nbv;i++) head_2[i]=-1;
820 for (i=0;i<nbv;i++) connectivitysize_2[i]=0;
821 k=0;
822 //Chains generation
823 for (i=0;i<i1;i++) {
824 for (j=0;j<2;j++){
825 int v=(int)bamgmesh->IssmEdges[i*i2+j]-1; //back to C indexing
826 if (k>2*i1-1 || k<0) _error_("Index exceed matrix dimensions (k=" << k << " not in [0 " << 2*i1-1 << "]");
827 next_2[k]=head_2[v];
828 if (v>nbv-1 || v<0) _error_("Index exceed matrix dimensions (v=" << v << " not in [0 " << nbv-1 << "])");
829 head_2[v]=k++;
830 connectivitysize_2[v]+=1;
831 }
832 }
833 //Get maximum connectivity
834 for (i=0;i<nbv;i++){
835 if (connectivitysize_2[i]>connectivitymax_2) connectivitymax_2=connectivitysize_2[i];
836 }
837 //Build output
838 connectivitymax_2++;//add last column for size
839 bamgmesh->NodalConnectivitySize[0]=nbv;
840 bamgmesh->NodalConnectivitySize[1]=connectivitymax_2;
841 bamgmesh->NodalConnectivity=xNew<double>(connectivitymax_2*nbv);
842 for (i=0;i<connectivitymax_2*nbv;i++) bamgmesh->NodalConnectivity[i]=0;
843 for (i=0;i<nbv;i++){
844 k=0;
845 for(j=head_2[i];j!=-1;j=next_2[j]){
846 _assert_(connectivitymax_2*i+k < connectivitymax_2*nbv);
847 num=(int)bamgmesh->IssmEdges[int(j/2)*i2+0];
848 if (i+1==num){ //carefull, ElementEdge is in M indexing
849 //i is the first vertex of the edge, it is therefore connected to the second vertex
850 bamgmesh->NodalConnectivity[connectivitymax_2*i+k]=bamgmesh->IssmEdges[int(j/2)*i2+1];
851 }
852 else{
853 bamgmesh->NodalConnectivity[connectivitymax_2*i+k]=num;
854 }
855 k++;
856 }
857 bamgmesh->NodalConnectivity[connectivitymax_2*(i+1)-1]=k;
858 }
859
860 /*Cracked vertices*/
861 if(verbose>5) _printf_(" writing Cracked vertices\n");
862 bamgmesh->CrackedVerticesSize[0]=NbCrackedVertices;
863 bamgmesh->CrackedVerticesSize[1]=2;
864 if (NbCrackedVertices){
865 bamgmesh->CrackedVertices=xNew<double>(2*NbCrackedVertices);
866 for (i=0;i<NbCrackedVertices;i++){
867 bamgmesh->CrackedVertices[i*2+0]=CrackedVertices[i*2+0]+1; //M indexing
868 bamgmesh->CrackedVertices[i*2+1]=CrackedVertices[i*2+1]+1; //M indexing
869 }
870 }
871
872 /*Cracked vertices*/
873 if(verbose>5) _printf_(" writing Cracked vertices\n");
874 bamgmesh->CrackedEdgesSize[0]=NbCrackedEdges;
875 bamgmesh->CrackedEdgesSize[1]=4;
876 if (NbCrackedEdges){
877 bamgmesh->CrackedEdges=xNew<double>(2*NbCrackedEdges);
878 for (i=0;i<NbCrackedEdges;i++){
879 bamgmesh->CrackedEdges[i*2+0]=0;//CrackedEdges[i]->+1; //M indexing
880 bamgmesh->CrackedEdges[i*2+1]=0;//CrackedEdges[i]-]->+1; //M indexing
881 }
882 }
883
884 //clean up
885 xDelete<int>(connectivitysize_1);
886 xDelete<int>(head_1);
887 xDelete<int>(next_1);
888 xDelete<int>(connectivitysize_2);
889 xDelete<int>(head_2);
890 xDelete<int>(next_2);
891 delete [] reft;
892 delete [] numt;
893 }
894 /*}}}*/
895 void Mesh::ReadMetric(const BamgOpts* bamgopts) {/*{{{*/
896
897 /*Intermediary*/
898 int i,j;
899
900 if(bamgopts->verbose>3) _printf_(" processing metric\n");
901 double hmin = Max(bamgopts->hmin,MinimalHmin());
902 double hmax = Min(bamgopts->hmax,MaximalHmax());
903 double coef = bamgopts->coeff;
904
905 //for now we only use j==3
906 j=3;
907
908 for (i=0;i<nbv;i++){
909 double h;
910 if (j == 1){
911 h=bamgopts->metric[i];
912 vertices[i].m=Metric(Max(hmin,Min(hmax, h*coef)));
913 }
914 else if (j==3){
915 //do not erase metric computed by hVertices
916 if (vertices[i].m.a11==1 && vertices[i].m.a21==0 && vertices[i].m.a22==1){
917 double a,b,c;
918 a=bamgopts->metric[i*3+0];
919 b=bamgopts->metric[i*3+1];
920 c=bamgopts->metric[i*3+2];
921 Metric M(a,b,c);
922 EigenMetric Vp(M/coef);
923
924 Vp.Maxh(hmax);
925 Vp.Minh(hmin);
926 vertices[i].m = Vp;
927 }
928 }
929 }
930 }
931 /*}}}*/
932 void Mesh::WriteMetric(BamgOpts* bamgopts) {/*{{{*/
933 int i;
934 xDelete<double>(bamgopts->metric);
935 bamgopts->metric=xNew<double>(3*nbv);
936 for (i=0;i<nbv;i++){
937 bamgopts->metric[i*3+0]=vertices[i].m.a11;
938 bamgopts->metric[i*3+1]=vertices[i].m.a21;
939 bamgopts->metric[i*3+2]=vertices[i].m.a22;
940 }
941 }
942 /*}}}*/
943 void Mesh::WriteIndex(int** pindex,int* pnels){/*{{{*/
944
945 /*Intermediary*/
946 int i,k;
947
948 /*output*/
949 int* index=NULL;
950 int num=0;
951
952 /*Get number of triangles*/
953 k=0;
954 for (i=0;i<nbt;i++){
955 Triangle &t=triangles[i];
956 if(t.det>0) k++;
957 }
958
959 if (k){
960 index=xNew<int>(3*k);
961 for (i=0;i<nbt;i++){
962 Triangle &t=triangles[i];
963 if (t.det>0 && !(t.Hidden(0)||t.Hidden(1) || t.Hidden(2) )){
964 /*Remove triangles that have a bad aspect ratio*/
965 //if(t.Anisotropy()<2 & t.Length()<1.e+5){
966 index[num*3+0]=GetId(t[0])+1; //back to M indexing
967 index[num*3+1]=GetId(t[1])+1; //back to M indexing
968 index[num*3+2]=GetId(t[2])+1; //back to M indexing
969 num=num+1;
970 //}
971 }
972 }
973 }
974
975 /*Assign output pointers*/
976 *pindex=index;
977 *pnels=num;
978 }
979 /*}}}*/
980
981 /*Methods*/
982 void Mesh::AddGeometryMetric(BamgOpts* bamgopts){/*{{{*/
983 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/IntersectGeomMetric)*/
984
985 /*Get options*/
986 double anisomax = bamgopts->anisomax;
987 double errg = bamgopts->errg;
988
989 double ss[2]={0.00001,0.99999};
990 double errC = 2*sqrt(2*errg);
991 double hmax = Gh.MaximalHmax();
992 double hmin = Gh.MinimalHmin();
993
994 //check that hmax is positive
995 _assert_(hmax>0);
996
997 //errC cannot be higher than 1
998 if(errC>1) errC=1;
999
1000 //Set all vertices to "on"
1001 SetVertexFieldOn();
1002
1003 //loop over all the vertices on edges
1004 for(int i=0;i<nbe;i++){
1005 for (int j=0;j<2;j++){
1006
1007 BamgVertex V;
1008 VertexOnGeom GV;
1009 Gh.ProjectOnCurve(edges[i],ss[j],V,GV);
1010
1011 GeomEdge* eg = GV;
1012 double s = GV;
1013 R2 tg;
1014 double R1= eg->R1tg(s,tg);
1015 double ht=hmax;
1016 // err relative to the length of the edge
1017 if (R1>1.0e-20) {
1018 ht = Min(Max(errC/R1,hmin),hmax);
1019 }
1020 double hn=Min(hmax,ht*anisomax);
1021
1022 if (ht<=0 || hn<=0){
1023 _error_("ht<=0 || hn<=0");
1024 }
1025 EigenMetric Vp(1/(ht*ht),1/(hn*hn),tg);
1026 Metric MVp(Vp);
1027 edges[i][j].m.IntersectWith(MVp);
1028 }
1029 }
1030 // the problem is for the vertex on vertex
1031 }
1032 /*}}}*/
1033 void Mesh::AddMetric(BamgOpts* bamgopts){/*{{{*/
1034 // Hessiantype = 0 => H is computed using double L2 projection
1035 // Hessiantype = 1 => H is computed with green formula
1036
1037 /*Options*/
1038 int Hessiantype=bamgopts->Hessiantype;
1039
1040 if (Hessiantype==0){
1041 BuildMetric0(bamgopts);
1042 }
1043 else if (Hessiantype==1){
1044 BuildMetric1(bamgopts);
1045 }
1046 else{
1047 _error_("Hessiantype " << Hessiantype << " not supported yet (1->use Green formula, 0-> double L2 projection)");
1048 }
1049 }
1050 /*}}}*/
1051 void Mesh::AddVertex( BamgVertex &s,Triangle* t, Icoor2* det3){/*{{{*/
1052 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Add)*/
1053 // -------------------------------
1054 // s2
1055 // !
1056 // /|\ !
1057 // / | \ !
1058 // / | \ !
1059 // tt1 / | \ tt0 !
1060 // / |s \ !
1061 // / . \ !
1062 // / . ` \ !
1063 // / . ` \ !
1064 // ---------------- !
1065 // s0 tt2 s1
1066 //-------------------------------
1067
1068 /*Intermediaries*/
1069 Triangle* tt[3]; //the three triangles
1070 Icoor2 det3local[3]; //three determinants (integer)
1071 int nbzerodet =0; //number of zeros in det3
1072 int izerodet=-1; //egde containing the vertex s
1073 int iedge;
1074
1075 /*three vertices of t*/
1076 BamgVertex* s0=t->GetVertex(0);
1077 BamgVertex* s1=t->GetVertex(1);
1078 BamgVertex* s2=t->GetVertex(2);
1079
1080 //determinant of t
1081 Icoor2 detOld=t->det;
1082
1083 /* infvertexindex = index of the infinite vertex (NULL)
1084 if no infinite vertex (NULL) infvertexindex=-1
1085 else if v_i is infinite, infvertexindex=i*/
1086 int infvertexindex = s0 ? ((s1? (s2?-1:2):1)):0;
1087
1088 //some checks
1089 if(((infvertexindex <0 ) && (detOld <0)) || ((infvertexindex >=0) && (detOld >0)) ){
1090 _error_("inconsistent configuration (Contact ISSM developers)");
1091 }
1092
1093 // if det3 does not exist, build it
1094 if (!det3){
1095 //allocate
1096 det3 = det3local;
1097 //if no infinite vertex
1098 if (infvertexindex<0 ) {
1099 det3[0]=bamg::det(s .GetIntegerCoordinates(),s1->GetIntegerCoordinates(),s2->GetIntegerCoordinates());
1100 det3[1]=bamg::det(s0->GetIntegerCoordinates(),s .GetIntegerCoordinates(),s2->GetIntegerCoordinates());
1101 det3[2]=bamg::det(s0->GetIntegerCoordinates(),s1->GetIntegerCoordinates(),s.GetIntegerCoordinates());}
1102 else {
1103 // one of &s1 &s2 &s0 is NULL
1104 det3[0]= s0 ? -1 : bamg::det(s.GetIntegerCoordinates(),s1->GetIntegerCoordinates(),s2->GetIntegerCoordinates()) ;
1105 det3[1]= s1 ? -1 : bamg::det(s0->GetIntegerCoordinates(),s.GetIntegerCoordinates(),s2->GetIntegerCoordinates()) ;
1106 det3[2]= s2 ? -1 : bamg::det(s0->GetIntegerCoordinates(),s1->GetIntegerCoordinates(),s.GetIntegerCoordinates()) ;
1107 }
1108 }
1109
1110 if (!det3[0]) izerodet=0,nbzerodet++;
1111 if (!det3[1]) izerodet=1,nbzerodet++;
1112 if (!det3[2]) izerodet=2,nbzerodet++;
1113
1114 //if nbzerodet>0, point s is on an egde or on a vertex
1115 if (nbzerodet>0){
1116 /*s is on an edge*/
1117 if (nbzerodet==1) {
1118 iedge = OppositeEdge[izerodet];
1119 AdjacentTriangle ta = t->Adj(iedge);
1120
1121 /*if the point is one the boundary
1122 add the point in outside part */
1123 if (t->det>=0){ // inside triangle
1124 if (((Triangle*)ta)->det<0 ) {
1125 // add in outside triangle
1126 AddVertex(s,( Triangle *)ta);
1127 return;
1128 }
1129 }
1130 }
1131 else{
1132 _error_("Cannot add a vertex more than once. Check duplicates");
1133 }
1134 }
1135
1136 // remove de MarkUnSwap edge
1137 t->SetUnMarkUnSwap(0);
1138 t->SetUnMarkUnSwap(1);
1139 t->SetUnMarkUnSwap(2);
1140
1141 tt[0]= t;
1142 tt[1]= &triangles[nbt++];
1143 tt[2]= &triangles[nbt++];
1144
1145 if (nbt>maxnbt) _error_("Not enough triangles");
1146
1147 *tt[1]=*tt[2]=*t;
1148 tt[0]->link=tt[1];
1149 tt[1]->link=tt[2];
1150
1151 (*tt[0])(OppositeVertex[0])=&s;
1152 (*tt[1])(OppositeVertex[1])=&s;
1153 (*tt[2])(OppositeVertex[2])=&s;
1154
1155 tt[0]->det=det3[0];
1156 tt[1]->det=det3[1];
1157 tt[2]->det=det3[2];
1158
1159 // update adj des triangles externe
1160 tt[0]->SetAdjAdj(0);
1161 tt[1]->SetAdjAdj(1);
1162 tt[2]->SetAdjAdj(2);
1163 // update des adj des 3 triangle interne
1164 const int i0 = 0;
1165 const int i1= NextEdge[i0];
1166 const int i2 = PreviousEdge[i0];
1167
1168 tt[i0]->SetAdj2(i2,tt[i2],i0);
1169 tt[i1]->SetAdj2(i0,tt[i0],i1);
1170 tt[i2]->SetAdj2(i1,tt[i1],i2);
1171
1172 tt[0]->SetSingleVertexToTriangleConnectivity();
1173 tt[1]->SetSingleVertexToTriangleConnectivity();
1174 tt[2]->SetSingleVertexToTriangleConnectivity();
1175
1176 // swap if the point s is on a edge
1177 if(izerodet>=0) {
1178 int rswap=tt[izerodet]->swap(iedge);
1179
1180 if (!rswap) {
1181 _error_("swap the point s is on a edge");
1182 }
1183 }
1184
1185 }/*}}}*/
1186 void Mesh::BoundAnisotropy(double anisomax,double hminaniso) {/*{{{*/
1187 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/BoundAnisotropy)*/
1188
1189 long int verbose=0;
1190 double lminaniso = 1/ (Max(hminaniso*hminaniso,1e-100));
1191
1192 //display info
1193 if (verbose > 1) _printf_(" BoundAnisotropy by " << anisomax << "\n");
1194
1195 double h1=1.e30,h2=1e-30;
1196 double coef = 1./(anisomax*anisomax);
1197 double hn1=1.e30,hn2=1e-30,rnx =1.e-30,rx=0;
1198
1199 //loop over all vertices
1200 for (int i=0;i<nbv;i++){
1201 EigenMetric Vp(vertices[i]);
1202 double lmax=Vp.lmax();
1203 Vp*=Min(lminaniso,lmax)/lmax;
1204 Vp.BoundAniso2(coef);
1205 vertices[i].m = Vp;
1206
1207 //info to be displayed
1208 if (verbose>2){
1209 h1 =Min(h1,Vp.lmin());
1210 h2 =Max(h2,Vp.lmax());
1211 hn1=Min(hn1,Vp.lmin());
1212 hn2=Max(hn2,Vp.lmax());
1213 rx =Max(rx,Vp.Aniso2());
1214 rnx= Max(rnx,Vp.Aniso2());
1215 }
1216 }
1217
1218 //display info
1219 if (verbose>2){
1220 _printf_(" input: Hmin = " << pow(h2,-0.5) << ", Hmax = " << pow(h1,-0.5) << ", factor of anisotropy max = " << pow(rx,0.5) << "\n");
1221 _printf_(" output: Hmin = " << pow(hn2,-0.5) << ", Hmax = " << pow(hn1,-0.5)<< ", factor of anisotropy max = " <<pow(rnx,0.5) << "\n");
1222 }
1223 }
1224 /*}}}*/
1225 void Mesh::BuildGeometryFromMesh(BamgOpts* bamgopts){/*{{{*/
1226 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/ConsGeometry)*/
1227
1228 /*Reconstruct Geometry from Mesh*/
1229
1230 /*Intermediary*/
1231 int i,j,k,kk,it,jt;
1232 int verbose=0;
1233 double cutoffradian=10*Pi/180;
1234
1235 /*Recover options*/
1236 if (bamgopts){
1237 verbose=bamgopts->verbose;
1238 cutoffradian=bamgopts->MaxCornerAngle*Pi/180;
1239 }
1240
1241 //display info
1242 if (verbose>1) _printf_(" construction of the geometry from the 2d mesh\n");
1243
1244 //check that the mesh is not empty
1245 if (nbt<=0 || nbv <=0 ) {
1246 _error_("nbt or nbv is negative (Mesh empty?)");
1247 }
1248
1249 //Gh is the geometry of the mesh (this), initialize MaxCornerAngle
1250 if (cutoffradian>=0) Gh.MaxCornerAngle = cutoffradian;
1251
1252 /*Construction of the edges*/
1253
1254 //initialize st and edge4
1255 SetOfEdges4* edge4= new SetOfEdges4(nbt*3,nbv);
1256 long* st = new long[nbt*3];
1257
1258 //initialize st as -1 (chaining algorithm)
1259 for (i=0;i<nbt*3;i++) st[i]=-1;
1260
1261 //build edge4 (chain)
1262 for (i=0;i<nbe;i++){
1263 edge4->SortAndAdd(GetId(edges[i][0]),GetId(edges[i][1]));
1264 }
1265 //check that there is no double edge
1266 if (nbe != edge4->nb()){
1267 delete [] st;
1268 _error_("Some Double edge in the mesh, the number is " << nbe << ", nbe4=" << edge4->nb());
1269 }
1270 //keep nbe in nbeold
1271 long nbeold = nbe;
1272
1273 //Go through the triangles and ass the edges in edge4 if they are not there yet
1274 for (i=0;i<nbt;i++){
1275 //3 edges per triangle
1276 for (j=0;j<3;j++) {
1277 //Add Edge to edge4 (k=numberofedges in edge4)
1278 long k =edge4->SortAndAdd(GetId(triangles[i][VerticesOfTriangularEdge[j][0]]), GetId(triangles[i][VerticesOfTriangularEdge[j][1]]));
1279 long invisible = triangles[i].Hidden(j);
1280
1281 //if st[k] has not been changed yet, add 3*i+j (= vertex position in the index)
1282 if(st[k]==-1) st[k]=3*i+j;
1283
1284 //else st[k]>=0 -> the edge already exist, check
1285 else if(st[k]>=0) {
1286 //check that it is not an edge on boundary (should not already exist)
1287 if (triangles[i].TriangleAdj(j) || triangles[st[k]/3].TriangleAdj((int) (st[k]%3))){
1288 _error_("problem in Geometry reconstruction: an edge on boundary is duplicated (double element?)");
1289 }
1290 //OK, the element is not on boundary, is belongs to 2 triangles -> build Adjacent triangles list
1291 triangles[i].SetAdj2(j,triangles + st[k] / 3,(int) (st[k]%3));
1292 if (invisible) triangles[i].SetHidden(j);
1293 // if k < nbe mark the edge as on Boundary (Locked)
1294 if (k<nbe) {
1295 triangles[i].SetLocked(j);
1296 }
1297 //set st[k] as negative so that the edge should not be called again
1298 st[k]=-2-st[k];
1299 }
1300 //else (see 3 lines above), the edge has been called more than twice: return error
1301 else {
1302 _printf_("The edge (" << GetId(triangles[i][VerticesOfTriangularEdge[j][0]]) << "," << GetId(triangles[i][VerticesOfTriangularEdge[j][1]]) << ") belongs to more than 2 triangles (" << k << ")\n");
1303 _printf_("Edge " << j << " of triangle " << i << "\n");
1304 _printf_("Edge " << (-st[k]+2)%3 << " of triangle " << (-st[k]+2)/3 << "\n");
1305 _printf_("Edge " << triangles[(-st[k]+2)/3].NuEdgeTriangleAdj((int)((-st[k]+2)%3)) << " of triangle " << GetId(triangles[(-st[k]+2)/3].TriangleAdj((int)((-st[k]+2)%3))) << "\n");
1306 _error_("An edge belongs to more than 2 triangles");
1307 }
1308 }
1309 }
1310
1311 //delete edge4
1312 long nbedges = edge4->nb(); // the total number of edges
1313 delete edge4; edge4=NULL;
1314
1315 //display info
1316 if(verbose>5) {
1317 _printf_(" info on Mesh:\n");
1318 _printf_(" - number of vertices = " << nbv << "\n");
1319 _printf_(" - number of triangles = " << nbt << "\n");
1320 _printf_(" - number of given edges = " << nbe << "\n");
1321 _printf_(" - number of all edges = " << nbedges << "\n");
1322 _printf_(" - Euler number 1 - nb of holes = " << nbt-nbedges+nbv << "\n");
1323 }
1324
1325 // check consistency of edge[].adj and geometrical required vertices
1326 k=0; kk=0;
1327 for (i=0;i<nbedges;i++){
1328 //internal edge
1329 if (st[i] <-1) {
1330 //get triangle number back
1331 it = (-2-st[i])/3;
1332 //get edge position back
1333 j = (int) ((-2-st[i])%3);
1334 Triangle &tt=*triangles[it].TriangleAdj(j);
1335 if (triangles[it].color != tt.color|| i < nbeold) k++;
1336 }
1337 //boundary edge (alone)
1338 else if (st[i] >=0)
1339 kk++;
1340 }
1341
1342 /*Constructions of edges*/
1343
1344 k += kk;
1345 kk=0;
1346 if (k) {
1347 nbe = k;
1348 Edge* edgessave=edges;
1349 edges = new Edge[nbe];
1350 k =0;
1351
1352 //display info
1353 if(verbose>4) _printf_(" Construction of the edges " << nbe << "\n");
1354
1355 for (i=0;i<nbedges;i++){
1356 long add= -1;
1357
1358 //internal edge (belongs to two triangles)
1359 if (st[i] <-1){
1360 it = (-2-st[i])/3;
1361 j = (int) ((-2-st[i])%3);
1362 Triangle & tt = * triangles[it].TriangleAdj(j);
1363 if (triangles[it].color != tt.color || i < nbeold) add=k++;
1364 }
1365 //boundary edge
1366 else if (st[i] >=0){
1367 it = st[i]/3;
1368 j = (int) (st[i]%3);
1369 add=k++;
1370 }
1371 if (add>=0 && add < nbe){
1372 edges[add].v[0] = &triangles[it][VerticesOfTriangularEdge[j][0]];
1373 edges[add].v[1] = &triangles[it][VerticesOfTriangularEdge[j][1]];
1374 edges[add].GeomEdgeHook=NULL;
1375 //if already existed
1376 if (i<nbeold){
1377 edges[add].ReferenceNumber=edgessave[i].ReferenceNumber;
1378 edges[add].GeomEdgeHook=edgessave[i].GeomEdgeHook; // HACK to get required edges
1379 _printf_("oh no...\n");
1380 }
1381 else
1382 edges[add].ReferenceNumber=Min(edges[add].v[0]->GetReferenceNumber(),edges[add].v[1]->GetReferenceNumber());
1383 }
1384 }
1385
1386 //check that we have been through all edges
1387 if (k!=nbe){
1388 _error_("problem in edge construction process: k!=nbe (should not happen)");
1389 }
1390 //delete edgessave
1391 if (edgessave) delete [] edgessave;
1392 }
1393
1394 /*Color the vertices*/
1395
1396 //initialize color of all vertices as 0
1397 for (i=0;i<nbv;i++) vertices[i].color =0;
1398
1399 //go through the edges and add a color to corresponding vertices
1400 //(A vertex in 4 edges will have a color 4)
1401 for (i=0;i<nbe;i++){
1402 for (j=0;j<2;j++) edges[i].v[j]->color++;
1403 }
1404
1405 //change the color: if a vertex belongs to 2 edges -1, else -2
1406 for (i=0;i<nbv;i++) {
1407 vertices[i].color=(vertices[i].color ==2)? -1 : -2;
1408 }
1409
1410 /*Build edges[i].adj: adjacency of each edge (if on the same curve)*/
1411 for (i=0;i<nbe;i++){
1412 for (j=0;j<2;j++){
1413 //get current vertex
1414 BamgVertex* v=edges[i].v[j];
1415 //get vertex color (i0)
1416 long i0=v->color;
1417 long j0;
1418
1419 //if color<0 (first time), no adjacent edge
1420 if(i0<0) edges[i].adj[j]=NULL;
1421
1422 //if color=-1 (corner),change the vertex color as 2*i+j (position of the vertex in edges)
1423 if(i0==-1) v->color=i*2+j;
1424
1425 //if color>=0 (i and i0 edge are adjacent by the vertex v)
1426 else if (i0>=0) {
1427 //get position of v in edges back
1428 j0 = i0%2; //column in edges
1429 i0 = i0/2; //line in edges
1430
1431 //check that we have the correct vertex
1432 if (v!=edges[i0 ].v[j0]){
1433 _error_("v!=edges[i0 ].v[j0]: this should not happen as the vertex belongs to this edge");
1434 }
1435
1436 //Add adjacence
1437 edges[i ].adj[j ]=edges +i0;
1438 edges[i0].adj[j0]=edges +i ;
1439
1440 //change color to -3
1441 v->color = -3;
1442 }
1443 }
1444 }
1445
1446 /*Reconstruct subdomains info*/
1447
1448 //check that nbsubdomains is empty
1449 if (nbsubdomains){
1450 _error_("nbsubdomains should be 0");
1451 }
1452 nbsubdomains=0;
1453
1454 //color the subdomains
1455 long* colorT= new long[nbt];
1456 Triangle *tt,*t;
1457
1458 //initialize the color of each triangle as -1
1459 for (it=0;it<nbt;it++) colorT[it]=-1;
1460
1461 //loop over the triangles
1462 for (it=0;it<nbt;it++){
1463
1464 //if the triangle has not been colored yet:
1465 if (colorT[it]<0){
1466
1467 //color = number of subdomains
1468 colorT[it]=nbsubdomains;
1469
1470 //color all the adjacent triangles of T that share a non marked edge
1471 int level =1;
1472 int kolor=triangles[it].color;
1473 st[0]=it; // stack
1474 st[1]=0;
1475 k=1;
1476 while (level>0){
1477 if( (j=st[level]++)<3 ){
1478 t = &triangles[st[level-1]];
1479 tt=t->TriangleAdj((int)j);
1480
1481 //color the adjacent triangle
1482 if ( ! t->Locked(j) && tt && (colorT[jt = GetId(tt)] == -1) && ( tt->color==kolor)) {
1483 colorT[jt]=nbsubdomains;
1484 st[++level]=jt;
1485 st[++level]=0;
1486 k++;
1487 }
1488 }
1489 else level-=2;
1490 }
1491 nbsubdomains++;
1492 }
1493 }
1494 if (verbose> 3) _printf_(" The Number of sub domain = " << nbsubdomains << "\n");
1495
1496 //build subdomains
1497 long isd;
1498 subdomains = new SubDomain[nbsubdomains];
1499
1500 //initialize subdomains[isd].head as 0
1501 for (isd=0;isd<nbsubdomains;isd++) subdomains[isd].head =0;
1502
1503 k=0;
1504 for (it=0;it<nbt;it++){
1505 for (int j=0;j<3;j++){
1506 tt=triangles[it].TriangleAdj(j);
1507 if ((!tt || tt->color != triangles[it].color) && !subdomains[isd=colorT[it]].head){
1508 subdomains[isd].head = triangles+it;
1509 subdomains[isd].ReferenceNumber = triangles[it].color;
1510 subdomains[isd].direction = j; // hack
1511 subdomains[isd].edge = 0;
1512 k++;
1513 }
1514 }
1515 }
1516 //check that we have been through all subdomains
1517 if (k!= nbsubdomains){
1518 delete [] colorT;
1519 _error_("k!= nbsubdomains");
1520 }
1521 //delete colorT and st
1522 delete [] colorT;
1523 delete [] st;
1524
1525 /*Reconstruct Geometry Gh*/
1526
1527 //build colorV -1 for all vertex and 0 for the vertices belonging to edges
1528 long* colorV = new long[nbv];
1529 for (i=0;i<nbv;i++) colorV[i]=-1;
1530 for (i=0;i<nbe;i++){
1531 for ( j=0;j<2;j++) colorV[GetId(edges[i][j])]=0;
1532 }
1533 //number the vertices belonging to edges
1534 k=0;
1535 for (i=0;i<nbv;i++){
1536 if(!colorV[i]) colorV[i]=k++;
1537 }
1538
1539 //Build Gh
1540 Gh.nbv=k;
1541 Gh.nbe = nbe;
1542 Gh.vertices = new GeomVertex[k];
1543 Gh.edges = new GeomEdge[nbe];
1544 Gh.nbsubdomains = nbsubdomains;
1545 Gh.subdomains = new GeomSubDomain[nbsubdomains];
1546 if (verbose>3) _printf_(" number of vertices = " << Gh.nbv << "\n number of edges = " << Gh.nbe << "\n");
1547 NbVerticesOnGeomVertex = Gh.nbv;
1548 VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];
1549 NbVerticesOnGeomEdge =0;
1550 VerticesOnGeomEdge =0;
1551
1552 //Build VertexOnGeom
1553 for (i=0;i<nbv;i++){
1554 if((j=colorV[i])>=0){
1555 BamgVertex & v = Gh.vertices[j];
1556 v = vertices[i];
1557 v.color =0;
1558 VerticesOnGeomVertex[j] = VertexOnGeom(vertices[i], Gh.vertices[j]);
1559 }
1560 }
1561
1562 //Buid pmin and pmax of Gh (extrema coordinates)
1563 Gh.pmin = Gh.vertices[0].r;
1564 Gh.pmax = Gh.vertices[0].r;
1565 // recherche des extrema des vertices pmin,pmax
1566 for (i=0;i<Gh.nbv;i++) {
1567 Gh.pmin.x = Min(Gh.pmin.x,Gh.vertices[i].r.x);
1568 Gh.pmin.y = Min(Gh.pmin.y,Gh.vertices[i].r.y);
1569 Gh.pmax.x = Max(Gh.pmax.x,Gh.vertices[i].r.x);
1570 Gh.pmax.y = Max(Gh.pmax.y,Gh.vertices[i].r.y);
1571 }
1572 R2 DD05 = (Gh.pmax-Gh.pmin)*0.05;
1573 Gh.pmin -= DD05;
1574 Gh.pmax += DD05;
1575
1576 //Build Gh.coefIcoor
1577 int MaxICoord = 1073741823; //2^30 - 1 = =111...111 (29 times one)
1578 Gh.coefIcoor= (MaxICoord)/(Max(Gh.pmax.x-Gh.pmin.x,Gh.pmax.y-Gh.pmin.y));
1579 if (Gh.coefIcoor<=0){
1580 delete [] colorV;
1581 _error_("Gh.coefIcoor<=0 in infered Geometry (this should not happen)");
1582 }
1583
1584 /*Build Gh.edges*/
1585
1586 //initialize len as 0
1587 double * len = new double[Gh.nbv];
1588 for(i=0;i<Gh.nbv;i++) len[i]=0;
1589
1590 //initialize edge4 again
1591 edge4= new SetOfEdges4(nbe,nbv);
1592 double hmin = HUGE_VAL;
1593 int kreq=0;
1594 for (i=0;i<nbe;i++){
1595
1596 long i0 = GetId(edges[i][0]);
1597 long i1 = GetId(edges[i][1]);
1598 long j0 = colorV[i0];
1599 long j1 = colorV[i1];
1600
1601 Gh.edges[i].v[0] = Gh.vertices + j0;
1602 Gh.edges[i].v[1] = Gh.vertices + j1;
1603
1604 Gh.edges[i].type = 0;
1605
1606 Gh.edges[i].tg[0]=R2();
1607 Gh.edges[i].tg[1]=R2();
1608
1609 bool required= edges[i].GeomEdgeHook;
1610 if(required) kreq++;
1611 edges[i].GeomEdgeHook = Gh.edges + i;
1612 if(required){
1613 Gh.edges[i].v[0]->SetRequired();
1614 Gh.edges[i].v[1]->SetRequired();
1615 Gh.edges[i].SetRequired();
1616 }
1617
1618 R2 x12 = Gh.vertices[j0].r-Gh.vertices[j1].r;
1619 double l12=Norme2(x12);
1620 hmin = Min(hmin,l12);
1621
1622 Gh.vertices[j1].color++;
1623 Gh.vertices[j0].color++;
1624
1625 len[j0]+= l12;
1626 len[j1] += l12;
1627 hmin = Min(hmin,l12);
1628 Gh.edges[i].ReferenceNumber = edges[i].ReferenceNumber;
1629
1630 k = edge4->SortAndAdd(i0,i1);
1631 if (k != i){
1632 delete [] len;
1633 delete [] colorV;
1634 _error_("problem in Edge4 construction: k != i");
1635 }
1636 }
1637
1638 //Build metric for all vertices of Gh
1639 for (i=0;i<Gh.nbv;i++){
1640 if (Gh.vertices[i].color > 0)
1641 Gh.vertices[i].m= Metric(len[i] /(double) Gh.vertices[i].color);
1642 else
1643 Gh.vertices[i].m= Metric(hmin);
1644 }
1645 //delete len
1646 delete [] len;
1647
1648 //Build Gh.subdomains
1649 for (i=0;i<nbsubdomains;i++){
1650 it = GetId(subdomains[i].head);
1651 j = subdomains[i].direction;
1652 long i0 = GetId(triangles[it][VerticesOfTriangularEdge[j][0]]);
1653 long i1 = GetId(triangles[it][VerticesOfTriangularEdge[j][1]]);
1654 k = edge4->SortAndFind(i0,i1);
1655 _assert_(k>=0);
1656 subdomains[i].direction = (vertices + i0 == edges[k].v[0]) ? 1 : -1;
1657 subdomains[i].edge = edges+k;
1658 Gh.subdomains[i].edge = Gh.edges + k;
1659 Gh.subdomains[i].direction = subdomains[i].direction;
1660 Gh.subdomains[i].ReferenceNumber = subdomains[i].ReferenceNumber;
1661 }
1662
1663 delete edge4;
1664 delete [] colorV;
1665
1666 //unset adj
1667 for (i=0;i<nbt;i++){
1668 for (j=0;j<3;j++){
1669 triangles[i].SetAdj2(j,0,triangles[i].GetAllflag(j));
1670 }
1671 }
1672
1673 }
1674 /*}}}*/
1675 void Mesh::BuildMetric0(BamgOpts* bamgopts){/*{{{*/
1676
1677 /*Options*/
1678 double* s=NULL;
1679 long nbsol;
1680 int verbose;
1681
1682 int i,j,k,iA,iB,iC;
1683 int iv;
1684
1685 /*Recover options*/
1686 verbose=bamgopts->verbose;
1687
1688 /*Get and process fields*/
1689 s=bamgopts->field;
1690 nbsol=bamgopts->fieldSize[1];
1691
1692 /*Check size*/
1693 if (bamgopts->fieldSize[0] != nbv) _error_("'field' should have " << nbv << " rows");
1694
1695 //initialization of some variables
1696 double* ss=(double*)s;
1697 double sA,sB,sC;
1698 double* detT = new double[nbt];
1699 double* sumareas = new double[nbv];
1700 double* alpha= new double[nbt*3];
1701 double* beta = new double[nbt*3];
1702 double* dx_elem = new double[nbt];
1703 double* dy_elem = new double[nbt];
1704 double* dx_vertex = new double[nbv];
1705 double* dy_vertex = new double[nbv];
1706 double* dxdx_elem = new double[nbt];
1707 double* dxdy_elem = new double[nbt];
1708 double* dydy_elem = new double[nbt];
1709 double* dxdx_vertex= new double[nbv];
1710 double* dxdy_vertex= new double[nbv];
1711 double* dydy_vertex= new double[nbv];
1712
1713 //display infos
1714 if(verbose>1) {
1715 _printf_(" Construction of Metric: number of field: " << nbsol << " (nbt=" << nbt << ", nbv=" << nbv << ")\n");
1716 }
1717
1718 //first, build the chains that will be used for the Hessian computation, as weel as the area of each element
1719 int* head_s=NULL;
1720 head_s=xNew<int>(nbv);
1721 int* next_p=NULL;
1722 next_p=xNew<int>(3*nbt);
1723 int p=0;
1724 //initialization
1725 for(i=0;i<nbv;i++){
1726 sumareas[i]=0;
1727 head_s[i]=-1;
1728 }
1729 for(i=0;i<nbt;i++){
1730
1731 //lopp over the real triangles (no boundary elements)
1732 if(triangles[i].link){
1733
1734 //get current triangle t
1735 const Triangle &t=triangles[i];
1736
1737 // coor of 3 vertices
1738 R2 A=t[0];
1739 R2 B=t[1];
1740 R2 C=t[2];
1741
1742 //compute triangle determinant (2*Area)
1743 double dett = bamg::Area2(A,B,C);
1744 detT[i]=dett;
1745
1746 /*The nodal functions are such that for a vertex A:
1747 * N_A(x,y)=alphaA x + beta_A y +gamma_A
1748 * N_A(A) = 1, N_A(B) = 0, N_A(C) = 0
1749 * solving this system of equation (determinant = 2Area(T) != 0 if A,B and C are not inlined)
1750 * leads to:
1751 * N_A = (xB yC - xC yB + x(yB-yC) +y(xC-xB))/(2*Area(T))
1752 * and this gives:
1753 * alpha_A = (yB-yC)/(2*Area(T))*/
1754 alpha[i*3+0]=(B.y-C.y)/dett;
1755 alpha[i*3+1]=(C.y-A.y)/dett;
1756 alpha[i*3+2]=(A.y-B.y)/dett;
1757 beta[ i*3+0]=(C.x-B.x)/dett;
1758 beta[ i*3+1]=(A.x-C.x)/dett;
1759 beta[ i*3+2]=(B.x-A.x)/dett;
1760
1761 //compute chains
1762 for(j=0;j<3;j++){
1763 k=GetId(triangles[i][j]);
1764 next_p[p]=head_s[k];
1765 head_s[k]=p++;
1766
1767 //add area to sumareas
1768 sumareas[k]+=dett;
1769 }
1770
1771 }
1772 }
1773
1774 //for all Solutions
1775 for (int nusol=0;nusol<nbsol;nusol++) {
1776 double smin=ss[nusol],smax=ss[nusol];
1777
1778 //get min(s), max(s) and initialize Hessian (dxdx,dxdy,dydy)
1779 for ( iv=0,k=0; iv<nbv; iv++){
1780 smin=Min(smin,ss[iv*nbsol+nusol]);
1781 smax=Max(smax,ss[iv*nbsol+nusol]);
1782 }
1783 double sdelta=smax-smin;
1784 double absmax=Max(Abs(smin),Abs(smax));
1785
1786 //display info
1787 if(verbose>2) _printf_(" Solution " << nusol << ", Min = " << smin << ", Max = " << smax << ", Delta = " << sdelta << "\n");
1788
1789 //skip constant field
1790 if (sdelta < 1.0e-10*Max(absmax,1e-20)){
1791 _printf_(" Solution " << nusol << " is constant, skipping...\n");
1792 continue;
1793 }
1794
1795 //initialize the hessian and gradient matrices
1796 for ( iv=0,k=0; iv<nbv; iv++) dxdx_vertex[iv]=dxdy_vertex[iv]=dydy_vertex[iv]=dx_vertex[iv]=dy_vertex[iv]=0;
1797
1798 //1: Compute gradient for each element (exact)
1799 for (i=0;i<nbt;i++){
1800 if(triangles[i].link){
1801 // number of the 3 vertices
1802 iA = GetId(triangles[i][0]);
1803 iB = GetId(triangles[i][1]);
1804 iC = GetId(triangles[i][2]);
1805
1806 // value of the P1 fonction on 3 vertices
1807 sA = ss[iA*nbsol+nusol];
1808 sB = ss[iB*nbsol+nusol];
1809 sC = ss[iC*nbsol+nusol];
1810
1811 //gradient = (sum alpha_i s_i, sum_i beta_i s_i)
1812 dx_elem[i]=sA*alpha[3*i+0]+sB*alpha[3*i+1]+sC*alpha[3*i+2];
1813 dy_elem[i]=sA*beta[ 3*i+0]+sB*beta[ 3*i+1]+sC*beta[ 3*i+2];
1814 }
1815 }
1816
1817 //2: then compute a gradient for each vertex using a P2 projection
1818 for(i=0;i<nbv;i++){
1819 for(p=head_s[i];p!=-1;p=next_p[p]){
1820 //Get triangle number
1821 k=(long)(p/3);
1822 dx_vertex[i]+=dx_elem[k]*detT[k]/sumareas[i];
1823 dy_vertex[i]+=dy_elem[k]*detT[k]/sumareas[i];
1824 }
1825 }
1826
1827 //3: compute Hessian matrix on each element
1828 for (i=0;i<nbt;i++){
1829 if(triangles[i].link){
1830 // number of the 3 vertices
1831 iA = GetId(triangles[i][0]);
1832 iB = GetId(triangles[i][1]);
1833 iC = GetId(triangles[i][2]);
1834
1835 //Hessian
1836 dxdx_elem[i]=dx_vertex[iA]*alpha[3*i+0]+dx_vertex[iB]*alpha[3*i+1]+dx_vertex[iC]*alpha[3*i+2];
1837 dxdy_elem[i]=dy_vertex[iA]*alpha[3*i+0]+dy_vertex[iB]*alpha[3*i+1]+dy_vertex[iC]*alpha[3*i+2];
1838 dydy_elem[i]=dy_vertex[iA]*beta[3*i+0]+dy_vertex[iB]*beta[3*i+1]+dy_vertex[iC]*beta[3*i+2];
1839 }
1840 }
1841
1842 //4: finaly compute Hessian on each vertex using the second P2 projection
1843 for(i=0;i<nbv;i++){
1844 for(p=head_s[i];p!=-1;p=next_p[p]){
1845 //Get triangle number
1846 k=(long)(p/3);
1847 dxdx_vertex[i]+=dxdx_elem[k]*detT[k]/sumareas[i];
1848 dxdy_vertex[i]+=dxdy_elem[k]*detT[k]/sumareas[i];
1849 dydy_vertex[i]+=dydy_elem[k]*detT[k]/sumareas[i];
1850 }
1851 }
1852
1853 /*Compute Metric from Hessian*/
1854 for ( iv=0;iv<nbv;iv++){
1855 vertices[iv].MetricFromHessian(dxdx_vertex[iv],dxdy_vertex[iv],dydy_vertex[iv],smin,smax,ss[iv*nbsol+nusol],bamgopts->err[nusol],bamgopts);
1856 }
1857
1858 }//for all solutions
1859
1860 //clean up
1861 xDelete<int>(head_s);
1862 xDelete<int>(next_p);
1863 delete [] detT;
1864 delete [] alpha;
1865 delete [] beta;
1866 delete [] sumareas;
1867 delete [] dx_elem;
1868 delete [] dy_elem;
1869 delete [] dx_vertex;
1870 delete [] dy_vertex;
1871 delete [] dxdx_elem;
1872 delete [] dxdy_elem;
1873 delete [] dydy_elem;
1874 delete [] dxdx_vertex;
1875 delete [] dxdy_vertex;
1876 delete [] dydy_vertex;
1877 }
1878 /*}}}*/
1879 void Mesh::BuildMetric1(BamgOpts* bamgopts){/*{{{*/
1880 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/IntersectConsMetric)*/
1881
1882 /*Options*/
1883 double* s=NULL;
1884 long nbsol;
1885 int NbJacobi;
1886 int verbose;
1887
1888 /*Recover options*/
1889 verbose=bamgopts->verbose;
1890 NbJacobi=bamgopts->nbjacobi;
1891
1892 /*Get and process fields*/
1893 s=bamgopts->field;
1894 nbsol=bamgopts->fieldSize[1];
1895
1896 /*Check size*/
1897 if (bamgopts->fieldSize[0] != nbv) _error_("'field' should have " << nbv << " rows");
1898
1899 //initialization of some variables
1900 long i,k,iA,iB,iC,iv;
1901 R2 O(0,0);
1902 double* ss=(double*)s;
1903 double sA,sB,sC;
1904 double* detT = new double[nbt];
1905 double* Mmass= new double[nbv];
1906 double* Mmassxx= new double[nbv];
1907 double* dxdx= new double[nbv];
1908 double* dxdy= new double[nbv];
1909 double* dydy= new double[nbv];
1910 double* workT= new double[nbt];
1911 double* workV= new double[nbv];
1912 int* OnBoundary = new int[nbv];
1913
1914 //display infos
1915 if(verbose>1) {
1916 _printf_(" Construction of Metric: number of field: " << nbsol << " (nbt=" << nbt << ", nbv=" << nbv << ")\n");
1917 }
1918
1919 //initialize Mmass, OnBoundary and Massxx by zero
1920 for (iv=0;iv<nbv;iv++){
1921 Mmass[iv]=0;
1922 OnBoundary[iv]=0;
1923 Mmassxx[iv]=0;
1924 }
1925
1926 //Build detT Mmas Mmassxx workT and OnBoundary
1927 for (i=0;i<nbt;i++){
1928
1929 //lopp over the real triangles (no boundary elements)
1930 if(triangles[i].link){
1931
1932 //get current triangle t
1933 const Triangle &t=triangles[i];
1934
1935 // coor of 3 vertices
1936 R2 A=t[0];
1937 R2 B=t[1];
1938 R2 C=t[2];
1939
1940 // number of the 3 vertices
1941 iA = GetId(t[0]);
1942 iB = GetId(t[1]);
1943 iC = GetId(t[2]);
1944
1945 //compute triangle determinant (2*Area)
1946 double dett = bamg::Area2(A,B,C);
1947 detT[i]=dett;
1948 dett /= 6;
1949
1950 // construction of OnBoundary (flag=1 if on boundary, else 0)
1951 int nbb=0;
1952 for(int j=0;j<3;j++){
1953 //get adjacent triangle
1954 Triangle *ta=t.Adj(j);
1955 //if there is no adjacent triangle, the edge of the triangle t is on boundary
1956 if ( !ta || !ta->link){
1957 //mark the two vertices of the edge as OnBoundary
1958 OnBoundary[GetId(t[VerticesOfTriangularEdge[j][0]])]=1;
1959 OnBoundary[GetId(t[VerticesOfTriangularEdge[j][1]])]=1;
1960 nbb++;
1961 }
1962 }
1963
1964 //number of vertices on boundary for current triangle t
1965 workT[i] = nbb;
1966
1967 //Build Mmass Mmass[i] = Mmass[i] + Area/3
1968 Mmass[iA] += dett;
1969 Mmass[iB] += dett;
1970 Mmass[iC] += dett;
1971
1972 //Build Massxx = Mmass
1973 Mmassxx[iA] += dett;
1974 Mmassxx[iB] += dett;
1975 Mmassxx[iC] += dett;
1976 }
1977
1978 //else: the triangle is a boundary triangle -> workT=-1
1979 else workT[i]=-1;
1980 }
1981
1982 //for all Solution
1983 for (int nusol=0;nusol<nbsol;nusol++) {
1984
1985 double smin=ss[nusol],smax=ss[nusol];
1986 double h1=1.e30,h2=1e-30,rx=0;
1987 double hn1=1.e30,hn2=1e-30,rnx =1.e-30;
1988
1989 //get min(s), max(s) and initialize Hessian (dxdx,dxdy,dydy)
1990 for ( iv=0,k=0; iv<nbv; iv++ ){
1991 dxdx[iv]=dxdy[iv]=dydy[iv]=0;
1992 smin=Min(smin,ss[iv*nbsol+nusol]);
1993 smax=Max(smax,ss[iv*nbsol+nusol]);
1994 }
1995 double sdelta=smax-smin;
1996 double absmax=Max(Abs(smin),Abs(smax));
1997
1998 //display info
1999 if(verbose>2) _printf_(" Solution " << nusol << ", Min = " << smin << ", Max = " << smax << ", Delta = " << sdelta << ", number of fields = " << nbsol << "\n");
2000
2001 //skip constant field
2002 if (sdelta < 1.0e-10*Max(absmax,1e-20) ){
2003 if (verbose>2) _printf_(" Solution " << nusol << " is constant, skipping...\n");
2004 continue;
2005 }
2006
2007 //pointer toward ss that is also a pointer toward s (solutions)
2008 double* sf=ss;
2009
2010 //initialize the hessian matrix
2011 for ( iv=0,k=0; iv<nbv; iv++) dxdx[iv]=dxdy[iv]=dydy[iv]=0;
2012
2013 //loop over the triangles
2014 for (i=0;i<nbt;i++){
2015
2016 //for real all triangles
2017 if(triangles[i].link){
2018
2019 // coor of 3 vertices
2020 R2 A=triangles[i][0];
2021 R2 B=triangles[i][1];
2022 R2 C=triangles[i][2];
2023
2024 //warning: the normal is internal and the size is the length of the edge
2025 R2 nAB = Orthogonal(B-A);
2026 R2 nBC = Orthogonal(C-B);
2027 R2 nCA = Orthogonal(A-C);
2028 //note that : nAB + nBC + nCA == 0
2029
2030 // number of the 3 vertices
2031 iA = GetId(triangles[i][0]);
2032 iB = GetId(triangles[i][1]);
2033 iC = GetId(triangles[i][2]);
2034
2035 // for the test of boundary edge
2036 // the 3 adj triangles
2037 Triangle *tBC = triangles[i].TriangleAdj(OppositeEdge[0]);
2038 Triangle *tCA = triangles[i].TriangleAdj(OppositeEdge[1]);
2039 Triangle *tAB = triangles[i].TriangleAdj(OppositeEdge[2]);
2040
2041 // value of the P1 fonction on 3 vertices
2042 sA = ss[iA*nbsol+nusol];
2043 sB = ss[iB*nbsol+nusol];
2044 sC = ss[iC*nbsol+nusol];
2045
2046 /*The nodal functions are such that for a vertex A:
2047 N_A(x,y)=alphaA x + beta_A y +gamma_A
2048 N_A(A) = 1, N_A(B) = 0, N_A(C) = 0
2049 solving this system of equation (determinant = 2Area(T) != 0 if A,B and C are not inlined)
2050 leads to:
2051 N_A = (xB yC - xC yB + x(yB-yC) +y(xC-xB))/(2*Area(T))
2052 and this gives:
2053 alpha_A = (yB-yC)/(2*Area(T))
2054 beta_A = (xC-xB)/(2*Area(T))
2055 and therefore:
2056 grad N_A = nA / detT
2057 for an interpolation of a solution s:
2058 grad(s) = s * sum_{i=A,B,C} grad(N_i) */
2059
2060 R2 Grads=(nAB*sC+nBC*sA+nCA*sB)/detT[i];
2061
2062 //Use Green to compute Hessian Matrix
2063
2064 // if edge on boundary no contribution => normal = 0
2065 if ( !tBC || !tBC->link ) nBC=O;
2066 if ( !tCA || !tCA->link ) nCA=O;
2067 if ( !tAB || !tAB->link ) nAB=O;
2068
2069 // remark we forgot a 1/2 because
2070 // int_{edge} w_i = 1/2 if i is in edge
2071 // 0 if not
2072 // if we don't take the boundary
2073 dxdx[iA] += ( nCA.x + nAB.x ) *Grads.x;
2074 dxdx[iB] += ( nAB.x + nBC.x ) *Grads.x;
2075 dxdx[iC] += ( nBC.x + nCA.x ) *Grads.x;
2076
2077 //warning optimization (1) the division by 2 is done on the metric construction
2078 dxdy[iA] += (( nCA.y + nAB.y ) *Grads.x + ( nCA.x + nAB.x ) *Grads.y) ;
2079 dxdy[iB] += (( nAB.y + nBC.y ) *Grads.x + ( nAB.x + nBC.x ) *Grads.y) ;
2080 dxdy[iC] += (( nBC.y + nCA.y ) *Grads.x + ( nBC.x + nCA.x ) *Grads.y) ;
2081
2082 dydy[iA] += ( nCA.y + nAB.y ) *Grads.y;
2083 dydy[iB] += ( nAB.y + nBC.y ) *Grads.y;
2084 dydy[iC] += ( nBC.y + nCA.y ) *Grads.y;
2085
2086 } // for real all triangles
2087 }
2088
2089 long kk=0;
2090 for ( iv=0,k=0 ; iv<nbv; iv++){
2091 if(Mmassxx[iv]>0){
2092 dxdx[iv] /= 2*Mmassxx[iv];
2093 // warning optimization (1) on term dxdy[iv]*ci/2
2094 dxdy[iv] /= 4*Mmassxx[iv];
2095 dydy[iv] /= 2*Mmassxx[iv];
2096 // Compute the matrix with abs(eigen value)
2097 Metric M(dxdx[iv], dxdy[iv], dydy[iv]);
2098 EigenMetric Vp(M);
2099 Vp.Abs();
2100 M = Vp;
2101 dxdx[iv] = M.a11;
2102 dxdy[iv] = M.a21;
2103 dydy[iv] = M.a22;
2104 }
2105 else kk++;
2106 }
2107
2108 // correction of second derivative
2109 // by a laplacien
2110 double* dd;
2111 for (int xy = 0;xy<3;xy++) {
2112 if (xy==0) dd=dxdx;
2113 else if (xy==1) dd=dxdy;
2114 else if (xy==2) dd=dydy;
2115 else _error_("not supported yet");
2116 // do leat 2 iteration for boundary problem
2117 for (int ijacobi=0;ijacobi<Max(NbJacobi,2);ijacobi++){
2118 for (i=0;i<nbt;i++)
2119 if(triangles[i].link){// the real triangles
2120 // number of the 3 vertices
2121 iA = GetId(triangles[i][0]);
2122 iB = GetId(triangles[i][1]);
2123 iC = GetId(triangles[i][2]);
2124 double cc=3;
2125 if(ijacobi==0)
2126 cc = Max((double) ((Mmassxx[iA]>0)+(Mmassxx[iB]>0)+(Mmassxx[iC]>0)),1.);
2127 workT[i] = (dd[iA]+dd[iB]+dd[iC])/cc;
2128 }
2129 for (iv=0;iv<nbv;iv++) workV[iv]=0;
2130
2131 for (i=0;i<nbt;i++){
2132 if(triangles[i].link){ // the real triangles
2133 // number of the 3 vertices
2134 iA = GetId(triangles[i][0]);
2135 iB = GetId(triangles[i][1]);
2136 iC = GetId(triangles[i][2]);
2137 double cc = workT[i]*detT[i];
2138 workV[iA] += cc;
2139 workV[iB] += cc;
2140 workV[iC] += cc;
2141 }
2142 }
2143
2144 for (iv=0;iv<nbv;iv++){
2145 if( ijacobi<NbJacobi || OnBoundary[iv]){
2146 dd[iv] = workV[iv]/(Mmass[iv]*6);
2147 }
2148 }
2149 }
2150 }
2151
2152 /*Compute Metric from Hessian*/
2153 for ( iv=0;iv<nbv;iv++){
2154 vertices[iv].MetricFromHessian(dxdx[iv],dxdy[iv],dydy[iv],smin,smax,ss[iv*nbsol+nusol],bamgopts->err[nusol],bamgopts);
2155 }
2156
2157 }// end for all solution
2158
2159 delete [] detT;
2160 delete [] Mmass;
2161 delete [] dxdx;
2162 delete [] dxdy;
2163 delete [] dydy;
2164 delete [] workT;
2165 delete [] workV;
2166 delete [] Mmassxx;
2167 delete [] OnBoundary;
2168
2169 }
2170 /*}}}*/
2171 void Mesh::CrackMesh(BamgOpts* bamgopts) {/*{{{*/
2172 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/CrackMesh)*/
2173
2174 /*Intermediary*/
2175 int i,j,k,num,count;
2176 int i1,i2;
2177 int j1,j2;
2178
2179 /*Options*/
2180 int verbose=bamgopts->verbose;
2181
2182 // computed the number of cracked edge
2183 for (k=i=0;i<nbe;i++){
2184 if(edges[i].GeomEdgeHook->Cracked()) k++;
2185 }
2186
2187 //Return if no edge is cracked
2188 if(k==0) return;
2189 if (verbose>4) _printf_(" number of Cracked Edges = " << k << "\n");
2190
2191 //Initialize Cracked edge
2192 NbCrackedEdges=k;
2193 CrackedEdges=new CrackedEdge[k];
2194
2195 //Compute number of Cracked Vertices
2196 k=0;
2197 NbCrackedVertices=0;
2198
2199 int* splitvertex=new int[nbv];
2200 for (i=0;i<nbv;i++) splitvertex[i]=0;
2201
2202 for (i=0;i<nbe;i++){
2203 if(edges[i].GeomEdgeHook->Cracked()){
2204
2205 //Fill edges fields of CrackedEdges
2206 CrackedEdges[k ].E =edges[i].GeomEdgeHook;
2207 CrackedEdges[k++].e1=&edges[i];
2208
2209 //Get number of the two vertices on the edge
2210 i1=GetId(edges[i][0]);
2211 i2=GetId(edges[i][1]);
2212 _assert_(i1>=0 && i1<nbv && i2>=0 && i2<nbv);
2213 splitvertex[i1]++;
2214 splitvertex[i2]++;
2215
2216 //If the vertex has already been flagged once, it is a cracked vertex (tip otherwise)
2217 if (splitvertex[i1]==2) NbCrackedVertices++;
2218 if (splitvertex[i2]==2) NbCrackedVertices++;
2219
2220 //The vertex cannot be marked more than twice
2221 if (splitvertex[i1]==3 || splitvertex[i2]==3){
2222 delete [] splitvertex;
2223 _error_("Crossing rifts not supported yet");
2224 }
2225 }
2226 }
2227 _assert_(k==NbCrackedEdges);
2228
2229 //Add new vertices
2230 if (verbose>4) _printf_(" number of Cracked Vertices = " << NbCrackedVertices << "\n");
2231 if (NbCrackedVertices){
2232 CrackedVertices=xNew<long>(2*NbCrackedVertices);
2233 num=0;
2234 for (i=0;i<nbv;i++){
2235 if (splitvertex[i]==2){
2236 CrackedVertices[num*2+0]=i; //index of first vertex
2237 CrackedVertices[num*2+1]=nbv+num;//index of new vertex
2238 num++;
2239 }
2240 }
2241 _assert_(num==NbCrackedVertices);
2242 }
2243 delete [] splitvertex;
2244
2245 //Now, find the triangles that hold a cracked edge
2246 CreateSingleVertexToTriangleConnectivity();
2247
2248 long* Edgeflags=new long[NbCrackedEdges];
2249 for(i=0;i<NbCrackedEdges;i++) Edgeflags[i]=0;
2250
2251 for(i=0;i<NbCrackedEdges;i++){
2252 //Get the numbers of the 2 vertices of the crren cracked edge
2253 i1=GetId((*CrackedEdges[i].e1)[0]);
2254 i2=GetId((*CrackedEdges[i].e1)[1]);
2255
2256 //find a triangle holding the vertex i1 (first vertex of the ith cracked edge)
2257 Triangle* tbegin=vertices[i1].t;
2258 k=vertices[i1].IndexInTriangle;//local number of i in triangle tbegin
2259 _assert_(GetId((*tbegin)[k])==GetId(vertices[i1]));
2260
2261 //Now, we are going to go through the adjacent triangle that hold i1 till
2262 //we find one that has the cracked edge
2263 AdjacentTriangle ta(tbegin,EdgesVertexTriangle[k][0]);
2264 count=0;
2265 do {
2266 for(j=0;j<3;j++){
2267 //Find the position of i1 in the triangle index
2268 if (GetId((*ta.t)[j])==i1){
2269 j1=j;
2270 break;
2271 }
2272 }
2273 for(j=0;j<3;j++){
2274 //Check wether i2 is also in the triangle index
2275 if (GetId((*ta.t)[j])==i2){
2276 j2=j;
2277 //Invert j1 and j2 if necessary
2278 if ((j1+1)%3==j2){
2279 int j3=j1;
2280 j1=j2;
2281 j2=j3;
2282 }
2283 if (Edgeflags[i]==0){
2284 //first element
2285 CrackedEdges[i].a=ta.t;
2286 CrackedEdges[i].length=Norme2((*ta.t)[j1].r-(*ta.t)[j2].r);
2287 CrackedEdges[i].normal=Orthogonal((*ta.t)[j1].r-(*ta.t)[j2].r);
2288 }
2289 else{
2290 //Second element -> to renumber
2291 CrackedEdges[i].b=ta.t;
2292 CrackedEdges[i].length=Norme2((*ta.t)[j1].r-(*ta.t)[j2].r);
2293 CrackedEdges[i].normal=Orthogonal((*ta.t)[j1].r-(*ta.t)[j2].r);
2294 }
2295 Edgeflags[i]++;
2296 break;
2297 }
2298 }
2299 //_printf_(element_renu[GetId(ta.t)] << " -> " << GetId((*ta.t)[0])+1 << " " << GetId((*ta.t)[1])+1 << " " << GetId((*ta.t)[2])+1 << ", edge [" << i1 << "->" << j1 << " " << i2 << "->" << j2 << "]\n");
2300 ta = Next(ta).Adj();
2301 if (count++>50) _error_("Maximum number of iteration exceeded");
2302 }while ((tbegin != ta));
2303 }
2304
2305 //Check EdgeFlag
2306 for(i=0;i<NbCrackedEdges;i++){
2307 if (Edgeflags[i]!=2){
2308 _error_("A problem occured: at least one crack edge (number " << i+1 << ") does not belong to 2 elements");
2309 }
2310 }
2311 delete [] Edgeflags;
2312
2313 //Reset BamgVertex to On
2314 SetVertexFieldOn();
2315
2316 }
2317 /*}}}*/
2318 void Mesh::Echo(void) {/*{{{*/
2319
2320 int i;
2321
2322 _printf_("Mesh Echo:\n");
2323 _printf_(" nbv = " << nbv << "\n");
2324 _printf_(" nbt = " << nbt << "\n");
2325 _printf_(" nbe = " << nbe << "\n");
2326 _printf_(" index:\n");
2327 for (i=0;i<nbt;i++){
2328 _printf_(" " << setw(4) << i+1 << ": ["
2329 << setw(4) << (((BamgVertex*)triangles[i](0))?GetId(triangles[i][0])+1:0) << " "
2330 << setw(4) << (((BamgVertex*)triangles[i](1))?GetId(triangles[i][1])+1:0) << " "
2331 << setw(4) << (((BamgVertex*)triangles[i](2))?GetId(triangles[i][2])+1:0) << "]\n");
2332 }
2333 _printf_(" coordinates:\n");
2334 for (i=0;i<nbv;i++){
2335 _printf_(" " << setw(4) << i+1 << ": [" << vertices[i].r.x << " " << vertices[i].r.y << "] and [" << vertices[i].i.x << " " << vertices[i].i.y << "]\n");
2336 }
2337
2338 }
2339 /*}}}*/
2340 void Mesh::ForceBoundary() {/*{{{*/
2341 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/ForceBoundary)*/
2342
2343 long int verbose=2;
2344 int k=0;
2345 int nbfe=0,nbswp=0,Nbswap=0;
2346
2347 //display
2348 if (verbose > 2) _printf_(" ForceBoundary nb of edge: " << nbe << "\n");
2349
2350 //check that there is no triangle with 0 determinant
2351 for (int t = 0; t < nbt; t++){
2352 if (!triangles[t].det) k++;
2353 }
2354 if (k!=0) {
2355 _error_("there is " << k << " triangles of mes = 0");
2356 }
2357
2358 //Force Edges
2359 AdjacentTriangle ta(0,0);
2360 for (int i = 0; i < nbe; i++){
2361
2362 //Force edge i
2363 nbswp = ForceEdge(edges[i][0],edges[i][1],ta);
2364 if (nbswp<0) k++;
2365 else Nbswap += nbswp;
2366
2367 if (nbswp) nbfe++;
2368 if ( nbswp < 0 && k < 5){
2369 _error_("Missing Edge " << i << ", v0=" << GetId(edges[i][0]) << ",v1=" << GetId(edges[i][1]));
2370 }
2371 }
2372
2373 if (k!=0) {
2374 _error_("There are " << k << " lost edges, the boundary might be crossing");
2375 }
2376 for (int j=0;j<nbv;j++){
2377 Nbswap += vertices[j].Optim(1,0);
2378 }
2379 if (verbose > 3) _printf_(" number of inforced edge = " << nbfe << ", number of swap= " << Nbswap << "\n");
2380 }
2381 /*}}}*/
2382 void Mesh::FindSubDomain(int OutSide) {/*{{{*/
2383 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/FindSubDomain)*/
2384
2385 long int verbose=0;
2386
2387 if (verbose >2){
2388 if (OutSide) _printf_(" Find all external sub-domain\n");
2389 else _printf_(" Find all internal sub-domain\n");
2390 }
2391 short * HeapArete = new short[nbt];
2392 Triangle ** HeapTriangle = new Triangle* [nbt];
2393 Triangle *t,*t1;
2394 long k,it;
2395
2396 for (int itt=0;itt<nbt;itt++)
2397 triangles[itt].link=0; // par defaut pas de couleur
2398
2399 long NbSubDomTot =0;
2400 for ( it=0;it<nbt;it++) {
2401 if ( ! triangles[it].link ) {
2402 t = triangles + it;
2403 NbSubDomTot++;; // new composante connexe
2404 long i = 0; // niveau de la pile
2405 t->link = t ; // sd forme d'un triangle cicular link
2406
2407 HeapTriangle[i] =t ;
2408 HeapArete[i] = 3;
2409
2410 while (i >= 0) // boucle sur la pile
2411 { while ( HeapArete[i]--) // boucle sur les 3 aretes
2412 {
2413 int na = HeapArete[i];
2414 Triangle * tc = HeapTriangle[i]; // triangle courant
2415 if( ! tc->Locked(na)) // arete non frontiere
2416 {
2417 Triangle * ta = tc->TriangleAdj(na) ; // næ triangle adjacent
2418 if (ta->link == 0 ) // non deja chainer => on enpile
2419 {
2420 i++;
2421 ta->link = t->link ; // on chaine les triangles
2422 t->link = ta ; // d'un meme sous domaine
2423 HeapArete[i] = 3; // pour les 3 triangles adjacents
2424 HeapTriangle[i] = ta;
2425 }}
2426 } // deplie fin de boucle sur les 3 adjacences
2427 i--;
2428 }
2429 }
2430 }
2431
2432 // supression de tous les sous domaine infini <=> contient le sommet NULL
2433 it =0;
2434 nbtout = 0;
2435 while (it<nbt) {
2436 if (triangles[it].link)
2437 {
2438 if (!( triangles[it](0) && triangles[it](1) && triangles[it](2) ))
2439 {
2440 // infini triangle
2441 NbSubDomTot --;
2442 t=&triangles[it];
2443 nbtout--; // on fait un coup de trop.
2444 while (t){
2445 nbtout++;
2446 t1=t;
2447 t=t->link;
2448 t1->link=0;
2449 }
2450 }
2451 }
2452 it++;} // end while (it<nbt)
2453 if (nbt == nbtout || !NbSubDomTot) {
2454 delete [] HeapArete;
2455 _error_("The boundary is not close: all triangles are outside");
2456 }
2457
2458 delete [] HeapArete;
2459 delete [] HeapTriangle;
2460
2461 if (OutSide|| !Gh.subdomains || !Gh.nbsubdomains )
2462 { // No geom sub domain
2463 long i;
2464 if (subdomains) delete [] subdomains;
2465 subdomains = new SubDomain[ NbSubDomTot];
2466 nbsubdomains= NbSubDomTot;
2467 for ( i=0;i<nbsubdomains;i++) {
2468 subdomains[i].head=NULL;
2469 subdomains[i].ReferenceNumber=i+1;
2470 }
2471 long * mark = new long[nbt];
2472 for (it=0;it<nbt;it++)
2473 mark[it]=triangles[it].link ? -1 : -2;
2474
2475 it =0;
2476 k = 0;
2477 while (it<nbt) {
2478 if (mark[it] == -1) {
2479 t1 = & triangles[it];
2480 t = t1->link;
2481 mark[it]=k;
2482 subdomains[k].head = t1;
2483 do {
2484 mark[GetId(t)]=k;
2485 t=t->link;
2486 } while (t!=t1);
2487 mark[it]=k++;}
2488 // else if(mark[it] == -2 ) triangles[it].Draw(999);
2489 it++;} // end white (it<nbt)
2490 if (k!=nbsubdomains){
2491 delete [] mark;
2492 _error_("k!=nbsubdomains");
2493 }
2494 if(OutSide)
2495 {
2496 // to remove all the sub domain by parity adjacents
2497 // because in this case we have only the true boundary edge
2498 // so teh boundary is manifold
2499 long nbk = nbsubdomains;
2500 while (nbk)
2501 for (it=0;it<nbt && nbk ;it++)
2502 for (int na=0;na<3 && nbk ;na++)
2503 {
2504 Triangle *ta = triangles[it].TriangleAdj(na);
2505 long kl = ta ? mark[GetId(ta)] : -2;
2506 long kr = mark[it];
2507 if(kr !=kl) {
2508 if (kl >=0 && subdomains[kl].ReferenceNumber <0 && kr >=0 && subdomains[kr].ReferenceNumber>=0)
2509 nbk--,subdomains[kr].ReferenceNumber=subdomains[kl].ReferenceNumber-1;
2510 if (kr >=0 && subdomains[kr].ReferenceNumber <0 && kl >=0 && subdomains[kl].ReferenceNumber>=0)
2511 nbk--,subdomains[kl].ReferenceNumber=subdomains[kr].ReferenceNumber-1;
2512 if(kr<0 && kl >=0 && subdomains[kl].ReferenceNumber>=0)
2513 nbk--,subdomains[kl].ReferenceNumber=-1;
2514 if(kl<0 && kr >=0 && subdomains[kr].ReferenceNumber>=0)
2515 nbk--,subdomains[kr].ReferenceNumber=-1;
2516 }
2517 }
2518 long j=0;
2519 for ( i=0;i<nbsubdomains;i++)
2520 if((-subdomains[i].ReferenceNumber) %2) { // good
2521 if(i != j)
2522 Exchange(subdomains[i],subdomains[j]);
2523 j++;}
2524 else{
2525 t= subdomains[i].head;
2526 while (t){
2527 nbtout++;
2528 t1=t;
2529 t=t->link;
2530 t1->link=0;
2531 }//while (t)
2532 }
2533 if(verbose>4) _printf_(" Number of removes subdomains (OutSideMesh) = " << nbsubdomains-j << "\n");
2534 nbsubdomains=j;
2535 }
2536
2537 delete [] mark;
2538
2539 }
2540 else{ // find the head for all subdomains
2541 if (Gh.nbsubdomains != nbsubdomains && subdomains)
2542 delete [] subdomains, subdomains=0;
2543 if (! subdomains )
2544 subdomains = new SubDomain[ Gh.nbsubdomains];
2545 nbsubdomains =Gh.nbsubdomains;
2546 CreateSingleVertexToTriangleConnectivity();
2547 long * mark = new long[nbt];
2548 Edge **GeomEdgetoEdge = MakeGeomEdgeToEdge();
2549
2550 for (it=0;it<nbt;it++)
2551 mark[it]=triangles[it].link ? -1 : -2;
2552 long inew =0;
2553 for (int i=0;i<nbsubdomains;i++) {
2554 GeomEdge &eg = *Gh.subdomains[i].edge;
2555 subdomains[i].ReferenceNumber = Gh.subdomains[i].ReferenceNumber;
2556 // by carefull is not easy to find a edge create from a GeomEdge
2557 // see routine MakeGeomEdgeToEdge
2558 Edge &e = *GeomEdgetoEdge[Gh.GetId(eg)];
2559 _assert_(&e);
2560 BamgVertex * v0 = e(0),*v1 = e(1);
2561 Triangle *t = v0->t;
2562 int direction = Gh.subdomains[i].direction;
2563 // test if ge and e is in the same direction
2564 if (((eg[0].r-eg[1].r),(e[0].r-e[1].r))<0) direction = -direction ;
2565 subdomains[i].direction = direction;
2566 subdomains[i].edge = &e;
2567 _assert_(t && direction);
2568
2569 AdjacentTriangle ta(t,EdgesVertexTriangle[v0->IndexInTriangle][0]);// previous edges
2570
2571 while (1) {
2572 _assert_(v0==ta.EdgeVertex(1));
2573 if (ta.EdgeVertex(0) == v1) { // ok we find the edge
2574 if (direction>0)
2575 subdomains[i].head=t=Adj(ta);
2576 else
2577 subdomains[i].head=t=ta;
2578 if(t<triangles || t >= triangles+nbt || t->det < 0 || t->link == 0) {
2579 _error_("bad definition of SubSomain " << i);
2580 }
2581 long it = GetId(t);
2582 if (mark[it] >=0) {
2583 break;
2584 }
2585 if(i != inew)
2586 Exchange(subdomains[i],subdomains[inew]);
2587 inew++;
2588 Triangle *tt=t;
2589 long kkk=0;
2590 do
2591 {
2592 kkk++;
2593 if (mark[GetId(tt)]>=0){
2594 _error_("mark[GetId(tt)]>=0");
2595 }
2596 mark[GetId(tt)]=i;
2597 tt=tt->link;
2598 } while (tt!=t);
2599 break;
2600 }
2601 ta = Previous(Adj(ta));
2602 if(t == (Triangle *) ta) {
2603 _error_("bad definition of SubSomain " << i);
2604 }
2605 }
2606 }
2607
2608 if (inew < nbsubdomains) {
2609 if (verbose>5) _printf_("WARNING: " << nbsubdomains-inew << " SubDomains are being removed\n");
2610 nbsubdomains=inew;}
2611
2612 for (it=0;it<nbt;it++)
2613 if ( mark[it] ==-1 )
2614 nbtout++,triangles[it].link =0;
2615 delete [] GeomEdgetoEdge;
2616 delete [] mark;
2617
2618 }
2619 nbtout=0;
2620 for (it=0;it<nbt;it++)
2621 if(!triangles[it].link) nbtout++;
2622 }
2623 /*}}}*/
2624 long Mesh::GetId(const Triangle & t) const { /*{{{*/
2625 return &t - triangles;
2626 }
2627 /*}}}*/
2628 long Mesh::GetId(const Triangle * t) const { /*{{{*/
2629 return t - triangles;
2630 }
2631 /*}}}*/
2632 long Mesh::GetId(const BamgVertex & t) const { /*{{{*/
2633 return &t - vertices;
2634 }
2635 /*}}}*/
2636 long Mesh::GetId(const BamgVertex * t) const { /*{{{*/
2637 return t - vertices;
2638 }
2639 /*}}}*/
2640 long Mesh::GetId(const Edge & t) const { /*{{{*/
2641 return &t - edges;
2642 }
2643 /*}}}*/
2644 long Mesh::GetId(const Edge * t) const { /*{{{*/
2645 return t - edges;
2646 }
2647 /*}}}*/
2648 void Mesh::Init(long maxnbv_in) {/*{{{*/
2649 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/PreInit)*/
2650
2651 /* initialize random seed: */
2652 srand(19999999);
2653
2654 /*Initialize fields*/
2655 NbRef=0;
2656 quadtree=NULL;
2657 nbv=0;
2658 nbt=0;
2659 nbe=0;
2660 edges=NULL;
2661 nbsubdomains=0;
2662 subdomains=NULL;
2663 maxnbv=maxnbv_in;
2664 maxnbt=2 *maxnbv_in-2;
2665 NbVertexOnBThVertex=0;
2666 VertexOnBThVertex=NULL;
2667 NbVertexOnBThEdge=0;
2668 VertexOnBThEdge=NULL;
2669 NbCrackedVertices=0;
2670 CrackedVertices =NULL;
2671 NbCrackedEdges =0;
2672 CrackedEdges =NULL;
2673 NbVerticesOnGeomVertex=0;
2674 VerticesOnGeomVertex=NULL;
2675 NbVerticesOnGeomEdge=0;
2676 VerticesOnGeomEdge=NULL;
2677
2678 /*Allocate if maxnbv_in>0*/
2679 if(maxnbv_in){
2680 vertices=new BamgVertex[maxnbv];
2681 _assert_(vertices);
2682 orderedvertices=new BamgVertex* [maxnbv];
2683 _assert_(orderedvertices);
2684 triangles=new Triangle[maxnbt];
2685 _assert_(triangles);
2686 }
2687 else{
2688 vertices=NULL;
2689 orderedvertices=NULL;
2690 triangles=NULL;
2691 maxnbt=0;
2692 }
2693 }
2694 /*}}}*/
2695 void Mesh::Insert(bool random) {/*{{{*/
2696 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Insert)*/
2697
2698 /*Insert points in the existing Geometry*/
2699
2700 //Intermediary
2701 int i;
2702
2703 /*Get options*/
2704 long int verbose=2;
2705
2706 //Display info
2707 if (verbose>2) _printf_(" Insert initial " << nbv << " vertices\n");
2708
2709 //Compute integer coordinates for the existing vertices
2710 SetIntCoor();
2711
2712 /*Now we want to build a list (orderedvertices) of the vertices in a random
2713 * order. To do so, we use the following method:
2714 *
2715 * From an initial k0 in [0 nbv[ random (vertex number)
2716 * the next k (vertex number) is computed using a big
2717 * prime number (PN>>nbv) following:
2718 *
2719 * k_{i+1} = k_i + PN [nbv]
2720 *
2721 * let's show that:
2722 *
2723 * for all j in [0 nbv[, there is a unique i in [0 nbv[ such that k_i=j
2724 *
2725 * Let's assume that there are 2 distinct j1 and j2 such that
2726 * k_j1 = k_j2
2727 *
2728 * This means that
2729 *
2730 * k0+j1*PN = k0+j2*PN [nbv]
2731 * (j1-j2)*PN =0 [nbv]
2732 * since PN is a prime number larger than nbv, and nbv!=1
2733 * j1-j2=0 [nbv]
2734 * BUT
2735 * j1 and j2 are in [0 nbv[ which is impossible.
2736 *
2737 * We hence have built a random list of nbv elements of
2738 * [0 nbv[ all distincts*/
2739
2740 //Get Prime number
2741 const long PrimeNumber= BigPrimeNumber(nbv);
2742 int temp = rand(); if(!random) temp = 756804110;
2743 int k0=temp%nbv;
2744
2745 //Build orderedvertices
2746 for (i=0; i<nbv; i++){
2747 orderedvertices[i]=&vertices[k0=(k0+PrimeNumber)%nbv];
2748 }
2749
2750 /*Modify orderedvertices such that the first 3 vertices form a triangle*/
2751
2752 //get first vertex i such that [0,1,i] are not aligned
2753 for (i=2; det(orderedvertices[0]->i,orderedvertices[1]->i,orderedvertices[i]->i)==0;){
2754 //if i is higher than nbv, it means that all the determinants are 0,
2755 //all vertices are aligned!
2756 if (++i>=nbv) _error_("all the vertices are aligned");
2757 }
2758 // exchange i et 2 in "orderedvertices" so that
2759 // the first 3 vertices are not aligned (real triangle)
2760 Exchange(orderedvertices[2], orderedvertices[i]);
2761
2762 /*Take the first edge formed by the first two vertices and build
2763 * the initial simple mesh from this edge and 2 boundary triangles*/
2764
2765 BamgVertex *v0=orderedvertices[0], *v1=orderedvertices[1];
2766
2767 nbt = 2;
2768 triangles[0](0) = NULL;//infinite vertex
2769 triangles[0](1) = v0;
2770 triangles[0](2) = v1;
2771 triangles[1](0) = NULL;//infinite vertex
2772 triangles[1](2) = v0;
2773 triangles[1](1) = v1;
2774
2775 //Build adjacence
2776 const int e0 = OppositeEdge[0];
2777 const int e1 = NextEdge[e0];
2778 const int e2 = PreviousEdge[e0];
2779 triangles[0].SetAdj2(e0, &triangles[1] ,e0);
2780 triangles[0].SetAdj2(e1, &triangles[1] ,e2);
2781 triangles[0].SetAdj2(e2, &triangles[1] ,e1);
2782
2783 triangles[0].det = -1; //boundary triangle: det = -1
2784 triangles[1].det = -1; //boundary triangle: det = -1
2785
2786 triangles[0].SetSingleVertexToTriangleConnectivity();
2787 triangles[1].SetSingleVertexToTriangleConnectivity();
2788
2789 triangles[0].link=&triangles[1];
2790 triangles[1].link=&triangles[0];
2791
2792 //build quadtree
2793 if (!quadtree) quadtree = new BamgQuadtree(this,0);
2794 quadtree->Add(*v0);
2795 quadtree->Add(*v1);
2796
2797 /*Now, add the vertices One by One*/
2798 long NbSwap=0;
2799 if (verbose>3) _printf_(" Begining of insertion process...\n");
2800
2801 for (int icount=2; icount<nbv; icount++) {
2802
2803 //Get new vertex
2804 BamgVertex *newvertex=orderedvertices[icount];
2805
2806 //Find the triangle in which newvertex is located
2807 Icoor2 det3[3];
2808 Triangle* tcvi = TriangleFindFromCoord(newvertex->i,det3); //(newvertex->i = integer coordinates)
2809
2810 //Add newvertex to the quadtree
2811 quadtree->Add(*newvertex);
2812
2813 //Add newvertex to the existing mesh
2814 AddVertex(*newvertex,tcvi,det3);
2815
2816 //Make the mesh Delaunay around newvertex by swaping the edges
2817 NbSwap += newvertex->Optim(1,0);
2818 }
2819
2820 //Display info
2821 if (verbose>3) {
2822 _printf_(" NbSwap of insertion: " << NbSwap << "\n");
2823 _printf_(" NbSwap/nbv: " << NbSwap/nbv << "\n");
2824 }
2825 }
2826 /*}}}*/
2827 long Mesh::InsertNewPoints(long nbvold,long & NbTSwap,bool random) {/*{{{*/
2828 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/InsertNewPoints)*/
2829
2830 long int verbose=0;
2831 double seuil= 1.414/2 ;// for two close point
2832 long i;
2833 long NbSwap=0;
2834 Icoor2 det3[3];
2835
2836 //number of new points
2837 const long nbvnew=nbv-nbvold;
2838
2839 //display info if required
2840 if (verbose>5) _printf_(" Try to Insert " << nbvnew << " new points\n");
2841
2842 //return if no new points
2843 if (!nbvnew) return 0;
2844
2845 /*construction of a random order*/
2846 const long PrimeNumber= BigPrimeNumber(nbv) ;
2847 //remainder of the division of rand() by nbvnew
2848 int temp = rand(); if(!random) temp = 1098566905;
2849 long k3 = temp%nbvnew;
2850 //loop over the new points
2851 for (int is3=0; is3<nbvnew; is3++){
2852 long j=nbvold +(k3 = (k3+PrimeNumber)%nbvnew);
2853 long i=nbvold+is3;
2854 orderedvertices[i]= vertices + j;
2855 orderedvertices[i]->ReferenceNumber=i;
2856 }
2857
2858 // for all the new point
2859 long iv=nbvold;
2860 for(i=nbvold;i<nbv;i++){
2861 BamgVertex &vi=*orderedvertices[i];
2862 vi.i=R2ToI2(vi.r);
2863 vi.r=I2ToR2(vi.i);
2864 double hx,hy;
2865 vi.m.Box(hx,hy);
2866 int hi=(int) (hx*coefIcoor),hj=(int) (hy*coefIcoor);
2867 if(!quadtree->TooClose(&vi,seuil,hi,hj)){
2868 // a good new point
2869 BamgVertex &vj = vertices[iv];
2870 long j=vj.ReferenceNumber;
2871 if (&vj!=orderedvertices[j]){
2872 _error_("&vj!= orderedvertices[j]");
2873 }
2874 if(i!=j){
2875 Exchange(vi,vj);
2876 Exchange(orderedvertices[j],orderedvertices[i]);
2877 }
2878 vj.ReferenceNumber=0;
2879 Triangle *tcvj=TriangleFindFromCoord(vj.i,det3);
2880 if (tcvj && !tcvj->link){
2881 _printf_("While trying to add the following point:\n");
2882 vj.Echo();
2883 _printf_("BAMG determined that it was inside the following triangle, which probably lies outside of the geometric domain\n");
2884 tcvj->Echo();
2885 _error_("problem inserting point in InsertNewPoints (tcvj=" << tcvj << " and tcvj->link=" << tcvj->link << ")");
2886 }
2887 quadtree->Add(vj);
2888 AddVertex(vj,tcvj,det3);
2889 NbSwap += vj.Optim(1);
2890 iv++;
2891 }
2892 else{
2893 vi.PreviousNumber = 0;
2894 }
2895 }
2896 if (verbose>3) {
2897 _printf_(" number of new points: " << iv << "\n");
2898 _printf_(" number of to close (?) points: " << nbv-iv << "\n");
2899 _printf_(" number of swap after: " << NbSwap << "\n");
2900 }
2901 nbv = iv;
2902
2903 for (i=nbvold;i<nbv;i++) NbSwap += vertices[i].Optim(1);
2904 if (verbose>3) _printf_(" NbSwap=" << NbSwap << "\n");
2905
2906 NbTSwap += NbSwap ;
2907 return nbv-nbvold;
2908 }
2909 /*}}}*/
2910 Edge** Mesh::MakeGeomEdgeToEdge() {/*{{{*/
2911 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/MakeGeomEdgeToEdge)*/
2912
2913 if (!Gh.nbe){
2914 _error_("!Gh.nbe");
2915 }
2916 Edge **e= new Edge* [Gh.nbe];
2917
2918 long i;
2919 for ( i=0;i<Gh.nbe ; i++)
2920 e[i]=NULL;
2921 for ( i=0;i<nbe ; i++)
2922 {
2923 Edge * ei = edges+i;
2924 GeomEdge *GeomEdgeHook = ei->GeomEdgeHook;
2925 e[Gh.GetId(GeomEdgeHook)] = ei;
2926 }
2927 for ( i=0;i<nbe ; i++)
2928 for (int ii=0;ii<2;ii++) {
2929 Edge * ei = edges+i;
2930 GeomEdge *GeomEdgeHook = ei->GeomEdgeHook;
2931 int j= ii;
2932 while (!(*GeomEdgeHook)[j].Required()) {
2933 Adj(GeomEdgeHook,j); // next geom edge
2934 j=1-j;
2935 if (e[Gh.GetId(GeomEdgeHook)]) break; // optimisation
2936 e[Gh.GetId(GeomEdgeHook)] = ei;
2937 }
2938 }
2939
2940 int kk=0;
2941 for ( i=0;i<Gh.nbe ; i++){
2942 if (!e[i]){
2943 kk++;
2944 if(kk<10) _printf_("BUG: the geometrical edge " << i << " is on no edge curve\n");
2945 }
2946 }
2947 if(kk) _error_("See above");
2948
2949 return e;
2950 }
2951 /*}}}*/
2952 void Mesh::MakeBamgQuadtree() { /*{{{*/
2953 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/MakeBamgQuadtree)*/
2954 if(!quadtree) quadtree = new BamgQuadtree(this);
2955 }
2956 /*}}}*/
2957 double Mesh::MaximalHmax() {/*{{{*/
2958 return Max(pmax.x-pmin.x,pmax.y-pmin.y);
2959 }
2960 /*}}}*/
2961 void Mesh::MaxSubDivision(double maxsubdiv) {/*{{{*/
2962 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/MaxSubDivision)*/
2963
2964 long int verbose=0;
2965
2966 const double maxsubdiv2 = maxsubdiv*maxsubdiv;
2967 if(verbose>1) _printf_(" Limit the subdivision of a edges in the new mesh by " << maxsubdiv << "\n");
2968 // for all the edges
2969 // if the len of the edge is to long
2970 long it,nbchange=0;
2971 double lmax=0;
2972 for (it=0;it<nbt;it++){
2973 Triangle &t=triangles[it];
2974 for (int j=0;j<3;j++){
2975 Triangle *ptt=t.TriangleAdj(j);
2976 Triangle &tt = *ptt;
2977 if ( (!ptt || it < GetId(tt)) && ( tt.link || t.link)){
2978 BamgVertex &v0 = t[VerticesOfTriangularEdge[j][0]];
2979 BamgVertex &v1 = t[VerticesOfTriangularEdge[j][1]];
2980 R2 AB= (R2) v1-(R2) v0;
2981 Metric M = v0;
2982 double l = M(AB,AB);
2983 lmax = Max(lmax,l);
2984 if(l> maxsubdiv2){
2985 R2 AC = M.Orthogonal(AB);// the ortogonal vector of AB in M
2986 double lc = M(AC,AC);
2987 D2xD2 Rt(AB,AC);// Rt.x = AB , Rt.y = AC;
2988 D2xD2 Rt1(Rt.inv());
2989 D2xD2 D(maxsubdiv2,0,0,lc);
2990 D2xD2 MM = Rt1*D*Rt1.t();
2991 v0.m = M = Metric(MM.x.x,MM.y.x,MM.y.y);
2992 nbchange++;
2993 }
2994 M = v1;
2995 l = M(AB,AB);
2996 lmax = Max(lmax,l);
2997 if(l> maxsubdiv2){
2998 R2 AC = M.Orthogonal(AB);// the ortogonal vector of AB in M
2999 double lc = M(AC,AC);
3000 D2xD2 Rt(AB,AC);// Rt.x = AB , Rt.y = AC;
3001 D2xD2 Rt1(Rt.inv());
3002 D2xD2 D(maxsubdiv2,0,0,lc);
3003 D2xD2 MM = Rt1*D*Rt1.t();
3004 v1.m = M = Metric(MM.x.x,MM.y.x,MM.y.y);
3005 nbchange++;
3006 }
3007 }
3008 }
3009 }
3010 if(verbose>3){
3011 _printf_(" number of metric changes = " << nbchange << ", maximum number of subdivision of a edges before change = " << pow(lmax,0.5) << "\n");
3012 }
3013 }
3014 /*}}}*/
3015 Metric Mesh::MetricAt(const R2 & A) const { /*{{{*/
3016 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/MetricAt)*/
3017
3018 I2 a = R2ToI2(A);
3019 Icoor2 deta[3];
3020 Triangle * t =TriangleFindFromCoord(a,deta);
3021 if (t->det <0) { // outside
3022 double ba,bb;
3023 AdjacentTriangle edge= CloseBoundaryEdge(a,t,ba,bb) ;
3024 return Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1));}
3025 else { // inside
3026 double aa[3];
3027 double s = deta[0]+deta[1]+deta[2];
3028 aa[0]=deta[0]/s;
3029 aa[1]=deta[1]/s;
3030 aa[2]=deta[2]/s;
3031 return Metric(aa,(*t)[0],(*t)[1],(*t)[2]);
3032 }
3033 }
3034 /*}}}*/
3035 double Mesh::MinimalHmin() {/*{{{*/
3036 return 2.0/coefIcoor;
3037 }
3038 /*}}}*/
3039 BamgVertex* Mesh::NearestVertex(int i,int j) {/*{{{*/
3040 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/NearestVertex)*/
3041 return quadtree->NearestVertex(i,j);
3042 }
3043 /*}}}*/
3044 void Mesh::NewPoints(Mesh & Bh,BamgOpts* bamgopts,int KeepVertices){/*{{{*/
3045 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/NewPoints)*/
3046
3047 int i,j,k;
3048 long NbTSwap=0;
3049 long nbtold=nbt;
3050 long nbvold=nbv;
3051 long Headt=0;
3052 long next_t;
3053 long* first_np_or_next_t=new long[maxnbt];
3054 Triangle* t=NULL;
3055
3056 /*Recover options*/
3057 int verbose=bamgopts->verbose;
3058
3059 /*First, insert old points if requested*/
3060 if(KeepVertices && (&Bh != this) && (nbv+Bh.nbv< maxnbv)){
3061 if (verbose>5) _printf_(" Inserting initial mesh points\n");
3062 bool pointsoutside = false;
3063 for(i=0;i<Bh.nbv;i++){
3064 BamgVertex &bv=Bh[i];
3065 /*Do not insert if the point is outside*/
3066 long long det3[3];
3067 Triangle* tcvj=TriangleFindFromCoord(bv.i,det3);
3068 if(tcvj->det<0 || !tcvj->link){
3069 pointsoutside = true;
3070 continue;
3071 }
3072 IssmDouble area_1=((bv.r.x -(*tcvj)(2)->r.x)*((*tcvj)(1)->r.y-(*tcvj)(2)->r.y)
3073 - (bv.r.y -(*tcvj)(2)->r.y)*((*tcvj)(1)->r.x-(*tcvj)(2)->r.x));
3074 IssmDouble area_2=(((*tcvj)(0)->r.x -(*tcvj)(2)->r.x)*(bv.r.y -(*tcvj)(2)->r.y)
3075 - ((*tcvj)(0)->r.y -(*tcvj)(2)->r.y)*(bv.r.x -(*tcvj)(2)->r.x));
3076 IssmDouble area_3 =((bv.r.x -(*tcvj)(1)->r.x)*((*tcvj)(0)->r.y-(*tcvj)(1)->r.y)
3077 - (bv.r.y -(*tcvj)(1)->r.y)*((*tcvj)(0)->r.x-(*tcvj)(1)->r.x));
3078 if(area_1<0 || area_2<0 || area_3<0){
3079 pointsoutside = true;
3080 continue;
3081 }
3082 if(!bv.GeomEdgeHook){
3083 vertices[nbv].r = bv.r;
3084 vertices[nbv].PreviousNumber = i+1;
3085 vertices[nbv++].m = bv.m;
3086 }
3087 }
3088 if(pointsoutside) _printf_("WARNING: One or more points of the initial mesh fall outside of the geometric boundary\n");
3089 Bh.CreateSingleVertexToTriangleConnectivity();
3090 InsertNewPoints(nbvold,NbTSwap,bamgopts->random);
3091 }
3092 else Bh.CreateSingleVertexToTriangleConnectivity();
3093
3094 // generation of the list of next Triangle
3095 for(i=0;i<nbt;i++) first_np_or_next_t[i]=-(i+1);
3096 // the next traingle of i is -first_np_or_next_t[i]
3097
3098 // Big loop (most time consuming)
3099 int iter=0;
3100 if (verbose>5) _printf_(" Big loop\n");
3101 do {
3102 /*Update variables*/
3103 iter++;
3104 nbtold=nbt;
3105 nbvold=nbv;
3106
3107 /*We test all triangles*/
3108 i=Headt;
3109 next_t=-first_np_or_next_t[i];
3110 for(t=&triangles[i];i<nbt;t=&triangles[i=next_t],next_t=-first_np_or_next_t[i]){
3111
3112 //check i
3113 if (i<0 || i>=nbt ){
3114 _error_("Index problem in NewPoints (i=" << i << " not in [0 " << nbt-1 << "])");
3115 }
3116 //change first_np_or_next_t[i]
3117 first_np_or_next_t[i] = iter;
3118
3119 //Loop over the edges of t
3120 for(j=0;j<3;j++){
3121 AdjacentTriangle tj(t,j);
3122 BamgVertex &vA = *tj.EdgeVertex(0);
3123 BamgVertex &vB = *tj.EdgeVertex(1);
3124
3125 //if t is a boundary triangle, or tj locked, continue
3126 if (!t->link) continue;
3127 if (t->det <0) continue;
3128 if (t->Locked(j)) continue;
3129
3130 AdjacentTriangle tadjj = t->Adj(j);
3131 Triangle* ta=tadjj;
3132
3133 //if the adjacent triangle is a boundary triangle, continur
3134 if (ta->det<0) continue;
3135
3136 R2 A=vA;
3137 R2 B=vB;
3138 k=GetId(ta);
3139
3140 //if this edge has already been done, go to next edge of triangle
3141 if(first_np_or_next_t[k]==iter) continue;
3142
3143 lIntTria.SplitEdge(Bh,A,B);
3144 lIntTria.NewPoints(vertices,nbv,maxnbv);
3145 } // end loop for each edge
3146 }// for triangle
3147
3148 if (!InsertNewPoints(nbvold,NbTSwap,bamgopts->random)) break;
3149 for (i=nbtold;i<nbt;i++) first_np_or_next_t[i]=iter;
3150 Headt = nbt; // empty list
3151
3152 // for all the triangle containing the vertex i
3153 for (i=nbvold;i<nbv;i++){
3154 BamgVertex* s = vertices + i;
3155 AdjacentTriangle ta(s->t, EdgesVertexTriangle[s->IndexInTriangle][1]);
3156 Triangle* tbegin= (Triangle*) ta;
3157 long kt;
3158 do {
3159 kt = GetId((Triangle*) ta);
3160 if (first_np_or_next_t[kt]>0){
3161 first_np_or_next_t[kt]=-Headt;
3162 Headt=kt;
3163 }
3164 if (ta.EdgeVertex(0)!=s){
3165 _error_("ta.EdgeVertex(0)!=s");
3166 }
3167 ta = Next(Adj(ta));
3168 } while ( (tbegin != (Triangle*) ta));
3169 }
3170
3171 }while(nbv!=nbvold);
3172 delete [] first_np_or_next_t;
3173
3174 long NbSwapf =0;
3175 for(i=0;i<nbv;i++) NbSwapf += vertices[i].Optim(0);
3176 }/*}}}*/
3177 GeomEdge* Mesh::ProjectOnCurve( Edge & BhAB, BamgVertex & vA, BamgVertex & vB,/*{{{*/
3178 double theta,BamgVertex & R,VertexOnEdge & BR,VertexOnGeom & GR) {
3179 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshQuad.cpp/ProjectOnCurve)*/
3180
3181 void *pA=0,*pB=0;
3182 double tA=0,tB=0;
3183 R2 A=vA,B=vB;
3184 BamgVertex * pvA=&vA, * pvB=&vB;
3185 if (vA.IndexInTriangle == IsVertexOnVertex){
3186 pA=vA.BackgroundVertexHook;
3187 }
3188 else if (vA.IndexInTriangle == IsVertexOnEdge){
3189 pA=vA.BackgroundEdgeHook->be;
3190 tA=vA.BackgroundEdgeHook->abcisse;
3191 }
3192 else {
3193 _error_("ProjectOnCurve On BamgVertex " << BTh.GetId(vA) << " forget call to SetVertexFieldOnBTh");
3194 }
3195
3196 if (vB.IndexInTriangle == IsVertexOnVertex){
3197 pB=vB.BackgroundVertexHook;
3198 }
3199 else if(vB.IndexInTriangle == IsVertexOnEdge){
3200 pB=vB.BackgroundEdgeHook->be;
3201 tB=vB.BackgroundEdgeHook->abcisse;
3202 }
3203 else {
3204 _error_("ProjectOnCurve On BamgVertex " << BTh.GetId(vB) << " forget call to SetVertexFieldOnBTh");
3205 }
3206 Edge * e = &BhAB;
3207 if (!pA || !pB || !e){
3208 _error_("!pA || !pB || !e");
3209 }
3210 // be carefull the back ground edge e is on same geom edge
3211 // of the initiale edge def by the 2 vertex A B;
3212 //check Is a background Mesh;
3213 if (e<BTh.edges || e>=BTh.edges+BTh.nbe){
3214 _error_("e<BTh.edges || e>=BTh.edges+BTh.nbe");
3215 }
3216 // walk on BTh edge
3217 //not finish ProjectOnCurve with BackGround Mesh);
3218 // 1 first find a back ground edge contening the vertex A
3219 // 2 walk n back gound boundary to find the final vertex B
3220
3221 if( vA.IndexInTriangle == IsVertexOnEdge)
3222 { // find the start edge
3223 e = vA.BackgroundEdgeHook->be;
3224
3225 }
3226 else if (vB.IndexInTriangle == IsVertexOnEdge)
3227 {
3228 theta = 1-theta;
3229 Exchange(tA,tB);
3230 Exchange(pA,pB);
3231 Exchange(pvA,pvB);
3232 Exchange(A,B);
3233 e = vB.BackgroundEdgeHook->be;
3234
3235 }
3236 else{ // do the search by walking
3237 _error_("case not supported yet");
3238 }
3239
3240 // find the direction of walking with direction of edge and pA,PB;
3241 R2 AB=B-A;
3242
3243 double cosE01AB = (( (R2) (*e)[1] - (R2) (*e)[0] ) , AB);
3244 int kkk=0;
3245 int direction = (cosE01AB>0) ? 1 : 0;
3246
3247 // double l=0; // length of the edge AB
3248 double abscisse = -1;
3249
3250 for (int step=0;step<2;step++){
3251 // 2 times algo:
3252 // 1 for computing the length l
3253 // 2 for find the vertex
3254 int iii;
3255 BamgVertex *v0=pvA,*v1;
3256 Edge *neee,*eee;
3257 double lg =0; // length of the curve
3258 double te0;
3259 // we suppose take the curve's abcisse
3260 for ( eee=e,iii=direction,te0=tA;
3261 eee && ((( void*) eee) != pB) && (( void*) (v1=&((*eee)[iii]))) != pB ;
3262 neee = eee->adj[iii],iii = 1-neee->Intersection(*eee),eee = neee,v0=v1,te0=1-iii ) {
3263
3264 kkk=kkk+1;
3265 _assert_(kkk<100);
3266 _assert_(eee);
3267 double lg0 = lg;
3268 double dp = LengthInterpole(v0->m,v1->m,(R2) *v1 - (R2) *v0);
3269 lg += dp;
3270 if (step && abscisse <= lg) { // ok we find the geom edge
3271 double sss = (abscisse-lg0)/dp;
3272 double thetab = te0*(1-sss)+ sss*iii;
3273 _assert_(thetab>=0 && thetab<=1);
3274 BR = VertexOnEdge(&R,eee,thetab);
3275 return Gh.ProjectOnCurve(*eee,thetab,R,GR);
3276 }
3277 }
3278 // we find the end
3279 if (v1 != pvB){
3280 if (( void*) v1 == pB)
3281 tB = iii;
3282
3283 double lg0 = lg;
3284 _assert_(eee);
3285 v1 = pvB;
3286 double dp = LengthInterpole(v0->m,v1->m,(R2) *v1 - (R2) *v0);
3287 lg += dp;
3288 abscisse = lg*theta;
3289 if (abscisse <= lg && abscisse >= lg0 ) // small optimisation we know the lenght because end
3290 { // ok we find the geom edge
3291 double sss = (abscisse-lg0)/dp;
3292 double thetab = te0*(1-sss)+ sss*tB;
3293 _assert_(thetab>=0 && thetab<=1);
3294 BR = VertexOnEdge(&R,eee,thetab);
3295 return Gh.ProjectOnCurve(*eee,thetab,R,GR);
3296 }
3297 }
3298 abscisse = lg*theta;
3299
3300 }
3301 _error_("Big bug...");
3302 return 0; // just for the compiler
3303 }
3304 /*}}}*/
3305 void Mesh::ReconstructExistingMesh(){/*{{{*/
3306 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/FillHoleInMesh)*/
3307
3308 /*This routine reconstruct an existing mesh to make it CONVEX:
3309 * -all the holes are filled
3310 * -concave boundaries are filled
3311 * A convex mesh is required for a lot of operations. This is why every mesh
3312 * goes through this process.
3313 * This routine also generates mesh properties such as adjencies,...
3314 */
3315
3316 /*Intermediary*/
3317 int verbose=0;
3318
3319 // generation of the integer coordinate
3320
3321 // find extrema coordinates of vertices pmin,pmax
3322 long i;
3323 if(verbose>2) _printf_(" Reconstruct mesh of " << nbv << " vertices\n");
3324
3325 //initialize orderedvertices
3326 _assert_(orderedvertices);
3327 for (i=0;i<nbv;i++) orderedvertices[i]=0;
3328
3329 //Initialize nbsubdomains
3330 nbsubdomains =0;
3331
3332 /* generation of triangles adjacency*/
3333
3334 //First add existing edges
3335 long kk =0;
3336 SetOfEdges4* edge4= new SetOfEdges4(nbt*3,nbv);
3337 for (i=0;i<nbe;i++){
3338 kk=kk+(i==edge4->SortAndAdd(GetId(edges[i][0]),GetId(edges[i][1])));
3339 }
3340 if (kk != nbe){
3341 _error_("There are " << kk-nbe << " double edges in the mesh");
3342 }
3343
3344 //Add edges of all triangles in existing mesh
3345 long* st = new long[nbt*3];
3346 for (i=0;i<nbt*3;i++) st[i]=-1;
3347 for (i=0;i<nbt;i++){
3348 for (int j=0;j<3;j++){
3349
3350 //Add current triangle edge to edge4
3351 long k =edge4->SortAndAdd(GetId(triangles[i][VerticesOfTriangularEdge[j][0]]),GetId(triangles[i][VerticesOfTriangularEdge[j][1]]));
3352
3353 long invisible=triangles[i].Hidden(j);
3354
3355 //If the edge has not been added to st, add it
3356 if(st[k]==-1) st[k]=3*i+j;
3357
3358 //If the edge already exists, add adjacency
3359 else if(st[k]>=0) {
3360 _assert_(!triangles[i].TriangleAdj(j));
3361 _assert_(!triangles[st[k]/3].TriangleAdj((int) (st[k]%3)));
3362
3363 triangles[i].SetAdj2(j,triangles+st[k]/3,(int)(st[k]%3));
3364 if (invisible) triangles[i].SetHidden(j);
3365 if (k<nbe) triangles[i].SetLocked(j);
3366
3367 //Make st[k] negative so that it will throw an error message if it is found again
3368 st[k]=-2-st[k];
3369 }
3370
3371 //An edge belongs to 2 triangles
3372 else {
3373 _error_("The edge (" << GetId(triangles[i][VerticesOfTriangularEdge[j][0]]) << " , " << GetId(triangles[i][VerticesOfTriangularEdge[j][1]]) << ") belongs to more than 2 triangles");
3374 }
3375 }
3376 }
3377
3378 //Display info if required
3379 if(verbose>5) {
3380 _printf_(" info of Mesh:\n");
3381 _printf_(" - number of vertices = " << nbv << " \n");
3382 _printf_(" - number of triangles = " << nbt << " \n");
3383 _printf_(" - number of given edges = " << nbe << " \n");
3384 _printf_(" - number of all edges = " << edge4->nb() << "\n");
3385 _printf_(" - Euler number 1 - nb of holes = " << nbt-edge4->nb()+nbv << "\n");
3386 }
3387
3388 //check the consistency of edge[].adj and the geometrical required vertex
3389 long k=0;
3390 for (i=0;i<edge4->nb();i++){
3391 if (st[i]>=0){ // edge alone
3392 if (i<nbe){
3393 long i0=edge4->i(i);
3394 orderedvertices[i0] = vertices+i0;
3395 long i1=edge4->j(i);
3396 orderedvertices[i1] = vertices+i1;
3397 }
3398 else {
3399 k=k+1;
3400 if (k<10) {
3401 //print only 10 edges
3402 _printf_("Lost boundary edges " << i << " : " << edge4->i(i) << " " << edge4->j(i) << "\n");
3403 }
3404 else if (k==10){
3405 _printf_("Other lost boundary edges not shown...\n");
3406 }
3407 }
3408 }
3409 }
3410 if(k) {
3411 _error_(k << " boundary edges (from the geometry) are not defined as mesh edges");
3412 }
3413
3414 /* mesh generation with boundary points*/
3415 long nbvb=0;
3416 for (i=0;i<nbv;i++){
3417 vertices[i].t=0;
3418 vertices[i].IndexInTriangle=0;
3419 if (orderedvertices[i]) orderedvertices[nbvb++]=orderedvertices[i];
3420 }
3421
3422 Triangle* savetriangles=triangles;
3423 long savenbt=nbt;
3424 long savemaxnbt=maxnbt;
3425 SubDomain* savesubdomains=subdomains;
3426 subdomains=0;
3427
3428 long Nbtriafillhole=2*nbvb;
3429 Triangle* triafillhole=new Triangle[Nbtriafillhole];
3430 triangles = triafillhole;
3431
3432 nbt=2;
3433 maxnbt= Nbtriafillhole;
3434
3435 //Find a vertex that is not aligned with vertices 0 and 1
3436 for (i=2;det(orderedvertices[0]->i,orderedvertices[1]->i,orderedvertices[i]->i)==0;)
3437 if (++i>=nbvb) {
3438 _error_("ReconstructExistingMesh: All the vertices are aligned");
3439 }
3440 //Move this vertex (i) to the 2d position in orderedvertices
3441 Exchange(orderedvertices[2], orderedvertices[i]);
3442
3443 /*Reconstruct mesh beginning with 2 triangles*/
3444 BamgVertex * v0=orderedvertices[0], *v1=orderedvertices[1];
3445
3446 triangles[0](0) = NULL; // Infinite vertex
3447 triangles[0](1) = v0;
3448 triangles[0](2) = v1;
3449
3450 triangles[1](0) = NULL;// Infinite vertex
3451 triangles[1](2) = v0;
3452 triangles[1](1) = v1;
3453 const int e0 = OppositeEdge[0];
3454 const int e1 = NextEdge[e0];
3455 const int e2 = PreviousEdge[e0];
3456 triangles[0].SetAdj2(e0, &triangles[1] ,e0);
3457 triangles[0].SetAdj2(e1, &triangles[1] ,e2);
3458 triangles[0].SetAdj2(e2, &triangles[1] ,e1);
3459
3460 triangles[0].det = -1; // boundary triangles
3461 triangles[1].det = -1; // boundary triangles
3462
3463 triangles[0].SetSingleVertexToTriangleConnectivity();
3464 triangles[1].SetSingleVertexToTriangleConnectivity();
3465
3466 triangles[0].link=&triangles[1];
3467 triangles[1].link=&triangles[0];
3468
3469 if (!quadtree) delete quadtree; //ReInitialise;
3470 quadtree = new BamgQuadtree(this,0);
3471 quadtree->Add(*v0);
3472 quadtree->Add(*v1);
3473
3474 // vertices are added one by one
3475 long NbSwap=0;
3476 for (int icount=2; icount<nbvb; icount++) {
3477 BamgVertex *vi = orderedvertices[icount];
3478 Icoor2 det3[3];
3479 Triangle *tcvi = TriangleFindFromCoord(vi->i,det3);
3480 quadtree->Add(*vi);
3481 AddVertex(*vi,tcvi,det3);
3482 NbSwap += vi->Optim(1,1);
3483 }
3484
3485 //enforce the boundary
3486 AdjacentTriangle ta(0,0);
3487 long nbloss = 0,knbe=0;
3488 for ( i = 0; i < nbe; i++){
3489 if (st[i] >=0){ //edge alone => on border
3490 BamgVertex &a=edges[i][0], &b=edges[i][1];
3491 if (a.t && b.t){
3492 knbe++;
3493 if (ForceEdge(a,b,ta)<0) nbloss++;
3494 }
3495 }
3496 }
3497 if(nbloss) {
3498 _error_("we lost " << nbloss << " existing edges other " << knbe);
3499 }
3500
3501 FindSubDomain(1);
3502 // remove all the hole
3503 // remove all the good sub domain
3504 long krm =0;
3505 for (i=0;i<nbt;i++){
3506 if (triangles[i].link){ // remove triangles
3507 krm++;
3508 for (int j=0;j<3;j++){
3509 AdjacentTriangle ta = triangles[i].Adj(j);
3510 Triangle &tta = *(Triangle*)ta;
3511 //if edge between remove and not remove
3512 if(! tta.link){
3513 // change the link of ta;
3514 int ja = ta;
3515 BamgVertex *v0= ta.EdgeVertex(0);
3516 BamgVertex *v1= ta.EdgeVertex(1);
3517 long k =edge4->SortAndAdd(v0?GetId(v0):nbv,v1? GetId(v1):nbv);
3518
3519 _assert_(st[k]>=0);
3520 tta.SetAdj2(ja,savetriangles + st[k] / 3,(int) (st[k]%3));
3521 ta.SetLock();
3522 st[k]=-2-st[k];
3523 }
3524 }
3525 }
3526 }
3527 long NbTfillHoll =0;
3528 for (i=0;i<nbt;i++){
3529 if (triangles[i].link) {
3530 triangles[i]=Triangle((BamgVertex *) NULL,(BamgVertex *) NULL,(BamgVertex *) NULL);
3531 triangles[i].color=-1;
3532 }
3533 else{
3534 triangles[i].color= savenbt+ NbTfillHoll++;
3535 }
3536 }
3537 _assert_(savenbt+NbTfillHoll<=savemaxnbt);
3538
3539 // copy of the outside triangles in saveMesh
3540 for (i=0;i<nbt;i++){
3541 if(triangles[i].color>=0) {
3542 savetriangles[savenbt]=triangles[i];
3543 savetriangles[savenbt].link=0;
3544 savenbt++;
3545 }
3546 }
3547 // gestion of the adj
3548 k =0;
3549 Triangle * tmax = triangles + nbt;
3550 for (i=0;i<savenbt;i++) {
3551 Triangle & ti = savetriangles[i];
3552 for (int j=0;j<3;j++){
3553 Triangle * ta = ti.TriangleAdj(j);
3554 int aa = ti.NuEdgeTriangleAdj(j);
3555 int lck = ti.Locked(j);
3556 if (!ta) k++; // bug
3557 else if ( ta >= triangles && ta < tmax){
3558 ta= savetriangles + ta->color;
3559 ti.SetAdj2(j,ta,aa);
3560 if(lck) ti.SetLocked(j);
3561 }
3562 }
3563 }
3564
3565 // restore triangles;
3566 nbt=savenbt;
3567 maxnbt=savemaxnbt;
3568 delete [] triangles;
3569 delete [] subdomains;
3570 triangles = savetriangles;
3571 subdomains = savesubdomains;
3572 if (k) {
3573 _error_("number of triangles edges alone = " << k);
3574 }
3575 FindSubDomain();
3576
3577 delete edge4;
3578 delete [] st;
3579 for (i=0;i<nbv;i++) quadtree->Add(vertices[i]);
3580
3581 SetVertexFieldOn();
3582
3583 /*Check requirements consistency*/
3584 for (i=0;i<nbe;i++){
3585 /*If the current mesh edge is on Geometry*/
3586 if(edges[i].GeomEdgeHook){
3587 for(int j=0;j<2;j++){
3588 /*Go through the edges adjacent to current edge (if on the same curve)*/
3589 if (!edges[i].adj[j]){
3590 /*The edge is on Geometry and does not have 2 adjacent edges... (not on a closed curve)*/
3591 /*Check that the 2 vertices are on geometry AND required*/
3592 if(!edges[i][j].GeomEdgeHook->IsRequiredVertex()){
3593 _printf_("ReconstructExistingMesh error message: problem with the edge number " << i+1 << ": [" << GetId(edges[i][0])+1 << " " << GetId(edges[i][1])+1 << "]\n");
3594 _printf_("This edge is on geometrical edge number " << Gh.GetId(edges[i].GeomEdgeHook)+1 << "\n");
3595 if (edges[i][j].GeomEdgeHook->OnGeomVertex())
3596 _printf_("the vertex number " << GetId(edges[i][j])+1 << " of this edge is a geometric BamgVertex number " << Gh.GetId(edges[i][j].GeomEdgeHook->gv)+1 << "\n");
3597 else if (edges[i][j].GeomEdgeHook->OnGeomEdge())
3598 _printf_("the vertex number " << GetId(edges[i][j])+1 << " of this edge is a geometric Edge number " << Gh.GetId(edges[i][j].GeomEdgeHook->ge)+1 << "\n");
3599 else
3600 _printf_("Its pointer is " << edges[i][j].GeomEdgeHook << "\n");
3601
3602 _printf_("This edge is on geometry and has no adjacent edge (open curve) and one of the tip is not required\n");
3603 _error_("See above (might be cryptic...)");
3604 }
3605 }
3606 }
3607 }
3608 }
3609 }
3610 /*}}}*/
3611 void Mesh::TrianglesRenumberBySubDomain(bool justcompress){/*{{{*/
3612 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/ReNumberingTheTriangleBySubDomain)*/
3613
3614 long *renu= new long[nbt];
3615 Triangle *t0,*t,*te=triangles+nbt;
3616 long k=0,it,i,j;
3617
3618 for ( it=0;it<nbt;it++)
3619 renu[it]=-1; // outside triangle
3620 for ( i=0;i<nbsubdomains;i++)
3621 {
3622 t=t0=subdomains[i].head;
3623 if (!t0){ // not empty sub domain
3624 _error_("!t0");
3625 }
3626 do {
3627 long kt = GetId(t);
3628 if (kt<0 || kt >= nbt ){
3629 _error_("kt<0 || kt >= nbt");
3630 }
3631 if (renu[kt]!=-1){
3632 _error_("renu[kt]!=-1");
3633 }
3634 renu[kt]=k++;
3635 }
3636 while (t0 != (t=t->link));
3637 }
3638 // take is same numbering if possible
3639 if(justcompress)
3640 for ( k=0,it=0;it<nbt;it++)
3641 if(renu[it] >=0 )
3642 renu[it]=k++;
3643
3644 // put the outside triangles at the end
3645 for ( it=0;it<nbt;it++){
3646 if (renu[it]==-1) renu[it]=k++;
3647 }
3648 if (k != nbt){
3649 _error_("k != nbt");
3650 }
3651 // do the change on all the pointeur
3652 for ( it=0;it<nbt;it++)
3653 triangles[it].Renumbering(triangles,te,renu);
3654
3655 for ( i=0;i<nbsubdomains;i++)
3656 subdomains[i].head=triangles+renu[GetId(subdomains[i].head)];
3657
3658 // move the Triangles without a copy of the array
3659 // be carefull not trivial code
3660 for ( it=0;it<nbt;it++) // for all sub cycles of the permutation renu
3661 if (renu[it] >= 0) // a new sub cycle
3662 {
3663 i=it;
3664 Triangle ti=triangles[i],tj;
3665 while ( (j=renu[i]) >= 0)
3666 { // i is old, and j is new
3667 renu[i] = -1; // mark
3668 tj = triangles[j]; // save new
3669 triangles[j]= ti; // new <- old
3670 i=j; // next
3671 ti = tj;
3672 }
3673 }
3674 delete [] renu;
3675
3676 }
3677 /*}}}*/
3678 void Mesh::SetIntCoor(const char * strfrom) {/*{{{*/
3679 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/SetIntCoor)*/
3680
3681 /*Set integer coordinate for existing vertices*/
3682
3683 //Get extrema coordinates of the existing vertices
3684 pmin = vertices[0].r;
3685 pmax = vertices[0].r;
3686 long i;
3687 for (i=0;i<nbv;i++) {
3688 pmin.x = Min(pmin.x,vertices[i].r.x);
3689 pmin.y = Min(pmin.y,vertices[i].r.y);
3690 pmax.x = Max(pmax.x,vertices[i].r.x);
3691 pmax.y = Max(pmax.y,vertices[i].r.y);
3692 }
3693 R2 DD = (pmax-pmin)*0.05;
3694 pmin = pmin-DD;
3695 pmax = pmax+DD;
3696
3697 //Compute coefIcoor
3698 int MaxICoord = 1073741823; //2^30 - 1 = =111...111 (29 times one)
3699 coefIcoor= (MaxICoord)/(Max(pmax.x-pmin.x,pmax.y-pmin.y));
3700 if (coefIcoor<=0){
3701 _error_("coefIcoor should be positive, a problem in the geometry is likely");
3702 }
3703
3704 // generation of integer coord
3705 for (i=0;i<nbv;i++) {
3706 vertices[i].i = R2ToI2(vertices[i].r);
3707 }
3708
3709 // computation of the det
3710 int number_of_errors=0;
3711 for (i=0;i<nbt;i++) {
3712 BamgVertex* v0 = triangles[i](0);
3713 BamgVertex* v1 = triangles[i](1);
3714 BamgVertex* v2 = triangles[i](2);
3715
3716 //If this is not a boundary triangle
3717 if (v0 && v1 && v2){
3718
3719 /*Compute determinant*/
3720 triangles[i].det= det(v0->GetIntegerCoordinates(),v1->GetIntegerCoordinates(),v2->GetIntegerCoordinates());
3721
3722 /*Check that determinant is positive*/
3723 if (triangles[i].det <=0){
3724
3725 /*increase number_of_errors and print error only for the first 20 triangles*/
3726 number_of_errors++;
3727 if (number_of_errors<20){
3728 _printf_("Area of Triangle " << i+1 << " < 0 (det=" << triangles[i].det << ")\n");
3729 }
3730 }
3731 }
3732
3733 //else, set as -1
3734 else triangles[i].det=-1;
3735 }
3736
3737 if (number_of_errors) _error_("Fatal error: some triangles have negative areas, see above");
3738 }
3739 /*}}}*/
3740 void Mesh::SmoothingVertex(int nbiter,double omega ) { /*{{{*/
3741 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/SmoothingVertex)*/
3742
3743 long int verbose=0;
3744 // if quatree exist remove it end reconstruct
3745 if (quadtree) delete quadtree;
3746 quadtree=0;
3747 CreateSingleVertexToTriangleConnectivity();
3748 Triangle vide; // a triangle to mark the boundary vertex
3749 Triangle ** tstart= new Triangle* [nbv];
3750 long i,j,k;
3751 // attention si Background == Triangle alors on ne peut pas utiliser la rechech rapide
3752 if ( this == & BTh)
3753 for ( i=0;i<nbv;i++)
3754 tstart[i]=vertices[i].t;
3755 else
3756 for ( i=0;i<nbv;i++)
3757 tstart[i]=0;
3758 for ( j=0;j<NbVerticesOnGeomVertex;j++ )
3759 tstart[ GetId(VerticesOnGeomVertex[j].meshvertex)]=&vide;
3760 for ( k=0;k<NbVerticesOnGeomEdge;k++ )
3761 tstart[ GetId(VerticesOnGeomEdge[k].meshvertex)]=&vide;
3762 if(verbose>2) _printf_(" SmoothingVertex: nb Iteration = " << nbiter << ", Omega=" << omega << "\n");
3763 for (k=0;k<nbiter;k++)
3764 {
3765 long i,NbSwap =0;
3766 double delta =0;
3767 for ( i=0;i<nbv;i++)
3768 if (tstart[i] != &vide) // not a boundary vertex
3769 delta=Max(delta,vertices[i].Smoothing(*this,BTh,tstart[i],omega));
3770 for ( i=0;i<nbv;i++)
3771 if (tstart[i] != &vide) // not a boundary vertex
3772 NbSwap += vertices[i].Optim(1);
3773 if (verbose>3) _printf_(" move max = " << pow(delta,0.5) << ", iteration = " << k << ", nb of swap = " << NbSwap << "\n");
3774 }
3775
3776 delete [] tstart;
3777 if (quadtree) quadtree= new BamgQuadtree(this);
3778 }
3779 /*}}}*/
3780 void Mesh::SmoothMetric(double raisonmax) { /*{{{*/
3781 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/SmoothMetric)*/
3782
3783 long int verbose=0;
3784
3785 if(raisonmax<1.1) return;
3786 if(verbose > 1) _printf_(" Mesh::SmoothMetric raisonmax = " << raisonmax << "\n");
3787 CreateSingleVertexToTriangleConnectivity();
3788 long i,j,kch,kk,ip;
3789 long *first_np_or_next_t0 = new long[nbv];
3790 long *first_np_or_next_t1 = new long[nbv];
3791 long Head0 =0,Head1=-1;
3792 double logseuil= log(raisonmax);
3793
3794 for(i=0;i<nbv-1;i++)
3795 first_np_or_next_t0[i]=i+1;
3796 first_np_or_next_t0[nbv-1]=-1;// end;
3797 for(i=0;i<nbv;i++)
3798 first_np_or_next_t1[i]=-1;
3799 kk=0;
3800 while(Head0>=0&& kk++<100){
3801 kch=0;
3802 for(i=Head0;i>=0;i=first_np_or_next_t0[ip=i],first_np_or_next_t0[ip]=-1) {
3803 // pour tous les triangles autour du sommet s
3804 Triangle* t= vertices[i].t;
3805 if (!t){
3806 _error_("!t");
3807 }
3808 BamgVertex & vi = vertices[i];
3809 AdjacentTriangle ta(t,EdgesVertexTriangle[vertices[i].IndexInTriangle][0]);
3810 BamgVertex *pvj0 = ta.EdgeVertex(0);
3811 while (1) {
3812 ta=Previous(Adj(ta));
3813 if (vertices+i != ta.EdgeVertex(1)){
3814 _error_("vertices+i != ta.EdgeVertex(1)");
3815 }
3816 BamgVertex *pvj = (ta.EdgeVertex(0));
3817 BamgVertex & vj = *pvj;
3818 if(pvj){
3819 j= &vj-vertices;
3820 if (j<0 || j >= nbv){
3821 _error_("j<0 || j >= nbv");
3822 }
3823 R2 Aij = (R2) vj - (R2) vi;
3824 double ll = Norme2(Aij);
3825 if (0) {
3826 double hi = ll/vi.m.Length(Aij.x,Aij.y);
3827 double hj = ll/vj.m.Length(Aij.x,Aij.y);
3828 if(hi < hj)
3829 {
3830 double dh=(hj-hi)/ll;
3831 if (dh>logseuil) {
3832 vj.m.IntersectWith(vi.m/(1 +logseuil*ll/hi));
3833 if(first_np_or_next_t1[j]<0)
3834 kch++,first_np_or_next_t1[j]=Head1,Head1=j;
3835 }
3836 }
3837 }
3838 else
3839 {
3840 double li = vi.m.Length(Aij.x,Aij.y);
3841 if( vj.m.IntersectWith(vi.m/(1 +logseuil*li)) )
3842 if(first_np_or_next_t1[j]<0) // if the metrix change
3843 kch++,first_np_or_next_t1[j]=Head1,Head1=j;
3844 }
3845 }
3846 if ( &vj == pvj0 ) break;
3847 }
3848 }
3849 Head0 = Head1;
3850 Head1 = -1;
3851 Exchange(first_np_or_next_t0,first_np_or_next_t1);
3852 }
3853 if(verbose>2) _printf_(" number of iterations = " << kch << "\n");
3854 delete [] first_np_or_next_t0;
3855 delete [] first_np_or_next_t1;
3856 }
3857 /*}}}*/
3858 long Mesh::SplitInternalEdgeWithBorderVertices(){/*{{{*/
3859 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/SplitInternalEdgeWithBorderVertices)*/
3860
3861 long NbSplitEdge=0;
3862 SetVertexFieldOn();
3863 long it;
3864 long nbvold=nbv;
3865 long int verbose=2;
3866 for (it=0;it<nbt;it++){
3867 Triangle &t=triangles[it];
3868 if (t.link)
3869 for (int j=0;j<3;j++)
3870 if(!t.Locked(j) && !t.Hidden(j)){
3871
3872 Triangle *ptt = t.TriangleAdj(j);
3873 Triangle &tt = *ptt;
3874
3875 if( ptt && tt.link && it < GetId(tt))
3876 { // an internal edge
3877 BamgVertex &v0 = t[VerticesOfTriangularEdge[j][0]];
3878 BamgVertex &v1 = t[VerticesOfTriangularEdge[j][1]];
3879 if (v0.GeomEdgeHook && v1.GeomEdgeHook){
3880 R2 P= ((R2) v0 + (R2) v1)*0.5;
3881 if ( nbv<maxnbv) {
3882 vertices[nbv].r = P;
3883 vertices[nbv++].m = Metric(0.5,v0.m,0.5,v1.m);
3884 vertices[nbv].ReferenceNumber=0;
3885 }
3886 NbSplitEdge++;
3887 }
3888 }
3889 }
3890 }
3891 CreateSingleVertexToTriangleConnectivity();
3892 if (nbvold!=nbv){
3893 long iv = nbvold;
3894 long NbSwap = 0;
3895 Icoor2 det3[3];
3896 for (int i=nbvold;i<nbv;i++) {// for all the new point
3897 BamgVertex & vi = vertices[i];
3898 vi.i = R2ToI2(vi.r);
3899 vi.r = I2ToR2(vi.i);
3900
3901 // a good new point
3902 vi.ReferenceNumber=0;
3903 Triangle *tcvi = TriangleFindFromCoord(vi.i,det3);
3904 if (tcvi && !tcvi->link) {
3905 _printf_("problem inserting point in SplitInternalEdgeWithBorderVertices (tcvj && !tcvj->link)\n");
3906 }
3907
3908 quadtree->Add(vi);
3909 if (!tcvi || tcvi->det<0){// internal
3910 _error_("!tcvi || tcvi->det < 0");
3911 }
3912 AddVertex(vi,tcvi,det3);
3913 NbSwap += vi.Optim(1);
3914 iv++;
3915 }
3916 if (verbose>3) {
3917 _printf_(" number of points: " << iv << "\n");
3918 _printf_(" number of swap to split internal edges with border vertices: " << NbSwap << "\n");
3919 nbv = iv;
3920 }
3921 }
3922 if (NbSplitEdge>nbv-nbvold) _printf_("WARNING: not enough vertices to split all internal edges, we lost " << NbSplitEdge - ( nbv-nbvold) << " edges...\n");
3923 if (verbose>2) _printf_("SplitInternalEdgeWithBorderVertices: Number of splited edge " << NbSplitEdge << "\n");
3924
3925 return NbSplitEdge;
3926 }
3927 /*}}}*/
3928 I2 Mesh::R2ToI2(const R2 & P) const {/*{{{*/
3929 return I2( (int) (coefIcoor*(P.x-pmin.x)),(int) (coefIcoor*(P.y-pmin.y)) );
3930 }
3931 /*}}}*/
3932 R2 Mesh::I2ToR2(const I2 & P) const {/*{{{*/
3933 return R2( (double) P.x/coefIcoor+pmin.x, (double) P.y/coefIcoor+pmin.y);
3934 }
3935 /*}}}*/
3936 Triangle * Mesh::TriangleFindFromCoord(const I2 & B,Icoor2 det3[3], Triangle *tstart) const {/*{{{*/
3937 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/FindTriangleContening)*/
3938
3939 Triangle * t=0;
3940 int j,jp,jn,jj;
3941 int counter;
3942
3943 /*Get starting triangle. Take tsart if provided*/
3944 if (tstart) t=tstart;
3945
3946 /*Else find the closest Triangle using the quadtree*/
3947 else {
3948
3949 /*Check that the quadtree does exist*/
3950 if (!quadtree) _error_("no starting triangle provided and no quadtree available");
3951
3952 /*Call NearestVertex*/
3953 BamgVertex *a = quadtree->NearestVertex(B.x,B.y) ;
3954
3955 /*Check output (Vertex a)*/
3956 if (!a) _error_("problem while trying to find nearest vertex from a given point. No output found");
3957 if (!a->t) _error_("no triangle is associated to vertex number " << GetId(a)+1 << " (orphan?)");
3958 _assert_(a>=vertices && a<vertices+nbv);
3959
3960 /*Get starting triangle*/
3961 t = a->t;
3962 _assert_(t>=triangles && t<triangles+nbt);
3963 }
3964
3965 Icoor2 detop ;
3966
3967 /*initialize number of test triangle*/
3968 counter=0;
3969
3970 /*The initial triangle might be outside*/
3971 while (t->det < 0){
3972
3973 /*Get a real vertex from this triangle (k0)*/
3974 int k0=(*t)(0)?(((*t)(1)?((*t)(2)?-1:2):1)):0;
3975 _assert_(k0>=0);// k0 the NULL vertex
3976 int k1=NextVertex[k0],k2=PreviousVertex[k0];
3977 det3[k0]=det(B,(*t)[k1],(*t)[k2]);
3978 det3[k1]=det3[k2]=-1;
3979 if (det3[k0] > 0) // outside B
3980 return t;
3981 t = t->TriangleAdj(OppositeEdge[k0]);
3982 counter++;
3983 _assert_(counter<2);
3984 }
3985
3986 jj=0;
3987 detop = det(*(*t)(VerticesOfTriangularEdge[jj][0]),*(*t)(VerticesOfTriangularEdge[jj][1]),B);
3988
3989 while(t->det>0){
3990
3991 /*Increase counter*/
3992 if (++counter>=10000) _error_("Maximum number of iteration reached (threshold = " << counter << ").");
3993
3994 j= OppositeVertex[jj];
3995 det3[j] = detop; //det(*b,*s1,*s2);
3996 jn = NextVertex[j];
3997 jp = PreviousVertex[j];
3998 det3[jp]= det(*(*t)(j),*(*t)(jn),B);
3999 det3[jn] = t->det-det3[j] -det3[jp];
4000
4001 // count the number k of det3 <0
4002 int k=0,ii[3];
4003 if (det3[0] < 0 ) ii[k++]=0;
4004 if (det3[1] < 0 ) ii[k++]=1;
4005 if (det3[2] < 0 ) ii[k++]=2;
4006 // 0 => ok
4007 // 1 => go in way 1
4008 // 2 => two way go in way 1 or 2 randomly
4009
4010 if (k==0) break;
4011 if (k==2 && BinaryRand()) Exchange(ii[0],ii[1]);
4012 _assert_(k<3);
4013 AdjacentTriangle t1 = t->Adj(jj=ii[0]);
4014 if ((t1.det() < 0 ) && (k == 2))
4015 t1 = t->Adj(jj=ii[1]);
4016 t=t1;
4017 j=t1;// for optimisation we now the -det[OppositeVertex[j]];
4018 detop = -det3[OppositeVertex[jj]];
4019 jj = j;
4020 }
4021
4022 if (t->det<0) // outside triangle
4023 det3[0]=det3[1]=det3[2]=-1,det3[OppositeVertex[jj]]=detop;
4024 return t;
4025 }
4026 /*}}}*/
4027 void Mesh::TriangleIntNumbering(long* renumbering){/*{{{*/
4028
4029 long num=0;
4030 for (int i=0;i<nbt;i++){
4031 if (triangles[i].det>0) renumbering[i]=num++;
4032 else renumbering[i]=-1;
4033 }
4034 return;
4035 }
4036 /*}}}*/
4037 long Mesh::TriangleReferenceList(long* reft) const {/*{{{*/
4038 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/ConsRefTriangle)*/
4039
4040 Triangle *t0,*t;
4041 long k=0, num;
4042
4043 //initialize all triangles as -1 (outside)
4044 for (int it=0;it<nbt;it++) reft[it]=-1;
4045
4046 //loop over all subdomains
4047 for (int i=0;i<nbsubdomains;i++){
4048
4049 //first triangle of the subdomain i
4050 t=t0=subdomains[i].head;
4051
4052 //check that the subdomain is not empty
4053 if (!t0){ _error_("At least one subdomain is empty");}
4054
4055 //loop
4056 do{
4057 k++;
4058
4059 //get current triangle number
4060 num = GetId(t);
4061
4062 //check that num is in [0 nbt[
4063 _assert_(num>=0 && num<nbt);
4064
4065 //reft of this triangle is the subdomain number
4066 reft[num]=i;
4067
4068 } while (t0 != (t=t->link));
4069 //stop when all triangles of subdomains have been tagged
4070
4071 }
4072 return k;
4073 }
4074 /*}}}*/
4075 void Mesh::Triangulate(double* x,double* y,int nods){/*{{{*/
4076
4077 int verbose=0;
4078 int i;
4079 Metric M1(1);
4080
4081 /*Initialize mesh*/
4082 Init(nods);//this resets nbv to 0
4083 nbv=nods;
4084
4085 //Vertices
4086 if(verbose) _printf_("Reading vertices (" << nbv << ")\n");
4087 for(i=0;i<nbv;i++){
4088 vertices[i].r.x=x[i];
4089 vertices[i].r.y=y[i];
4090 vertices[i].ReferenceNumber=1;
4091 vertices[i].m=M1;
4092 vertices[i].color=0;
4093 }
4094 maxnbt=2*maxnbv-2; // for filling The Holes and quadrilaterals
4095
4096 /*Insert Vertices*/
4097 Insert(true);
4098 }
4099 /*}}}*/
4100 void Mesh::TriangulateFromGeom0(BamgOpts* bamgopts){/*{{{*/
4101 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/GeomToTriangles0)*/
4102 /*Generate mesh from geometry*/
4103
4104 /*Intermediaries*/
4105 int i,k;
4106 int nbcurves = 0;
4107 int NbNewPoints,NbEdgeCurve;
4108 double lcurve,lstep,s;
4109 const int MaxSubEdge = 10;
4110
4111 R2 AB;
4112 GeomVertex *a, *b;
4113 BamgVertex *va,*vb;
4114 GeomEdge *e;
4115
4116 // add a ref to GH to make sure that it is not destroyed by mistake
4117 Gh.NbRef++;
4118
4119 /*Get options*/
4120 int verbose=bamgopts->verbose;
4121
4122 //build background mesh flag (1 if background, else 0)
4123 bool background=(&BTh != this);
4124
4125 /*Build VerticesOnGeomVertex*/
4126
4127 //Compute the number of geometrical vertices that we are going to use to mesh
4128 for (i=0;i<Gh.nbv;i++){
4129 if (Gh[i].Required()) NbVerticesOnGeomVertex++;
4130 }
4131 //allocate
4132 VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];
4133 if(NbVerticesOnGeomVertex >= maxnbv) _error_("too many vertices on geometry: " << NbVerticesOnGeomVertex << " >= " << maxnbv);
4134 _assert_(nbv==0);
4135 //Build VerticesOnGeomVertex
4136 for (i=0;i<Gh.nbv;i++){
4137 /* Add vertex only if required*/
4138 if (Gh[i].Required()) {//Gh vertices Required
4139
4140 //Add the vertex
4141 _assert_(nbv<maxnbv);
4142 vertices[nbv]=Gh[i];
4143
4144 //Add pointer from geometry (Gh) to vertex from mesh (Th)
4145 Gh[i].MeshVertexHook=vertices+nbv;
4146
4147 //Build VerticesOnGeomVertex for current point
4148 VerticesOnGeomVertex[nbv]=VertexOnGeom(*Gh[i].MeshVertexHook,Gh[i]);
4149
4150 //nbv increment
4151 nbv++;
4152 }
4153 }
4154
4155 /*Build VerticesOnGeomEdge*/
4156
4157 //check that edges is still empty (Init)
4158 _assert_(!edges);
4159
4160 /* Now we are going to create the first edges corresponding
4161 * to the one present in the geometry provided.
4162 * We proceed in 2 steps
4163 * -step 0: we count all the edges
4164 * we allocate the number of edges at the end of step 0
4165 * -step 1: the edges are created */
4166 for (int step=0;step<2;step++){
4167
4168 //initialize number of edges and number of edges max
4169 long nbex=0;
4170 nbe=0;
4171 long NbVerticesOnGeomEdge0=NbVerticesOnGeomEdge;
4172 Gh.UnMarkEdges();
4173 nbcurves=0;
4174
4175 //go through the edges of the geometry
4176 for (i=0;i<Gh.nbe;i++){
4177
4178 //ei = current Geometrical edge
4179 GeomEdge &ei=Gh.edges[i];
4180
4181 //loop over the two vertices of the edge ei
4182 for(int j=0;j<2;j++) {
4183
4184 /*Take only required vertices (corner->beginning of a new curve)*/
4185 if (!ei.Mark() && ei[j].Required()){
4186
4187 long nbvend=0;
4188 Edge* PreviousNewEdge=NULL;
4189 lstep = -1;
4190
4191 /*If Edge is required (do that only once for the 2 vertices)*/
4192 if(ei.Required()){
4193 if (j==0){
4194 //do not create internal points if required (take it as is)
4195 if(step==0) nbe++;
4196 else{
4197 e=&ei;
4198 a=ei(0);
4199 b=ei(1);
4200
4201 //check that edges has been allocated
4202 _assert_(edges);
4203 edges[nbe].v[0]=a->MeshVertexHook;
4204 edges[nbe].v[1]=b->MeshVertexHook;;
4205 edges[nbe].ReferenceNumber = e->ReferenceNumber;
4206 edges[nbe].GeomEdgeHook = e;
4207 edges[nbe].adj[0] = 0;
4208 edges[nbe].adj[1] = 0;
4209 nbe++;
4210 }
4211 }
4212 }
4213
4214 /*If Edge is not required: we are on a curve*/
4215 else {
4216 for (int kstep=0;kstep<=step;kstep++){
4217 //kstep=0, compute number of edges (discretize curve)
4218 //kstep=1 create the points and edge
4219 PreviousNewEdge=0;
4220 NbNewPoints=0;
4221 NbEdgeCurve=0;
4222 if (nbvend>=maxnbv) _error_("maximum number of vertices too low! Check the domain outline or increase maxnbv");
4223 lcurve =0;
4224 s = lstep; //-1 initially, then length of each sub edge
4225
4226 /*reminder: i = edge number, j=[0;1] vertex index in edge*/
4227 k=j; // k = vertex index in edge (0 or 1)
4228 e=&ei; // e = reference of current edge
4229 a=ei(k); // a = pointer toward the kth vertex of the current edge
4230 va = a->MeshVertexHook; // va = pointer toward mesh vertex associated
4231 e->SetMark(); // Mark edge
4232
4233 /*Loop until we reach the end of the curve*/
4234 for(;;){
4235 k = 1-k; // other vertx index of the curve
4236 b = (*e)(k); // b = pointer toward the other vertex of the current edge
4237 AB= b->r - a->r; // AB = vector of the current edge
4238 Metric MA = background ? BTh.MetricAt(a->r) :a->m ; //Get metric associated to A
4239 Metric MB = background ? BTh.MetricAt(b->r) :b->m ; //Get metric associated to B
4240 double ledge = (MA.Length(AB.x,AB.y) + MB.Length(AB.x,AB.y))/2; //Get edge length in metric
4241
4242 /* We are now creating the mesh edges from the geometrical edge selected above.
4243 * The edge will be divided according to the metric previously computed and cannot
4244 * be divided more than 10 times (MaxSubEdge). */
4245
4246 //By default, there is only one subedge that is the geometrical edge itself
4247 int NbSubEdge = 1;
4248
4249 //initialize lSubEdge, holding the length of each subedge (cannot be higher than 10)
4250 double lSubEdge[MaxSubEdge];
4251
4252 //Build Subedges according to the edge length
4253 if (ledge < 1.5){
4254 //if ledge < 1.5 (between one and 2), take the edge as is
4255 lSubEdge[0] = ledge;
4256 }
4257 //else, divide the edge
4258 else {
4259 //compute number of subedges (division of the edge), Maximum is 10
4260 NbSubEdge = Min( MaxSubEdge, (int) (ledge +0.5));
4261 /*Now, we are going to divide the edge according to the metric.
4262 * Get segment by sement along the edge.
4263 * Build lSubEdge, which holds the distance between the first vertex
4264 * of the edge and the next point on the edge according to the
4265 * discretization (each SubEdge is AB)*/
4266 R2 A,B;
4267 A=a->r;
4268 Metric MAs=MA,MBs;
4269 ledge=0;
4270 double x =0, xstep= 1./NbSubEdge;
4271 for (int kk=0; kk < NbSubEdge; kk++,A=B,MAs=MBs ) {
4272 x += xstep;
4273 B = e->F(k ? x : 1-x);
4274 MBs= background ? BTh.MetricAt(B) : Metric(1-x,MA,x,MB);
4275 AB = A-B;
4276 lSubEdge[kk]=(ledge+=(MAs.Length(AB.x,AB.y)+MBs.Length(AB.x,AB.y))/2);
4277 }
4278 }
4279
4280 double lcurveb = lcurve+ledge;
4281
4282 /*Now, create corresponding points*/
4283 while(s>=lcurve && s<=lcurveb && nbv<nbvend){
4284
4285 /*Schematic of current curve
4286 *
4287 * a vb b // vertex
4288 * 0 ll0 ll1 ledge // length from a
4289 * + --- + - ... - + --S-- + --- + - ... - + // where is S
4290 * 0 kk0 kk1 NbSubEdge // Sub edge index
4291 *
4292 */
4293
4294 double ss = s-lcurve;
4295
4296 /*Find the SubEdge containing ss using Dichotomy*/
4297 int kk0=-1,kk1=NbSubEdge-1,kkk;
4298 double ll0=0,ll1=ledge,llk;
4299 while (kk1-kk0>1){
4300 if (ss < (llk=lSubEdge[kkk=(kk0+kk1)/2]))
4301 kk1=kkk,ll1=llk;
4302 else
4303 kk0=kkk,ll0=llk;
4304 }
4305 _assert_(kk1!=kk0);
4306
4307 /*Curvilinear coordinate in [0 1] of ss in current edge*/
4308 // WARNING: This is what we would do
4309 // ssa = (ss-ll0)/(ll1-ll0);
4310 // aa = (kk0+ssa)/NbSubEdge
4311 // This is what Bamg does:
4312 double sbb = (ss-ll0)/(ll1-ll0);
4313 /*Curvilinear coordinate in [0 1] of ss in current curve*/
4314 double bb = (kk1+sbb)/NbSubEdge;
4315 double aa = 1-bb;
4316
4317 // new vertex on edge
4318 vb = &vertices[nbv++];
4319 vb->m = Metric(aa,a->m,bb,b->m);
4320 vb->ReferenceNumber = e->ReferenceNumber;
4321 double abcisse = k ? bb : aa;
4322 vb->r = e->F(abcisse);
4323 VerticesOnGeomEdge[NbVerticesOnGeomEdge++]= VertexOnGeom(*vb,*e,abcisse);
4324
4325 // to take into account the direction of the edge
4326 s += lstep;
4327 edges[nbe].v[0]=va;
4328 edges[nbe].v[1]=vb;
4329 edges[nbe].ReferenceNumber =e->ReferenceNumber;
4330 edges[nbe].GeomEdgeHook = e;
4331 edges[nbe].adj[0] = PreviousNewEdge;
4332 if(PreviousNewEdge) PreviousNewEdge->adj[1]=&edges[nbe];
4333 PreviousNewEdge=edges+nbe;
4334 nbe++;
4335 va = vb;
4336 }
4337
4338 /*We just added one edge to the curve: Go to the next one*/
4339 lcurve = lcurveb;
4340 e->SetMark();
4341 a=b;
4342
4343 /*If b is required, we are on a new curve->break*/
4344 if (b->Required()) break;
4345 int kprev=k;
4346 k = e->AdjVertexIndex[kprev];// next vertices
4347 e = e->Adj[kprev];
4348 _assert_(e);
4349 }// for(;;)
4350 vb = b->MeshVertexHook;
4351
4352 /*Number of edges in the last disretized curve*/
4353 NbEdgeCurve = Max((long) (lcurve +0.5), (long) 1);
4354 /*Number of internal vertices in the last disretized curve*/
4355 NbNewPoints = NbEdgeCurve-1;
4356 if(!kstep){
4357 NbVerticesOnGeomEdge0 += NbNewPoints;
4358 nbcurves++;
4359 }
4360 nbvend=nbv+NbNewPoints;
4361 lstep = lcurve / NbEdgeCurve; //approximately one
4362 }// end of curve --
4363 if (edges) { // last edges of the curves
4364 edges[nbe].v[0]=va;
4365 edges[nbe].v[1]=vb;
4366 edges[nbe].ReferenceNumber = e->ReferenceNumber;
4367 edges[nbe].GeomEdgeHook = e;
4368 edges[nbe].adj[0] = PreviousNewEdge;
4369 edges[nbe].adj[1] = 0;
4370 if(PreviousNewEdge) PreviousNewEdge->adj[1] = & edges[nbe];
4371 nbe++;
4372 }
4373 else nbe += NbEdgeCurve;
4374 } // end on curve ---
4375 }
4376 }
4377 } // for (i=0;i<nbe;i++)
4378 if(!step) {
4379 _assert_(!edges);
4380 _assert_(!VerticesOnGeomEdge);
4381
4382 edges = new Edge[nbex=nbe];
4383 if(NbVerticesOnGeomEdge0) VerticesOnGeomEdge = new VertexOnGeom[NbVerticesOnGeomEdge0];
4384
4385 // do the vertex on a geometrical vertex
4386 _assert_(VerticesOnGeomEdge || NbVerticesOnGeomEdge0==0);
4387 NbVerticesOnGeomEdge0 = NbVerticesOnGeomEdge;
4388 }
4389 else{
4390 _assert_(NbVerticesOnGeomEdge==NbVerticesOnGeomEdge0);
4391 }
4392 }
4393
4394 //Insert points inside existing triangles
4395 if (verbose>4) _printf_(" -- current number of vertices = " << nbv << "\n");
4396 if (verbose>3) _printf_(" Creating initial Constrained Delaunay Triangulation...\n");
4397 if (verbose>3) _printf_(" Inserting boundary points\n");
4398 Insert(bamgopts->random);
4399
4400 //Force the boundary
4401 if (verbose>3) _printf_(" Forcing boundaries\n");
4402 ForceBoundary();
4403
4404 //Extract SubDomains
4405 if (verbose>3) _printf_(" Extracting subdomains\n");
4406 FindSubDomain();
4407
4408 if (verbose>3) _printf_(" Inserting internal points\n");
4409 NewPoints(*this,bamgopts,0) ;
4410 if (verbose>4) _printf_(" -- current number of vertices = " << nbv << "\n");
4411 }
4412 /*}}}*/
4413 void Mesh::TriangulateFromGeom1(BamgOpts* bamgopts,int KeepVertices){ /*{{{*/
4414 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/GeomToTriangles1)*/
4415
4416 /*Get options*/
4417 int verbose=bamgopts->verbose;
4418
4419 Gh.NbRef++;// add a ref to Gh
4420
4421 /*************************************************************************
4422 * method in 2 steps
4423 * 1 - compute the number of new edges to allocate
4424 * 2 - construct the edges
4425 * remark:
4426 * in this part we suppose to have a background mesh with the same geometry
4427 *
4428 * To construct the discretization of the new mesh we have to
4429 * rediscretize the boundary of background Mesh
4430 * because we have only the pointeur from the background mesh to the geometry.
4431 * We need the abcisse of the background mesh vertices on geometry
4432 * so a vertex is
4433 * 0 on GeomVertex ;
4434 * 1 on GeomEdge + abcisse
4435 * 2 internal
4436 *************************************************************************/
4437
4438 //Check that background mesh and current mesh do have the same geometry
4439 _assert_(&BTh.Gh==&Gh);
4440 BTh.NbRef++; // add a ref to BackGround Mesh
4441
4442 //Initialize new mesh
4443 BTh.SetVertexFieldOn();
4444 int* bcurve = new int[Gh.nbcurves]; //
4445
4446 /* There are 2 ways to make the loop
4447 * 1) on the geometry
4448 * 2) on the background mesh
4449 * if you do the loop on geometry, we don't have the pointeur on background,
4450 * and if you do the loop in background we have the pointeur on geometry
4451 * so do the walk on background */
4452
4453 NbVerticesOnGeomVertex=0;
4454 NbVerticesOnGeomEdge=0;
4455
4456 /*STEP 1 copy of Required vertices*/
4457
4458 int i;
4459 for (i=0;i<Gh.nbv;i++) if (Gh[i].Required()) NbVerticesOnGeomVertex++;
4460 printf("\n");
4461 if(NbVerticesOnGeomVertex >= maxnbv){
4462 _error_("too many vertices on geometry: " << NbVerticesOnGeomVertex << " >= " << maxnbv);
4463 }
4464
4465 VerticesOnGeomVertex = new VertexOnGeom[ NbVerticesOnGeomVertex];
4466 VertexOnBThVertex = new VertexOnVertex[NbVerticesOnGeomVertex];
4467
4468 //At this point there is NO vertex but vertices should have been allocated by Init
4469 _assert_(vertices);
4470 for (i=0;i<Gh.nbv;i++){
4471 if (Gh[i].Required()) {//Gh vertices Required
4472 vertices[nbv] =Gh[i];
4473 vertices[nbv].i=I2(0,0);
4474 Gh[i].MeshVertexHook = vertices + nbv;// save Geom -> Th
4475 VerticesOnGeomVertex[nbv]= VertexOnGeom(vertices[nbv],Gh[i]);
4476 nbv++;
4477 }
4478 else Gh[i].MeshVertexHook=0;
4479 }
4480 for (i=0;i<BTh.NbVerticesOnGeomVertex;i++){
4481 VertexOnGeom &vog=BTh.VerticesOnGeomVertex[i];
4482 if (vog.IsRequiredVertex()){
4483 GeomVertex* gv=vog;
4484 BamgVertex *bv = vog;
4485 _assert_(gv->MeshVertexHook); // use of Geom -> Th
4486 VertexOnBThVertex[NbVertexOnBThVertex++]=VertexOnVertex(gv->MeshVertexHook,bv);
4487 gv->MeshVertexHook->m = bv->m; // for taking the metric of the background mesh
4488 }
4489 }
4490 _assert_(NbVertexOnBThVertex==NbVerticesOnGeomVertex); /*This might be due to MaxCornerAngle too small*/
4491
4492 /*STEP 2: reseed boundary edges*/
4493
4494 // find the begining of the curve in BTh
4495 Gh.UnMarkEdges();
4496 int bfind=0;
4497 for (int i=0;i<Gh.nbcurves;i++) bcurve[i]=-1;
4498
4499 /*Loop over the backgrounf mesh BTh edges*/
4500 for (int iedge=0;iedge<BTh.nbe;iedge++){
4501 Edge &ei = BTh.edges[iedge];
4502
4503 /*Loop over the 2 vertices of the current edge*/
4504 for(int je=0;je<2;je++){
4505
4506 /* If one of the vertex is required we are in a new curve*/
4507 if (ei[je].GeomEdgeHook->IsRequiredVertex()){
4508
4509 /*Get curve number*/
4510 int nc=ei.GeomEdgeHook->CurveNumber;
4511
4512 //_printf_("Dealing with curve number " << nc << "\n");
4513 //_printf_("edge on geometry is same as GhCurve? " << (ei.GeomEdgeHook==Gh.curves[nc].FirstEdge || ei.GeomEdgeHook==Gh.curves[nc].LastEdge)?"yes":"no\n");
4514 //if(ei.GeomEdgeHook==Gh.curves[nc].FirstEdge || ei.GeomEdgeHook==Gh.curves[nc].LastEdge){
4515 // _printf_("Do we have the right extremity? curve first vertex -> " << ((GeomVertex *)*ei[je].GeomEdgeHook==&(*Gh.curves[nc].FirstEdge)[Gh.curves[nc].FirstVertexIndex])?"yes":"no\n");
4516 // _printf_("Do we have the right extremity? curve last vertex -> " << ((GeomVertex *)*ei[je].GeomEdgeHook==&(*Gh.curves[nc].LastEdge)[Gh.curves[nc].LastVertexIndex])?"yes":"no\n");
4517 //}
4518 //BUG FIX from original bamg
4519 /*Check that we are on the same edge and right vertex (0 or 1) */
4520 if(ei.GeomEdgeHook==Gh.curves[nc].FirstEdge && (GeomVertex *)*ei[je].GeomEdgeHook==&(*Gh.curves[nc].FirstEdge)[Gh.curves[nc].FirstVertexIndex]){
4521 bcurve[nc]=iedge*2+je;
4522 bfind++;
4523 }
4524 else if ((ei.GeomEdgeHook==Gh.curves[nc].LastEdge && (GeomVertex *)*ei[je].GeomEdgeHook==&(*Gh.curves[nc].LastEdge)[Gh.curves[nc].LastVertexIndex]) && bcurve[nc]==-1){
4525 bcurve[nc]=iedge*2+je;
4526 bfind++;
4527 }
4528 }
4529 }
4530 }
4531 if (bfind!=Gh.nbcurves){
4532 delete [] bcurve;
4533 _error_("problem generating number of curves (" << Gh.nbcurves << " found in the geometry but " << bfind << " curve found in the mesh)");
4534 }
4535
4536 // method in 2 + 1 step
4537 // 0.0) compute the length and the number of vertex to do allocation
4538 // 1.0) recompute the length
4539 // 1.1) compute the vertex
4540
4541 long nbex=0,NbVerticesOnGeomEdgex=0;
4542 for (int step=0; step <2;step++){
4543
4544 long NbOfNewPoints=0;
4545 long NbOfNewEdge=0;
4546 long iedge;
4547 Gh.UnMarkEdges();
4548 double L=0;
4549
4550 /*Go through all geometrical curve*/
4551 for (int icurve=0;icurve<Gh.nbcurves;icurve++){
4552
4553 /*Get edge and vertex (index) of background mesh on this curve*/
4554 iedge=bcurve[icurve]/2;
4555 int jedge=bcurve[icurve]%2;
4556
4557 /*Get edge of Bth with index iedge*/
4558 Edge &ei = BTh.edges[iedge];
4559
4560 /*Initialize variables*/
4561 double Lstep=0; // step between two points (phase==1)
4562 long NbCreatePointOnCurve=0;// Nb of new points on curve (phase==1)
4563
4564 /*Do phase 0 to step*/
4565 for(int phase=0;phase<=step;phase++){
4566
4567 /*Current curve pointer*/
4568 Curve *curve= Gh.curves+icurve;
4569
4570 /*Get index of current curve*/
4571 int icurveequi= Gh.GetId(curve);
4572
4573 /*For phase 0, check that we are at the begining of the curve only*/
4574 if(phase==0 && icurveequi!=icurve) continue;
4575
4576 int k0=jedge,k1;
4577 Edge* pe= BTh.edges+iedge;
4578 int iedgeequi=bcurve[icurveequi]/2;
4579 int jedgeequi=bcurve[icurveequi]%2;
4580
4581 int k0equi=jedgeequi,k1equi;
4582 Edge * peequi= BTh.edges+iedgeequi;
4583 GeomEdge *ongequi = peequi->GeomEdgeHook;
4584
4585 double sNew=Lstep;// abscisse of the new points (phase==1)
4586 L=0;// length of the curve
4587 long i=0;// index of new points on the curve
4588 GeomVertex * GA0 = *(*peequi)[k0equi].GeomEdgeHook;
4589 BamgVertex *A0;
4590 A0 = GA0->MeshVertexHook; // the vertex in new mesh
4591 BamgVertex *A1;
4592 VertexOnGeom *GA1;
4593 Edge* PreviousNewEdge = 0;
4594
4595 // New Curve phase
4596 _assert_(A0-vertices>=0 && A0-vertices<nbv);
4597 if(ongequi->Required()){
4598 GeomVertex *GA1 = *(*peequi)[1-k0equi].GeomEdgeHook;
4599 A1 = GA1->MeshVertexHook; //
4600 }
4601 else {
4602 for(;;){
4603 Edge &ee=*pe;
4604 Edge &eeequi=*peequi;
4605 k1 = 1-k0; // next vertex of the edge
4606 k1equi= 1 - k0equi;
4607 _assert_(pe && ee.GeomEdgeHook);
4608 ee.GeomEdgeHook->SetMark();
4609 BamgVertex & v0=ee[0], & v1=ee[1];
4610 R2 AB=(R2)v1-(R2)v0;
4611 double L0=L,LAB;
4612 LAB=LengthInterpole(v0.m,v1.m,AB);
4613 L+= LAB;
4614
4615 if (phase){
4616 // computation of the new points for the given curve
4617 while ((i!=NbCreatePointOnCurve) && sNew<=L) {
4618
4619 //some checks
4620 _assert_(sNew>=L0);
4621 _assert_(LAB);
4622 _assert_(vertices && nbv<maxnbv);
4623 _assert_(edges && nbe<nbex);
4624 _assert_(VerticesOnGeomEdge && NbVerticesOnGeomEdge<NbVerticesOnGeomEdgex);
4625
4626 // new vertex on edge
4627 A1=vertices+nbv++;
4628 GA1=VerticesOnGeomEdge+NbVerticesOnGeomEdge;
4629 Edge* e = edges + nbe++;
4630 double se= (sNew-L0)/LAB;
4631 if (se<0 || se>=1.000000001){
4632 _error_("Problem creating point on a boundary: se=" << se << " should be in [0 1]");
4633 }
4634 se = abscisseInterpole(v0.m,v1.m,AB,se,1);
4635 if (se<0 || se>1){
4636 _error_("Problem creating point on a boundary: se=" << se << " should be in [0 1]");
4637 }
4638 se = k1 ? se : 1. - se;
4639 se = k1==k1equi ? se : 1. - se;
4640 VertexOnBThEdge[NbVerticesOnGeomEdge++] = VertexOnEdge(A1,&eeequi,se); // save
4641 ongequi=Gh.ProjectOnCurve(eeequi,se,*A1,*GA1);
4642 A1->ReferenceNumber = eeequi.ReferenceNumber;
4643 e->GeomEdgeHook = ongequi;
4644 e->v[0]=A0;
4645 e->v[1]=A1;
4646 e->ReferenceNumber = eeequi.ReferenceNumber;
4647 e->adj[0]=PreviousNewEdge;
4648
4649 if (PreviousNewEdge) PreviousNewEdge->adj[1]=e;
4650 PreviousNewEdge=e;
4651 A0=A1;
4652 sNew += Lstep;
4653 if (++i== NbCreatePointOnCurve) break;
4654 }
4655 }
4656
4657 //some checks
4658 _assert_(ee.GeomEdgeHook->CurveNumber==ei.GeomEdgeHook->CurveNumber);
4659 if (ee[k1].GeomEdgeHook->IsRequiredVertex()) {
4660 _assert_(eeequi[k1equi].GeomEdgeHook->IsRequiredVertex());
4661 GeomVertex * GA1 = *eeequi[k1equi].GeomEdgeHook;
4662 A1=GA1->MeshVertexHook;// the vertex in new mesh
4663 _assert_(A1-vertices>=0 && A1-vertices<nbv);
4664 break;
4665 }
4666 if (!ee.adj[k1]) {
4667 _error_("adj edge " << BTh.GetId(ee) << ", nbe=" << nbe << ", Gh.vertices=" << Gh.vertices);
4668 }
4669 pe = ee.adj[k1]; // next edge
4670 k0 = pe->Intersection(ee);
4671 peequi= eeequi.adj[k1equi]; // next edge
4672 k0equi=peequi->Intersection(eeequi);
4673 }// for(;;) end of the curve
4674 }
4675
4676 if (phase){ // construction of the last edge
4677 Edge* e=edges + nbe++;
4678 e->GeomEdgeHook = ongequi;
4679 e->v[0]=A0;
4680 e->v[1]=A1;
4681 e->ReferenceNumber = peequi->ReferenceNumber;
4682 e->adj[0]=PreviousNewEdge;
4683 e->adj[1]=0;
4684 if (PreviousNewEdge) PreviousNewEdge->adj[1]=e;
4685 PreviousNewEdge = e;
4686
4687 _assert_(i==NbCreatePointOnCurve);
4688 }
4689
4690 if (!phase) { //
4691 long NbSegOnCurve = Max((long)(L+0.5),(long) 1);// nb of seg
4692 Lstep = L/NbSegOnCurve;
4693 NbCreatePointOnCurve = NbSegOnCurve-1;
4694 NbOfNewEdge += NbSegOnCurve;
4695 NbOfNewPoints += NbCreatePointOnCurve;
4696 }
4697 }
4698 }// end of curve loop
4699
4700 //Allocate memory
4701 if(step==0){
4702 if(nbv+NbOfNewPoints > maxnbv) {
4703 _error_("too many vertices on geometry: " << nbv+NbOfNewPoints << " >= " << maxnbv);
4704 }
4705 edges = new Edge[NbOfNewEdge];
4706 nbex = NbOfNewEdge;
4707 if(NbOfNewPoints) {
4708 VerticesOnGeomEdge = new VertexOnGeom[NbOfNewPoints];
4709 NbVertexOnBThEdge = NbOfNewPoints;
4710 VertexOnBThEdge = new VertexOnEdge[NbOfNewPoints];
4711 NbVerticesOnGeomEdgex = NbOfNewPoints;
4712 }
4713 NbOfNewPoints =0;
4714 NbOfNewEdge = 0;
4715 }
4716 }
4717 _assert_(nbe!=0);
4718 delete [] bcurve;
4719
4720 //Insert points inside existing triangles
4721 if (verbose>4) _printf_(" -- current number of vertices = " << nbv << "\n");
4722 if (verbose>3) _printf_(" Creating initial Constrained Delaunay Triangulation...\n");
4723 if (verbose>3) _printf_(" Inserting boundary points\n");
4724 Insert(bamgopts->random);
4725
4726 //Force the boundary
4727 if (verbose>3) _printf_(" Forcing boundaries\n");
4728 ForceBoundary();
4729
4730 //Extract SubDomains
4731 if (verbose>3) _printf_(" Extracting subdomains\n");
4732 FindSubDomain();
4733
4734 if (verbose>3) _printf_(" Inserting internal points\n");
4735 NewPoints(BTh,bamgopts,KeepVertices) ;
4736 if (verbose>4) _printf_(" -- current number of vertices = " << nbv << "\n");
4737 }
4738 /*}}}*/
4739
4740 /*Intermediary*/
4741 AdjacentTriangle CloseBoundaryEdge(I2 A,Triangle *t, double &a,double &b) {/*{{{*/
4742 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/CloseBoundaryEdge)*/
4743
4744 int k=(*t)(0) ? (( (*t)(1) ? ( (*t)(2) ? -1 : 2) : 1 )) : 0;
4745 int dir=0;
4746 if (k<0){
4747 _error_("k<0");
4748 }
4749 int kkk=0;
4750 Icoor2 IJ_IA,IJ_AJ;
4751 AdjacentTriangle edge(t,OppositeEdge[k]);
4752 for (;;edge = dir >0 ? Next(Adj(Next(edge))) : Previous(Adj(Previous(edge)))) {
4753 kkk++;
4754 if (kkk>=1000){
4755 _error_("kkk>=1000");
4756 }
4757 BamgVertex &vI = *edge.EdgeVertex(0);
4758 BamgVertex &vJ = *edge.EdgeVertex(1);
4759 I2 I=vI, J=vJ, IJ= J-I;
4760 IJ_IA = (IJ ,(A-I));
4761 if (IJ_IA<0) {
4762 if (dir>0) {a=1;b=0;return edge;}// change of signe => I
4763 else {dir=-1;
4764 continue;}};// go in direction i
4765 IJ_AJ = (IJ ,(J-A));
4766 if (IJ_AJ<0) {
4767 if(dir<0) {a=0;b=1;return edge;}
4768 else {dir = 1;
4769 continue;}}// go in direction j
4770 double IJ2 = IJ_IA + IJ_AJ;
4771 if (IJ2==0){
4772 _error_("IJ2==0");
4773 }
4774 a= IJ_AJ/IJ2;
4775 b= IJ_IA/IJ2;
4776 return edge;
4777 }
4778 }
4779 /*}}}*/
4780 int ForceEdge(BamgVertex &a, BamgVertex & b,AdjacentTriangle & taret) { /*{{{*/
4781 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/ForceEdge)*/
4782
4783 int NbSwap =0;
4784 if (!a.t || !b.t){ // the 2 vertex is in a mesh
4785 _error_("!a.t || !b.t");
4786 }
4787 int k=0;
4788 taret=AdjacentTriangle(0,0); // erreur
4789
4790 AdjacentTriangle tta(a.t,EdgesVertexTriangle[a.IndexInTriangle][0]);
4791 BamgVertex *v1, *v2 = tta.EdgeVertex(0),*vbegin =v2;
4792 // we turn around a in the direct direction
4793
4794 Icoor2 det2 = v2 ? det(*v2,a,b): -1 , det1;
4795 if(v2) // normal case
4796 det2 = det(*v2,a,b);
4797 else { // no chance infini vertex try the next
4798 tta= Previous(Adj(tta));
4799 v2 = tta.EdgeVertex(0);
4800 vbegin =v2;
4801 if (!v2){
4802 _error_("!v2");
4803 }
4804 det2 = det(*v2,a,b);
4805 }
4806
4807 while (v2 != &b) {
4808 AdjacentTriangle tc = Previous(Adj(tta));
4809 v1 = v2;
4810 v2 = tc.EdgeVertex(0);
4811 det1 = det2;
4812 det2 = v2 ? det(*v2,a,b): det2;
4813
4814 if((det1 < 0) && (det2 >0)) {
4815 // try to force the edge
4816 BamgVertex * va = &a, *vb = &b;
4817 tc = Previous(tc);
4818 if (!v1 || !v2){
4819 _error_("!v1 || !v2");
4820 }
4821 Icoor2 detss = 0,l=0;
4822 while ((SwapForForcingEdge( va, vb, tc, detss, det1,det2,NbSwap)))
4823 if(l++ > 10000000) {
4824 _error_("Loop in forcing Egde, nb de swap=" << NbSwap << ", nb of try swap (" << l << ") too big");
4825 }
4826 BamgVertex *aa = tc.EdgeVertex(0), *bb = tc.EdgeVertex(1);
4827 if (((aa == &a ) && (bb == &b)) ||((bb == &a ) && (aa == &b))){
4828 tc.SetLock();
4829 a.Optim(1,0);
4830 b.Optim(1,0);
4831 taret = tc;
4832 return NbSwap;
4833 }
4834 else
4835 {
4836 taret = tc;
4837 return -2; // error boundary is crossing
4838 }
4839 }
4840 tta = tc;
4841 k++;
4842 if (k>=2000){
4843 _error_("k>=2000");
4844 }
4845 if ( vbegin == v2 ) return -1;// error
4846 }
4847
4848 tta.SetLock();
4849 taret=tta;
4850 a.Optim(1,0);
4851 b.Optim(1,0);
4852 return NbSwap;
4853 }
4854 /*}}}*/
4855 void swap(Triangle *t1,short a1, Triangle *t2,short a2, BamgVertex *s1,BamgVertex *s2,Icoor2 det1,Icoor2 det2){ /*{{{*/
4856 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/swap)*/
4857 // --------------------------------------------------------------
4858 // short a2=aa[a];// les 2 numero de l arete dans les 2 triangles
4859 //
4860 // sb sb
4861 // / | \ / \ !
4862 // as1/ | \ /a2 \ !
4863 // / | \ / t2 \ !
4864 // s1 /t1 | t2 \s2 --> s1 /___as2___\s2 !
4865 // \ a1|a2 / \ as1 /
4866 // \ | / \ t1 /
4867 // \ | / as2 \ a1/
4868 // \ | / \ /
4869 // sa sa
4870 // -------------------------------------------------------------
4871 int as1 = NextEdge[a1];
4872 int as2 = NextEdge[a2];
4873 int ap1 = PreviousEdge[a1];
4874 int ap2 = PreviousEdge[a2];
4875 (*t1)(VerticesOfTriangularEdge[a1][1]) = s2 ; // avant sb
4876 (*t2)(VerticesOfTriangularEdge[a2][1]) = s1 ; // avant sa
4877 // mise a jour des 2 adjacences externes
4878 AdjacentTriangle taas1 = t1->Adj(as1),
4879 taas2 = t2->Adj(as2),
4880 tas1(t1,as1), tas2(t2,as2),
4881 ta1(t1,a1),ta2(t2,a2);
4882 // externe haut gauche
4883 taas1.SetAdj2(ta2, taas1.GetAllFlag_UnSwap());
4884 // externe bas droite
4885 taas2.SetAdj2(ta1, taas2.GetAllFlag_UnSwap());
4886 // remove the Mark UnMarkSwap
4887 t1->SetUnMarkUnSwap(ap1);
4888 t2->SetUnMarkUnSwap(ap2);
4889 // interne
4890 tas1.SetAdj2(tas2);
4891
4892 t1->det = det1;
4893 t2->det = det2;
4894
4895 t1->SetSingleVertexToTriangleConnectivity();
4896 t2->SetSingleVertexToTriangleConnectivity();
4897 } // end swap
4898 /*}}}*/
4899 int SwapForForcingEdge(BamgVertex * & pva ,BamgVertex * & pvb ,AdjacentTriangle & tt1,Icoor2 & dets1, Icoor2 & detsa,Icoor2 & detsb, int & NbSwap) {/*{{{*/
4900 /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/SwapForForcingEdge)*/
4901 // l'arete ta coupe l'arete pva pvb
4902 // de cas apres le swap sa coupe toujours
4903 // on cherche l'arete suivante
4904 // on suppose que detsa >0 et detsb <0
4905 // attention la routine echange pva et pvb
4906
4907 if(tt1.Locked()) return 0; // frontiere croise
4908
4909 AdjacentTriangle tt2 = Adj(tt1);
4910 Triangle *t1=tt1,*t2=tt2;// les 2 triangles adjacent
4911 short a1=tt1,a2=tt2;// les 2 numero de l arete dans les 2 triangles
4912 if ( a1<0 || a1>=3 ){
4913 _error_("a1<0 || a1>=3");
4914 }
4915
4916 BamgVertex & sa= (* t1)[VerticesOfTriangularEdge[a1][0]];
4917 BamgVertex & s1= (*t1)[OppositeVertex[a1]];
4918 BamgVertex & s2= (*t2)[OppositeVertex[a2]];
4919
4920 Icoor2 dets2 = det(*pva,*pvb,s2);
4921 Icoor2 det1=t1->det , det2=t2->det ;
4922 Icoor2 detT = det1+det2;
4923 if ((det1<=0 ) || (det2<=0)){
4924 _error_("(det1<=0 ) || (det2<=0)");
4925 }
4926 if ( (detsa>=0) || (detsb<=0) ){ // [a,b] cut infinite line va,bb
4927 _error_("(detsa>=0) || (detsb<=0)");
4928 }
4929 Icoor2 ndet1 = bamg::det(s1,sa,s2);
4930 Icoor2 ndet2 = detT - ndet1;
4931
4932 int ToSwap =0; //pas de swap
4933 if ((ndet1 >0) && (ndet2 >0))
4934 { // on peut swaper
4935 if ((dets1 <=0 && dets2 <=0) || (dets2 >=0 && detsb >=0))
4936 ToSwap =1;
4937 else // swap alleatoire
4938 if (BinaryRand())
4939 ToSwap =2;
4940 }
4941 if (ToSwap) NbSwap++,
4942 bamg::swap(t1,a1,t2,a2,&s1,&s2,ndet1,ndet2);
4943
4944 int ret=1;
4945
4946 if (dets2 < 0) {// haut
4947 dets1 = ToSwap ? dets1 : detsa ;
4948 detsa = dets2;
4949 tt1 = Previous(tt2) ;}
4950 else if (dets2 > 0){// bas
4951 dets1 = ToSwap ? dets1 : detsb ;
4952 detsb = dets2;
4953 //xxxx tt1 = ToSwap ? tt1 : Next(tt2);
4954 if(!ToSwap) tt1 = Next(tt2);
4955 }
4956 else { // changement de direction
4957 ret = -1;
4958 Exchange(pva,pvb);
4959 Exchange(detsa,detsb);
4960 Exchange(dets1,dets2);
4961 Exchange(tt1,tt2);
4962 dets1=-dets1;
4963 dets2=-dets2;
4964 detsa=-detsa;
4965 detsb=-detsb;
4966
4967 if(ToSwap){
4968 if (dets2 < 0) {// haut
4969 dets1 = (ToSwap ? dets1 : detsa) ;
4970 detsa = dets2;
4971 tt1 = Previous(tt2) ;}
4972 else if(dets2 > 0){// bas
4973 dets1 = (ToSwap ? dets1 : detsb) ;
4974 detsb = dets2;
4975 if(!ToSwap) tt1 = Next(tt2);
4976 }
4977 else {// on a fin ???
4978 tt1 = Next(tt2);
4979 ret =0;}
4980 }
4981
4982 }
4983 return ret;
4984 }
4985 /*}}}*/
4986}
Note: See TracBrowser for help on using the repository browser.