diff --git a/Doc/subdivider.docu b/Doc/subdivider.docu index 27bd7a84..1d98a91c 100644 --- a/Doc/subdivider.docu +++ b/Doc/subdivider.docu @@ -13,6 +13,8 @@ subdivision: -# OpenMesh::Subdivider::Uniform::CompositeT -# Adaptive subdivision -# OpenMesh::Subdivider::Adaptive::CompositeT +-# Simple subdivision + -# OpenMesh::Subdivider::Uniform::LongestEdgeT */ diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/LongestEdgeT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/LongestEdgeT.hh new file mode 100644 index 00000000..a8ff1ce6 --- /dev/null +++ b/src/OpenMesh/Tools/Subdivider/Uniform/LongestEdgeT.hh @@ -0,0 +1,219 @@ +/*===========================================================================*\ +* * +* OpenMesh * +* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * +* www.openmesh.org * +* * +*---------------------------------------------------------------------------* +* This file is part of OpenMesh. * +* * +* OpenMesh is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as * +* published by the Free Software Foundation, either version 3 of * +* the License, or (at your option) any later version with the * +* following exceptions: * +* * +* If other files instantiate templates or use macros * +* or inline functions from this file, or you compile this file and * +* link it with other files to produce an executable, this file does * +* not by itself cause the resulting executable to be covered by the * +* GNU Lesser General Public License. This exception does not however * +* invalidate any other reasons why the executable file might be * +* covered by the GNU Lesser General Public License. * +* * +* OpenMesh is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU LesserGeneral Public * +* License along with OpenMesh. If not, * +* see . * +* * +\*==========================================================================*/ + +/*==========================================================================*\ +* * +* $Revision: 410 $ * +* $Date: 2010-06-17 12:45:58 +0200 (Do, 17. Jun 2010) $ * +* * +\*==========================================================================*/ + +/** \file LongestEdgeT.hh + +*/ + +//============================================================================= +// +// CLASS LongestEdgeT +// +//============================================================================= + + +#ifndef LINEAR_H +#define LINEAR_H + +#include +#include +#include +// -------------------- STL +#include +#include +#if defined(OM_CC_MIPS) +# include +#else +# include +#endif + + +//== NAMESPACE ================================================================ + +namespace OpenMesh { // BEGIN_NS_OPENMESH +namespace Subdivider { // BEGIN_NS_DECIMATER +namespace Uniform { // BEGIN_NS_UNIFORM + + +//== CLASS DEFINITION ========================================================= + +template +class CompareLengthFunction { + public: + + bool operator()( const std::pair< typename MeshType::EdgeHandle, RealType >& t1, const std::pair< typename MeshType::EdgeHandle, RealType >& t2) // Returns true if t1 is earlier than t2 + { + if (t1.second < t2.second) + return true; + else + return false; + } +}; + + +/** %Uniform LongestEdgeT subdivision algorithm + * + * Very simple algorithm splitting all edges which are longer than given via + * set_max_edge_length(). The split is always performed on the longest + * edge in the mesh. + */ +template +class LongestEdgeT : public SubdividerT +{ +public: + + typedef RealType real_t; + typedef MeshType mesh_t; + typedef SubdividerT< mesh_t, real_t > parent_t; + + typedef std::vector< std::vector > weights_t; + typedef std::vector weight_t; + +public: + + + LongestEdgeT() : parent_t() + { } + + + LongestEdgeT( mesh_t& _m) : parent_t(_m) + { } + + + ~LongestEdgeT() {} + + +public: + + + const char *name() const { return "Longest Edge Split"; } + + void set_max_edge_length(double _value) { + max_edge_length_squared_ = _value * _value; + } + +protected: + + + bool prepare( mesh_t& _m ) + { + return true; + } + + + bool cleanup( mesh_t& _m ) + { + return true; + } + + + bool subdivide( MeshType& _m, size_t _n , const bool _update_points = true) + { + + std::cerr << "Longest" << std::endl; + typedef std::pair< typename mesh_t::EdgeHandle, real_t > queueElement; + // Sorted queue containing all edges sorted by their decreasing length + std::priority_queue< queueElement, std::vector< queueElement > , CompareLengthFunction< typename mesh_t::EdgeHandle, real_t > > queue; + + // Build the initial queue + // First element should be longest edge + typename mesh_t::EdgeIter edgesEnd = _m.edges_end(); + for ( typename mesh_t::EdgeIter eit = _m.edges_begin(); eit != edgesEnd; ++eit) { + const typename MeshType::Point to = _m.point(_m.to_vertex_handle(_m.halfedge_handle(eit,0))); + const typename MeshType::Point from = _m.point(_m.from_vertex_handle(_m.halfedge_handle(eit,0))); + + real_t length = (to - from).sqrnorm(); + + // Only push the edges that need to be split + if ( length > max_edge_length_squared_ ) + queue.push( queueElement(eit.handle(),length) ); + } + + bool stop = false; + while ( !stop && ! queue.empty() ) { + queueElement a = queue.top(); + queue.pop(); + + if ( a.second < max_edge_length_squared_ ) { + stop = true; + break; + } else { + const typename MeshType::Point to = _m.point(_m.to_vertex_handle(_m.halfedge_handle(a.first,0))); + const typename MeshType::Point from = _m.point(_m.from_vertex_handle(_m.halfedge_handle(a.first,0))); + const typename MeshType::Point midpoint = 0.5 * ( to + from ); + + const typename MeshType::VertexHandle newVertex = _m.add_vertex(midpoint); + _m.split(a.first,newVertex); + + for ( typename MeshType::VertexOHalfedgeIter voh_it(_m,newVertex); voh_it; ++voh_it) { + typename MeshType::EdgeHandle eh = _m.edge_handle(voh_it.handle()); + const typename MeshType::Point to = _m.point(_m.to_vertex_handle(voh_it)); + const typename MeshType::Point from = _m.point(_m.from_vertex_handle(voh_it)); + real_t length = (to - from).sqrnorm(); + + // Only push the edges that need to be split + if ( length > max_edge_length_squared_ ) + queue.push( queueElement(eh,length) ); + + } + } + } + +#if defined(_DEBUG) || defined(DEBUG) + // Now we have an consistent mesh! + assert( OpenMesh::Utils::MeshCheckerT(_m).check() ); +#endif + + + return true; + } + + +private: // data + real_t max_edge_length_squared_; + +}; + +} // END_NS_UNIFORM +} // END_NS_SUBDIVIDER +} // END_NS_OPENMESH +#endif +