2015-04-28 11:54:17 +00:00
|
|
|
/* ========================================================================= *
|
2009-06-04 08:46:29 +00:00
|
|
|
* *
|
|
|
|
|
* OpenMesh *
|
2023-03-01 13:03:33 +01:00
|
|
|
* Copyright (c) 2001-2023, RWTH-Aachen University *
|
2015-04-28 13:07:46 +00:00
|
|
|
* Department of Computer Graphics and Multimedia *
|
2015-04-28 11:33:32 +00:00
|
|
|
* All rights reserved. *
|
|
|
|
|
* www.openmesh.org *
|
2009-06-04 08:46:29 +00:00
|
|
|
* *
|
2015-04-28 11:33:32 +00:00
|
|
|
*---------------------------------------------------------------------------*
|
|
|
|
|
* This file is part of OpenMesh. *
|
|
|
|
|
*---------------------------------------------------------------------------*
|
2009-06-04 08:46:29 +00:00
|
|
|
* *
|
2015-04-28 11:33:32 +00:00
|
|
|
* Redistribution and use in source and binary forms, with or without *
|
|
|
|
|
* modification, are permitted provided that the following conditions *
|
|
|
|
|
* are met: *
|
2009-06-04 08:46:29 +00:00
|
|
|
* *
|
2015-04-28 11:33:32 +00:00
|
|
|
* 1. Redistributions of source code must retain the above copyright notice, *
|
|
|
|
|
* this list of conditions and the following disclaimer. *
|
2009-06-04 08:46:29 +00:00
|
|
|
* *
|
2015-04-28 11:33:32 +00:00
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright *
|
|
|
|
|
* notice, this list of conditions and the following disclaimer in the *
|
|
|
|
|
* documentation and/or other materials provided with the distribution. *
|
2009-06-04 08:46:29 +00:00
|
|
|
* *
|
2015-04-28 11:33:32 +00:00
|
|
|
* 3. Neither the name of the copyright holder nor the names of its *
|
|
|
|
|
* contributors may be used to endorse or promote products derived from *
|
|
|
|
|
* this software without specific prior written permission. *
|
2009-06-04 08:46:29 +00:00
|
|
|
* *
|
2015-04-28 11:33:32 +00:00
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
|
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
|
|
|
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
|
|
|
|
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
|
|
|
|
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
|
|
|
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
|
|
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
|
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
|
|
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
|
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
|
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
2015-04-28 11:54:17 +00:00
|
|
|
* *
|
|
|
|
|
* ========================================================================= */
|
2009-06-04 08:46:29 +00:00
|
|
|
|
2019-01-15 11:21:12 +01:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
//
|
|
|
|
|
// CLASS StripifierT - IMPLEMENTATION
|
|
|
|
|
//
|
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
|
|
#define OPENMESH_STRIPIFIERT_C
|
|
|
|
|
|
|
|
|
|
//== INCLUDES =================================================================
|
|
|
|
|
|
|
|
|
|
#include <OpenMesh/Tools/Utils/StripifierT.hh>
|
|
|
|
|
#include <list>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//== NAMESPACES ===============================================================
|
|
|
|
|
|
|
|
|
|
namespace OpenMesh {
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
//== IMPLEMENTATION ==========================================================
|
2009-04-27 12:42:13 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
template <class Mesh>
|
|
|
|
|
StripifierT<Mesh>::
|
2009-04-27 12:42:13 +00:00
|
|
|
StripifierT(Mesh& _mesh) :
|
|
|
|
|
mesh_(_mesh)
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
2009-04-27 13:53:13 +00:00
|
|
|
|
2009-04-27 12:42:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <class Mesh>
|
|
|
|
|
StripifierT<Mesh>::
|
|
|
|
|
~StripifierT() {
|
2009-04-27 13:53:13 +00:00
|
|
|
|
2009-04-27 12:42:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <class Mesh>
|
2013-08-15 08:43:04 +00:00
|
|
|
size_t
|
2009-04-27 12:42:13 +00:00
|
|
|
StripifierT<Mesh>::
|
|
|
|
|
stripify()
|
|
|
|
|
{
|
2009-04-27 13:53:13 +00:00
|
|
|
// preprocess: add new properties
|
|
|
|
|
mesh_.add_property( processed_ );
|
|
|
|
|
mesh_.add_property( used_ );
|
|
|
|
|
mesh_.request_face_status();
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// build strips
|
|
|
|
|
clear();
|
|
|
|
|
build_strips();
|
2009-04-27 12:42:13 +00:00
|
|
|
|
2009-04-27 13:53:13 +00:00
|
|
|
// postprocess: remove properties
|
|
|
|
|
mesh_.remove_property(processed_);
|
|
|
|
|
mesh_.remove_property(used_);
|
|
|
|
|
mesh_.release_face_status();
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
return n_strips();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <class Mesh>
|
|
|
|
|
void
|
|
|
|
|
StripifierT<Mesh>::
|
|
|
|
|
build_strips()
|
|
|
|
|
{
|
|
|
|
|
Strip experiments[3];
|
|
|
|
|
typename Mesh::HalfedgeHandle h[3];
|
|
|
|
|
FaceHandles faces[3];
|
|
|
|
|
typename FaceHandles::iterator fh_it, fh_end;
|
|
|
|
|
typename Mesh::FaceIter f_it, f_end=mesh_.faces_end();
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// init faces to be un-processed and un-used
|
|
|
|
|
// deleted or hidden faces are marked processed
|
|
|
|
|
if (mesh_.has_face_status())
|
|
|
|
|
{
|
|
|
|
|
for (f_it=mesh_.faces_begin(); f_it!=f_end; ++f_it)
|
2013-08-07 11:59:44 +00:00
|
|
|
if (mesh_.status(*f_it).hidden() || mesh_.status(*f_it).deleted())
|
|
|
|
|
processed(*f_it) = used(*f_it) = true;
|
2009-02-06 13:37:46 +00:00
|
|
|
else
|
2013-08-07 11:59:44 +00:00
|
|
|
processed(*f_it) = used(*f_it) = false;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (f_it=mesh_.faces_begin(); f_it!=f_end; ++f_it)
|
2013-08-07 11:59:44 +00:00
|
|
|
processed(*f_it) = used(*f_it) = false;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
for (f_it=mesh_.faces_begin(); true; )
|
|
|
|
|
{
|
|
|
|
|
// find start face
|
|
|
|
|
for (; f_it!=f_end; ++f_it)
|
2013-08-07 11:59:44 +00:00
|
|
|
if (!processed(*f_it))
|
2009-02-06 13:37:46 +00:00
|
|
|
break;
|
|
|
|
|
if (f_it==f_end) break; // stop if all have been processed
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// collect starting halfedges
|
2013-08-07 10:26:50 +00:00
|
|
|
h[0] = mesh_.halfedge_handle(*f_it);
|
2009-02-06 13:37:46 +00:00
|
|
|
h[1] = mesh_.next_halfedge_handle(h[0]);
|
|
|
|
|
h[2] = mesh_.next_halfedge_handle(h[1]);
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// build 3 strips, take best one
|
2013-08-21 11:29:16 +00:00
|
|
|
size_t best_length = 0;
|
|
|
|
|
size_t best_idx = 0;
|
2013-08-21 12:03:51 +00:00
|
|
|
|
2013-08-15 08:43:04 +00:00
|
|
|
for (size_t i=0; i<3; ++i)
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
build_strip(h[i], experiments[i], faces[i]);
|
2013-08-21 12:03:51 +00:00
|
|
|
|
|
|
|
|
const size_t length = experiments[i].size();
|
|
|
|
|
if ( length > best_length)
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
best_length = length;
|
|
|
|
|
best_idx = i;
|
|
|
|
|
}
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
for (fh_it=faces[i].begin(), fh_end=faces[i].end();
|
2009-02-06 13:37:46 +00:00
|
|
|
fh_it!=fh_end; ++fh_it)
|
|
|
|
|
used(*fh_it) = false;
|
|
|
|
|
}
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// update processed status
|
|
|
|
|
fh_it = faces[best_idx].begin();
|
|
|
|
|
fh_end = faces[best_idx].end();
|
|
|
|
|
for (; fh_it!=fh_end; ++fh_it)
|
|
|
|
|
processed(*fh_it) = true;
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// add best strip to strip-list
|
|
|
|
|
strips_.push_back(experiments[best_idx]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <class Mesh>
|
|
|
|
|
void
|
|
|
|
|
StripifierT<Mesh>::
|
|
|
|
|
build_strip(typename Mesh::HalfedgeHandle _start_hh,
|
|
|
|
|
Strip& _strip,
|
|
|
|
|
FaceHandles& _faces)
|
|
|
|
|
{
|
|
|
|
|
std::list<unsigned int> strip;
|
|
|
|
|
typename Mesh::HalfedgeHandle hh;
|
|
|
|
|
typename Mesh::FaceHandle fh;
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// reset face list
|
|
|
|
|
_faces.clear();
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// init strip
|
|
|
|
|
strip.push_back(mesh_.from_vertex_handle(_start_hh).idx());
|
|
|
|
|
strip.push_back(mesh_.to_vertex_handle(_start_hh).idx());
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// walk along the strip: 1st direction
|
|
|
|
|
hh = mesh_.prev_halfedge_handle(mesh_.opposite_halfedge_handle(_start_hh));
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
// go right
|
|
|
|
|
hh = mesh_.next_halfedge_handle(hh);
|
|
|
|
|
hh = mesh_.opposite_halfedge_handle(hh);
|
|
|
|
|
hh = mesh_.next_halfedge_handle(hh);
|
|
|
|
|
if (mesh_.is_boundary(hh)) break;
|
|
|
|
|
fh = mesh_.face_handle(hh);
|
2009-04-27 12:42:13 +00:00
|
|
|
if (processed(fh) || used(fh)) break;
|
2009-02-06 13:37:46 +00:00
|
|
|
_faces.push_back(fh);
|
|
|
|
|
used(fh) = true;
|
|
|
|
|
strip.push_back(mesh_.to_vertex_handle(hh).idx());
|
2009-04-27 12:42:13 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// go left
|
|
|
|
|
hh = mesh_.opposite_halfedge_handle(hh);
|
|
|
|
|
hh = mesh_.next_halfedge_handle(hh);
|
|
|
|
|
if (mesh_.is_boundary(hh)) break;
|
|
|
|
|
fh = mesh_.face_handle(hh);
|
2009-04-27 12:42:13 +00:00
|
|
|
if (processed(fh) || used(fh)) break;
|
2009-02-06 13:37:46 +00:00
|
|
|
_faces.push_back(fh);
|
|
|
|
|
used(fh) = true;
|
|
|
|
|
strip.push_back(mesh_.to_vertex_handle(hh).idx());
|
|
|
|
|
}
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// walk along the strip: 2nd direction
|
|
|
|
|
bool flip(false);
|
|
|
|
|
hh = mesh_.prev_halfedge_handle(_start_hh);
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
// go right
|
|
|
|
|
hh = mesh_.next_halfedge_handle(hh);
|
|
|
|
|
hh = mesh_.opposite_halfedge_handle(hh);
|
|
|
|
|
hh = mesh_.next_halfedge_handle(hh);
|
|
|
|
|
if (mesh_.is_boundary(hh)) break;
|
|
|
|
|
fh = mesh_.face_handle(hh);
|
2009-04-27 12:42:13 +00:00
|
|
|
if (processed(fh) || used(fh)) break;
|
2009-02-06 13:37:46 +00:00
|
|
|
_faces.push_back(fh);
|
|
|
|
|
used(fh) = true;
|
|
|
|
|
strip.push_front(mesh_.to_vertex_handle(hh).idx());
|
|
|
|
|
flip = true;
|
2009-04-27 12:42:13 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// go left
|
|
|
|
|
hh = mesh_.opposite_halfedge_handle(hh);
|
|
|
|
|
hh = mesh_.next_halfedge_handle(hh);
|
|
|
|
|
if (mesh_.is_boundary(hh)) break;
|
|
|
|
|
fh = mesh_.face_handle(hh);
|
2009-04-27 12:42:13 +00:00
|
|
|
if (processed(fh) || used(fh)) break;
|
2009-02-06 13:37:46 +00:00
|
|
|
_faces.push_back(fh);
|
|
|
|
|
used(fh) = true;
|
|
|
|
|
strip.push_front(mesh_.to_vertex_handle(hh).idx());
|
|
|
|
|
flip = false;
|
|
|
|
|
}
|
2009-04-27 12:42:13 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
if (flip) strip.push_front(strip.front());
|
2009-04-27 12:42:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// copy final strip to _strip
|
|
|
|
|
_strip.clear();
|
|
|
|
|
_strip.reserve(strip.size());
|
|
|
|
|
std::copy(strip.begin(), strip.end(), std::back_inserter(_strip));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
} // namespace OpenMesh
|
|
|
|
|
//=============================================================================
|