StripifierT_impl.hh 8.67 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1
/* ========================================================================= *
2 3
 *                                                                           *
 *                               OpenMesh                                    *
Jan Möbius's avatar
Jan Möbius committed
4
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
Jan Möbius's avatar
Typo  
Jan Möbius committed
5
 *           Department of Computer Graphics and Multimedia                  *
Jan Möbius's avatar
Jan Möbius committed
6 7
 *                          All rights reserved.                             *
 *                            www.openmesh.org                               *
8
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
9 10 11
 *---------------------------------------------------------------------------*
 * This file is part of OpenMesh.                                            *
 *---------------------------------------------------------------------------*
12
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
13 14 15
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
16
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
17 18
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
19
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
20 21 22
 * 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.   *
23
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
24 25 26
 * 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.               *
27
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
28 29 30 31 32 33 34 35 36 37 38
 * 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.              *
Jan Möbius's avatar
Jan Möbius committed
39 40
 *                                                                           *
 * ========================================================================= */
41

42

Jan Möbius's avatar
Jan Möbius committed
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

//=============================================================================
//
//  CLASS StripifierT - IMPLEMENTATION
//
//=============================================================================

#define OPENMESH_STRIPIFIERT_C

//== INCLUDES =================================================================

#include <OpenMesh/Tools/Utils/StripifierT.hh>
#include <list>


//== NAMESPACES ===============================================================

