$search
00001 /* 00002 James R. Diebel 00003 Stanford University 00004 00005 Started: 24 August 2004 00006 Last revised: 27 Sugust 2004 00007 00008 mesh.cc - class implementation of Mesh class (mesh.hh) 00009 00010 Depends on: 00011 - Mesh class (mesh.hh) 00012 */ 00013 00014 #include "bmtk/triangulate.h" 00015 #include "bmtk/mesh.hh" 00016 #include <iostream> 00017 #include <fstream> 00018 #include <math.h> 00019 #include <stdlib.h> 00020 #include <stdio.h> 00021 #include <list> 00022 #include <vector> 00023 #include <algorithm> 00024 00025 namespace bmtk { 00026 00027 00028 // Constructor 00029 Mesh::Mesh() { 00030 po = true; 00031 ut = true; 00032 ib = false; 00033 00034 gs2 = 10; 00035 gsn2 = 0.001; 00036 00037 segThresh = 0.02; 00038 00039 //psiSpline = new USpline(50,0.0,2.0,2.0,2*(1-4/gsn2)*exp(-4/gsn2)); 00040 psiSpline = new USpline(500,0.0,2.0,2.0,2.0); 00041 setNormalVar(gsn2); 00042 00043 /*ofstream fout1("psi.dat"); 00044 ofstream fout2("psi0.dat"); 00045 ofstream fout3("dpsi.dat"); 00046 ofstream fout4("dpsi0.dat"); 00047 for (float y=0;y<2;y+=0.001) { 00048 fout1 << y << " " << psiSpline->evalf(y) << endl; 00049 fout2 << y << " " << 2*y*exp(-2*y/gsn2) << endl; 00050 fout3 << y << " " << psiSpline->evaldf(y) << endl; 00051 fout4 << y << " " << 2*(1-2*y/gsn2)*exp(-2*y/gsn2) << endl; 00052 } 00053 fout1.close(); 00054 fout2.close(); 00055 fout3.close(); 00056 fout4.close();*/ 00057 00058 nv = ne = nf = nn = 0; 00059 nd = 0; 00060 psi = 0; 00061 normGradPsi = 0; 00062 l = 1; 00063 iter = 1; 00064 nStepsForReset = 100; 00065 wroteIter = 0; 00066 maxIter = 100; 00067 00068 rho[0] = rho[1] = 0; 00069 ut = (po || ut); 00070 tCG = new Timer("","\n"); 00071 tLS = new Timer("","\n"); 00072 tMP = new Timer("","\n"); 00073 tVG = new Timer("","\n"); 00074 tFN = new Timer("","\n"); 00075 callBackExists = 0; 00076 00077 foutConv.open("convergence.dat"); 00078 } 00079 00080 // Destructor 00081 Mesh::~Mesh() { 00082 cleanUp(); 00083 delete psiSpline; 00084 foutConv.close(); 00085 delete tCG; 00086 delete tLS; 00087 delete tMP; 00088 delete tVG; 00089 delete tFN; 00090 if (po) cout << "Done." << endl << flush; 00091 } 00092 00093 void Mesh::cleanUp() { 00094 if (po) cout << "Deleting mesh data..." << flush; 00095 if (nv) delete [] v; if (po) cout << " vertices," << flush; 00096 if (nv) delete [] qv; if (po) cout << "vertex queue," << flush; 00097 if (ne) delete [] e; if (po) cout << "edges," << flush; 00098 if (nf) delete [] f; if (po) cout << "faces," << flush; 00099 if (nf) delete [] r; if (po) cout << "regions," << flush; 00100 if (nf) delete [] q; if (po) cout << "face queue, " << flush; 00101 } 00102 00103 void Mesh::registerCB(void (*callBack_)(void)) { 00104 callBackExists = 1; 00105 callBack = callBack_; 00106 } 00107 00108 // update calls callback function to refresh GUI display 00109 void Mesh::update() { 00110 if (callBackExists) 00111 (*callBack)(); 00112 } 00113 00114 void Mesh::setVertVar(float gs2_) { 00115 gs2 = gs2_; 00116 } 00117 00118 void Mesh::setNormalVar(float gsn2_) { 00119 gsn2 = gsn2_; 00120 for (int i=0;i<psiSpline->n;i++) { 00121 float p = 2.0*float(i)/float(psiSpline->n - 1); 00122 psiSpline->y[i] = sqrt(p+gsn2); 00123 } 00124 psiSpline->b0 = 0.5/sqrt(gsn2); 00125 psiSpline->bn = 0.5/sqrt(2.0f+gsn2); 00126 /*float a,b,c,d; 00127 c = 4; d = 0.5; 00128 b = (d*d-1)*c/(2.0f*(d-d*d)); 00129 a = (-c-2*b)/3.0f; 00130 00131 for (int i=0;i<psiSpline->n;i++) { 00132 float p = 2.0*float(i)/float(psiSpline->n - 1); 00133 psiSpline->y[i] = a*p*p*p + b*p*p + c*p; 00134 } 00135 psiSpline->b0 = c; 00136 psiSpline->bn = 12.0f*a + 4.0f*b + c;*/ 00137 00138 psiSpline->update(); 00139 } 00140 00142 // General Mesh Functions // 00144 void Mesh::findBBox() { 00145 if (po) cout << "- Finding bounding box..." << flush; 00146 boxMin = boxMax = v[0].x; 00147 for (int i=1;i<nv;i++) { 00148 for (int j=0;j<3;j++) { 00149 if (boxMin[j] < v[i].x[j]) boxMin[j] = v[i].x[j]; 00150 if (boxMax[j] > v[i].x[j]) boxMax[j] = v[i].x[j]; 00151 } 00152 } 00153 box = ~(boxMax - boxMin); 00154 if (po) cout << "Done." << endl << flush; 00155 } 00156 00157 void Mesh::normalize() { 00158 if (po) cout << "- Scaling mesh for unity median edge length..." << endl 00159 << flush; 00160 for (int i=0;i<nv;i++) { 00161 v[i].x /= l; 00162 v[i].x0 /= l; 00163 if (nd) for (int k=0;k<nd;k++) v[i].xs[k] /= l; 00164 v[i].l /= l; 00165 } 00166 for (int i=0;i<ne;i++) e[i].l /= l; 00167 for (int i=0;i<nf;i++) { 00168 f[i].d /= l; 00169 f[i].x /= l; 00170 } 00171 cout << " "; 00172 findBBox(); 00173 cout << " "; 00174 findFaceAreas(); 00175 if (po) cout << " Done." << endl << flush; 00176 } 00177 00178 void Mesh::findLength() { 00179 if (po) cout << "- Computing the median edge length..." << flush; 00180 vector<float> lengths; 00181 for (int i=0;i<ne;i++) lengths.push_back(e[i].l); 00182 nth_element(lengths.begin(), 00183 lengths.begin()+lengths.size()/2, 00184 lengths.end()); 00185 l = lengths[lengths.size()/2]; 00186 if (po) cout << "Done." << endl << flush; 00187 } 00188 00189 Mesh* Mesh::pruneFaces(float factor) { 00190 if (po) cout << "- Flagging triangles with edges longer than " 00191 << factor << " times the median edge length" << flush << endl; 00192 00193 resetFaceFlags(); 00194 findLength(); 00195 00196 // flag faces with long edges, keeping count 00197 int count = 0; 00198 for (int i=0;i<nf;i++) { 00199 if (f[i].e[0]->l > l*factor || 00200 f[i].e[1]->l > l*factor || 00201 f[i].e[2]->l > l*factor) 00202 f[i].flag = 1; 00203 else count++; 00204 } 00205 00206 if (po) cout << " - Keeping " << count << " of " << nf << " faces" 00207 << flush << endl; 00208 00209 // fill new vertex and face lists 00210 float* vertices = new float[3*nv]; 00211 int* faces = new int[3*count]; 00212 for (int i=0;i<nv;i++) for (int j=0;j<3;j++) vertices[3*i+j] = v[i].x[j]; 00213 for (int i=0,k=0;i<nf;i++) if (f[i].flag != 1) { 00214 for (int j=0;j<3;j++) faces[3*k+j] = f[i].v[j]->i; 00215 k++; 00216 } 00217 00218 // and build the new Mesh 00219 Mesh* nm = new Mesh(); 00220 nm->buildFrom(vertices,nv,faces,count); 00221 00222 delete [] vertices; 00223 delete [] faces; 00224 00225 if (po) cout << " Done." << flush << endl; 00226 return nm; 00227 } 00228 00229 void Mesh::findMeshProps() { 00230 findBBox(); 00231 findFaceProps(); 00232 findEdgeProps(); 00233 findVertProps(); 00234 findLength(); 00235 } 00236 00237 void Mesh::reset() { 00238 if (po) cout << "- Reverting to original mesh..." << flush; 00239 bool temp = po; 00240 po = false; 00241 for (int i=0;i<nv;i++) v[i].x = v[i].x0; 00242 findFaceProps(); 00243 findEdgeProps(); 00244 findVertProps(); 00245 findMeshPotential(); 00246 findLocalEdgePotentials(); 00247 findVertGradients(); 00248 findSearchDirs(true); 00249 rho[0] = rho[1] = 0; 00250 po = temp; 00251 if (po) cout << "Done." << endl << flush; 00252 } 00253 00254 void Mesh::findMeshPotential() { 00255 if (ut) tMP->start(); 00256 if (po) cout << "- Computing mesh potential..." << endl << flush; 00257 if (po) cout << " "; 00258 findEdgePotentials(); 00259 if (po) cout << " "; 00260 findVertPotentials(); 00261 psi = psiVert = psiEdge = 0; 00262 for (int i=0;i<ne;i++) if (ib || e[i].nf > 1) psiEdge += e[i].psi; 00263 for (int i=0;i<nv;i++) if (ib || !v[i].bound) psiVert += v[i].psi; 00264 psi = psiVert + psiEdge; 00265 if (po) cout << " Psi = " << psiVert << " (v) + " << psiEdge 00266 << " (e) = " << psi << " ...Done." << flush; 00267 if (po) tMP->printMark(); 00268 if (ut) tMP->mark(); 00269 } 00270 00271 void Mesh::findPotentials() { 00272 findEdgePotentials(); 00273 findVertPotentials(); 00274 } 00275 00276 void Mesh::doBisectionLineSearch() { 00277 if (ut) tLS->start(); 00278 if (po) cout << " - Performing Bisection line search..." << endl << flush; 00279 float psi0 = psi; 00280 float step = 0.001f; 00281 float total = 0; 00282 bool temp = po; 00283 po = false; 00284 while (fabs(step) > 1e-5) { 00285 if (psi>psi0) { 00286 step *= -0.5; 00287 } 00288 psi0 = psi; 00289 total += step; 00290 moveVerts(total); 00291 findFaceNormals(); 00292 findMeshPotential(); 00293 if (ut) { 00294 tCG->stop(); 00295 tLS->stop(); 00296 } 00297 update(); 00298 if (ut) { 00299 tCG->start(); 00300 tLS->start(); 00301 } 00302 } 00303 po = temp; 00304 if (po) cout << " Total Movement = " << total << endl << flush; 00305 if (po) cout << " Done." << flush; 00306 if (po) tLS->printMark(); 00307 if (ut) tLS->mark(); 00308 } 00309 00310 void Mesh::doNewtonLineSearch() { 00311 if (ut) tLS->start(); 00312 if (po) cout << " - Performing Newton line search..." << endl << flush; 00313 float normGradPsi0 = normGradPsi; 00314 //float step = nv*0.001f/normDir; 00315 float step = 0.001f; 00316 float istep = 1/step; 00317 float total = 0; 00318 bool temp = po; 00319 po = false; 00320 do { 00321 moveVerts(total+step); 00322 findFaceNormals(); 00323 findEdgePotentials(); 00324 findVertGradients(); 00325 findNormGradPsi(); 00326 float diff = istep*normGradPsi - istep*normGradPsi0; 00327 00328 total -= normGradPsi0/diff; 00329 moveVerts(total); 00330 00331 findFaceNormals(); 00332 findEdgePotentials(); 00333 findVertGradients(); 00334 findNormGradPsi(); 00335 normGradPsi0 = normGradPsi; 00336 00337 if (ut) { 00338 tCG->stop(); 00339 tLS->stop(); 00340 } 00341 update(); 00342 if (ut) { 00343 tCG->start(); 00344 tLS->start(); 00345 } 00346 } while (fabs(normGradPsi - normGradPsi0)/normGradPsi > 1e-5); 00347 00348 po = temp; 00349 if (po) cout << " Total Movement = " << total << endl << flush; 00350 if (po) cout << " Done." << flush; 00351 if (po) tLS->printMark(); 00352 if (ut) tLS->mark(); 00353 } 00354 00355 void Mesh::runCG() { 00356 float psi0; 00357 int iter0 = iter; 00358 writeConvDetails(); 00359 do { 00360 psi0 = psi; 00361 if (ut) tCG->start(); 00362 if (po) cout << endl << "- Performing CG iteration #" << iter; 00363 if (po) if ((iter-iter0)%nStepsForReset == 0) 00364 cout << " with restart..."; 00365 if (po) cout << endl << flush; 00366 if (po) cout << " "; 00367 findVertGradients(); 00368 if (po) cout << " "; 00369 if ((iter-iter0)%nStepsForReset == 0) findSearchDirs(true); 00370 else findSearchDirs(); 00371 if (po) cout << " "; 00372 findNormGradPsi(); 00373 if (po) cout << " "; 00374 saveRefVerts(); 00375 doNewtonLineSearch(); 00376 findMeshPotential(); 00377 findLocalEdgePotentials(); 00378 iter++; 00379 writeConvDetails(); 00380 if (po) cout << " Done. " << flush; 00381 if (po) tCG->printMark(); 00382 if (ut) tCG->mark(); 00383 cout << "Relative change: " << fabs(psi-psi0)/psi << endl << flush; 00384 } while ((fabs(psi-psi0)/psi > 1e-3 && psi < psi0) || iter < 20); 00385 00386 if (po) { 00387 cout << endl 00388 << "Summary of time spent so far:" << endl 00389 << "-----------------------------" << endl; 00390 tCG->printStore("Cojugate Gradient Search"); 00391 tLS->printStore(" Line Search"); 00392 tMP->printStore("Computing Mesh Potential"); 00393 tVG->printStore("Computing Vert Gradients"); 00394 tFN->printStore(" Comuting Face Normals"); 00395 } 00396 } 00397 00398 void Mesh::anneal() { 00399 if (po) cout << endl << "- Performing Annealing iteration #" << iter 00400 << "..." << endl << flush; 00401 writeConvDetails(); 00402 // perturb vertex field 00403 //blurFaceNormals(2); 00404 //findVertNormals(); 00405 vertFaceConsistency(1); 00406 00407 // fix everything up for next iteration 00408 findFaceNormals(); 00409 findMeshPotential(); 00410 findLocalEdgePotentials(); 00411 findVertGradients(); 00412 findSearchDirs(true); 00413 iter++; 00414 writeConvDetails(); 00415 update(); 00416 } 00417 00418 void Mesh::writeConvDetails() { 00419 if (wroteIter < iter) { 00420 foutConv << wroteIter << " " 00421 << psi << " " 00422 << psiVert << " " 00423 << psiEdge << " " 00424 << endl; 00425 wroteIter++; 00426 } 00427 } 00428 00429 // Equality tests 00430 bool Mesh::operator == (const Mesh &m) const { 00431 if (nv != m.nv || nf != m.nf || ne != m.ne) return false; 00432 for (int i=0;i<nv;i++) { 00433 if ((v[i].x!=m.v[i].x) || (v[i].nf!=m.v[i].nf) || (v[i].ne!=m.v[i].ne)) 00434 return false; 00435 for (int j=0;j<v[i].nf;j++) 00436 if (v[i].f[j]->i != m.v[i].f[j]->i) return false; 00437 for (int j=0;j<v[i].ne;j++) 00438 if ((v[i].e[j]->i!=m.v[i].e[j]->i) || (v[i].v[j]->i!=m.v[i].v[j]->i)) 00439 return false; 00440 } 00441 for (int i=0;i<nf;i++) { 00442 for (int j=0;j<3;j++) 00443 if ((f[i].v[j]->i!=m.f[i].v[j]->i) || (f[i].e[j]->i!=m.f[i].e[j]->i)) 00444 return false; 00445 for (int j=0;j<f[i].nf;j++) 00446 if (f[i].f[j]->i != m.f[i].f[j]->i) return false; 00447 } 00448 for (int i=0;i<ne;i++) { 00449 for (int j=0;j<2;j++) if (e[i].v[j]->i != m.e[i].v[j]->i) return false; 00450 for (int j=0;j<e[i].nf;j++) 00451 if (e[i].f[j]->i != m.e[i].f[j]->i) return false; 00452 } 00453 return true; 00454 } 00455 00456 bool Mesh::operator != (const Mesh &m) const { 00457 return (!(m==*this)); 00458 } 00459 00460 } // namespace bmtk