PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // SurfaceMesh.cc 00004 // 00005 // Copyright (C) 2004 Pascal Lamblin 00006 // 00007 // Redistribution and use in source and binary forms, with or without 00008 // modification, are permitted provided that the following conditions are met: 00009 // 00010 // 1. Redistributions of source code must retain the above copyright 00011 // notice, this list of conditions and the following disclaimer. 00012 // 00013 // 2. Redistributions in binary form must reproduce the above copyright 00014 // notice, this list of conditions and the following disclaimer in the 00015 // documentation and/or other materials provided with the distribution. 00016 // 00017 // 3. The name of the authors may not be used to endorse or promote 00018 // products derived from this software without specific prior written 00019 // permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00022 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00023 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00024 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00026 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 // 00032 // This file is part of the PLearn library. For more information on the PLearn 00033 // library, go to the PLearn Web site at www.plearn.org 00034 00035 /* ******************************************************* 00036 * $Id: SurfaceMesh.cc,v 1.18 2005/12/29 13:44:35 lamblinp Exp $ 00037 ******************************************************* */ 00038 00039 // Authors: Pascal Lamblin 00040 00044 #include "SurfaceMesh.h" 00045 #include "geometry.h" 00046 00047 namespace PLearn { 00048 using namespace std; 00049 00050 SurfaceMesh::SurfaceMesh() : 00051 computed_vtx_norm( false ), 00052 mesh_type( "PointSet" ), 00053 verbosity(1) 00054 { 00055 p_mesh = new Graph_(); 00056 // because graph_ppt field isn't correctly initialized 00057 mg = new MeshGraph(); 00058 set_property( *p_mesh, graph_ppt, mg ); 00059 00060 } 00061 00062 PLEARN_IMPLEMENT_OBJECT(SurfaceMesh, 00063 "Mesh covering a Surface, with Vertices, Edges, and Faces", 00064 "" ); 00065 00066 SurfaceMesh::SurfaceMesh( Graph g ) : 00067 computed_vtx_norm( false ), 00068 p_mesh( g ), 00069 mesh_type( "PointSet" ) 00070 { 00071 mg = new MeshGraph(); 00072 set_property( *p_mesh, graph_ppt, mg ); 00073 } 00074 00075 00076 SurfaceMesh::SurfaceMesh( const SurfaceMesh& m ) : 00077 computed_vtx_norm( m.computed_vtx_norm ), 00078 p_mesh( m.p_mesh ), 00079 mesh_type( m.mesh_type ) 00080 { 00081 mg = new MeshGraph( *(m.mg) ) ; 00082 set_property( *p_mesh, graph_ppt, mg ); 00083 } 00084 00085 00086 SurfaceMesh::~SurfaceMesh() 00087 {} 00088 00089 void SurfaceMesh::declareOptions(OptionList& ol) 00090 { 00091 declareOption(ol, "mesh_type", &SurfaceMesh::mesh_type, 00092 OptionBase::learntoption, 00093 "Type of mesh, describing the kind of information that is available.\n" 00094 "Supported options are:\n" 00095 " - 'FaceSet': Vertices, Faces, and Edges;\n" 00096 " - 'LineSet': Vertices and Edges;\n" 00097 " - 'PointSet' (default): Vertices.\n" ); 00098 00099 declareOption(ol, "verbosity", &SurfaceMesh::verbosity, 00100 OptionBase::buildoption, 00101 "Level of verbosity. If 0 should not write anything on perr.\n" 00102 "If >0 may write some info on the steps performed" 00103 " along the way.\n" 00104 "The level of details written should depend on this value.\n" 00105 ); 00106 00107 inherited::declareOptions(ol); 00108 } 00109 00110 void SurfaceMesh::build_() 00111 { 00112 // build_vertex_normals(); 00113 string mt = lowerstring( mesh_type ); 00114 mt = space_to_underscore( mt ); 00115 search_replace( mt, "_", "" ); 00116 if( mt == "faceset" ) 00117 mesh_type = "FaceSet"; 00118 else if( mt == "lineset" ) 00119 mesh_type = "LineSet"; 00120 else if( mt == "pointset" ) 00121 mesh_type = "PointSet"; 00122 else 00123 PLERROR( "mesh_type '%s' not supported", mesh_type.c_str() ); 00124 } 00125 00126 void SurfaceMesh::build() 00127 { 00128 inherited::build(); 00129 build_(); 00130 } 00131 00132 void SurfaceMesh::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00133 { 00134 inherited::makeDeepCopyFromShallowCopy(copies); 00135 00136 Graph p_mesh2 = new Graph_( *p_mesh ); 00137 00138 property_map< graph, vertex_ppt_t >::type vertex_ppt_map = 00139 get( vertex_ppt, *p_mesh2 ); 00140 00141 map< vertex_descriptor, vertex_descriptor > vertex_corresp; 00142 00143 vertex_iterator vi, vi_end; 00144 vertex_iterator vi2, vi2_end; 00145 tie( vi, vi_end ) = vertices( *p_mesh ); 00146 tie( vi2, vi2_end ) = vertices( *p_mesh2 ); 00147 for( ; vi != vi_end ; vi++, vi2++ ) 00148 { 00149 vertex_ppt_map[ *vi2 ] = vertex_ppt_map[*vi2]->deepCopy(copies); 00150 vertex_corresp[ *vi ] = *vi2; 00151 } 00152 00153 property_map< graph, edge_ppt_t >::type edge_ppt_map = 00154 get( edge_ppt, *p_mesh2 ); 00155 00156 edge_iterator ei2, ei2_end; 00157 for( tie(ei2,ei2_end) = edges( *p_mesh2 ) ; ei2 != ei2_end ; ei2++ ) 00158 { 00159 edge_ppt_map[ *ei2 ] = edge_ppt_map[*ei2]->deepCopy(copies); 00160 } 00161 00162 mg->makeDeepCopyFromShallowCopy( copies ); 00163 int n_faces = numFaces(); 00164 00165 for( int i=0 ; i<n_faces ; i++ ) 00166 { 00167 MFace face = getFace(i); 00168 for( int j=0 ; j<3 ; j++ ) 00169 { 00170 face->pts[j] = vertex_corresp[ face->pts[j] ]; 00171 } 00172 00173 for( int j=0 ; j<3 ; j++ ) 00174 { 00175 int jj = (j+1)%3; // jj == j+1 if j==0 or 1, jj==0 if j=3 00176 out_edge_iterator oei, oei_end; 00177 vertex_descriptor src = face->pts[j]; 00178 vertex_descriptor tgt = face->pts[jj]; 00179 for( tie(oei, oei_end)=out_edges(src, *p_mesh2) ; oei != oei_end ; oei++ ) 00180 { 00181 if( target( *oei, *p_mesh2 ) == tgt ) 00182 { 00183 face->edges[j] = *oei; 00184 } 00185 } 00186 } 00187 } 00188 00189 p_mesh = p_mesh2; 00190 00191 } 00192 00193 vertex_descriptor SurfaceMesh::addVertex( MVertex mv ) 00194 { 00195 vertex_descriptor vtx = add_vertex( mv, *p_mesh ); 00196 return vtx; 00197 } 00198 00199 vertex_descriptor SurfaceMesh::addVertex( Vec coord, Vec features ) 00200 { 00201 MVertex mv = new MeshVertex(); 00202 00203 if( coord.length() != 3 ) 00204 PLERROR("Error in addVertex(Vec coord): coord size is supposed to be 3 (or not to be!)"); 00205 00206 mv->coord << coord; 00207 00208 mv->features.resize( features.size() ); 00209 mv->features << features; 00210 00211 vertex_descriptor vtx = addVertex( mv ); 00212 return vtx; 00213 } 00214 00215 vertex_descriptor SurfaceMesh::addVertex( real x, real y, real z ) 00216 { 00217 Vec coord( 3 ); 00218 coord[0] = x; 00219 coord[1] = y; 00220 coord[2] = z; 00221 vertex_descriptor vtx = addVertex( coord ); 00222 return vtx; 00223 } 00224 00225 void SurfaceMesh::delVertex( vertex_descriptor vtx ) 00226 { 00227 remove_vertex( vtx, *p_mesh ); 00228 } 00229 00230 MVertex SurfaceMesh::getVertex( vertex_descriptor vtx ) 00231 { 00232 MVertex mv = get( vertex_ppt, *p_mesh, vtx ); 00233 return mv; 00234 } 00235 00236 void SurfaceMesh::setVertex( vertex_descriptor vtx, const MVertex& mv ) 00237 { 00238 put( vertex_ppt, *p_mesh, vtx, mv ); 00239 } 00240 00241 00242 Mat SurfaceMesh::getVertexCoords() 00243 { 00244 int n_pts = num_vertices( *p_mesh ); 00245 Mat coords( n_pts, 3 ); 00246 00247 property_map< graph, vertex_ppt_t >::type 00248 vertex_ppt_map = get( vertex_ppt, *p_mesh ); 00249 00250 vertex_iterator vi, vi_end; 00251 tie( vi, vi_end ) = vertices( *p_mesh ); 00252 for( int i=0 ; i<n_pts ; i++, vi++ ) 00253 { 00254 coords(i) << vertex_ppt_map[ *vi ]->coord; 00255 } 00256 return coords; 00257 } 00258 00259 Mat SurfaceMesh::getVertexCoordsAndFeatures() 00260 { 00261 int n_pts = num_vertices( *p_mesh ); 00262 Mat coords_and_features; 00263 00264 property_map< graph, vertex_ppt_t >::type 00265 vertex_ppt_map = get( vertex_ppt, *p_mesh ); 00266 00267 vertex_iterator vi, vi_end; 00268 tie( vi, vi_end ) = vertices( *p_mesh ); 00269 00270 int feat_size = vertex_ppt_map[ *vi ]->features.size(); 00271 coords_and_features.resize( n_pts, 3+feat_size ); 00272 00273 for( int i=0 ; i<n_pts ; i++, vi++ ) 00274 { 00275 MVertex mv = vertex_ppt_map[ *vi ]; 00276 coords_and_features(i).subVec(0,3) << mv->coord; 00277 coords_and_features(i).subVec(3,feat_size) << mv->features; 00278 } 00279 return coords_and_features; 00280 } 00281 00282 void SurfaceMesh::setVertexCoords( const Mat& coords ) 00283 { 00284 int n_pts = num_vertices( *p_mesh ); 00285 if( coords.length() != n_pts ) 00286 { 00287 PLERROR( "setVertexCoords: coords.length()=%d different from n_pts=%d", 00288 coords.length(), n_pts ); 00289 } 00290 else 00291 { 00292 property_map< graph, vertex_ppt_t >::type 00293 vertex_ppt_map = get( vertex_ppt, *p_mesh ); 00294 00295 vertex_iterator vi, vi_end; 00296 tie( vi, vi_end ) = vertices( *p_mesh ); 00297 for( int i=0 ; i<n_pts ; i++, vi++ ) 00298 { 00299 vertex_ppt_map[ *vi ]->coord << coords(i); 00300 } 00301 } 00302 } 00303 00304 void SurfaceMesh::setVertexFeatures( const Mat& features ) 00305 { 00306 int n_pts = num_vertices( *p_mesh ); 00307 if( features.length() != n_pts ) 00308 { 00309 PLERROR( "setVertexFeatures: features.length()=%d different from n_pts=%d", 00310 features.length(), n_pts ); 00311 } 00312 else 00313 { 00314 property_map< graph, vertex_ppt_t >::type 00315 vertex_ppt_map = get( vertex_ppt, *p_mesh ); 00316 00317 vertex_iterator vi, vi_end; 00318 tie( vi, vi_end ) = vertices( *p_mesh ); 00319 for( int i=0 ; i<n_pts ; i++, vi++ ) 00320 { 00321 vertex_ppt_map[ *vi ]->features << features(i); 00322 } 00323 } 00324 } 00325 00326 void SurfaceMesh::setVertexCoordsAndFeatures( const Mat& coords, 00327 const Mat& features ) 00328 { 00329 int n_pts = num_vertices( *p_mesh ); 00330 if( coords.length() != n_pts ) 00331 { 00332 PLERROR( "setVertexCoordsAndFeatures:" 00333 " coords.length()=%d different from n_pts=%d", 00334 coords.length(), n_pts ); 00335 } 00336 if( features.length() != n_pts ) 00337 { 00338 PLERROR( "setVertexCoordsAndFeatures:" 00339 " features.length()=%d different from n_pts=%d", 00340 features.length(), n_pts ); 00341 } 00342 else 00343 { 00344 property_map< graph, vertex_ppt_t >::type 00345 vertex_ppt_map = get( vertex_ppt, *p_mesh ); 00346 00347 vertex_iterator vi, vi_end; 00348 tie( vi, vi_end ) = vertices( *p_mesh ); 00349 for( int i=0 ; i<n_pts ; i++, vi++ ) 00350 { 00351 vertex_ppt_map[ *vi ]->coord << coords(i); 00352 vertex_ppt_map[ *vi ]->features << features(i); 00353 } 00354 } 00355 } 00356 00357 int SurfaceMesh::numVertices() 00358 { 00359 return( num_vertices(*p_mesh) ); 00360 } 00361 00362 TVec<vertex_descriptor> SurfaceMesh::getVertexDescriptors() 00363 { 00364 int n_pts = numVertices(); 00365 TVec<vertex_descriptor> result( n_pts ); 00366 00367 vertex_iterator vi, vi_end; 00368 tie( vi, vi_end ) = vertices( *p_mesh ); 00369 for( int i=0 ; i<n_pts ; i++, vi++ ) 00370 { 00371 result[i] = *vi; 00372 } 00373 return( result ); 00374 } 00375 00376 00377 Mat SurfaceMesh::getVertexNorms() 00378 { 00379 if( !computed_vtx_norm ) 00380 { 00381 PLWARNING( "Trying to get vertex normals, but they\'re not initialized" ); 00382 } 00383 int n_pts = num_vertices( *p_mesh ); 00384 Mat norms( n_pts, 3 ); 00385 00386 property_map< graph, vertex_ppt_t >::type 00387 vertex_ppt_map = get( vertex_ppt, *p_mesh ); 00388 00389 vertex_iterator vi, vi_end; 00390 tie( vi, vi_end ) = vertices( *p_mesh ); 00391 for( int i=0 ; i<n_pts ; i++, vi++ ) 00392 { 00393 norms(i) << vertex_ppt_map[ *vi ]->norm; 00394 } 00395 return norms; 00396 } 00397 00398 void SurfaceMesh::setVertexNorms( const Mat& norms ) 00399 { 00400 int n_pts = num_vertices( *p_mesh ); 00401 if( norms.length() != n_pts ) 00402 { 00403 PLERROR( "setVertexNorms: norms.length()=%d different from n_pts=%d", 00404 norms.length(), n_pts ); 00405 } 00406 else 00407 { 00408 property_map< graph, vertex_ppt_t >::type 00409 vertex_ppt_map = get( vertex_ppt, *p_mesh ); 00410 00411 vertex_iterator vi, vi_end; 00412 tie( vi, vi_end ) = vertices( *p_mesh ); 00413 for( int i=0 ; i<n_pts ; i++, vi++ ) 00414 { 00415 vertex_ppt_map[ *vi ]->norm << norms(i); 00416 } 00417 } 00418 } 00419 00420 00421 00422 00423 edge_descriptor SurfaceMesh::addEdge( vertex_descriptor first, 00424 vertex_descriptor second, 00425 MEdge me ) 00426 { 00427 edge_descriptor ed = add_edge( first, second, me, *p_mesh ).first; 00428 return ed; 00429 } 00430 00431 void SurfaceMesh::delEdge( edge_descriptor ed ) 00432 { 00433 PLERROR( "SurfaceMesh::delEdge() not implemented yet." ); 00434 } 00435 00436 MEdge SurfaceMesh::getEdge( edge_descriptor ed ) 00437 { 00438 MEdge me = get( edge_ppt, *p_mesh, ed ); 00439 return me; 00440 } 00441 00442 void SurfaceMesh::setEdge( edge_descriptor ed, const MEdge& me ) 00443 { 00444 put( edge_ppt, *p_mesh, ed, me ); 00445 } 00446 00447 int SurfaceMesh::numEdges() 00448 { 00449 return( num_edges(*p_mesh) ); 00450 } 00451 00452 00453 int SurfaceMesh::addFace( MFace mf ) 00454 { 00455 mg->faces.append( mf ); 00456 return( mg->faces.length() - 1 ); 00457 } 00458 00459 int SurfaceMesh::addFace( TVec<vertex_descriptor> pts ) 00460 { 00461 if( pts.length() != 3 ) 00462 PLERROR("Error in addFace(TVec<...> pts): you can only create a triangle face."); 00463 00464 MFace mf = new MeshFace(); 00465 mf->pts << pts; 00466 int face_index = addFace( mf ); 00467 return face_index; 00468 } 00469 00470 int SurfaceMesh::addFace( vertex_descriptor first, 00471 vertex_descriptor second, 00472 vertex_descriptor third ) 00473 { 00474 TVec<vertex_descriptor> pts( 3 ); 00475 pts[0] = first; 00476 pts[1] = second; 00477 pts[2] = third; 00478 00479 int face_index = addFace( pts ); 00480 return face_index; 00481 } 00482 00483 void SurfaceMesh::delFace( int face_index) 00484 { 00485 PLERROR( "SurfaceMesh::delFace() not implemented yet." ); 00486 } 00487 00488 MFace SurfaceMesh::getFace( int face_index ) 00489 { 00490 MFace mf = mg->faces[ face_index ]; 00491 return mf; 00492 } 00493 00494 void SurfaceMesh::setFace( int face_index, const MFace& mf ) 00495 { 00496 mg->faces[ face_index ] = mf; 00497 } 00498 00499 int SurfaceMesh::numFaces() 00500 { 00501 return mg->faces.length(); 00502 } 00503 00504 00505 TVec< set<int> > SurfaceMesh::cacheNeighborFaces() 00506 { 00507 int n_pts = numVertices(); 00508 TVec< set<int> > face_cache( n_pts ); 00509 00510 vertex_iterator vi, vi_end; 00511 tie(vi, vi_end) = vertices( *p_mesh ); 00512 for( int i=0 ; vi != vi_end ; i++, vi++ ) 00513 { 00514 out_edge_iterator oei, oei_end; 00515 tie( oei, oei_end ) = out_edges( *vi, *p_mesh ); 00516 for( ; oei != oei_end ; oei++ ) 00517 { 00518 MEdge me = getEdge( *oei ); 00519 face_cache[i].insert( me->face1 ); 00520 face_cache[i].insert( me->face2 ); 00521 } 00522 face_cache[i].erase( -1 ); 00523 } 00524 return( face_cache ); 00525 } 00526 00527 00528 int SurfaceMesh::buildEdges() 00529 { 00530 TVec<MFace> faces = mg->faces; 00531 00532 property_map< graph, vertex_ppt_t >::type 00533 vertex_ppt_map = get( vertex_ppt, *p_mesh ); 00534 00535 property_map< graph, edge_ppt_t >::type 00536 edge_ppt_map = get( edge_ppt, *p_mesh ); 00537 00538 int n_faces = faces.size(); 00539 int nerrors = 0; 00540 00541 for( int i=0 ; i<n_faces ; i++ ) 00542 { 00543 MFace mf = faces[i]; 00544 TVec< vertex_descriptor > pts = mf->pts; 00545 00546 /* we build 3 edges from each face */ 00547 for( int j=0 ; j<3 ; j++ ) 00548 { 00549 MEdge me = new MeshEdge(); 00550 me->face1 = i; 00551 me->bf = 1; 00552 00553 int jj = (j+1)%3; // jj == j+1 if j==0 or 1, jj==0 if j=3 00554 me->length = dist( vertex_ppt_map[ pts[j] ]->coord, 00555 vertex_ppt_map[ pts[jj] ]->coord, 00556 2 ); 00557 00558 edge_descriptor ed; 00559 bool added; 00560 00561 /* ed is the descriptor of the edge linking pts[j] and pts[jj], 00562 added is "true" if it didn't exist and was just created. 00563 In this last case, the "MeshEdge" property was added too, 00564 i.e. face1 is set to current face, 00565 and the edge is considered as a "boundary" (bf=1) */ 00566 tie( ed, added ) = add_edge_ifnew( pts[j], pts[jj], me, *p_mesh ); 00567 00568 mf->edges[j] = ed; 00569 00570 /* if the edge was not added (it already existed)... */ 00571 if( !added ) 00572 { 00573 /* either there is no "face2" yet : mf is the other face, 00574 which is adjacent to "face1", 00575 and current edge isn't a border any more */ 00576 if( edge_ppt_map[ed]->face2<0 ) 00577 { 00578 edge_ppt_map[ed]->face2 = i; 00579 int k = edge_ppt_map[ed]->face1; 00580 00581 mf->adj_faces[j] = k; 00582 MFace neighbor_f = faces[k]; 00583 for( int l=0 ; l<3 ; l++ ) 00584 { 00585 if( neighbor_f->edges[l] == ed ) 00586 { 00587 neighbor_f->adj_faces[l] = i; 00588 } 00589 } 00590 00591 edge_ppt_map[ed]->bf = 0; 00592 } 00593 else 00594 { 00595 vertex_descriptor src = source( ed, *p_mesh ); 00596 vertex_descriptor tgt = target( ed, *p_mesh ); 00597 cerr << "Edge between " << src << " and " << tgt 00598 << " has more than 2 faces." << endl; 00599 00600 nerrors++; 00601 } 00602 } 00603 } 00604 } 00605 return( nerrors ); 00606 } 00607 00608 int SurfaceMesh::buildBoundaries() 00609 { 00610 int nerrors = 0; 00611 property_map< graph, vertex_ppt_t >::type 00612 vertex_ppt_map = get( vertex_ppt, *p_mesh ); 00613 00614 property_map< graph, edge_ppt_t >::type 00615 edge_ppt_map = get( edge_ppt, *p_mesh ); 00616 00617 /* we mark as "boundary" vertices all vertices belonging to 00618 at least a "boundary" edge */ 00619 edge_iterator ei, ei_end; 00620 for( tie(ei,ei_end)=edges( *p_mesh ) ; ei != ei_end ; ei++ ) 00621 { 00622 if( edge_ppt_map[ *ei ]->bf == 1 ) 00623 { 00624 vertex_ppt_map[ source( *ei, *p_mesh ) ]->bf = 1; 00625 } 00626 } 00627 00628 /* we check that a "boundary" vertex belongs to, at least, 00629 two boundary edges (otherwise, it wouldn't make any sense) */ 00630 vertex_iterator vi, vi_end; 00631 for( tie(vi,vi_end)=vertices( *p_mesh ) ; vi != vi_end ; vi++ ) 00632 { 00633 if( vertex_ppt_map[ *vi ]->bf ) 00634 { 00635 int bound_count = 0; 00636 adjacency_iterator ai, ai_end; 00637 for( tie(ai,ai_end)=adjacent_vertices( *vi, *p_mesh ) ; ai!=ai_end ; ai++ ) 00638 { 00639 if( vertex_ppt_map[ *ai ]->bf ) 00640 { bound_count++; } 00641 } 00642 00643 if( bound_count < 2 ) 00644 { 00645 cerr << "Wrong number of points on adjacent boundary to point " 00646 << *vi << endl; 00647 nerrors++; 00648 } 00649 } 00650 } 00651 return nerrors; 00652 } 00653 00654 real SurfaceMesh::getResolution() 00655 { 00656 return mg->resolution; 00657 } 00658 00659 00660 void SurfaceMesh::setResolution( real resolution ) 00661 { 00662 mg->resolution = resolution; 00663 } 00664 00665 00666 real SurfaceMesh::computeResolution() 00667 { 00668 /* we compute the mesh resolution : 00669 it is the median of the vertices' length */ 00670 int n_edges = num_edges( *p_mesh ); 00671 00672 property_map< graph, edge_ppt_t >::type 00673 edge_ppt_map = get( edge_ppt, *p_mesh ); 00674 00675 Vec lengths( n_edges ); 00676 edge_iterator ei, ei_end; 00677 tie(ei,ei_end)=edges( *p_mesh ); 00678 for( int i=0 ; i<n_edges ; i++ ) 00679 { 00680 lengths[i] = edge_ppt_map[*ei]->length; 00681 ei++; 00682 } 00683 00684 real resolution = median( lengths ); 00685 return( resolution ); 00686 } 00687 00688 /* 00689 * Functions to read a mesh from a VRML file, and write to it. 00690 * protected functions (names ending with a '_') are helper functions, 00691 * public functions should be used (and added if needed). 00692 * 00693 */ 00694 00695 /* Protected functions */ 00696 00697 // reads coordinates of the points in the "in" stream, 00698 // add them to the mesh, and stores correspondance between indices 00699 // in the file and vertex descriptors (in "vertices") 00700 bool SurfaceMesh::readVRMLCoordinate3_( ifstream& in, 00701 TVec<vertex_descriptor>& vertices, 00702 Mat vtx_features ) 00703 { 00704 string buf; 00705 00706 /* read from the file until "Coordinate3" is reached */ 00707 while( buf.compare( 0, 11, "Coordinate3" ) && in ) 00708 { 00709 in >> buf; 00710 } 00711 00712 /* read characters until the open bracket */ 00713 getline( in, buf, '[' ); 00714 00715 /* reading coordinates until close bracket */ 00716 getline( in, buf, ']' ); 00717 istringstream all_coords( buf ); 00718 00719 /* read coordinates by comma-separated triplets */ 00720 while( all_coords ) 00721 { 00722 Vec coord( 3 ); 00723 string coords; 00724 getline( all_coords, coords ); 00725 coords = removeblanks( coords ); 00726 remove_comments( coords ); 00727 int vertex_index = 0; 00728 if( coords != "" ) 00729 { 00730 istringstream point_coords( coords ); 00731 00732 if ( point_coords >> coord[0] >> coord[1] >> coord[2] ) 00733 { 00734 vertex_descriptor vtx; 00735 if( vtx_features.size() == 0 ) 00736 vtx = addVertex( coord ); 00737 else 00738 vtx = addVertex( coord, vtx_features(vertex_index) ); 00739 00740 /* store the correspondence between order in VRML file 00741 and vertex descriptor */ 00742 vertices.append( vtx ); 00743 vertex_index++; 00744 } 00745 else 00746 { 00747 return false; 00748 } 00749 } 00750 } 00751 return true; 00752 } 00753 00754 // reads indices of faces' vertices in the "in" stream, 00755 // add them to the mesh, with the help of the "vertices" correspondence 00756 bool SurfaceMesh::readVRMLIndexedFaceSet_( ifstream& in, 00757 TVec<vertex_descriptor>& vertices ) 00758 { 00759 string buf; 00760 00761 /* read from file until "IndexedFaceSet" is reached */ 00762 while( buf.compare( 0, 14, "IndexedFaceSet" ) ) 00763 { 00764 if( !in ) 00765 return false; 00766 00767 in >> buf; 00768 } 00769 00770 /* read characters until the open bracket */ 00771 getline( in, buf, '[' ); 00772 00773 /* reading coordinates until close bracket */ 00774 getline( in, buf, ']' ); 00775 istringstream all_faces( buf ); 00776 // bool end_list = false; 00777 00778 while( all_faces ) 00779 { 00780 TVec<int> pts(3); 00781 int delim; 00782 string face; 00783 getline( all_faces, face ); 00784 face = removeblanks( face ); 00785 remove_comments( face ); 00786 if( face != "" ) 00787 { 00788 istringstream point_indices( face ); 00789 // if( point_indices >> pts[0] >> pts[1] >> pts[2] ) 00790 bool ok = true; 00791 for( int i=0 ; i<3 ; i++ ) 00792 { 00793 string pt; 00794 getline( point_indices, pt, ',' ); 00795 istringstream point( pt ); 00796 ok = (point >> pts[i]) && ok; 00797 } 00798 00799 if( ok ) 00800 { 00801 if( (point_indices >> delim) && (delim != -1) ) 00802 PLERROR( "Non-triangular face found in 'IndexedFaceSet'.\n" ); 00803 00804 addFace( vertices[ pts[0] ], vertices[ pts[1] ], vertices[ pts[2] ] ); 00805 } 00806 else 00807 { 00808 PLERROR( "Parse error in 'IndexedFaceSet': expecting an integer.\n" ); 00809 } 00810 } 00811 } 00812 00813 int nerrors = createSurfaceMesh(); 00814 // delOrphanVertices(); 00815 00816 if( nerrors ) 00817 { return 0; } 00818 else 00819 { return 1; } 00820 00821 } 00822 00823 // reads indices of edges' vertices in the "in" stream, 00824 // add them to the mesh, with the help of the "vertices" correspondence 00825 bool SurfaceMesh::readVRMLIndexedLineSet_( ifstream& in, 00826 TVec<vertex_descriptor>& vertices ) 00827 { 00828 string buf; 00829 00830 /* read from file until "IndexedLineSet" is reached */ 00831 while( buf.compare( 0, 14, "IndexedLineSet" ) ) 00832 { 00833 if( !in ) 00834 return false; 00835 00836 in >> buf; 00837 } 00838 00839 /* read characters until the open bracket */ 00840 getline( in, buf, '[' ); 00841 00842 /* reading coordinates until close bracket */ 00843 getline( in, buf, ']' ); 00844 istringstream all_edges( buf ); 00845 00846 while( all_edges ) 00847 { 00848 TVec<int> pts(2); 00849 int delim; 00850 string edge; 00851 00852 getline( all_edges, edge ); 00853 edge = removeblanks( edge ); 00854 remove_comments( edge ); 00855 if( edge != "" ) 00856 { 00857 istringstream point_indices( edge ); 00858 bool ok = true; 00859 for( int i=0 ; i<2 ; i++ ) 00860 { 00861 string pt; 00862 getline( point_indices, pt, ',' ); 00863 istringstream point( pt ); 00864 ok = (point >> pts[i]) && ok; 00865 } 00866 00867 if( ok ) 00868 { 00869 if( (point_indices >> delim) && (delim != -1) ) 00870 PLERROR( "Edge of more than 2 points found in 'IndexedLineSet'.\n" ); 00871 00872 MEdge me = new MeshEdge(); 00873 addEdge( vertices[ pts[0] ], vertices[ pts [1] ], me ); 00874 } 00875 else 00876 { 00877 PLERROR( "Parse error in 'IndexedLineSet': expecting an integer.\n" ); 00878 } 00879 } 00880 } 00881 00882 return true; 00883 } 00884 00885 00886 // writes the "Coordinate3" VRML node in "out" file stream, 00887 // containing coordinates of the vertices, and store correspondance 00888 // between vertex descriptors and indices in the file (in "pts_indices"). 00889 void SurfaceMesh::writeVRMLCoordinate3_( 00890 ofstream& out, 00891 map< vertex_descriptor, int >& pts_indices ) 00892 { 00893 out << " Coordinate3 {\n" 00894 << " point [ #line format:\n" 00895 << "# point coordinates" 00896 << " # point index" 00897 << " # normal vector" 00898 << " # boundary flag" 00899 << "\n" 00900 ; 00901 00902 vertex_iterator vi, vi_end; 00903 int vtx_counter=0; 00904 for( tie( vi, vi_end )=vertices( *p_mesh ) ; vi != vi_end ; vi++ ) 00905 { 00906 MVertex mv = get( vertex_ppt, *p_mesh, *vi ); 00907 Vec coord = mv->coord; 00908 // property_map< graph, vertex_index_t >::type pts_indices; 00909 Vec norm = mv->norm; 00910 00911 pts_indices[ *vi ] = vtx_counter; 00912 vtx_counter++ ; 00913 00914 out << " " 00915 << coord[0] << " " << coord[1] << " " << coord[2] << "," 00916 /* comments */ 00917 // point number 00918 << " # " << pts_indices[ *vi ] 00919 // normal vector 00920 << " # " << norm[0] << " " << norm[1] << " "<< norm[2] 00921 // boundary flag 00922 << " # " << mv->bf 00923 << "\n"; 00924 00925 } 00926 00927 out << " ]\n" 00928 << " }\n\n"; 00929 } 00930 00931 // writes the "IndexedFaceSet" VRML node in "out" file stream, 00932 // with the help of the "pts_indices" correspondance table 00933 void SurfaceMesh::writeVRMLIndexedFaceSet_( 00934 ofstream& out, 00935 map< vertex_descriptor, int >& pts_indices ) 00936 { 00937 out << " IndexedFaceSet {\n" 00938 << " coordIndex [ # line format:\n" 00939 << "# indices of the points, -1 (end of face)" 00940 << " # face index" 00941 << " # adjacent faces' indices" 00942 // << " # face normal" 00943 << " # edges' boundary flags" 00944 << "\n"; 00945 00946 TVec< MFace > faces = mg->faces; 00947 for( int i=0 ; i < faces.length() ; i++ ) 00948 { 00949 MFace face = faces[i]; 00950 TVec< vertex_descriptor > pts = face->pts; 00951 00952 00953 TVec<int> adj_faces = face->adj_faces; 00954 Vec face_norm = face->face_norm; 00955 00956 TVec< edge_descriptor > edges = face->edges; 00957 00958 out << " " 00959 << pts_indices[ pts[0] ] << ", " 00960 << pts_indices[ pts[1] ] << ", " 00961 << pts_indices[ pts[2] ] << ", -1," 00962 /* comments */ 00963 // index 00964 << " # " << i 00965 // index of adjacent faces 00966 << " # " << adj_faces[0] << " " << adj_faces[1] << " " << adj_faces[2] 00967 // face normal 00968 /* not calculated yet 00969 << "# " << face_norm[0] << " " << face_norm[0] << " " << face_norm[0] 00970 */ 00971 // edges' boundary flags 00972 << " # " << getEdge( edges[0] )->bf << " " 00973 << getEdge( edges[1] )->bf << " " 00974 << getEdge( edges[2] )->bf 00975 << "\n"; 00976 } 00977 00978 out << " ]\n" 00979 << " }\n"; 00980 } 00981 00982 // writes the "IndexedFaceSet" VRML node in "out" file stream, 00983 // with the help of the "pts_indices" correspondance table 00984 void SurfaceMesh::writeVRMLIndexedLineSet_( 00985 ofstream& out, 00986 map< vertex_descriptor, int >& pts_indices ) 00987 { 00988 out << " IndexedLineSet {\n" 00989 << " coordIndex [ # line format:\n" 00990 << "# indices of the points, -1 (end of edge)" 00991 << "\n"; 00992 00993 edge_iterator ei, ei_end; 00994 for( tie( ei, ei_end )=edges( *p_mesh ) ; ei != ei_end ; ei ++ ) 00995 { 00996 vertex_descriptor src = source( *ei, *p_mesh ); 00997 vertex_descriptor tgt = target( *ei, *p_mesh ); 00998 out << " " 00999 << pts_indices[ src ] <<", "<< pts_indices[ tgt ] 01000 << ", -1,\n"; 01001 } 01002 01003 out << " ]\n" 01004 << " }\n"; 01005 } 01006 01007 /* Public functions */ 01008 01009 // reads from a VRML file, getting at least point coordinates, 01010 // if possible face data (from "IndexedFaceSet" node), 01011 // else if possible edge date (from "IndexedLineSet" node) 01012 bool SurfaceMesh::readVRMLFile( string filename, Mat vtx_features ) 01013 { 01014 ifstream in( filename.c_str() ); 01015 if( !in ) 01016 PLERROR( "Cannot open file: %s.\n", filename.c_str() ); 01017 01018 TVec<vertex_descriptor> vertices; 01019 if( !readVRMLCoordinate3_( in, vertices, vtx_features ) ) 01020 { 01021 PLERROR( "Parse error in %s: expecting a floating-point number.\n", 01022 filename.c_str() ); 01023 } 01024 01025 ifstream in_( filename.c_str() ); 01026 if( !in_ ) 01027 PLERROR( "Cannot open file: %s.\n", filename.c_str() ); 01028 01029 string buf; 01030 01031 // check if a "IndexedFaceSet" node is present 01032 bool face_set = false; 01033 bool line_set = false; 01034 01035 while( in_ >> buf ) 01036 { 01037 if( !buf.compare( 0, 14, "IndexedFaceSet" ) ) 01038 face_set = true; 01039 01040 if( !buf.compare( 0, 14, "IndexedLineSet" ) ) 01041 line_set = true; 01042 } 01043 01044 if( face_set && readVRMLIndexedFaceSet_( in, vertices ) ) 01045 mesh_type = "FaceSet"; 01046 else if( line_set && readVRMLIndexedLineSet_( in, vertices ) ) 01047 mesh_type = "LineSet"; 01048 else 01049 mesh_type = "PointSet"; 01050 01051 return true; 01052 } 01053 01054 // reads from a VRML file, getting point coordinates, and 01055 // face data from "IndexedFaceSet" node 01056 bool SurfaceMesh::readVRMLIndexedFaceSet( string filename, Mat vtx_features ) 01057 { 01058 if( verbosity >= 1 ) 01059 pout << "\nreadVRMLIndexedFaceSet " << filename << endl; 01060 01061 ifstream in( filename.c_str() ); 01062 if( !in ) 01063 { 01064 PLERROR( "Cannot open file: %s.\n", filename.c_str() ); 01065 } 01066 01067 TVec<vertex_descriptor> vertices; 01068 if( !readVRMLCoordinate3_( in, vertices, vtx_features ) ) 01069 { 01070 PLERROR( "Parse error in %s: expecting a floating-point number.\n", 01071 filename.c_str() ); 01072 } 01073 01074 if( !readVRMLIndexedFaceSet_( in, vertices ) ) 01075 { 01076 PLERROR( "Error while parsing 'IndexedFaceSet' in file '%s'.\n", 01077 filename.c_str() ); 01078 } 01079 01080 mesh_type = "FaceSet"; 01081 return true; 01082 } 01083 01084 // reads from a VRML file, getting point coordinates, and 01085 // edge data from "IndexedLineSet" node 01086 bool SurfaceMesh::readVRMLIndexedLineSet( string filename, Mat vtx_features ) 01087 { 01088 // probably to be rewritten using PPath 01089 if( verbosity >= 1 ) 01090 pout << "\nreadVRMLIndexedLineSet " << filename << endl; 01091 01092 ifstream in( filename.c_str() ); 01093 if( !in ) 01094 { 01095 PLERROR( "Cannot open file: %s.\n", filename.c_str() ); 01096 } 01097 01098 TVec<vertex_descriptor> vertices; 01099 if( !readVRMLCoordinate3_( in, vertices, vtx_features ) ) 01100 { 01101 PLERROR( "Parse error in %s: expecting a floating-point number.\n", 01102 filename.c_str() ); 01103 } 01104 01105 if( !readVRMLIndexedLineSet_( in, vertices ) ) 01106 { 01107 PLERROR( "Error while parsing 'IndexedLineSet' in file '%s'.\n", 01108 filename.c_str() ); 01109 } 01110 01111 mesh_type = "LineSet"; 01112 return true; 01113 } 01114 01115 01116 // writes mesh as a VRML file, using a "Coordinate3" node in any case, 01117 // an "IndexedFaceSet" node if face data is present, 01118 // else an "IndexedLineSet" node if edge data is present. 01119 void SurfaceMesh::writeVRMLFile( string filename ) 01120 { 01121 if( verbosity >= 1 ) 01122 pout << "\nwriteVRMLFile " << filename << endl; 01123 01124 ofstream out( filename.c_str(), ios::trunc ); 01125 if( !out ) 01126 { 01127 PLERROR( "Cannot open file: %s.\n", filename.c_str() ); 01128 } 01129 01130 /* map used to remember points' index in the vrml file */ 01131 map< vertex_descriptor, int > pts_indices; 01132 01133 out << "#VRML V1.0 ascii\n\n" 01134 << "Separator {\n" 01135 << " Material {\n" 01136 << " diffuseColor [ 1 1 1 ]\n" 01137 << " }\n\n"; 01138 01139 writeVRMLCoordinate3_( out, pts_indices ); 01140 01141 if( mesh_type == "FaceSet" ) 01142 writeVRMLIndexedFaceSet_( out, pts_indices ); 01143 else if( mesh_type == "LineSet" ) 01144 writeVRMLIndexedLineSet_( out, pts_indices ); 01145 01146 out << "}\n"; 01147 } 01148 01149 // writes mesh as a VRML file, 01150 // using an "IndexedFaceSet" to store face information 01151 void SurfaceMesh::writeVRMLIndexedFaceSet( string filename ) 01152 { 01153 if( verbosity >= 1 ) 01154 pout << "\nwriteVRMLIndexedFaceSet " << filename << endl; 01155 01156 ofstream out( filename.c_str(), ios::trunc ); 01157 if( !out ) 01158 { 01159 PLERROR( "Cannot open file: %s.\n", filename.c_str() ); 01160 } 01161 01162 /* map used to remember points' index in the vrml file */ 01163 map< vertex_descriptor, int > pts_indices; 01164 01165 01166 out << "#VRML V1.0 ascii\n\n" 01167 << "Separator {\n" 01168 << " Material {\n" 01169 << " diffuseColor [ 1 1 1 ]\n" 01170 << " }\n\n" 01171 ; 01172 01173 writeVRMLCoordinate3_( out, pts_indices ); 01174 01175 writeVRMLIndexedFaceSet_( out, pts_indices ); 01176 01177 out << "}\n"; 01178 } 01179 01180 // writes mesh as a VRML file, 01181 // using an "IndexedLineSet" to store edge information, 01182 // not storing face information if any 01183 void SurfaceMesh::writeVRMLIndexedLineSet( string filename ) 01184 { 01185 if( verbosity >= 1 ) 01186 pout << "\nwriteVRMLIndexedLineSet " << filename << endl; 01187 01188 ofstream out( filename.c_str(), ios::trunc ); 01189 if( !out ) 01190 { 01191 PLERROR( "Cannot open file: %s.\n", filename.c_str() ); 01192 } 01193 01194 /* map used to remember points' index in the vrml file */ 01195 map< vertex_descriptor, int > pts_indices; 01196 01197 out << "#VRML V1.0 ascii\n\n" 01198 << "Separator {\n" 01199 << " Material {\n" 01200 << " diffuseColor [ 1 1 1 ]\n" 01201 << " }\n\n" 01202 ; 01203 01204 writeVRMLCoordinate3_( out, pts_indices ); 01205 01206 writeVRMLIndexedLineSet_( out, pts_indices ); 01207 01208 out << "}\n"; 01209 } 01210 01211 // writes edges having a boundary flag in a VRML file 01212 void SurfaceMesh::writeVRMLBoundaries( string filename ) 01213 { 01214 if( verbosity >= 1 ) 01215 pout << "\nwriteVRMLBoundaries " << filename << endl; 01216 01217 ofstream out( filename.c_str(), ios::trunc ); 01218 if( !out ) 01219 { 01220 PLERROR( "Cannot open file: %s.\n", filename.c_str() ); 01221 } 01222 01223 /* map used to remember points' index in the vrml file */ 01224 map< vertex_descriptor, int > pts_indices; 01225 01226 out << "#VRML V1.0 ascii\n\n" 01227 << "Separator {\n" 01228 << " Material {\n" 01229 << " diffuseColor [ 1 1 1 ]\n" 01230 << " }\n\n"; 01231 01232 writeVRMLCoordinate3_( out, pts_indices ); 01233 01234 out << " IndexedLineSet {\n" 01235 << " coordIndex [ # line format:\n" 01236 /* << "# indices of the points, -1 (end of face)" 01237 << " # face index" 01238 << " # adjacent faces' indices" 01239 // << " # face normal" 01240 << " # edges' boundary flags" 01241 */ << "\n"; 01242 01243 TVec< MFace > faces = mg->faces; 01244 for( int i=0 ; i < faces.length() ; i++ ) 01245 { 01246 MFace face = faces[i]; 01247 TVec< vertex_descriptor > pts = face->pts; 01248 01249 01250 TVec<int> adj_faces = face->adj_faces; 01251 Vec face_norm = face->face_norm; 01252 01253 TVec< edge_descriptor > edges = face->edges; 01254 01255 if( getEdge( edges[0] )->bf == 1 ) 01256 { 01257 out << pts_indices[ pts[0] ] <<", "<< pts_indices[ pts[1] ] << ", -1,\n"; 01258 } 01259 if( getEdge( edges[1] )->bf == 1 ) 01260 { 01261 out << pts_indices[ pts[1] ] <<", "<< pts_indices[ pts[2] ] << ", -1,\n"; 01262 } 01263 if( getEdge( edges[2] )->bf == 1 ) 01264 { 01265 out << pts_indices[ pts[2] ] <<", "<< pts_indices[ pts[0] ] << ", -1,\n"; 01266 } 01267 } 01268 01269 out << " ]\n" 01270 << " }\n" 01271 << "}\n"; 01272 } 01273 01274 01275 /* fills all the vertex, edge and faces properties, 01276 according to the basic properties we already have. 01277 should probably be in a "build_" method. */ 01278 int SurfaceMesh::createSurfaceMesh() 01279 { 01280 int nerrors = 0; 01281 01282 /* initialisation from the faces */ 01283 01284 /* create edges and setting their length and boundary flag */ 01285 nerrors += buildEdges(); 01286 01287 /* set boundary flags to appropriate vertices */ 01288 nerrors += buildBoundaries(); 01289 01290 /* compute and set mesh resolution */ 01291 mg->resolution = computeResolution(); 01292 01293 findNormals(); 01294 01295 mg->size = averageSphereRadius(); 01296 01297 return nerrors; 01298 } 01299 01300 01301 int SurfaceMesh::delOrphanVertices() 01302 { 01303 int number_deleted = 0; 01304 vertex_iterator vi, vi_end, next; 01305 tie( vi, vi_end ) = vertices( *p_mesh ); 01306 for (next = vi; vi != vi_end; vi = next) 01307 { 01308 ++next; 01309 if( out_degree( *vi, *p_mesh ) == 0 ) 01310 { 01311 number_deleted++; 01312 delVertex( *vi ); 01313 } 01314 } 01315 return number_deleted; 01316 } 01317 01318 01319 /* 01320 ****************************************************************************** 01321 + FUNCTION: FindNormals 01322 + AUTHOR: Andrew E. Johnson (aej@ri.cmu.edu) 01323 + DATE: 6-Jul-94 01324 + PURPOSE: Calculate surface normal for each meshpoint in graph by finding 01325 + smallest eigenvector of inertial matrix made from the meshpoint's 01326 + neighbors. This vector corresponds to the smallest principal 01327 + direction. It also orients all of the mesh surface normals in 01328 + the same direction as their neighbors using relaxation 01329 ****************************************************************************** 01330 */ 01331 01332 void SurfaceMesh::findNormals() 01333 { 01334 // calculate initial normals 01335 01336 vertex_iterator vi, vi_end; 01337 for( tie( vi, vi_end )=vertices( *p_mesh ) ; vi != vi_end ; vi++ ) 01338 { 01339 Vec v(3); 01340 real fit_error = calcNormal( *p_mesh, *vi, v ); 01341 01342 MVertex mv = get( vertex_ppt, *p_mesh, *vi ); 01343 mv->error = fit_error; 01344 01345 /* orient the normal based on the orientation 01346 of the faces adjacent to the point */ 01347 01348 /* find adjacent faces */ 01349 set<int> adj_faces; 01350 out_edge_iterator ei, ei_end; 01351 for( tie(ei,ei_end)=out_edges(*vi, *p_mesh) ; ei!=ei_end ; ei++ ) 01352 { 01353 adj_faces.insert( get(edge_ppt,*p_mesh,*ei)->face1 ); 01354 adj_faces.insert( get(edge_ppt,*p_mesh,*ei)->face2 ); 01355 } 01356 adj_faces.erase( -1 ); // we don't want to keep "dummy" faces 01357 01358 int n_opposite = 0; 01359 int n_same = 0; 01360 01361 /* determine number of faces with similar normal 01362 and number of faces with opposite pointing normal */ 01363 01364 for( set<int>::iterator it=adj_faces.begin() ; it!=adj_faces.end() ; it++ ) 01365 { 01366 MFace mf = get_property( *p_mesh, graph_ppt )->faces[ *it ]; 01367 01368 Vec p0 = get( vertex_ppt, *p_mesh, mf->pts[0] )->coord; 01369 Vec p1 = get( vertex_ppt, *p_mesh, mf->pts[1] )->coord; 01370 Vec p2 = get( vertex_ppt, *p_mesh, mf->pts[2] )->coord; 01371 01372 Vec n( 3 ); 01373 n = cross( p2-p1, p0-p1 ); 01374 01375 if( dot(n,v) > 0 ) 01376 { n_same++ ;} 01377 else 01378 { n_opposite++ ;} 01379 } 01380 01381 /* if the number opposite is greater than the number the same, 01382 then flip the normal */ 01383 01384 mv->norm.resize(3); 01385 if( n_same >= n_opposite ) 01386 { mv->norm << v ; } 01387 else 01388 { mv->norm << -v ; } 01389 01390 /* write vertex property value in the mesh */ 01391 put( vertex_ppt, *p_mesh, *vi, mv ); 01392 } 01393 01394 computed_vtx_norm = true; 01395 } 01396 01397 01398 real SurfaceMesh::averageSphereRadius() 01399 { 01400 Vec c( 3 ); 01401 vertex_iterator vi, vi_end; 01402 for( tie(vi,vi_end)=vertices(*p_mesh) ; vi!=vi_end ; vi++ ) 01403 { 01404 c += get( vertex_ppt, *p_mesh, *vi )->coord; 01405 } 01406 01407 c *= real(1.0)/num_vertices( *p_mesh ); 01408 01409 real r = 0; 01410 for( tie(vi,vi_end)=vertices(*p_mesh) ; vi!=vi_end ; vi++ ) 01411 { 01412 r += norm( c - get( vertex_ppt, *p_mesh, *vi )->coord, 2 ); 01413 } 01414 01415 r *= real(1.0)/num_vertices( *p_mesh ); 01416 return r; 01417 } 01418 01419 01420 Mat SurfaceMesh::boundingBox() 01421 { 01422 Mat box( 2, 3 ); 01423 Vec mins(3); 01424 Vec max(3); 01425 01426 Mat coords = getVertexCoords(); 01427 columnMin( coords, mins ); 01428 columnMax( coords, max ); 01429 box(0) << mins; 01430 box(1) << max; 01431 01432 return( box ); 01433 } 01434 01435 01436 01437 01438 pair<edge_descriptor,bool> add_edge_ifnew( const vertex_descriptor& u, 01439 const vertex_descriptor& v, 01440 const graph::edge_property_type& ep, 01441 graph& g ) 01442 { 01443 out_edge_iterator ei, ei_end; 01444 for( tie(ei,ei_end)=out_edges(u,g) ; ei != ei_end ; ei++ ) 01445 { 01446 if( target( *ei, g ) == v ) 01447 { 01448 pair< edge_descriptor, bool > result( *ei, false ); 01449 return result; 01450 } 01451 } 01452 pair< edge_descriptor, bool > result = add_edge( u, v, ep, g ); 01453 return result; 01454 } 01455 01456 pair<edge_descriptor,bool> add_edge_ifnew(const vertex_descriptor& u, 01457 const vertex_descriptor& v, 01458 graph& g ) 01459 { 01460 out_edge_iterator ei, ei_end; 01461 for( tie(ei,ei_end)=out_edges(u,g) ; ei != ei_end ; ei++ ) 01462 { 01463 if( target( *ei, g ) == v ) 01464 { 01465 pair< edge_descriptor, bool > result( *ei, false ); 01466 return result; 01467 } 01468 } 01469 pair< edge_descriptor, bool > result = add_edge( u, v, g ); 01470 return result; 01471 } 01472 01473 01474 01475 01476 01477 01478 01479 01480 01481 01482 01483 01484 } // end of namespace PLearn