PLearn 0.1
SurfaceMesh.cc
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines