OpenMesh
OpenMesh/Tools/Subdivider/Uniform/LongestEdgeT.hh
Go to the documentation of this file.
00001 /*===========================================================================*\
00002 *                                                                           *
00003 *                               OpenMesh                                    *
00004 *      Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen      *
00005 *                           www.openmesh.org                                *
00006 *                                                                           *
00007 *---------------------------------------------------------------------------* 
00008 *  This file is part of OpenMesh.                                           *
00009 *                                                                           *
00010 *  OpenMesh is free software: you can redistribute it and/or modify         * 
00011 *  it under the terms of the GNU Lesser General Public License as           *
00012 *  published by the Free Software Foundation, either version 3 of           *
00013 *  the License, or (at your option) any later version with the              *
00014 *  following exceptions:                                                    *
00015 *                                                                           *
00016 *  If other files instantiate templates or use macros                       *
00017 *  or inline functions from this file, or you compile this file and         *
00018 *  link it with other files to produce an executable, this file does        *
00019 *  not by itself cause the resulting executable to be covered by the        *
00020 *  GNU Lesser General Public License. This exception does not however       *
00021 *  invalidate any other reasons why the executable file might be            *
00022 *  covered by the GNU Lesser General Public License.                        *
00023 *                                                                           *
00024 *  OpenMesh is distributed in the hope that it will be useful,              *
00025 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027 *  GNU Lesser General Public License for more details.                      *
00028 *                                                                           *
00029 *  You should have received a copy of the GNU LesserGeneral Public          *
00030 *  License along with OpenMesh.  If not,                                    *
00031 *  see <http://www.gnu.org/licenses/>.                                      *
00032 *                                                                           *
00033 \*==========================================================================*/ 
00034 
00035 /*==========================================================================*\
00036 *                                                                           *             
00037 *   $Revision: 410 $                                                        *
00038 *   $Date: 2010-06-17 12:45:58 +0200 (Do, 17. Jun 2010) $                   *
00039 *                                                                           *
00040 \*==========================================================================*/
00041 
00046 //=============================================================================
00047 //
00048 //  CLASS LongestEdgeT
00049 //
00050 //=============================================================================
00051 
00052 
00053 #ifndef LINEAR_H
00054 #define LINEAR_H
00055 
00056 #include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh>
00057 #include <OpenMesh/Core/Utils/vector_cast.hh>
00058 #include <OpenMesh/Core/Utils/Property.hh>
00059 // -------------------- STL
00060 #include <vector>
00061 #include <queue>
00062 #if defined(OM_CC_MIPS)
00063 #  include <math.h>
00064 #else
00065 #  include <cmath>
00066 #endif
00067 
00068 
00069 //== NAMESPACE ================================================================
00070 
00071 namespace OpenMesh   { // BEGIN_NS_OPENMESH
00072 namespace Subdivider { // BEGIN_NS_DECIMATER
00073 namespace Uniform    { // BEGIN_NS_UNIFORM
00074 
00075 
00076 //== CLASS DEFINITION =========================================================
00077 
00078 template <typename MeshType, typename RealType = float>
00079 class CompareLengthFunction {
00080   public:
00081 
00082     typedef std::pair<typename MeshType::EdgeHandle, RealType> queueElement;
00083 
00084     bool operator()(const queueElement& t1, const queueElement& t2) // Returns true if t1 is smaller than t2
00085     {
00086       return (t1.second < t2.second);
00087     }
00088 };
00089 
00090 
00097 template <typename MeshType, typename RealType = float>
00098 class LongestEdgeT : public SubdividerT<MeshType, RealType>
00099 {
00100 public:
00101 
00102   typedef RealType                                real_t;
00103   typedef MeshType                                mesh_t;
00104   typedef SubdividerT< mesh_t, real_t >           parent_t;
00105 
00106   typedef std::vector< std::vector<real_t> >      weights_t;
00107   typedef std::vector<real_t>                     weight_t;
00108 
00109   typedef std::pair< typename mesh_t::EdgeHandle, real_t > queueElement;
00110 
00111 public:
00112 
00113 
00114   LongestEdgeT() : parent_t()
00115   {  }
00116 
00117 
00118   LongestEdgeT( mesh_t& _m) : parent_t(_m)
00119   {  }
00120 
00121 
00122   ~LongestEdgeT() {}
00123 
00124 
00125 public:
00126 
00127 
00128   const char *name() const { return "Longest Edge Split"; }
00129 
00130   void set_max_edge_length(double _value) {
00131     max_edge_length_squared_ = _value * _value;
00132   }
00133 
00134 protected:
00135 
00136 
00137   bool prepare( mesh_t& _m )
00138   {
00139     return true;
00140   }
00141 
00142 
00143   bool cleanup( mesh_t& _m )
00144   {
00145     return true;
00146   }
00147 
00148 
00149   bool subdivide( MeshType& _m, size_t _n , const bool _update_points = true)
00150   {
00151 
00152     // Sorted queue containing all edges sorted by their decreasing length
00153     std::priority_queue< queueElement, std::vector< queueElement > , CompareLengthFunction< mesh_t, real_t > > queue;
00154 
00155     // Build the initial queue
00156     // First element should be longest edge
00157     typename mesh_t::EdgeIter edgesEnd = _m.edges_end();
00158     for ( typename mesh_t::EdgeIter eit  = _m.edges_begin(); eit != edgesEnd; ++eit) {
00159       const typename MeshType::Point to   = _m.point(_m.to_vertex_handle(_m.halfedge_handle(eit,0)));
00160       const typename MeshType::Point from = _m.point(_m.from_vertex_handle(_m.halfedge_handle(eit,0)));
00161 
00162       real_t length = (to - from).sqrnorm();
00163 
00164       // Only push the edges that need to be split
00165       if ( length > max_edge_length_squared_ )
00166         queue.push( queueElement(eit.handle(),length) );
00167     }
00168 
00169     bool stop = false;
00170     while ( !stop && ! queue.empty() ) {
00171       queueElement a = queue.top();
00172       queue.pop();
00173 
00174       if ( a.second < max_edge_length_squared_ ) {
00175         stop = true;
00176         break;
00177       } else {
00178         const typename MeshType::Point to   = _m.point(_m.to_vertex_handle(_m.halfedge_handle(a.first,0)));
00179         const typename MeshType::Point from = _m.point(_m.from_vertex_handle(_m.halfedge_handle(a.first,0)));
00180         const typename MeshType::Point midpoint = 0.5 * ( to + from );
00181 
00182         const typename MeshType::VertexHandle newVertex = _m.add_vertex(midpoint);
00183         _m.split(a.first,newVertex);
00184 
00185         for ( typename MeshType::VertexOHalfedgeIter voh_it(_m,newVertex); voh_it; ++voh_it) {
00186           typename MeshType::EdgeHandle eh = _m.edge_handle(voh_it.handle());
00187           const typename MeshType::Point to   = _m.point(_m.to_vertex_handle(voh_it));
00188           const typename MeshType::Point from = _m.point(_m.from_vertex_handle(voh_it));
00189           real_t length = (to - from).sqrnorm();
00190 
00191           // Only push the edges that need to be split
00192           if ( length > max_edge_length_squared_ )
00193             queue.push( queueElement(eh,length) );
00194 
00195         }
00196       }
00197     }
00198 
00199 #if defined(_DEBUG) || defined(DEBUG)
00200       // Now we have an consistent mesh!
00201       assert( OpenMesh::Utils::MeshCheckerT<mesh_t>(_m).check() );
00202 #endif
00203 
00204 
00205     return true;
00206   }
00207 
00208 
00209 private: // data
00210   real_t max_edge_length_squared_;
00211 
00212 };
00213 
00214 } // END_NS_UNIFORM
00215 } // END_NS_SUBDIVIDER
00216 } // END_NS_OPENMESH
00217 #endif
00218 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines