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