namespace OpenMesh {
61 62


Jan Möbius's avatar
Jan Möbius committed
63
  //== IMPLEMENTATION ==========================================================
64

Jan Möbius's avatar
Jan Möbius committed
65 66
template <class Mesh>
StripifierT<Mesh>::
67 68
StripifierT(Mesh& _mesh) :
    mesh_(_mesh)
Jan Möbius's avatar
Jan Möbius committed
69
{
Jan Möbius's avatar
Jan Möbius committed
70

71 72 73 74 75
}

template <class Mesh>
StripifierT<Mesh>::
~StripifierT() {
Jan Möbius's avatar
Jan Möbius committed
76

77 78 79
}

template <class Mesh>
Jan Möbius's avatar
Jan Möbius committed
80
size_t
81 82 83
StripifierT<Mesh>::
stripify()
{
Jan Möbius's avatar
Jan Möbius committed
84 85 86 87 88
  // preprocess:  add new properties
  mesh_.add_property( processed_ );
  mesh_.add_property( used_ );
  mesh_.request_face_status();

Jan Möbius's avatar
Jan Möbius committed
89 90 91
  // build strips
  clear();
  build_strips();
92

Jan Möbius's avatar
Jan Möbius committed
93 94 95 96 97
  // postprocess:  remove properties
  mesh_.remove_property(processed_);
  mesh_.remove_property(used_);
  mesh_.release_face_status();

Jan Möbius's avatar
Jan Möbius committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
  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();
115 116 117



Jan Möbius's avatar
Jan Möbius committed
118 119 120 121 122
  // 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)
Jan Möbius's avatar
Jan Möbius committed
123 124
      if (mesh_.status(*f_it).hidden() || mesh_.status(*f_it).deleted())
        processed(*f_it) = used(*f_it) = true;
Jan Möbius's avatar
Jan Möbius committed
125
      else
Jan Möbius's avatar
Jan Möbius committed
126
        processed(*f_it) = used(*f_it) = false;
Jan Möbius's avatar
Jan Möbius committed
127 128 129 130
  }
  else
  {
    for (f_it=mesh_.faces_begin(); f_it!=f_end; ++f_it)
Jan Möbius's avatar
Jan Möbius committed
131
      processed(*f_it) = used(*f_it) = false;
Jan Möbius's avatar
Jan Möbius committed
132
  }
133 134 135



Jan Möbius's avatar
Jan Möbius committed
136 137 138 139
  for (f_it=mesh_.faces_begin(); true; )
  {
    // find start face
    for (; f_it!=f_end; ++f_it)
Jan Möbius's avatar
Jan Möbius committed
140
      if (!processed(*f_it))
Jan Möbius's avatar
Jan Möbius committed
141 142
        break;
    if (f_it==f_end) break; // stop if all have been processed
143 144


Jan Möbius's avatar
Jan Möbius committed
145
    // collect starting halfedges
146
    h[0] = mesh_.halfedge_handle(*f_it);
Jan Möbius's avatar
Jan Möbius committed
147 148
    h[1] = mesh_.next_halfedge_handle(h[0]);
    h[2] = mesh_.next_halfedge_handle(h[1]);
149 150


Jan Möbius's avatar
Jan Möbius committed
151
    // build 3 strips, take best one
Jan Möbius's avatar
Jan Möbius committed
152 153
    size_t best_length = 0;
    size_t best_idx    = 0;
Jan Möbius's avatar
Jan Möbius committed
154

Jan Möbius's avatar
Jan Möbius committed
155
    for (size_t i=0; i<3; ++i)
Jan Möbius's avatar
Jan Möbius committed
156 157
    {
      build_strip(h[i], experiments[i], faces[i]);
Jan Möbius's avatar
Jan Möbius committed
158 159 160

      const size_t length = experiments[i].size();
      if ( length  > best_length)
Jan Möbius's avatar
Jan Möbius committed
161 162 163 164
      {
        best_length = length;
        best_idx    = i;
      }
165 166

      for (fh_it=faces[i].begin(), fh_end=faces[i].end();
Jan Möbius's avatar
Jan Möbius committed
167 168 169
           fh_it!=fh_end; ++fh_it)
        used(*fh_it) = false;
    }
170 171


Jan Möbius's avatar
Jan Möbius committed
172 173 174 175 176
    // 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;
177 178 179



Jan Möbius's avatar
Jan Möbius committed
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
    // 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;
199 200


Jan Möbius's avatar
Jan Möbius committed
201 202
  // reset face list
  _faces.clear();
203 204


Jan Möbius's avatar
Jan Möbius committed
205 206 207
  // init strip
  strip.push_back(mesh_.from_vertex_handle(_start_hh).idx());
  strip.push_back(mesh_.to_vertex_handle(_start_hh).idx());
208 209


Jan Möbius's avatar
Jan Möbius committed
210 211 212 213 214 215 216 217 218 219
  // 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);
220
    if (processed(fh) || used(fh)) break;
Jan Möbius's avatar
Jan Möbius committed
221 222 223
    _faces.push_back(fh);
    used(fh) = true;
    strip.push_back(mesh_.to_vertex_handle(hh).idx());
224

Jan Möbius's avatar
Jan Möbius committed
225 226 227 228 229
    // 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);
230
    if (processed(fh) || used(fh)) break;
Jan Möbius's avatar
Jan Möbius committed
231 232 233 234
    _faces.push_back(fh);
    used(fh) = true;
    strip.push_back(mesh_.to_vertex_handle(hh).idx());
  }
235 236


Jan Möbius's avatar
Jan Möbius committed
237 238 239 240 241 242 243 244 245 246 247
  // 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);
248
    if (processed(fh) || used(fh)) break;
Jan Möbius's avatar
Jan Möbius committed
249 250 251 252
    _faces.push_back(fh);
    used(fh) = true;
    strip.push_front(mesh_.to_vertex_handle(hh).idx());
    flip = true;
253

Jan Möbius's avatar
Jan Möbius committed
254 255 256 257 258
    // 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);
259
    if (processed(fh) || used(fh)) break;
Jan Möbius's avatar
Jan Möbius committed
260 261 262 263 264
    _faces.push_back(fh);
    used(fh) = true;
    strip.push_front(mesh_.to_vertex_handle(hh).idx());
    flip = false;
  }
265

Jan Möbius's avatar
Jan Möbius committed
266
  if (flip) strip.push_front(strip.front());
267 268 269



Jan Möbius's avatar
Jan Möbius committed
270 271 272 273 274 275 276 277 278 279
  // copy final strip to _strip
  _strip.clear();
  _strip.reserve(strip.size());
  std::copy(strip.begin(), strip.end(), std::back_inserter(_strip));
}


//=============================================================================
} // namespace OpenMesh
  //=============================================================================