Ice Sheet System Model  4.18
Code documentation
Geometry.cpp
Go to the documentation of this file.
1 #include <cstdio>
2 #include <cstring>
3 #include <cmath>
4 #include <ctime>
5 
6 #include "./bamgobjects.h"
7 #include "../shared/shared.h"
8 
9 namespace bamg {
10 
11  /*Constructors/Destructors*/
13  Init();
14  }
15  /*}}}*/
16  Geometry::Geometry(BamgGeom* bamggeom, BamgOpts* bamgopts){/*{{{*/
17  Init();
18  ReadGeometry(bamggeom,bamgopts);
19  PostRead();
20  }
21  /*}}}*/
22  Geometry::Geometry(const Geometry & Gh) {/*{{{*/
23  /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/Geometry)*/
24 
25  long i;
26  *this = Gh;
27  NbRef =0;
28  quadtree=0;
29  vertices = nbv ? new GeomVertex[nbv] : NULL;
30  edges = nbe ? new GeomEdge[nbe]:NULL;
31  curves= nbcurves ? new Curve[nbcurves]:NULL;
33  for (i=0;i<nbe;i++)
34  edges[i].Set(Gh.edges[i],Gh,*this);
35  for (i=0;i<nbcurves;i++)
36  curves[i].Set(Gh.curves[i],Gh,*this);
37  for (i=0;i<nbsubdomains;i++)
38  subdomains[i].Set(Gh.subdomains[i],Gh,*this);
39  }
40  /*}}}*/
42  /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/~Geometry)*/
43  if(NbRef>0){ _printf_("Trying to delete geometry and NbRef>0, probably due to an error. NbRef:" << NbRef); return;}
44  if(vertices) delete [] vertices; vertices=0;
45  if(edges) delete [] edges; edges=0;
46  if(quadtree) delete quadtree; quadtree=0;
47  if(curves) delete [] curves; curves=0;nbcurves=0;
48  if(subdomains) delete [] subdomains;subdomains=0;
49  Init();
50  }
51  /*}}}*/
52 
53  /*IO*/
54  void Geometry::ReadGeometry(BamgGeom* bamggeom,BamgOpts* bamgopts){/*{{{*/
55 
56  int verbose;
57  nbcurves=0;
58 
59  double Hmin = HUGE_VAL;// the infinie value
60  int i,j,n,i0,i1,i2,i3;
61 
62  /*initialize some variables*/
63  verbose= bamgopts->verbose;
64  nbv = bamggeom->VerticesSize[0];
65  nbe = bamggeom->EdgesSize[0];
66 
67  //some checks
68  if (bamggeom->Vertices==NULL) _error_("the domain provided does not contain any vertex");
69  if (bamggeom->Edges==NULL) _error_("the domain provided does not contain any edge");
70 
71  //Vertices
72  if (bamggeom->Vertices){
73  if(verbose>5) _printf_(" processing Vertices\n");
74  if (bamggeom->VerticesSize[1]!=3) _error_("Vertices should have 3 columns");
75  vertices = new GeomVertex[nbv];
76  for (i=0;i<nbv;i++) {
77  vertices[i].r.x=(double)bamggeom->Vertices[i*3+0];
78  vertices[i].r.y=(double)bamggeom->Vertices[i*3+1];
79  vertices[i].ReferenceNumber=(long)bamggeom->Vertices[i*3+2];
80  vertices[i].color =0;
81  vertices[i].type=0;
82  }
83  /*find domain extrema (pmin,pmax) that will define the square box used for by the quadtree*/
84  pmin = vertices[0].r;
85  pmax = vertices[0].r;
86  for (i=0;i<nbv;i++) {
87  pmin.x = Min(pmin.x,vertices[i].r.x);
88  pmin.y = Min(pmin.y,vertices[i].r.y);
89  pmax.x = Max(pmax.x,vertices[i].r.x);
90  pmax.y = Max(pmax.y,vertices[i].r.y);
91  }
92  /*Offset pmin and pmax to avoid round-off errors*/
93  R2 offset = (pmax-pmin)*0.05;
94  pmin -= offset;
95  pmax += offset;
96  /*coefIcoor is the coefficient used for integer coordinates:
97  * (x-pmin.x)
98  * Icoor x = (2^30 -1) ------------
99  * D
100  * where D is the longest side of the domain (direction x or y)
101  * so that (x-pmin.x)/D is in ]0 1[
102  *
103  * coefIcoor = (2^30 -1)/D
104  */
105  int MaxICoord = 1073741823;
106  coefIcoor=(MaxICoord)/(Max(pmax.x-pmin.x,pmax.y-pmin.y));
107  if(coefIcoor<=0) _error_("coefIcoor should be positive");
108  }
109  else{
110  _error_("No BamgVertex provided");
111  }
112 
113  //Edges
114  if (bamggeom->Edges){
115  R2 zerovector(0,0);
116  double* verticeslength=NULL;
117 
118  if(verbose>5) _printf_(" processing Edges\n");
119  if (bamggeom->EdgesSize[1]!=3) _error_("Edges should have 3 columns");
120  edges = new GeomEdge[nbe];
121 
122  //initialize verticeslength (sum of the lengths of the edges holding vertex)
123  verticeslength = new double[nbv];
124  for(i=0;i<nbv;i++) verticeslength[i]=0;
125 
126  /*Loop over the edges*/
127  for (i=0;i<nbe;i++){
128 
129  i1=(int)bamggeom->Edges[i*3+0]-1; //-1 for C indexing
130  i2=(int)bamggeom->Edges[i*3+1]-1; //-1 for C indexing
131  edges[i].v[0]= vertices + i1; //pointer toward vertex i1 (=&vertices[i1])
132  edges[i].v[1]= vertices + i2; //pointer toward vertex i2
133  edges[i].ReferenceNumber=(long)bamggeom->Edges[i*3+2];
134 
135  //get length of edge
136  R2 x12=vertices[i2].r-vertices[i1].r;
137  double l12=sqrt((x12,x12));
138  Hmin=Min(Hmin,l12);
139 
140  //initialize other fields
141  edges[i].tg[0]=zerovector;
142  edges[i].tg[1]=zerovector;
143  edges[i].AdjVertexIndex[0] = edges[i].AdjVertexIndex[1] = -1;
144  edges[i].Adj[0] = edges[i].Adj[1] = NULL;
145  edges[i].type = 0;
146 
147  //Cracked?
148  if (edges[i].ReferenceNumber!=1) edges[i].SetCracked();
149 
150  //prepare metric
151  vertices[i1].color++;
152  vertices[i2].color++;
153  verticeslength[i1] += l12;
154  verticeslength[i2] += l12;
155  }
156 
157  // definition the default of the given mesh size
158  for (i=0;i<nbv;i++) {
159  if (vertices[i].color > 0)
160  vertices[i].m=Metric(verticeslength[i] /(double) vertices[i].color);
161  else
162  vertices[i].m=Metric(Hmin);
163  }
164  delete [] verticeslength;
165 
166  }
167  else{
168  _error_("No edges provided");
169  }
170 
171  //hVertices
172  if(bamgopts->hVertices && bamgopts->hVerticesLength==nbv){
173  if(verbose>5) _printf_(" processing hVertices\n");
174  for (i=0;i< nbv;i++){
175  if (!xIsNan<IssmPDouble>(bamgopts->hVertices[i])){
176  vertices[i].m=Metric((double)bamgopts->hVertices[i]);
177  }
178  }
179  }
180 
181  //MetricVertices
182  if(bamgopts->metric && bamgopts->metric[0]==nbv){
183  if(verbose>5) _printf_(" processing MetricVertices\n");
184  for (i=0;i< nbv;i++) {
185  vertices[i].m = Metric((double)bamgopts->metric[i*3+0],(double)bamgopts->metric[i*3+1],(double)bamgopts->metric[i*3+2]);
186  }
187  }
188 
189  //TangentAtEdges
190  if (bamggeom->TangentAtEdges){
191  if(verbose>5) _printf_(" processing TangentAtEdges");
192  if (bamggeom->TangentAtEdgesSize[1]!=4) _error_("TangentAtEdges should have 4 columns");
193  int n,i,j,k;
194  R2 tg;
195 
196  n=bamggeom->TangentAtEdgesSize[0];
197  for (k=0;k<n;k++) {
198  i=(int)bamggeom->TangentAtEdges[k*4+0]-1; //for C indexing
199  j=(int)bamggeom->TangentAtEdges[k*4+1]-1; //for C indexing
200  tg.x=bamggeom->TangentAtEdges[k*4+2];
201  tg.y=bamggeom->TangentAtEdges[k*4+3];
202  if (i<0 || i>=nbe) _error_("TangentAtEdges first index exceeds matrix dimension");
203  if (j!=0 && j!=1) _error_("TangentAtEdges second index should be 1 or 2 only");
204  edges[i].tg[j] = tg;
205  }
206  }
207 
208  //Corners
209  if(bamggeom->Corners){
210  if(verbose>5) _printf_(" processing Corners");
211  if (bamggeom->CornersSize[1]!=1) _error_("Corners should have 1 column");
212  n=bamggeom->CornersSize[0];
213  for (i=0;i<n;i++) {
214  j=(int)bamggeom->Corners[i]-1; //for C indexing
215  if (j>nbv-1 || j<0) _error_("Bad corner definition: should in [0 " << nbv << "]");
216  /*Required => at the same time SetRequired and SetCorner*/
217  vertices[j].SetCorner();
218  vertices[j].SetRequired();
219  }
220  }
221 
222  //RequiredVertices
223  if(bamggeom->RequiredVertices){
224  if(verbose>5) _printf_(" processing RequiredVertices\n");
225  if (bamggeom->RequiredVerticesSize[1]!=1) _error_("RequiredVertices should have 1 column");
226  n=bamggeom->RequiredVerticesSize[0];
227  for (i=0;i<n;i++) {
228  j=(int)bamggeom->RequiredVertices[i]-1; //for C indexing
229  if (j>nbv-1 || j<0) _error_("Bad RequiredVerticess definition: should in [0 " << nbv << "]");
230  vertices[j].SetRequired();
231  }
232  }
233 
234  //RequiredEdges
235  if(bamggeom->RequiredEdges){
236  if(verbose>5) _printf_(" processing RequiredEdges\n");
237  if (bamggeom->RequiredEdgesSize[1]!=1) _error_("RequiredEdges should have 1 column");
238  n=bamggeom->RequiredEdgesSize[0];
239  for (i=0;i<n;i++) {
240  j=(int)bamggeom->RequiredEdges[i]-1; //for C indexing
241  if (j>nbe-1 || j<0) _error_("Bad RequiredEdges definition: should in [0 " << nbe << "]");
242  edges[j].SetRequired();
243  }
244  }
245 
246  //SubDomain
247  if(bamggeom->SubDomains){
248  if(verbose>5) _printf_(" processing SubDomains\n");
249  if (bamggeom->SubDomainsSize[1]!=4) _error_("SubDomains should have 4 columns");
250  nbsubdomains=bamggeom->SubDomainsSize[0];
252  for (i=0;i<nbsubdomains;i++){
253  i0=(int)bamggeom->SubDomains[i*4+0];
254  i1=(int)bamggeom->SubDomains[i*4+1];
255  i2=(int)bamggeom->SubDomains[i*4+2];
256  i3=(int)bamggeom->SubDomains[i*4+3];
257  if (i0!=2) _error_("Bad Subdomain definition: first number should be 2 (for Edges)");
258  if (i1>nbe || i1<=0) _error_("Bad Subdomain definition: second number should in [1 " << nbe << "] (edge number)");
259  subdomains[i].edge=edges + (i1-1);
260  subdomains[i].direction = (int) i2;
261  subdomains[i].ReferenceNumber = i3;
262  }
263  }
264  }
265  /*}}}*/
266  void Geometry::WriteGeometry(BamgGeom* bamggeom, BamgOpts* bamgopts){/*{{{*/
267 
268  int verbose;
269  int nbreq=0;
270  int nbreqv=0;
271  int nbtan=0;
272  int i,count;
273 
274  /*Get options*/
275  verbose=bamgopts->verbose;
276 
277  /*Vertices*/
278  if(verbose>5) _printf_(" writing Vertices\n");
279  bamggeom->VerticesSize[0]=nbv;
280  bamggeom->VerticesSize[1]=3;
281  if (nbv){
282  bamggeom->Vertices=xNew<double>(3*nbv);
283  for (i=0;i<nbv;i++){
284  bamggeom->Vertices[i*3+0]=vertices[i].r.x;
285  bamggeom->Vertices[i*3+1]=vertices[i].r.y;
286  bamggeom->Vertices[i*3+2]=vertices[i].GetReferenceNumber();
287 
288  //update counters
289  if (vertices[i].Required()) nbreqv++;
290  }
291  }
292 
293  /*Edges*/
294  if(verbose>5) _printf_(" writing Edges\n");
295  bamggeom->EdgesSize[0]=nbe;
296  bamggeom->EdgesSize[1]=3;
297  if (nbe){
298  bamggeom->Edges=xNew<double>(3*nbe);
299  for (i=0;i<nbe;i++){
300  bamggeom->Edges[i*3+0]=GetId(edges[i][0])+1; //back to Matlab indexing
301  bamggeom->Edges[i*3+1]=GetId(edges[i][1])+1; //back to Matlab indexing
302  bamggeom->Edges[i*3+2]=(double)edges[i].ReferenceNumber;
303 
304  //update counters
305  if (edges[i].Required()) nbreq++;
306  if (edges[i].TgA() && edges[i][0].Corner()) nbtan++;
307  if (edges[i].TgB() && edges[i][1].Corner()) nbtan++;
308  }
309  }
310 
311  /*RequiredEdges*/
312  if(verbose>5) _printf_(" writing " << nbreq << " RequiredEdges\n");
313  bamggeom->RequiredEdgesSize[0]=nbreq;
314  bamggeom->RequiredEdgesSize[1]=1;
315  if (nbreq){
316  bamggeom->RequiredEdges=xNew<double>(1*nbreq);
317  count=0;
318  for (i=0;i<nbe;i++){
319  if (edges[i].Required()){
320  bamggeom->RequiredEdges[count]=i+1; //back to Matlab indexing
321  count=count+1;
322  }
323  }
324  }
325 
326  //No corners
327 
328  /*RequiredVertices*/
329  if(verbose>5) _printf_(" writing " << nbreqv << " RequiredVertices\n");
330  bamggeom->RequiredVerticesSize[0]=nbreqv;
331  bamggeom->RequiredVerticesSize[1]=1;
332  if (nbreqv){
333  bamggeom->RequiredVertices=xNew<double>(1*nbreqv);
334  count=0;
335  for (i=0;i<nbv;i++){
336  if (vertices[i].Required()){
337  bamggeom->RequiredVertices[count]=i+1; //back to Matlab indexing
338  count=count+1;
339  }
340  }
341  }
342 
343  /*SubDomains*/
344  if(verbose>5) _printf_(" writing SubDomains\n");
345  bamggeom->SubDomainsSize[0]=nbsubdomains;
346  bamggeom->SubDomainsSize[1]=4;
347  if (nbsubdomains){
348  bamggeom->SubDomains=xNew<double>(4*nbsubdomains);
349  for (i=0;i<nbsubdomains;i++){
350  bamggeom->SubDomains[4*i+0]=2;
351  bamggeom->SubDomains[4*i+1]=GetId(subdomains[i].edge)+1; //back to Matlab indexing
352  bamggeom->SubDomains[4*i+2]=subdomains[i].direction;
353  bamggeom->SubDomains[4*i+3]=subdomains[i].ReferenceNumber;
354  }
355  }
356 
357  /*TangentAtEdges*/
358  if(verbose>5) _printf_(" writing TangentAtEdges\n");
359  bamggeom->TangentAtEdgesSize[0]=nbtan;
360  bamggeom->TangentAtEdgesSize[1]=4;
361  if (nbtan){
362  bamggeom->TangentAtEdges=xNew<double>(4*nbtan);
363  for (i=0;i<nbe;i++){
364  if (edges[i].TgA() && edges[i][0].Corner()){
365  bamggeom->TangentAtEdges[4*i+0]=i+1; //back to Matlab indexing
366  bamggeom->TangentAtEdges[4*i+1]=1;
367  bamggeom->TangentAtEdges[4*i+2]=edges[i].tg[0].x;
368  bamggeom->TangentAtEdges[4*i+3]=edges[i].tg[0].y;
369  }
370  if (edges[i].TgB() && edges[i][1].Corner()){
371  bamggeom->TangentAtEdges[4*i+0]=i+1; //back to Matlab indexing
372  bamggeom->TangentAtEdges[4*i+1]=2;
373  bamggeom->TangentAtEdges[4*i+2]=edges[i].tg[1].x;
374  bamggeom->TangentAtEdges[4*i+3]=edges[i].tg[1].y;
375  }
376  }
377  }
378  }
379  /*}}}*/
380 
381  /*Methods*/
382  void Geometry::Echo(void){/*{{{*/
383 
384  _printf_("Geometry:\n");
385  _printf_(" nbv (number of vertices) : " << nbv << "\n");
386  _printf_(" nbe (number of edges) : " << nbe << "\n");
387  _printf_(" nbsubdomains: " << nbsubdomains << "\n");
388  _printf_(" nbcurves: " << nbcurves << "\n");
389  _printf_(" vertices: " << vertices << "\n");
390  _printf_(" edges: " << edges << "\n");
391  _printf_(" quadtree: " << quadtree << "\n");
392  _printf_(" subdomains: " << subdomains << "\n");
393  _printf_(" curves: " << curves << "\n");
394  _printf_(" pmin (x,y): (" << pmin.x << " " << pmin.y << ")\n");
395  _printf_(" pmax (x,y): (" << pmax.x << " " << pmax.y << ")\n");
396  _printf_(" coefIcoor: " << coefIcoor << "\n");
397 
398  return;
399  }
400  /*}}}*/
401  void Geometry::Init(void){/*{{{*/
402  /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/EmptyGeometry)*/
403 
404  NbRef=0;
405  nbv=0;
406  nbe=0;
407  quadtree=NULL;
408  curves=NULL;
409  edges=NULL;
410  vertices=NULL;
411  nbsubdomains=0;
412  nbcurves=0;
413  subdomains=NULL;
414  }
415  /*}}}*/
416  double Geometry::MinimalHmin() {/*{{{*/
417  /* coeffIcoor = (2^30-1)/D
418  * We cannot go beyond hmin = D/2^30 because of the quadtree
419  * hmin is therefore approximately 2/coeffIcoor */
420  return 2.0/coefIcoor;
421  }/*}}}*/
422  double Geometry::MaximalHmax() {/*{{{*/
423  return Max(pmax.x-pmin.x,pmax.y-pmin.y);
424  }/*}}}*/
425  long Geometry::GetId(const GeomVertex & t) const {/*{{{*/
426  return &t - vertices;
427  }/*}}}*/
428  long Geometry::GetId(const GeomVertex * t) const {/*{{{*/
429  return t - vertices;
430  }/*}}}*/
431  long Geometry::GetId(const GeomEdge & t) const {/*{{{*/
432  return &t - edges;
433  }/*}}}*/
434  long Geometry::GetId(const GeomEdge * t) const {/*{{{*/
435  return t - edges;
436  }/*}}}*/
437  long Geometry::GetId(const Curve * c) const {/*{{{*/
438  return c - curves;
439  }/*}}}*/
440  void Geometry::PostRead(bool checkcurve){/*{{{*/
441  /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/AfterRead)*/
442 
443  long i ,j,k;
444  long *head_v = new long[nbv];
445  long *next_p = new long[2 *nbe];
446  float *eangle = new float[nbe];
447  double eps = 1e-20;
448  BamgQuadtree quadtree; // build quadtree to find duplicates
449 
450  k=0;
451 
452  //build quadtree for this geometry
453  for (i=0;i<nbv;i++){
454 
455  /*build integer coordinates (non unique)
456  these coordinates are used by the quadtree to group
457  the vertices by groups of 5:
458  All the coordinates are transformed to ]0,1[^2
459  then, the integer coordinates are computed using
460  the transformation ]0,1[^2 -> [0 2^30-1[^2 for a quadtree of depth 30*/
461  vertices[i].i=R2ToI2(vertices[i].r);
462 
463  /*find nearest vertex already present in the quadtree (NULL if empty)*/
465 
466  /*if there is a vertex found that is to close to vertices[i] -> error*/
467  if( v && Norme1(v->r - vertices[i].r) < eps ){
468  _printf_("reference numbers: " << v->ReferenceNumber << " " << vertices[i].ReferenceNumber << "\n");
469  _printf_("Id: " << i+1 << "\n");
470  _printf_("Coords: ["<<v->r.x<<" "<<v->r.y<<"] ["<<vertices[i].r.x<<" "<<vertices[i].r.y<<"]\n");
471 
472  delete [] next_p;
473  delete [] head_v;
474  delete [] eangle;
475  _error_("two points of the geometry are very close to each other (see reference numbers above)");
476  }
477 
478  /*Add vertices[i] to the quadtree*/
479  quadtree.Add(vertices[i]);
480  }
481 
482  /* Here we use a powerful chaining algorithm
483  *
484  * 1. What is a chaining algorithm?
485  *
486  * If F is a function that goes from i in [0 n] to j in [0 m]
487  * and we want to compute the reciprocal function F-1 of F
488  * (what are the antecedents of a given j in Im(F) )
489  * We use 2 lists:
490  * head_F[j] that holds the head of lists
491  * next_F[i] that holds the list of elements that have the same image
492  *
493  * Example:
494  * i1, i2, ..., ip in [0,n] are all antecedents of a given j in [0 m]
495  * head_F[j] = ip
496  * next_F[ip]= ip-1
497  * ....
498  * next_F[i2]= i1
499  * next_F[i1]= -1 //end of the list
500  *
501  * Algorithm:
502  * for(j=0;j<m;j++) head_F[j] = -1 //initialization
503  * for(i=0;i<n;i++){
504  * j=F[i];
505  * next_F[i]= head_F[j];
506  * head_F[j]=i;
507  * }
508  *
509  * Then, we can go through all the elements that have for image j:
510  * for(i=head_F[j]; i!=-1; i=next_F[i])
511  * initialization of i by i=head_F[j]
512  * stop the loop when i=-1 (end of the chain)
513  * iterate using i=next_F[i] (next element that have for image j)
514  *
515  * 2. How to use this algorithm here?
516  *
517  * Here F is a function that associates two vertices v0 and v1 for a given edge E
518  * We want to build the reciprocal function: what are the edges that contains
519  * a vertex v?
520  * To do so, we use the same chaining algorithm but there is a difficulty
521  * coming from the fact that for F we have a couple of vertices and not one
522  * vertex.
523  * To overcome this difficulty, we use a global indexing exactly like in
524  * C/C++ so that
525  * a member of a 2-column-table can be described by one index p=i*2+j
526  * i=(int)p/2 line number of p
527  * j=p%2 column number of p
528  *
529  * Algorithm:
530  * for(i=0;i<nbv;i++) head_v[i] = -1 //initialization
531  * for(i=0;i<nbe;i++){
532  * for(j=0;j<2;j++){
533  * p=2*i+j;
534  * v=edges(i,j);
535  * next_p[p]= head_v[v];
536  * head_v[v]=p;
537  * }
538  * }
539  */
540 
541  //initialize head_v as -1
542  for (i=0;i<nbv;i++) head_v[i]=-1;
543  k=0;
544  for (i=0;i<nbe;i++) {
545  //compute vector of edge i that goes from vertex 0 to vertex 1
546  R2 v10=edges[i].v[1]->r - edges[i].v[0]->r;
547  double lv10=Norme2(v10);
548  //check that its length is not 0
549  if(lv10==0){
550  delete [] next_p;
551  delete [] head_v;
552  delete [] eangle;
553  _printf_("Length of edge " << i << " is 0\n");
554  _error_("Length of edge " << i << " is 0");
555  }
556  //compute angle in [-Pi Pi]
557  eangle[i] = atan2(v10.y,v10.x);
558  //build chains head_v and next_p
559  for (j=0;j<2;j++){
560  long v=GetId(edges[i].v[j]);
561  next_p[k]=head_v[v];
562  head_v[v]=k++; //post increment: head_v[v]=k; and then k=k+1;
563  }
564  }
565 
566  //sort head_v by order of increasing edges angle
567  for (i=0;i<nbv;i++) {
568  int exch=1,ord=0;
569 
570  //exchange vertices position in head_v and next_p till tey are sorted
571  while (exch){
572  long *p=head_v+i;
573  long *po=p;
574  long n=*p;
575  float angleold=-1000 ; // angle = - infinity
576  ord=0; exch=0;
577 
578  // loop over the edges that contain the vertex i (till -1)
579  while (n >=0){
580  ord++;
581  long i1=n/2; // i1 = floor (n/2) -> Edge number
582  long j1=n%2; // j1 = 1 if n is odd -> Vertex index for this edge (0 or 1)
583  long* pn=next_p+n;
584 
585  //Next vertex index
586  n=*pn;
587 
588  //compute angle between horizontal axis and v0->v1
589  float angle = j1 ? OppositeAngle(eangle[i1]): eangle[i1];
590 
591  //exchange if the current edge angle is smaller than the previous one
592  if (angleold > angle){
593  exch=1;
594  *pn=*po; // next_p[n] = n + 1
595  *po=*p; //
596  *p=n; // next_p[n+1] = n
597  po=pn; // po now point toward pn (invert next and current)
598  }
599 
600  //else, continue going to the next edge position
601  else{ // to have : po -> p -> pn
602  angleold=angle; // update maximum angle
603  po=p; // po now point toward p (current position)
604  p=pn; // p now point toward pn (next position)
605  }
606  }
607  }
608 
609  /*Do we want to check for curve? Default is no, but if we are reconstructing, it's better to turn it on with a small threshold*/
610  if(checkcurve){
611  /*angular test on current vertex to guess whether it is a corner (ord = number of edges holding i) */
612  if(ord==2){
613  IssmDouble MaxCornerAngle = 1*Pi/180; /*default is 1 degree*/
614  long n1 = head_v[i];
615  long n2 = next_p[n1];
616  long i1 = n1/2, i2 = n2/2; // edge number
617  long j1 = n1%2, j2 = n2%2; // vertex in the edge
618  float angle1= j1 ? OppositeAngle(eangle[i1]) : eangle[i1];
619  float angle2= !j2 ? OppositeAngle(eangle[i2]) : eangle[i2];
620  float da12 = Abs(angle2-angle1);
621  if (( da12 >= MaxCornerAngle ) && (da12 <= 2*Pi -MaxCornerAngle)) {
622  vertices[i].SetCorner() ;
623  }
624  /* if the edge type/referencenumber a changing then is SetRequired();*/
625  if(edges[i1].type != edges[i2].type || edges[i1].Required()){
626  vertices[i].SetRequired();
627  }
628  if(edges[i1].ReferenceNumber != edges[i2].ReferenceNumber) {
629  vertices[i].SetRequired();
630  }
631  }
632  if(ord!=2) vertices[i].SetCorner();
633  }
634  else{
635  /*all vertices provided in geometry are corners (ord = number of edges holding i)*/
636  vertices[i].SetCorner() ;
637  if(ord==2){
638  long n1 = head_v[i];
639  long n2 = next_p[n1];
640  long i1 = n1/2, i2 = n2/2; // edge number
641  long j1 = n1%2, j2 = n2%2; // vertex in the edge
642  /* if the edge type/referencenumber a changing then is SetRequired();*/
643  if (edges[i1].type != edges[i2].type || edges[i1].Required()){
644  vertices[i].SetRequired();
645  }
646  if (edges[i1].ReferenceNumber != edges[i2].ReferenceNumber) {
647  vertices[i].SetRequired();
648  }
649  }
650  }
651 
652  /*close the list around the vertex to have a circular loop*/
653  long no=-1, ne = head_v[i];
654  while (ne >=0) ne = next_p[no=ne];
655  if(no>=0) next_p[no] = head_v[i];
656  }
657 
658  /*Check that the list makes sense (we have all the time the same vertex)
659  * and build adjacent edges*/
660  k =0;
661  for (i=0;i<nbe;i++){
662  for (j=0;j<2;j++){
663 
664  long n1 = next_p[k++];
665  long i1 = n1/2 ,j1=n1%2;
666 
667  if( edges[i1].v[j1] != edges[i].v[j]) _error_("Problem while processing edges: check the edge list");
668 
669  edges[i1].Adj[j1] = edges + i;
670  edges[i1].AdjVertexIndex[j1] = j;
671  }
672  }
673 
674  /* generation of all the tangents*/
675  for (i=0;i<nbe;i++) {
676  R2 AB =edges[i].v[1]->r -edges[i].v[0]->r;// AB = vertex0 -> vertex1
677  double lAB=Norme2(AB); // Get length of AB
678  double ltg2[2]={0.0}; // initialize tangent
679 
680  //loop over the 2 vertices of the edge
681  for (j=0;j<2;j++) {
682  R2 tg =edges[i].tg[j];
683  double ltg=Norme2(tg);
684 
685  //by default, tangent=[0 0]
686  if(ltg==0){
687  //if the current vertex of the edge is not a corner
688  if(!edges[i].v[j]->Corner()){
689  /*The tangent is set as the vector between the
690  * previous and next vertices connected to current vertex
691  * normed by the edge length*/
692  tg = edges[i].v[1-j]->r - edges[i].Adj[j]->v[1-edges[i].AdjVertexIndex[j]]->r;
693  ltg= Norme2(tg);
694  tg = tg *(lAB/ltg);
695  ltg= lAB;
696  }
697  //else: a Corner no tangent => nothing to do
698  }
699  else{
700  //tangent has already been computed
701  tg = tg*(lAB/ltg),ltg=lAB;
702  }
703 
704  ltg2[j] = ltg;
705 
706  if ((tg,AB)<0) tg = -tg;
707 
708  edges[i].tg[j]=tg;
709  }
710  if (ltg2[0]!=0) edges[i].SetTgA();
711  if (ltg2[1]!=0) edges[i].SetTgB();
712  }
713 
714  /* generation of all curves (from corner to corner)*/
715  /*We proceed in 2 steps: first allocate, second build*/
716  for (int step=0;step<2;step++){
717 
718  //unmark all edges
719  for (i=0;i<nbe;i++) edges[i].SetUnMark();
720  long nb_marked_edges=0;
721 
722  //initialize number of curves
723  nbcurves = 0;
724 
725  for (int level=0;level<2 && nb_marked_edges!=nbe;level++){
726  for (i=0;i<nbe;i++){
727 
728  GeomEdge & ei=edges[i];
729  for(j=0;j<2;j++){
730  /*If current edge ei is unmarked and (level=1 or vertex i is required (corner)):
731  * we do have the first edge of a new curve*/
732  if (!ei.Mark() && (level || ei[j].Required())) {
733  int k0=j,k1;
734  GeomEdge *e=&ei;
735  GeomVertex *a=(*e)(k0); // begin
736  if(curves){
739  }
740  int nee=0;
741  for(;;){
742  nee++;
743  k1 = 1-k0; // next vertex of the edge
744  e->SetMark();
745  nb_marked_edges++;
747  GeomVertex *b=(*e)(k1);
748 
749  //break if we have reached the other end of the curve
750  if (a==b || b->Required()){
751  if(curves){
754  }
755  break;
756  }
757  //else: go to next edge (adjacent)
758  else{
759  k0 = e->AdjVertexIndex[k1];// vertex in next edge
760  e = e->Adj[k1]; // next edge
761  }
762  }
763  nbcurves++;
764  if(level) a->SetRequired();
765  }
766  }
767  }
768  }
769  _assert_(nb_marked_edges && nbe);
770  //allocate if first step
771  if(step==0) curves=new Curve[nbcurves];
772  }
773 
774  /*clean up*/
775  delete [] next_p;
776  delete [] head_v;
777  delete [] eangle;
778 
779  }
780  /*}}}*/
781  GeomEdge* Geometry::ProjectOnCurve(const Edge &e,double s,BamgVertex &V,VertexOnGeom &GV) const {/*{{{*/
782  /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/ProjectOnCurve)*/
783  /*Add a vertex on an existing geometrical edge according to the metrics of the two vertices constituting the edge*/
784  /*FIXME: should go away*/
785 
786  double save_s=s;
787  int NbTry=0;
788 
789 retry:
790 
791  s=save_s;
792  GeomEdge* on=e.GeomEdgeHook;
793  if (!on){
794  _error_("ProjectOnCurve error message: edge provided should be on geometry");
795  }
796  if (!e[0].GeomEdgeHook || !e[1].GeomEdgeHook){
797  _error_("ProjectOnCurve error message: at least one of the vertex of the edge provided is not on geometry");
798  }
799 
800  //Get the two vertices of the edge
801  const BamgVertex &v0=e[0];
802  const BamgVertex &v1=e[1];
803 
804  //Get position of V0, V1 and vector v0->v1
805  R2 V0=v0,V1=v1,V01=V1-V0;
806 
807  //Get geometrical vertices corresponding to v0 and v1
808  VertexOnGeom vg0=*v0.GeomEdgeHook, vg1=*v1.GeomEdgeHook;
809 
810  //build two pointers towrad current geometrical edge
811  GeomEdge *eg0=on, *eg1=on;
812 
813  //Get edge direction and swap v0 and v1 if necessary
814  R2 Ag=(R2)(*on)[0],Bg=(R2)(*on)[1],AB=Bg-Ag;
815  int OppositeSens = (V01,AB)<0;
816  int direction0=0,direction1=1;
817  if (OppositeSens) s=1-s,Exchange(vg0,vg1),Exchange(V0,V1);
818 
819  //Compute metric of new vertex as a linear interpolation of the two others
820  V.m=Metric(1.0-s,v0.m,s,v1.m);
821 
822  const int mxe=100;
823  GeomEdge* ge[mxe+1];
824  int directionge[mxe+1];
825  double lge[mxe+1];
826  int bge=mxe/2,tge=bge;
827  ge[bge] = e.GeomEdgeHook;
828  directionge[bge]=1;
829 
830  while(eg0!=(GeomEdge*)vg0 && (*eg0)(direction0)!=(GeomVertex*)vg0){
831  if (bge<=0) {
832  if(NbTry) {
833  _printf_("Fatal Error: on the class Mesh before call Geometry::ProjectOnCurve\n");
834  _printf_("That bug might come from:\n");
835  _printf_(" 1) a mesh edge containing more than " << mxe/2 << " geometrical edges\n");
836  _printf_(" 2) code bug : be sure that we call Mesh::SetVertexFieldOn() before\n");
837  _printf_("To solve the problem do a coarsening of the geometrical mesh or change the constant value of mxe (dangerous)\n");
838  _error_("see above");
839  }
840  NbTry++;
841  goto retry;
842  }
843  GeomEdge* tmpge = eg0;
844  ge[--bge] =eg0 = eg0->Adj[direction0];
845  _assert_(bge>=0 && bge<=mxe);
846  direction0 = 1-( directionge[bge] = tmpge->AdjVertexIndex[direction0]);
847  }
848  while (eg1 != (GeomEdge*) vg1 && (*eg1)(direction1) != (GeomVertex*) vg1) {
849  if(tge>=mxe ) {
850  _printf_("WARNING: on the class Mesh before call Geometry::ProjectOnCurve is having issues (isn't it Eric?)\n");
851  NbTry++;
852  if (NbTry<2) goto retry;
853  _printf_("Fatal Error: on the class Mesh before call Geometry::ProjectOnCurve\n");
854  _printf_("That bug might come from:\n");
855  _printf_(" 1) a mesh edge contening more than " << mxe/2 << " geometrical edges\n");
856  _printf_(" 2) code bug : be sure that we call Mesh::SetVertexFieldOn() before\n");
857  _printf_("To solve the problem do a coarsening of the geometrical mesh or change the constant value of mxe (dangerous)\n");
858  _error_("see above");
859  }
860  GeomEdge* tmpge = eg1;
861  ge[++tge] =eg1 = eg1->Adj[direction1];
862  directionge[tge]= direction1 = 1-tmpge->AdjVertexIndex[direction1];
863  _assert_(tge>=0 && tge<=mxe);
864  }
865 
866  if ((*eg0)(direction0)==(GeomVertex*)vg0)
867  vg0=VertexOnGeom(*(BamgVertex*) vg0,*eg0,direction0); //vg0 = absisce
868 
869  if ((*eg1)(direction1)==(GeomVertex*)vg1)
870  vg1=VertexOnGeom(*(BamgVertex*) vg1,*eg1,direction1);
871 
872  double sg;
873  if (eg0 == eg1) {
874  double s0=vg0,s1=vg1;
875  sg = s0*(1.0-s) + s*s1;
876  on=eg0;
877  }
878  else {
879  R2 AA=V0,BB;
880  double s0,s1;
881  int i=bge;
882  double ll=0;
883  for(i=bge;i<tge;i++){
884  _assert_(i>=0 && i<=mxe);
885  BB = (*ge[i])[directionge[i]];
886  lge[i]=ll += Norme2(AA-BB);
887  AA=BB ;}
888  lge[tge]=ll+=Norme2(AA-V1);
889  // search the geometrical edge
890  _assert_(s<=1.0);
891  double ls= s*ll;
892  on =0;
893  s0 = vg0;
894  s1= directionge[bge];
895  double l0=0,l1;
896  i=bge;
897  while ( (l1=lge[i]) < ls ) {
898  _assert_(i>=0 && i<=mxe);
899  i++,s0=1-(s1=directionge[i]),l0=l1;
900  }
901  on=ge[i];
902  if (i==tge)
903  s1=vg1;
904 
905  s =(ls-l0)/(l1-l0);
906  sg =s0*(1.0-s)+s*s1;
907  }
908  _assert_(on);
909  V.r= on->F(sg);
910  GV=VertexOnGeom(V,*on,sg);
911  return on;
912  }
913  /*}}}*/
914  I2 Geometry::R2ToI2(const R2 & P) const {/*{{{*/
915  /*coefIcoor is the coefficient used for integer coordinates:
916  * (x-pmin.x)
917  * Icoor x = (2^30 -1) ------------
918  * D
919  * where D is the longest side of the domain (direction x or y)
920  * so that (x-pmin.x)/D is in ]0 1[
921  *
922  * coefIcoor = (2^30 -1)/D
923  */
924  return I2( (int) (coefIcoor*(P.x-pmin.x)) ,(int) (coefIcoor*(P.y-pmin.y)) );
925  }/*}}}*/
926  void Geometry::UnMarkEdges() {/*{{{*/
927  for (int i=0;i<nbe;i++) edges[i].SetUnMark();
928  }/*}}}*/
929 }
BamgGeom::RequiredVertices
double * RequiredVertices
Definition: BamgGeom.h:19
BamgGeom::Edges
double * Edges
Definition: BamgGeom.h:13
bamg::BamgVertex
Definition: BamgVertex.h:15
bamg::GeomEdge::SetCracked
void SetCracked()
Definition: GeomEdge.cpp:76
bamg::Geometry::MinimalHmin
double MinimalHmin()
Definition: Geometry.cpp:416
_assert_
#define _assert_(ignore)
Definition: exceptions.h:37
bamg::GeomEdge::type
int type
Definition: GeomEdge.h:20
bamg::BamgVertex::i
I2 i
Definition: BamgVertex.h:20
IssmDouble
double IssmDouble
Definition: types.h:37
BamgGeom::CornersSize
int CornersSize[2]
Definition: BamgGeom.h:16
bamg::GeomSubDomain::edge
GeomEdge * edge
Definition: GeomSubDomain.h:13
bamg::BamgVertex::r
R2 r
Definition: BamgVertex.h:21
bamg::OppositeAngle
float OppositeAngle(float a)
Definition: OppositeAngle.h:8
bamg::Curve::FirstVertexIndex
int FirstVertexIndex
Definition: Curve.h:16
bamg::GeomEdge::Required
int Required()
Definition: GeomEdge.cpp:65
bamg::Geometry::pmin
R2 pmin
Definition: Geometry.h:32
bamg::Geometry::MaximalHmax
double MaximalHmax()
Definition: Geometry.cpp:422
_printf_
#define _printf_(StreamArgs)
Definition: Print.h:22
bamg::Geometry
Definition: Geometry.h:18
bamg::Geometry::nbsubdomains
long nbsubdomains
Definition: Geometry.h:25
bamg::BamgVertex::GetReferenceNumber
int GetReferenceNumber() const
Definition: BamgVertex.cpp:30
bamg::GeomEdge::Mark
int Mark() const
Definition: GeomEdge.cpp:62
bamg
Definition: AdjacentTriangle.cpp:9
BamgGeom::Corners
double * Corners
Definition: BamgGeom.h:17
bamg::Geometry::edges
GeomEdge * edges
Definition: Geometry.h:28
BamgGeom::TangentAtEdgesSize
int TangentAtEdgesSize[2]
Definition: BamgGeom.h:14
BamgGeom::RequiredEdgesSize
int RequiredEdgesSize[2]
Definition: BamgGeom.h:20
bamg::GeomVertex::SetCorner
void SetCorner()
Definition: GeomVertex.cpp:24
BamgOpts::verbose
int verbose
Definition: BamgOpts.h:26
bamg::Geometry::pmax
R2 pmax
Definition: Geometry.h:32
bamg::Geometry::vertices
GeomVertex * vertices
Definition: Geometry.h:27
BamgGeom::SubDomainsSize
int SubDomainsSize[2]
Definition: BamgGeom.h:24
bamg::GeomEdge
Definition: GeomEdge.h:11
bamg::GeomEdge::SetTgB
void SetTgB()
Definition: GeomEdge.cpp:82
bamg::GeomEdge::v
GeomVertex * v[2]
Definition: GeomEdge.h:14
bamg::Curve::FirstEdge
GeomEdge * FirstEdge
Definition: Curve.h:14
Exchange
void Exchange(T &a, T &b)
Definition: Exchange.h:4
BamgGeom::SubDomains
double * SubDomains
Definition: BamgGeom.h:25
bamg::GeomEdge::AdjVertexIndex
int AdjVertexIndex[2]
Definition: GeomEdge.h:19
bamg::Max
T Max(const T &a, const T &b)
Definition: extrema.h:7
BamgOpts::hVertices
double * hVertices
Definition: BamgOpts.h:41
bamg::BamgVertex::GeomEdgeHook
VertexOnGeom * GeomEdgeHook
Definition: BamgVertex.h:31
bamg::Geometry::Echo
void Echo()
Definition: Geometry.cpp:382
bamg::Geometry::subdomains
GeomSubDomain * subdomains
Definition: Geometry.h:30
bamg::GeomEdge::F
R2 F(double theta) const
Definition: GeomEdge.cpp:20
bamg::Geometry::ProjectOnCurve
GeomEdge * ProjectOnCurve(const Edge &, double, BamgVertex &, VertexOnGeom &) const
Definition: Geometry.cpp:781
bamg::VertexOnGeom
Definition: VertexOnGeom.h:13
BamgGeom::TangentAtEdges
double * TangentAtEdges
Definition: BamgGeom.h:15
bamg::GeomEdge::SetRequired
void SetRequired()
Definition: GeomEdge.cpp:91
bamg::Geometry::PostRead
void PostRead(bool checkcurve=false)
Definition: Geometry.cpp:440
bamg::GeomEdge::tg
R2 tg[2]
Definition: GeomEdge.h:17
bamg::Curve::LastEdge
GeomEdge * LastEdge
Definition: Curve.h:15
bamg::GeomEdge::ReferenceNumber
long ReferenceNumber
Definition: GeomEdge.h:15
BamgGeom::RequiredVerticesSize
int RequiredVerticesSize[2]
Definition: BamgGeom.h:18
bamg::Geometry::ReadGeometry
void ReadGeometry(BamgGeom *bamggeom, BamgOpts *bamgopts)
Definition: Geometry.cpp:54
bamg::BamgQuadtree
Definition: BamgQuadtree.h:10
bamg::Geometry::quadtree
BamgQuadtree * quadtree
Definition: Geometry.h:29
bamg::GeomVertex::Required
int Required() const
Definition: GeomVertex.cpp:19
bamg::Norme2
RR Norme2(const P2< R, RR > x)
Definition: R2.h:93
bamg::I2
P2< int, long long > I2
Definition: typedefs.h:11
bamg::Geometry::curves
Curve * curves
Definition: Geometry.h:31
bamg::Geometry::GetId
long GetId(const GeomVertex &t) const
Definition: Geometry.cpp:425
bamg::GeomEdge::CurveNumber
long CurveNumber
Definition: GeomEdge.h:16
bamg::Geometry::UnMarkEdges
void UnMarkEdges()
Definition: Geometry.cpp:926
BamgOpts
Definition: BamgOpts.h:8
bamg::Metric
Definition: Metric.h:17
bamg::GeomVertex::type
int type
Definition: GeomVertex.h:16
bamg::Edge
Definition: Edge.h:12
bamg::GeomEdge::Adj
GeomEdge * Adj[2]
Definition: GeomEdge.h:18
bamg::Geometry::R2ToI2
I2 R2ToI2(const R2 &P) const
Definition: Geometry.cpp:914
bamg::BamgQuadtree::NearestVertex
BamgVertex * NearestVertex(int i, int j)
Definition: BamgQuadtree.cpp:227
bamg::BamgVertex::ReferenceNumber
long ReferenceNumber
Definition: BamgVertex.h:23
BamgOpts::metric
double * metric
Definition: BamgOpts.h:43
bamg::Pi
const double Pi
Definition: macros.h:8
BamgGeom::VerticesSize
int VerticesSize[2]
Definition: BamgGeom.h:10
bamg::GeomVertex
Definition: GeomVertex.h:11
BamgGeom::EdgesSize
int EdgesSize[2]
Definition: BamgGeom.h:12
BamgGeom
Definition: BamgGeom.h:7
_error_
#define _error_(StreamArgs)
Definition: exceptions.h:49
bamg::Geometry::WriteGeometry
void WriteGeometry(BamgGeom *bamggeom, BamgOpts *bamgopts)
Definition: Geometry.cpp:266
bamg::GeomSubDomain::direction
int direction
Definition: GeomSubDomain.h:14
bamg::Geometry::nbe
long nbe
Definition: Geometry.h:24
bamg::R2
P2< double, double > R2
Definition: typedefs.h:12
bamg::P2::x
R x
Definition: R2.h:15
bamg::Geometry::nbcurves
long nbcurves
Definition: Geometry.h:26
bamg::GeomSubDomain
Definition: GeomSubDomain.h:11
BamgGeom::Vertices
double * Vertices
Definition: BamgGeom.h:11
BamgOpts::hVerticesLength
int hVerticesLength
Definition: BamgOpts.h:40
bamg::BamgVertex::color
long color
Definition: BamgVertex.h:29
bamg::GeomSubDomain::ReferenceNumber
long ReferenceNumber
Definition: GeomSubDomain.h:15
BamgGeom::RequiredEdges
double * RequiredEdges
Definition: BamgGeom.h:21
bamg::P2::y
R y
Definition: R2.h:15
bamg::BamgQuadtree::Add
void Add(BamgVertex &w)
Definition: BamgQuadtree.cpp:104
bamg::Geometry::nbv
long nbv
Definition: Geometry.h:23
bamg::P2< double, double >
bamg::Abs
T Abs(const T &a)
Definition: Abs.h:5
bamg::GeomEdge::SetMark
void SetMark()
Definition: GeomEdge.cpp:85
bamg::Min
T Min(const T &a, const T &b)
Definition: extrema.h:6
bamg::GeomVertex::SetRequired
void SetRequired()
Definition: GeomVertex.cpp:28
bamg::Geometry::Geometry
Geometry()
Definition: Geometry.cpp:12
bamg::BamgVertex::m
Metric m
Definition: BamgVertex.h:22
bamg::Edge::GeomEdgeHook
GeomEdge * GeomEdgeHook
Definition: Edge.h:17
bamg::Geometry::NbRef
long NbRef
Definition: Geometry.h:22
bamg::Geometry::Init
void Init(void)
Definition: Geometry.cpp:401
bamg::Curve::LastVertexIndex
int LastVertexIndex
Definition: Curve.h:17
bamgobjects.h
bamg::GeomEdge::SetTgA
void SetTgA()
Definition: GeomEdge.cpp:79
bamg::Geometry::coefIcoor
double coefIcoor
Definition: Geometry.h:33
bamg::Geometry::~Geometry
~Geometry()
Definition: Geometry.cpp:41
bamg::Curve
Definition: Curve.h:12
bamg::Norme1
R Norme1(const P2< R, RR > x)
Definition: R2.h:85