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