00001
00002
00003
00004
00005 #include "mesh.h"
00006
00007
00008 #include <iostream>
00009 #include <fstream>
00010
00011 #include "math.h"
00012
00013
00014 #include <CGAL/IO/Polyhedron_iostream.h>
00015 #include <CGAL/Triangulation_2.h>
00016
00017
00018 #include <GL/gl.h>
00019
00020
00021 Mesh::Mesh(const char* filename)
00022 {
00023 _isValid = false;
00024
00025 if(loadFromFile(filename))
00026 {
00027 _mesh->normalize_border();
00028
00029 if(!_mesh->is_closed())
00030 {
00031 std::cout << "*** Warning: mesh is not closed ***" << std::endl;
00032 }
00033 if(!_mesh->is_pure_triangle())
00034 {
00035 std::cout << "*** Warning: mesh is not pure triangle ***" << std::endl;
00036 }
00037 if(_mesh->empty())
00038 {
00039 std::cout << "*** Warning: mesh is empty ***" << std::endl;
00040 }
00041 if(!_mesh->is_valid(false,3))
00042 {
00043 _message = "Mesh is not combinatorially consistent";
00044 }
00045 else
00046 {
00047 _isValid = true;
00048 _mesh->set_index_vertices();
00049 _mesh->set_index_edges();
00050 _mesh->compute_normals();
00051 }
00052 }
00053 else _message = "Impossible to load file";
00054 };
00055
00056 Mesh::~Mesh()
00057 {
00058 delete _mesh;
00059 };
00060
00061 void Mesh::compute_normals()
00062 {
00063 _mesh->compute_normals();
00064 };
00065
00066 bool Mesh::isValid() const
00067 {
00068 return _isValid;
00069 };
00070 char* Mesh::message() const
00071 {
00072 return _message;
00073 };
00074
00075 std::size_t Mesh::size_of_vertices() const
00076 {
00077 return _mesh->size_of_vertices();
00078 };
00079
00080 std::size_t Mesh::size_of_facets() const
00081 {
00082 return _mesh->size_of_facets();
00083 };
00084
00085
00086 void Mesh::draw(bool smooth_shading, bool use_normals, bool invert_normals) const
00087 {
00088
00089 glColor3f(0.0,0.5,0.8);
00090
00091 Facet_iterator pFacet = facets_begin();
00092 for(;pFacet != facets_end();pFacet++)
00093 {
00094
00095 glBegin(GL_POLYGON);
00096 gl_draw_facet(pFacet,smooth_shading,use_normals,invert_normals);
00097 glEnd();
00098 }
00099 glFlush();
00100
00101 };
00102
00103 void Mesh::gl_draw_facet(Facet_handle pFacet, bool smooth_shading, bool use_normals, bool invert_normals) const
00104 {
00105
00106 if(use_normals && !smooth_shading)
00107 {
00108 const Vector& normal = pFacet->normal();
00109 if (invert_normals) glNormal3f(-normal[0],-normal[1],-normal[2]);
00110 else glNormal3f(normal[0],normal[1],normal[2]);
00111 }
00112
00113
00114 Halfedge_around_facet_circulator pHalfedge = pFacet->facet_begin();
00115 do
00116 {
00117
00118 if(use_normals && smooth_shading)
00119 {
00120 const Vector normal = pHalfedge->vertex()->normal();
00121 if (invert_normals) glNormal3f(-normal[0],-normal[1],-normal[2]);
00122 else glNormal3f(normal[0],normal[1],normal[2]);
00123 }
00124
00125
00126 const Point& point = pHalfedge->vertex()->point();
00127 glVertex3d(point[0],point[1],point[2]);
00128 }while(++pHalfedge != pFacet->facet_begin());
00129 };
00130
00131
00132 void Mesh::draw_edges() const
00133 {
00134 glColor3f(0.0,0.0,0.0);
00135 glBegin(GL_LINES);
00136 for(Halfedge_iterator h = _mesh->edges_begin(); h != _mesh->edges_end(); h++)
00137 {
00138
00139 const Point& p1 = h->prev()->vertex()->point();
00140 const Point& p2 = h->vertex()->point();
00141 glVertex3f(p1[0],p1[1],p1[2]);
00142 glVertex3f(p2[0],p2[1],p2[2]);
00143 }
00144 glEnd();
00145 };
00146
00147
00148 void Mesh::draw_vertices() const
00149 {
00150 glDisable(GL_LIGHTING);
00151 glPointSize(10.0);
00152 glColor3f(0.7,1.0,0.1);
00153 glBegin(GL_POINTS);
00154 for(Vertex_iterator pPoint = _mesh->vertices_begin(); pPoint != _mesh->vertices_end(); pPoint++)
00155 glVertex3f(pPoint->point()[0],pPoint->point()[1],pPoint->point()[2]);
00156 glEnd();
00157 glPointSize(1.0);
00158 glEnable(GL_LIGHTING);
00159 };
00160
00161 void Mesh::BoundingBox(double * centre, double * diameter)
00162
00163 {
00164 double w, h, k;
00165
00166 Vertex_iterator pPoint = vertices_begin();
00167
00168 double min[3] = { pPoint->point()[0],pPoint->point()[1],pPoint->point()[2] };
00169 double max[3] = { pPoint->point()[0],pPoint->point()[1],pPoint->point()[2] };
00170 for (Vertex_iterator pPoint = vertices_begin(); pPoint != vertices_end(); pPoint++) {
00171 if (pPoint->point()[0] > max[0]) max[0] = pPoint->point()[0];
00172 if (pPoint->point()[0] < min[0]) min[0] = pPoint->point()[0];
00173 if (pPoint->point()[1] > max[1]) max[1] = pPoint->point()[1];
00174 if (pPoint->point()[1] < min[1]) min[1] = pPoint->point()[1];
00175 if (pPoint->point()[2] > max[2]) max[2] = pPoint->point()[2];
00176 if (pPoint->point()[2] < min[2]) min[2] = pPoint->point()[2];
00177 }
00178 centre[0] = (max[0]+min[0])/2.0; w = (max[0]-min[0])/2.0;
00179 centre[1] = (max[1]+min[1])/2.0; h = (max[1]-min[1])/2.0;
00180 centre[2] = (max[2]+min[2])/2.0; k = (max[2]-min[2])/2.0;
00181 (*diameter) = (w>h)?w:h; if (k>(*diameter)) (*diameter) = k;
00182
00183 if (*diameter < 0.1) (*diameter) = 0.1;
00184 };
00185
00186
00187 bool Mesh::loadFromFile(const char* filename)
00188 {
00189 char* file_ext = strstr(filename,".off");
00190 if (( file_ext == NULL ) || ( strcmp(file_ext,".off") != 0 ))
00191 {
00192 std::cerr << " *** Unexpected file format (.off required)" << std::endl;
00193 return false;
00194 }
00195
00196
00197 _mesh = new Enriched_polyhedron<Enriched_kernel,Enriched_items>;
00198 CGAL_assertion(_mesh != NULL);
00199
00200
00201 std::ifstream stream(filename);
00202 if(!stream)
00203 {
00204 std::cerr << "*** Error while opening file " << filename << std::endl;
00205 return false;
00206 }
00207 stream >> *_mesh;
00208
00209 if ((_mesh->size_of_vertices() == 0)|| (_mesh->size_of_facets() == 0)) {
00210
00211 std::cout << "*** Warning: mesh is not manifold ***" << std::endl;
00212 return false;
00213 }
00214
00215 std::cout << _mesh->size_of_vertices() << " vertices, ";
00216 std::cout << _mesh->size_of_facets() << " faces" << std::endl;
00217
00218 return true;
00219 };
00220
00221 void Mesh::saveToFile(const char* filename) const
00222 {
00223 std::ofstream fichier;
00224
00225 fichier.open(filename, std::ios::out | std::ios::trunc);
00226 if(fichier.bad()){
00227 return;
00228 }
00229
00230
00231 CGAL::set_ascii_mode( fichier);
00232 fichier << "OFF" << std::endl << _mesh->size_of_vertices() << ' '
00233 << _mesh->size_of_facets() << " 0" << std::endl;
00234 std::copy( _mesh->points_begin(), _mesh->points_end(),
00235 std::ostream_iterator<Mesh::Point>( fichier, "\n"));
00236 for ( Mesh::Facet_iterator i = _mesh->facets_begin(); i != _mesh->facets_end(); ++i) {
00237 Mesh::Halfedge_around_facet_circulator j = i->facet_begin();
00238
00239 CGAL_assertion( CGAL::circulator_size(j) >= 3);
00240 fichier << CGAL::circulator_size(j) << ' ';
00241 do {
00242 fichier << ' ' << std::distance(_mesh->vertices_begin(), j->vertex());
00243 } while ( ++j != i->facet_begin());
00244 fichier << std::endl;
00245 }
00246 fichier.close();
00247 };
00248
00249
00250 Mesh::Vertex_handle Mesh::nearestVertexOnFacet(Mesh::Point selectedPoint) {
00251 Vertex_handle SommetMini = _mesh->vertices_begin();
00252 for(Mesh::Vertex_iterator j = _mesh->vertices_begin(); j != _mesh->vertices_end() ; ++j) {
00253 if (has_smaller_distance_to_point(selectedPoint,
00254 j->point(),
00255 SommetMini->point())) {
00256 SommetMini = j;
00257 }
00258 }
00259
00260 std::cout << "sommet le plus proche = "
00261 << SommetMini->point()[0] << ' '
00262 << SommetMini->point()[1] << ' '
00263 << SommetMini->point()[2] << std::endl ;
00264 return SommetMini ;
00265 };
00266
00267 void Mesh::drawUserSnake()
00268 {
00269
00270
00271
00272 Mesh::Vertex_handle vtx1 = *(_snake_vertex.begin()) ;
00273
00274
00275 glDisable(GL_LIGHTING) ;
00276 for(std::vector < Mesh::Vertex_handle >::iterator i=_snake_vertex.begin() ;
00277 i != _snake_vertex.end() ;
00278 ++i)
00279 {
00280 glPointSize(10.0) ;
00281
00282 glBegin(GL_POINTS) ;
00283
00284 glColor3f(1.0,0.0,0.0) ;
00285
00286 glVertex3f((*i)->point()[0]-0.01*dir[0],
00287 (*i)->point()[1]-0.01*dir[1],
00288 (*i)->point()[2]-0.01*dir[2]) ;
00289
00290 glEnd() ;
00291
00292 glPointSize(1.0) ;
00293
00294 drawSnakePath(vtx1, *i, 0) ;
00295
00296 vtx1 = *i ;
00297
00298 }
00299 glEnable(GL_LIGHTING) ;
00300
00301
00302
00303
00304
00305 }
00306
00307 void Mesh::drawSnakePath(Mesh::Vertex_handle source, Mesh::Vertex_handle target, int drawPathEnds = 3)
00308 {
00309
00310 glPointSize(6.0f);
00311
00312 glColor3f(1.0,0.0,0.0);
00313
00314 glBegin(GL_POINTS);
00315
00316 if (drawPathEnds == 1 || drawPathEnds == 3)
00317
00318 glVertex3f(source->point()[0],source->point()[1],source->point()[2]);
00319 if (drawPathEnds == 2 || drawPathEnds == 3)
00320
00321 glVertex3f(target->point()[0],target->point()[1],target->point()[2]);
00322
00323 glEnd();
00324
00325 glPointSize(1.0f);
00326
00327 glColor3f(1.0,1.0,0.0);
00328
00329 glLineWidth(5.0);
00330
00331 glBegin(GL_LINES);
00332
00333
00334
00335
00336 for (std::vector<Mesh::Vertex_chemin>::iterator vcv = _snake_total.begin() ;
00337 vcv != _snake_total.end() ;
00338 vcv++)
00339 {
00340
00341 Mesh::Point p1 = (*(vcv->begin()))->point() ;
00342
00343
00344 for (Mesh::Vertex_chemin::iterator vc = vcv->begin() ;
00345 vc != vcv->end() ;
00346 vc++)
00347 {
00348 Mesh::Point p2 = (*vc)->point() ;
00349
00350 glVertex3f(p1[0]-0.001*dir[0],
00351 p1[1]-0.001*dir[1],
00352 p1[2]-0.001*dir[2]);
00353
00354 glVertex3f(p2[0]-0.001*dir[0],
00355 p2[1]-0.001*dir[0],
00356 p2[2]-0.001*dir[0]);
00357
00358 p1=p2;
00359 }
00360 }
00361
00362
00363 glColor3f(0.3,0.6,0.4);
00364
00365 glLineWidth(15.0);
00366
00367 glBegin(GL_LINES);
00368
00369 for(Mesh::Halfedge_iterator h = _mesh->border_halfedges_begin(); h != _mesh->halfedges_end(); h++)
00370 {
00371
00372 const Mesh::Point& p1 = h->prev()->vertex()->point();
00373 const Mesh::Point& p2 = h->vertex()->point();
00374
00375 glVertex3f(p1[0],p1[1],p1[2]);
00376 glVertex3f(p2[0],p2[1],p2[2]);
00377 }
00378
00379 glEnd();
00380
00381 glLineWidth(1.0);
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 void Mesh::drawLocalRegion()
00395 {
00396 Polyhedron* P = _snake_fini.getRegion()->mesh3D() ;
00397 glColor3f(0.8,0.8,0.8);
00398 glLineWidth(2.0);
00399 for(Polyhedron::Facet_iterator pFacet = P->facets_begin(); pFacet != P->facets_end(); pFacet++)
00400 {
00401 glBegin(GL_POLYGON);
00402
00403 Polyhedron::Halfedge_around_facet_circulator pHalfedge = pFacet->facet_begin();
00404 do
00405 {
00406 const Vector& normal = orthogonal_vector ( pHalfedge->vertex()->point(),
00407 pHalfedge->next()->vertex()->point(),
00408 pHalfedge->prev()->vertex()->point());
00409
00410
00411
00412
00413
00414 glNormal3f(-normal[0],-normal[1],-normal[2]);
00415
00416
00417 const Point& point = pHalfedge->vertex()->point();
00418
00419 glVertex3d(point[0]-0.01*normal[0],point[1]-0.01*normal[1],point[2]-0.01*normal[2]);
00420
00421 }while(++pHalfedge != pFacet->facet_begin());
00422
00423 glEnd();
00424
00425 }
00426 glLineWidth(1.0);
00427
00428 }
00429
00430
00431
00432
00433
00434 void Mesh::draw2dRegion() {
00435 Polyhedron* P = _snake_fini.getRegion()->mesh2D() ;
00436 glColor3f(0.8,0.8,0.8);
00437 glLineWidth(2.0);
00438 for(Polyhedron::Facet_iterator pFacet = P->facets_begin(); pFacet != P->facets_end(); pFacet++)
00439 {
00440 glBegin(GL_POLYGON);
00441
00442 Polyhedron::Halfedge_around_facet_circulator pHalfedge = pFacet->facet_begin();
00443 do
00444 {
00445 const Vector& normal = orthogonal_vector ( pHalfedge->vertex()->point(),
00446 pHalfedge->next()->vertex()->point(),
00447 pHalfedge->prev()->vertex()->point());
00448
00449
00450
00451
00452
00453 glNormal3f(-normal[0],-normal[1],-normal[2]);
00454
00455
00456 const Point& point = pHalfedge->vertex()->point();
00457
00458 glVertex3d(point[0],point[1],point[2]);
00459
00460 }while(++pHalfedge != pFacet->facet_begin());
00461
00462 glEnd();
00463
00464 }
00465 glLineWidth(1.0);
00466
00467 }
00468
00469
00470
00471
00472
00473
00474
00475 void Mesh::approx_shortest_path(Mesh::Vertex_chemin &chemin, Vertex_handle source, Vertex_handle target) const
00476 {
00477 if (source == target)
00478 {
00479 std::cout<<"source == target !"<<std::endl ;
00480 exit(-1) ;
00481 }
00482 else
00483 {
00484
00485 }
00486
00487
00488
00489 Point prochainmin, prochainp;
00490
00491
00492 int count=0;
00493
00494
00495 chemin.push_back(source) ;
00496
00497 Vertex_handle pVertexCour = source ;
00498
00499 while( (pVertexCour!=target) && (count<=2000) ){
00500
00501
00502 Halfedge_around_vertex_circulator curr;
00503
00504
00505
00506 curr = pVertexCour->vertex_begin();
00507
00508 Vertex_handle pVermin = curr->prev()->vertex();
00509
00510 prochainmin=pVermin->point();
00511
00512 curr++;
00513 do {
00514 prochainp = curr->prev()->vertex()->point();
00515
00516 if( has_smaller_distance_to_point(target->point(), prochainp, prochainmin) ) {
00517 pVermin=curr->prev()->vertex();
00518 prochainmin=prochainp;
00519 }
00520
00521 } while (curr++ != pVertexCour->vertex_begin());
00522
00523
00524 chemin.push_back(pVermin) ;
00525
00526 pVertexCour=pVermin;
00527
00528 count++;
00529
00530 }
00531 if (count >= 2000)
00532 std::cout << "*** Warning ***: aucun plus court chemin n'a été trouvé" << std::endl ;
00533
00534 count=0;
00535
00536
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546 class Triangle {
00547 public:
00548 int p1, p2, p3 ;
00549 Triangle(int p1, int p2, int p3) : p1(p1), p2(p2), p3(p3) {};
00550 };
00551
00552
00553 std::ostream& operator<< (std::ostream& out, const Triangle& T) {
00554 return out << T.p1 << ' ' << T.p2 << ' ' << T.p3;
00555 }
00556
00557
00558
00559 class PtIndex {
00560 public:
00561 Mesh::Point p ;
00562 int i ;
00563 PtIndex() {}
00564 PtIndex(Mesh::Point p, int i): p(p), i(i) {}
00565 };
00566
00567
00568
00569 class PtVector : public std::vector<PtIndex> {
00570 public:
00571
00572 int isPresent(const Mesh::Point p) {
00573 for(std::vector<PtIndex>::iterator i = this->begin() ; i != this->end() ; i++) {
00574 if (i->p == p) return i->i ;
00575 }
00576 return -1 ;
00577 }
00578 };
00579
00580
00581 class TrVector : public std::vector<Triangle> {
00582 public:
00583
00584 int isPresent(const Triangle Tri) {
00585 for(std::vector<Triangle>::iterator i = this->begin() ; i != this->end() ; i++) {
00586 if (((i->p1 == Tri.p1) && (i->p2 == Tri.p2) && (i->p3 == Tri.p3)) ||
00587 ((i->p1 == Tri.p2) && (i->p2 == Tri.p3) && (i->p3 == Tri.p1)) ||
00588 ((i->p1 == Tri.p3) && (i->p2 == Tri.p1) && (i->p3 == Tri.p2)) ||
00589 ((i->p1 == Tri.p3) && (i->p2 == Tri.p2) && (i->p3 == Tri.p1)) ||
00590 ((i->p1 == Tri.p2) && (i->p2 == Tri.p1) && (i->p3 == Tri.p3)) ||
00591 ((i->p1 == Tri.p1) && (i->p2 == Tri.p3) && (i->p3 == Tri.p2)))
00592 return 1 ;
00593 }
00594 return -1 ;
00595 }
00596 };
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 Mesh::Polyhedron Mesh::Local_region( std::vector< Vertex_chemin >& Snake )
00608 {
00609 int vecsize = 0 ;
00610
00611
00612 PtVector S;
00613 TrVector T ;
00614 PtIndex pind1, pind2, pind3 ;
00615 int indice, ind1, ind2, ind3 ;
00616
00617 for(std::vector< Vertex_chemin >::const_iterator chem_it=Snake.begin(); chem_it!=Snake.end(); chem_it++)
00618 {
00619 for(std::vector< Vertex_handle >::const_iterator it=chem_it->begin(); it!=chem_it->end(); it++)
00620 {
00621
00622
00623
00624 Halfedge_around_vertex_circulator curr = (*it)->vertex_begin();
00625
00626 Point p1(curr->vertex()->point());
00627 indice = S.isPresent(p1) ;
00628 if (indice == -1)
00629 {
00630 ind1 = vecsize ;
00631 pind1 = PtIndex(p1, vecsize++) ;
00632 S.push_back(pind1) ;
00633
00634 }
00635 else
00636 {
00637 ind1 = indice ;
00638
00639 }
00640
00641 do
00642 {
00643
00644 Point p2(curr->prev()->vertex()->point());
00645 indice = S.isPresent(p2) ;
00646 if (indice == -1)
00647 {
00648 ind2 = vecsize ;
00649 pind2 = PtIndex(p2, vecsize++) ;
00650 S.push_back(pind2) ;
00651
00652 }
00653 else
00654 {
00655 ind2 = indice ;
00656
00657 }
00658
00659
00660 curr++;
00661
00662 Point p3(curr->prev()->vertex()->point());
00663 indice = S.isPresent(p3) ;
00664 if (indice == -1)
00665 {
00666 ind3 = vecsize ;
00667 pind3 = PtIndex(p3, vecsize++) ;
00668 S.push_back(pind3) ;
00669
00670 }
00671 else
00672 {
00673 ind3 = indice ;
00674
00675 }
00676
00677
00678 Triangle facette = Triangle(ind1, ind2, ind3) ;
00679 if (T.isPresent(facette) != -1)
00680 {
00681
00682
00683
00684
00685
00686
00687
00688 }
00689 else
00690
00691 T.push_back(Triangle(ind1, ind2, ind3)) ;
00692
00693
00694 } while (curr != (*it)->vertex_begin() );
00695 }
00696 }
00697
00698
00699 const char* filename = "SNAKETEMP.off" ;
00700 std::ofstream fichier;
00701
00702 fichier.open(filename, std::ios::out | std::ios::trunc);
00703 if(fichier.bad()){
00704 std::cout<<"erreur lecture fichier"<<std::endl ;
00705 exit(-1) ;
00706 }
00707
00708
00709 CGAL::set_ascii_mode( fichier);
00710 fichier << "OFF" << std::endl << S.size() << ' '
00711 << T.size() << " 0" << std::endl;
00712 for(PtVector::iterator ptv = S.begin() ; ptv != S.end() ; ptv++) {
00713 fichier<<ptv->p<<std::endl ;
00714 }
00715 for ( std::vector<Triangle>::iterator i = T.begin(); i != T.end(); i++) {
00716
00717
00718 fichier << '3' << ' ';
00719
00720
00721 fichier << *i;
00722 fichier << std::endl;
00723 }
00724 fichier.close();
00725
00726
00727 Mesh M(filename) ;
00728 return *M._mesh ;
00729 }
00730
00731
00732
00733
00734
00735
00736
00737