00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include <vector>
00047 #include <string>
00048 #include <stack>
00049
00050
00051 using namespace std;
00052
00053
00054 #include<vcg/simplex/vertex/vertex.h>
00055 #include<vcg/simplex/face/with/afav.h>
00056 #include<vcg/simplex/face/topology.h>
00057 #include<vcg/simplex/face/pos.h>
00058
00059
00060 #include<vcg/complex/trimesh/base.h>
00061 #include<vcg/complex/trimesh/update/topology.h>
00062 #include <vcg/complex/trimesh/update/edges.h>
00063 #include <vcg/complex/trimesh/update/bounding.h>
00064 #include <vcg/complex/trimesh/clean.h>
00065 #include <vcg/space/intersection/triangle_triangle3.h>
00066 #include <vcg/math/histogram.h>
00067 #include <wrap/io_trimesh/import.h>
00068 #include <wrap/io_trimesh/export_ply.h>
00069
00070
00071
00072 #include<wrap/io_trimesh/import_ply.h>
00073
00074 #include "defs.h"
00075
00076 using namespace vcg;
00077 using namespace tri;
00078 using namespace face;
00079
00080 class MyFace;
00081 class MyEdge;
00082 class MyVertex:public Vertex<float,MyEdge,MyFace>{};
00083 class MyFace :public FaceAFAV<MyVertex,MyEdge,MyFace>{};
00084 class MyMesh: public tri::TriMesh< std::vector<MyVertex>, std::vector<MyFace > >{};
00085
00086 void OpenMesh(const char *filename, MyMesh &m)
00087 {
00088 int err = tri::io::Importer<MyMesh>::Open(m,filename);
00089 if(err) {
00090 printf("Error in reading %s: '%s'\n",filename,tri::io::Importer<MyMesh>::ErrorMsg(err));
00091 exit(-1);
00092 }
00093 printf("read mesh `%s'\n", filename);
00094 }
00095
00096
00097 inline char* GetExtension(char* filename)
00098 {
00099 for(int i=strlen(filename)-1; i >= 0; i--)
00100 if(filename[i] == '.')
00101 break;
00102 if(i > 0)
00103 return &(filename[i+1]);
00104 else
00105 return NULL;
00106 }
00107
00108
00109 typedef MyMesh::VertexPointer VertexPointer;
00110 typedef MyMesh::VertexIterator VertexIterator;
00111
00112
00113 template <class VertexIterator>
00114 class DuplicateVert_Compare{
00115 public:
00116 inline bool operator() (VertexIterator a, VertexIterator b)
00117 {
00118 return *a < *b;
00119 }
00120 };
00121
00122 static int DuplicateVertex( MyMesh & m )
00123 {
00124 if(m.vert.size()==0 || m.vn==0)
00125 return 0;
00126 std::map<VertexPointer, VertexPointer> mp;
00127 int i,j;
00128 VertexIterator vi;
00129 int deleted=0;
00130 int k=0;
00131 int num_vert = m.vert.size();
00132 vector<VertexPointer> perm(num_vert);
00133 for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi, ++k)
00134 perm[k] = &(*vi);
00135
00136 DuplicateVert_Compare<VertexPointer> c_obj;
00137
00138 std::sort(perm.begin(),perm.end(),c_obj);
00139 j = 0;
00140 i = j;
00141 mp[perm[i]] = perm[j];
00142 ++i;
00143 for(;i!=num_vert;)
00144 {
00145 if( (! (*perm[i]).IsD()) &&
00146 (! (*perm[j]).IsD()) &&
00147 (*perm[i]).P() == (*perm[j]).cP() )
00148 {
00149 VertexPointer t = perm[i];
00150 mp[perm[i]] = perm[j];
00151 ++i;
00152 (*t).SetD();
00153 deleted++;
00154 }
00155 else
00156 {
00157 j = i;
00158 ++i;
00159 }
00160 }
00161 return deleted;
00162 }
00163 void main(int argc,char ** argv){
00164
00165 char *fmt;
00166 MyMesh m;
00167 bool DEBUG = false;
00168
00169
00170
00171
00172
00173
00174 printf("-------------------------------\n"
00175 " TriMeshInfo V.1.01 \n"
00176 " http://vcg.isti.cnr.it\n"
00177 " release date: "__DATE__"\n"
00178 "-------------------------------\n\n");
00179
00180
00181 if(DEBUG)
00182 argv[1] = "C:\\sf\\apps\\msvc\\trimeshinfo\\Release\\cube1.stl";
00183
00184 else
00185 {
00186
00187 if(argc <= 1)
00188 {
00189 printf(MSG_ERR_N_ARGS);
00190 exit(-1);
00191 }
00192 }
00193
00194
00195 OpenMesh(argv[1],m);
00196
00197
00198
00199 FILE * index;
00200 index = fopen((string(argv[1])+string("2.html")).c_str(),"w");
00201 fprintf(index,"<p>Mesh info: %s </p>\n\n\n", argv[1]);
00202
00203 fprintf(index,"<p>GENERAL INFO </p>\n\n");
00204 fprintf(index,"<p>Number of vertices: %d </p>\n", m.vn);
00205 fprintf(index,"<p>Number of faces: %d </p>\n", m.fn);
00206 printf("Mesh info:\n");
00207 printf(" M: '%s'\n\t Number of vertices: %d \n", argv[1], m.vn);
00208 printf("\t Number of faces: %d \n", m.fn);
00209
00210 if(m.HasPerFaceColor()||m.HasPerVertexColor())
00211 {
00212 Color4b Color=m.C();
00213 fprintf(index, "<p>Object color(4b): %f %f %f </p>\n\n", Color[0], Color[1], Color[2]);
00214 printf( "\t Object color(4b): %f %f %f \n", Color[0], Color[1], Color[2]);
00215 }
00216
00217
00218 vcg::tri::UpdateTopology<MyMesh>::FaceFace(m);
00219
00220
00221
00222 MyMesh::FaceIterator f;
00223 MyMesh::FaceIterator g;
00224 vcg::face::Pos<MyMesh::FaceType> he;
00225 vcg::face::Pos<MyMesh::FaceType> hei;
00226 int j;
00227 int man=0;
00228 bool Manifold = true;
00229
00230 MyMesh::FaceIterator prova;
00231 prova = m.face.end();
00232 for(f=m.face.begin();f!=m.face.end();++f)
00233 {
00234 for (j=0;j<3;++j)
00235 {
00236 if(!IsManifold(*f,j))
00237 {
00238 Manifold = false;
00239 f= m.face.end();
00240 --f;
00241 j=3;
00242 }
00243 }
00244 }
00245 if (!Manifold)
00246 {
00247 fprintf(index, "<p> Manifold: NO </p>");
00248 printf( "\t Manifold: NO\n");
00249 }
00250 else
00251 {
00252 fprintf(index, "<p> Manifold: YES </p>");
00253 printf( "\t Manifold: YES\n ");
00254 }
00255
00256
00257
00258 MyMesh::FaceIterator fi;
00259 int count_e = 0;
00260 bool counted=false;
00261 for(fi=m.face.begin();fi!=m.face.end();++fi)
00262 (*fi).ClearS();
00263
00264 for(fi=m.face.begin();fi!=m.face.end();++fi)
00265 {
00266 (*fi).SetS();
00267 count_e +=3;
00268 for(int i=0; i<3; ++i)
00269 {
00270 if (IsManifold(*fi,i))
00271 {
00272 if((*fi).FFp(i)->IsS())
00273 count_e--;
00274 }
00275 else
00276 {
00277 hei.Set(&(*fi), i , fi->V(i));
00278 he=hei;
00279 he.NextF();
00280 while (he.f!=hei.f)
00281 {
00282 if (he.f->IsS())
00283 {
00284 counted=true;
00285 break;
00286 }
00287 else
00288 {
00289 he.NextF();
00290 }
00291 }
00292 if (counted)
00293 {
00294 count_e--;
00295 counted=false;
00296 }
00297 }
00298 }
00299 }
00300 fprintf(index, "<p>Number of edges: %d </p>\n", count_e);
00301 printf("\t Number of edges: %d \n", count_e);
00302
00303
00304
00305
00306
00307
00308 int count_fd = 0;
00309 for(fi=m.face.begin(); fi!=m.face.end();++fi)
00310 if((*fi).Area() == 0)
00311 count_fd++;
00312 fprintf(index, "<p>Number of degenerated faces: %d </p>\n", count_fd);
00313 printf("\t Number of degenerated faces: %d \n", count_fd);
00314
00315
00316
00317 int count_uv = 0;
00318 MyMesh::VertexIterator v;
00319
00320
00321
00322 for(v=m.vert.begin();v!=m.vert.end();++v)
00323 (*v).ClearV();
00324
00325 for(f=m.face.begin();f!=m.face.end();++f)
00326 for(j=0;j<3;++j)
00327 (*f).V(j)->SetV();
00328
00329 for(v=m.vert.begin();v!=m.vert.end();++v)
00330 if( !(*v).IsV() )
00331 ++count_uv;
00332 fprintf(index,"<p>Number of unreferenced vertices: %d</p>\n",count_uv);
00333 printf("\t Number of unreferenced vertices: %d\n",count_uv);
00334
00335
00336
00337
00338 for(f=m.face.begin();f!=m.face.end();++f)
00339 (*f).ClearS();
00340 g=m.face.begin(); f=g;
00341
00342 int BEdges=0; int numholes=0;
00343
00344
00345 if (Manifold)
00346 {
00347 for(f=g;f!=m.face.end();++f)
00348 {
00349 if(!(*f).IsS())
00350 {
00351 for(j=0;j<3;j++)
00352 {
00353 if ((*f).IsBorder(j))
00354 {
00355 BEdges++;
00356
00357 if(!(IsManifold(*f,j)))
00358 {
00359 (*f).SetS();
00360 hei.Set(&(*f),j,f->V(j));
00361 he=hei;
00362 do
00363 {
00364 he.NextB();
00365 he.f->SetS();
00366
00367 }
00368 while (he.f!=hei.f);
00369
00370 numholes++;
00371 }
00372 }
00373 }
00374 }
00375 }
00376 }
00377 else
00378 {
00379 for(f=g;f!=m.face.end();++f)
00380 {
00381 for(j=0;j<3;j++)
00382 {
00383 if ((*f).IsBorder(j))
00384 {
00385 BEdges++;
00386 }
00387 }
00388 }
00389 }
00390 if (Manifold)
00391 {
00392 fprintf(index, "<p> Number of holes: %d </p> \n <p> Number of border edges: %d </p>", numholes, BEdges);
00393 printf("\t Number of holes: %d \n", numholes, BEdges);
00394 printf("\t Number of border edges: %d\n", numholes, BEdges);
00395 }
00396 else
00397 {
00398 fprintf(index, "<p> Number of border edges: %d </p>", BEdges);
00399 printf("\t Number of border edges: %d\n", BEdges);
00400 }
00401
00402
00403 float vol = m.Volume();
00404 int nuh = numholes;
00405 if((m.Volume()>0.)&&(Manifold)&&(numholes==0))
00406 {
00407 fprintf(index,"<p>Volume: %d </p>\n", m.Volume());
00408 printf("\t Volume: %f \n", m.Volume());
00409 }
00410
00411
00412
00413
00414
00415 for(f=m.face.begin();f!=m.face.end();++f)
00416 (*f).ClearS();
00417 g=m.face.begin(); f=g;
00418 int CountComp=0; int CountOrient=0;
00419 stack<MyMesh::FaceIterator> sf;
00420 MyMesh::FaceType *l;
00421 for(f=m.face.begin();f!=m.face.end();++f)
00422 {
00423 if (!(*f).IsS())
00424 {
00425 (*f).SetS();
00426 sf.push(f);
00427 while (!sf.empty())
00428 {
00429 g=sf.top();
00430 he.Set(&(*g),0,g->V(0));
00431 sf.pop();
00432 for(j=0;j<3;++j)
00433 if( !(*g).IsBorder(j) )
00434 {
00435 l=he.f->FFp(j);
00436 if( !(*l).IsS() )
00437 {
00438 (*l).SetS();
00439 sf.push(l);
00440 }
00441 }
00442 }
00443 CountComp++;
00444 }
00445 }
00446 fprintf(index, "<p> Number of connected components: %d </p>", CountComp);
00447 printf("\t Number of connected components: %d\n", CountComp);
00448
00449 if(CountComp ==1)
00450 {
00451 int eulero;
00452 eulero = (m.vn-count_uv)- (count_e+BEdges)+m.fn;
00453 if(Manifold)
00454 {
00455 int genus = (2-eulero)>>1;
00456 fprintf(index, "<p> Genus: %d </p> \n ", genus);
00457 printf( "\t Genus: %d \n", genus);
00458 }
00459 }
00460
00461
00462 bool Regular=true;
00463 bool Semiregular=true;
00464 int inc=0;
00465 for(v=m.vert.begin();v!=m.vert.end();++v)
00466 (*v).ClearS();
00467 for(f=m.face.begin();f!=m.face.end();++f)
00468 {
00469 for (j=0; j<3; j++)
00470 {
00471 he.Set(&(*f),j,f->V(j));
00472 if (!(*f).IsBorder(j) && !(*f).IsBorder((j+2)%3) && !f->V(j)->IsS())
00473 {
00474 hei=he;
00475 inc=1;
00476 he.FlipE();
00477 he.NextF();
00478 while (he.f!=hei.f)
00479 {
00480 he.FlipE();
00481 if (he.IsBorder())
00482 {
00483 inc=6;
00484 break;
00485 }
00486 he.NextF();
00487 inc++;
00488 }
00489 if (inc!=6)
00490 Regular=false;
00491 if (inc!=6 && inc!=5)
00492 Semiregular=false;
00493 f->V(j)->SetS();
00494
00495 }
00496 else
00497 f->V(j)->SetS();
00498 }
00499 if (Semiregular==false)
00500 break;
00501
00502 }
00503
00504 if (Regular)
00505 {
00506 fprintf(index, "<p> Type of Mesh: REGULAR</p>");
00507 printf("\t Type of Mesh: REGULAR\n");
00508 }
00509 else if (Semiregular)
00510 {
00511 fprintf(index, "<p> Type of Mesh: SEMIREGULAR</p>");
00512 printf("\t Type of Mesh: SEMIREGULAR\n");
00513 }
00514 else
00515 {
00516 fprintf(index, "<p> Type of Mesh: IRREGULAR</p>");
00517 printf("\t Type of Mesh: IRREGULAR\n");
00518 }
00519
00520
00521 bool Orientable=true;
00522 bool Oriented=true;
00523 if (!Manifold)
00524 {
00525 fprintf(index, "<p> Orientable Mesh: NO</p>");
00526 printf( "\t Orientable Mesh: NO\n");
00527 }
00528 else
00529 {
00530 for(f=m.face.begin();f!=m.face.end();++f)
00531 {
00532 (*f).ClearS();
00533 (*f).ClearUserBit(0);
00534 }
00535 g=m.face.begin(); f=g;
00536 for(f=m.face.begin();f!=m.face.end();++f)
00537 {
00538 if (!(*f).IsS())
00539 {
00540 (*f).SetS();
00541 sf.push(f);
00542
00543 while (!sf.empty())
00544 {
00545 g=sf.top();
00546 sf.pop();
00547 for(j=0;j<3;++j)
00548 {
00549 if( !(*g).IsBorder(j) )
00550 {
00551 he.Set(&(*g),0,g->V(0));
00552 l=he.f->FFp(j);
00553 he.Set(&(*g),j,g->V(j));
00554 hei.Set(he.f->FFp(j),he.f->FFi(j), (he.f->FFp(j))->V(he.f->FFi(j)));
00555 if( !(*g).IsUserBit(0) )
00556 {
00557 if (he.v!=hei.v)
00558 {
00559 if ((*l).IsS() && (*l).IsUserBit(0))
00560 {
00561 Orientable=false;
00562 break;
00563 }
00564 else if (!(*l).IsS())
00565 {
00566 (*l).SetS();
00567 sf.push(l);
00568 }
00569 }
00570 else if (!(*l).IsS())
00571 {
00572 Oriented=false;
00573 (*l).SetS();
00574 (*l).SetUserBit(0);
00575 sf.push(l);
00576 }
00577 else if ((*l).IsS() && !(*l).IsUserBit(0))
00578 {
00579 Orientable=false;
00580 break;
00581 }
00582 }
00583 else if (he.v==hei.v)
00584 {
00585 if ((*l).IsS() && (*l).IsUserBit(0))
00586 {
00587 Orientable=false;
00588 break;
00589 }
00590 else if (!(*l).IsS())
00591 {
00592 (*l).SetS();
00593 sf.push(l);
00594 }
00595 }
00596 else if (!(*l).IsS())
00597 {
00598 Oriented=false;
00599 (*l).SetS();
00600 (*l).SetUserBit(0);
00601 sf.push(l);
00602 }
00603 else if ((*l).IsS() && !(*l).IsUserBit(0))
00604 {
00605 Orientable=false;
00606 break;
00607 }
00608 }
00609 }
00610 }
00611 }
00612 if (!Orientable)
00613 break;
00614 }
00615 if (Orientable)
00616 {
00617 fprintf(index, "<p> Orientable Mesh: YES</p>");
00618 printf( "\t Orientable Mesh: YES\n");
00619 }
00620 else
00621 {
00622 fprintf(index, "<p> Orientable Mesh: NO</p>");
00623 printf( "\t Orientable Mesh: NO\n");
00624 }
00625 }
00626 if (Oriented && Manifold)
00627 {
00628 fprintf(index, "<p> Oriented Mesh: YES</p>");
00629 printf( "\t Oriented Mesh: YES\n");
00630 }
00631 else
00632 {
00633 fprintf(index, "<p> Oriented Mesh: NO</p>");
00634 printf( "\t Oriented Mesh: NO\n");
00635 }
00636 int dv = DuplicateVertex(m);
00637 if(dv>0)
00638 {
00639 fprintf(index, "<p> Duplicated vertices: %d</p>", dv);
00640 printf( "\t Duplicated vertices: %d\n",dv);
00641 }
00642 else
00643 {
00644 fprintf(index, "<p> Duplicated vertices: NO</p>");
00645 printf( "\t Duplicated vertices: NO\n");
00646 }
00647
00648
00649 if (m.fn<300000)
00650 {
00651 bool SelfInt=false;
00652 for(f=m.face.begin();f!=m.face.end();++f)
00653 {
00654 for(g=++f , f--;g!=m.face.end();++g)
00655 {
00656 if ((*f).FFp(0)!=&(*g) && (*f).FFp(1)!=&(*g) && (*f).FFp(2)!=&(*g) &&
00657 f->V(0)!=g->V(0) && f->V(0)!=g->V(1) && f->V(0)!=g->V(2) &&
00658 f->V(1)!=g->V(0) && f->V(1)!=g->V(1) && f->V(1)!=g->V(2) &&
00659 f->V(2)!=g->V(0) && f->V(2)!=g->V(1) && f->V(2)!=g->V(2))
00660 {
00661 if (NoDivTriTriIsect(f->V(0)->P(), f->V(1)->P(), f->V(2)->P(),g->V(0)->P(), g->V(1)->P(), g->V(2)->P()) )
00662 SelfInt=true;
00663 }
00664 }
00665 if (SelfInt)
00666 break;
00667 }
00668 if (SelfInt)
00669 {
00670 fprintf(index, "<p> Self Intersection: YES</p>");
00671 printf( "\t Self Intersection: YES\n");
00672 }
00673 else
00674 {
00675 fprintf(index, "<p> Self Intersection: NO</p>");
00676 printf( "\t Self Intersection: NO\n");
00677 }
00678 }
00679
00680
00681 fclose(index);
00682 }
00683