OpenMesh
|
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