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

Last change on this file since 21243 was 20621, checked in by Mathieu Morlighem, 9 years ago

BUG: fixing bamg compilation warnings

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