MeshSelectionT.cc 38.9 KB
Newer Older
1
/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
2 3
*                                                                            *
*                              OpenFlipper                                   *
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
 *           Department of Computer Graphics and Multimedia                  *
 *                          All rights reserved.                             *
 *                            www.openflipper.org                            *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenFlipper.                                         *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
 *                                                                           *
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
 *                                                                           *
 * 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.   *
 *                                                                           *
 * 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.               *
 *                                                                           *
 * 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
*                                                                            *
*   $Revision$                                                       *
*   $LastChangedBy$                                                *
*   $Date$                     *
*                                                                            *
48
\*===========================================================================*/
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66




//=============================================================================
//
//  IMPLEMENTATION
//
//=============================================================================

#define MESHSELECTION_C

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

#include "MeshSelectionT.hh"
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>

#include <stack>
67
#include <set>
68 69 70 71 72 73 74
//== NAMESPACES ===============================================================

namespace MeshSelection {

//== IMPLEMENTATION ==========================================================

//=========================================================
75 76 77
//== Vertex Selection =====================================
//=========================================================

78
template< typename MeshT >
79
inline
80
void selectVertices(MeshT* _mesh, const std::vector< int >& _vertices) {
81
  const int n_vertices = (int)_mesh->n_vertices();
82 83

  for ( uint i = 0 ; i < _vertices.size() ; ++i )
84
    if ( (_vertices[i] >= 0) && ( _vertices[i] < n_vertices ) )  {
85 86 87 88
      typename MeshT::VertexHandle vh(_vertices[i]);
      _mesh->status(vh).set_selected(true);
    }
}
89

90
//=========================================================
91

92
template< typename MeshT >
93
inline
94
void unselectVertices(MeshT* _mesh, const std::vector< int >& _vertices) {
95
  const int n_vertices = (int)_mesh->n_vertices();
96 97

  for ( uint i = 0 ; i < _vertices.size() ; ++i )
98
    if ( (_vertices[i] >= 0) && ( _vertices[i] < n_vertices ) )  {
99 100 101 102 103 104
      typename MeshT::VertexHandle vh(_vertices[i]);
      _mesh->status(vh).set_selected(false);
    }
}

//=========================================================
105

106
template< typename MeshT >
107
inline
108 109
void selectAllVertices(MeshT* _mesh) {
   typename MeshT::VertexIter v_it, v_end=_mesh->vertices_end();
110 111

   for (v_it = _mesh->vertices_begin(); v_it != v_end ; ++v_it)
Jan Möbius's avatar
Jan Möbius committed
112
      _mesh->status(*v_it).set_selected(true);
113 114

}
115 116

//=========================================================
117

118 119 120 121
template< typename MeshT >
inline
void clearVertexSelection(MeshT* _mesh) {
   typename MeshT::VertexIter v_it, v_end=_mesh->vertices_end();
122 123

   for (v_it = _mesh->vertices_begin(); v_it != v_end ; ++v_it)
Jan Möbius's avatar
Jan Möbius committed
124
      _mesh->status(*v_it).set_selected(false);
125 126 127 128 129
}

//=========================================================

template< typename MeshT >
130
inline
131 132
void invertVertexSelection(MeshT* _mesh) {
   typename MeshT::VertexIter v_it, v_end=_mesh->vertices_end();
133 134

   for (v_it = _mesh->vertices_begin(); v_it != v_end ; ++v_it)
Jan Möbius's avatar
Jan Möbius committed
135
      _mesh->status(*v_it).set_selected( ! _mesh->status(*v_it).selected());
136 137 138 139
}

//=========================================================

140

141 142 143 144
template< typename MeshT >
inline
void selectBoundaryVertices(MeshT* _mesh) {
   typename MeshT::HalfedgeIter he_it, he_end=_mesh->halfedges_end();
145 146

   for (he_it = _mesh->halfedges_begin(); he_it != he_end ; ++he_it)
Jan Möbius's avatar
Jan Möbius committed
147 148 149
      if (_mesh->is_boundary(*he_it) ) {
         _mesh->status(_mesh->to_vertex_handle(*he_it)).set_selected(true);
         _mesh->status(_mesh->from_vertex_handle(*he_it)).set_selected(true);
150 151 152 153 154 155
      }
}

//-----------------------------------------------------------------------------

template< typename MeshT >
156
inline
157 158
void shrinkVertexSelection(MeshT* _mesh) {
   OpenMesh::VPropHandleT< bool > temp_shrink;
159

160
   _mesh->add_property( temp_shrink, "Temp property for Vertex selection shrinking" );
161

162
   typename MeshT::VertexIter v_it, v_end=_mesh->vertices_end();
163

164
   // initialize property ( copy status to new property )
165
   for (v_it = _mesh->vertices_begin(); v_it != v_end ; ++v_it)
Jan Möbius's avatar
Jan Möbius committed
166
      _mesh->property(temp_shrink,*v_it) = _mesh->status(*v_it).selected();
167

168
   // update selection
169
   for (v_it = _mesh->vertices_begin(); v_it != v_end ; ++v_it)
Jan Möbius's avatar
Jan Möbius committed
170 171
      if ( _mesh->property(temp_shrink,*v_it) ) {
         _mesh->status(*v_it).set_selected( true );
172

Jan Möbius's avatar
Jan Möbius committed
173
         for ( typename MeshT::VertexVertexIter vv_it(*_mesh,*v_it); vv_it.is_valid(); ++vv_it)
Jan Möbius's avatar
Jan Möbius committed
174 175
            if ( ! _mesh->property(temp_shrink,*vv_it) ){
                _mesh->status(*v_it).set_selected( false );
176 177 178
                break;
            }
      }
179

180 181 182
   _mesh->remove_property(temp_shrink);
}

183
//=========================================================
184 185

template< typename MeshT >
186
inline
187 188
void growVertexSelection(MeshT* _mesh) {
   OpenMesh::VPropHandleT< bool > temp_grow;
189

190
   _mesh->add_property( temp_grow, "Temp property for Vertex selection growing" );
191

192 193
   // initialize property ( copy status to new property )
   typename MeshT::VertexIter v_it, v_end=_mesh->vertices_end();
194
   for (v_it = _mesh->vertices_begin(); v_it != v_end ; ++v_it)
Jan Möbius's avatar
Jan Möbius committed
195
      _mesh->property(temp_grow,*v_it) = _mesh->status(*v_it).selected();
196

197
   // update selection
198
   for (v_it = _mesh->vertices_begin(); v_it != v_end ; ++v_it)
Jan Möbius's avatar
Jan Möbius committed
199 200 201
      if ( _mesh->property(temp_grow,*v_it) )
         for ( typename MeshT::VertexVertexIter vv_it(*_mesh,*v_it); vv_it.is_valid(); ++vv_it)
            _mesh->status(*vv_it).set_selected( true );
202

203 204 205
   _mesh->remove_property(temp_grow);
}

206
//=========================================================
207 208

template< typename MeshT >
209
inline
210 211
std::vector< int > getVertexSelection(MeshT* _mesh) {
  std::vector< int > selection;
212

213
  for ( typename MeshT::VertexIter v_it= _mesh->vertices_begin() ; v_it != _mesh->vertices_end() ; ++v_it )
Jan Möbius's avatar
Jan Möbius committed
214 215
    if ( _mesh->status(*v_it).selected() )
      selection.push_back( v_it->idx() );
216

217 218 219
  return selection;
}

220
//=========================================================
221 222

template< typename MeshT >
223
inline
224 225
std::vector< int > getVertexSelection(MeshT* _mesh, bool& _invert) {
  std::vector< int > selection;
226

227
  int count = 0;
228

229
  for ( typename MeshT::VertexIter v_it= _mesh->vertices_begin() ; v_it != _mesh->vertices_end() ; ++v_it )
Jan Möbius's avatar
Jan Möbius committed
230
    if ( _mesh->status(*v_it).selected() )
231
      ++count;
232

233 234
  if ( count > (int)( _mesh->n_vertices() / 2) )
    _invert = true;
235
  else
236
    _invert = false;
237

238
  for ( typename MeshT::VertexIter v_it= _mesh->vertices_begin() ; v_it != _mesh->vertices_end() ; ++v_it )
Jan Möbius's avatar
Jan Möbius committed
239 240
    if ( _mesh->status(*v_it).selected() ^ _invert )
      selection.push_back( v_it->idx() );
241

242 243 244 245 246
  return selection;
}


template< typename MeshT >
247
inline
248
void selectBoundaryVertices(MeshT* _mesh, const typename MeshT::VertexHandle& _vh){
249

250 251 252 253 254
  OpenMesh::VPropHandleT< bool > visited;
  _mesh->add_property(visited, "Visited Vertices");

  typename MeshT::VertexIter v_it, v_end = _mesh->vertices_end();
  for (v_it = _mesh->vertices_begin(); v_it != v_end; ++v_it)
Jan Möbius's avatar
Jan Möbius committed
255
    _mesh->property(visited, *v_it) = false;
256 257 258 259 260 261 262 263 264 265 266 267 268

  std::stack< typename MeshT::VertexHandle > stack;
  stack.push( _vh );

  while (!stack.empty()){

    typename MeshT::VertexHandle vh = stack.top();
    stack.pop();

    if (_mesh->property(visited,vh))
      continue;

    //find outgoing boundary-edges
Jan Möbius's avatar
Jan Möbius committed
269
    for (typename MeshT::VertexOHalfedgeIter voh_it(*_mesh,vh); voh_it.is_valid(); ++voh_it)
Jan Möbius's avatar
Jan Möbius committed
270 271
      if ( _mesh->is_boundary( _mesh->edge_handle( *voh_it ) ) )
        stack.push( _mesh->to_vertex_handle(*voh_it) );
272 273 274 275 276 277 278 279

    //select vertex
    _mesh->property(visited,vh) = true;
    _mesh->status( vh ).set_selected(true);
  }
  _mesh->remove_property(visited);
}

280 281
template< typename MeshT >
inline
282
void convertVertexToEdgeSelection(MeshT* _mesh, const std::vector< int >& _vertices) {
283

284
  for ( std::vector<int>::const_iterator v = _vertices.begin(); v != _vertices.end(); ++v) {
285

286
    typename MeshT::VertexHandle vh(*v);
287 288
    typename MeshT::VertexOHalfedgeIter ohe_iter = _mesh->voh_iter(vh);

Jan Möbius's avatar
Jan Möbius committed
289
    for (; ohe_iter.is_valid(); ++ohe_iter) {
290
      // test if both incident vertices are in _vertices
Jan Möbius's avatar
Jan Möbius committed
291
      typename MeshT::VertexHandle ovh = _mesh->to_vertex_handle(*ohe_iter);
292
      // search for ovh in _vertices
293
      for(std::vector<int>::const_iterator it = _vertices.begin(); it != _vertices.end(); ++it) {
294
        if((*it) == ovh.idx()) {
Jan Möbius's avatar
Jan Möbius committed
295
          _mesh->status(_mesh->edge_handle(*ohe_iter)).set_selected(true);
296 297 298
          break;
        }
      }
299 300 301 302 303 304 305 306 307
    }
  }
}

template< typename MeshT >
inline
void convertVertexToEdgeSelection(MeshT* _mesh) {

  typename MeshT::VertexIter v_it, v_end = _mesh->vertices_end();
308
  for (v_it = _mesh->vertices_begin(); v_it != v_end; ++v_it) {
309

Jan Möbius's avatar
Jan Möbius committed
310
    if ( _mesh->status( *v_it ).selected() ) {
Jan Möbius's avatar
Jan Möbius committed
311
      typename MeshT::VertexOHalfedgeIter ohe_iter = _mesh->voh_iter(*v_it);
312

Jan Möbius's avatar
Jan Möbius committed
313
      for (; ohe_iter.is_valid(); ++ohe_iter) {
314
        // test if both incident vertices are in _vertices
Jan Möbius's avatar
Jan Möbius committed
315
        typename MeshT::VertexHandle ovh = _mesh->to_vertex_handle(*ohe_iter);
316
        if (_mesh->status(ovh).selected())
Jan Möbius's avatar
Jan Möbius committed
317
          _mesh->status(_mesh->edge_handle(*ohe_iter)).set_selected(true);
318
      }
319
    }
320
  }
321 322
}

323 324
template< typename MeshT >
inline
325
void convertVertexToHalfedgeSelection(MeshT* _mesh, const std::vector< int >& _vertices) {
326

327
  for (std::vector<int>::const_iterator v = _vertices.begin(); v != _vertices.end(); ++v) {
328 329

    typename MeshT::VertexHandle vh(*v);
330 331
    typename MeshT::VertexOHalfedgeIter ohe_iter = _mesh->voh_iter(vh);

Jan Möbius's avatar
Jan Möbius committed
332
    for (; ohe_iter.is_valid(); ++ohe_iter) {
333
      // test if both incident vertices are in _vertices
Jan Möbius's avatar
Jan Möbius committed
334
      typename MeshT::VertexHandle ovh = _mesh->to_vertex_handle(*ohe_iter);
335
      // search for ovh in _vertices
336
      for(std::vector<int>::const_iterator it = _vertices.begin(); it != _vertices.end(); ++it) {
337
        if((*it) == ovh.idx()) {
Jan Möbius's avatar
Jan Möbius committed
338 339
          _mesh->status(*ohe_iter).set_selected(true);
          _mesh->status(_mesh->opposite_halfedge_handle(*ohe_iter)).set_selected(true);
340 341 342
          break;
        }
      }
343 344 345 346 347 348 349 350 351 352
    }
  }
}

template< typename MeshT >
inline
void convertVertexToHalfedgeSelection(MeshT* _mesh) {

  typename MeshT::VertexIter v_it, v_end = _mesh->vertices_end();
  
353
  for (v_it = _mesh->vertices_begin(); v_it != v_end; ++v_it) {
354

Jan Möbius's avatar
Jan Möbius committed
355
    if ( _mesh->status( *v_it ).selected() ) {
356

Jan Möbius's avatar
Jan Möbius committed
357
      typename MeshT::VertexOHalfedgeIter ohe_iter = _mesh->voh_iter(*v_it);
358

Jan Möbius's avatar
Jan Möbius committed
359
      for (; ohe_iter.is_valid(); ++ohe_iter) {
360
        // test if both incident vertices are in _vertices
Jan Möbius's avatar
Jan Möbius committed
361
        typename MeshT::VertexHandle ovh = _mesh->to_vertex_handle(*ohe_iter);
362
        if (_mesh->status(ovh).selected()) {
Jan Möbius's avatar
Jan Möbius committed
363 364
          _mesh->status(*ohe_iter).set_selected(true);
          _mesh->status(_mesh->opposite_halfedge_handle(*ohe_iter)).set_selected(true);
365
        }
366 367
      }
    }
368
  }
369 370
}

371 372
template< typename MeshT >
inline
373
void convertVertexToFaceSelection(MeshT* _mesh, const std::vector< int >& _vertices) {
374

375
  for(typename MeshT::FaceIter f_it = _mesh->faces_begin(); f_it != _mesh->faces_end(); ++f_it) {
Jan Möbius's avatar
Jan Möbius committed
376
    typename MeshT::FaceVertexIter fv_it = _mesh->fv_iter(*f_it);
377 378
    // go over each vertex of each face and test if it's selected
    bool allfound = true;
Jan Möbius's avatar
Jan Möbius committed
379
    for(; fv_it.is_valid(); ++fv_it) {
380 381
      // search fv_it in _vertices
      bool onefound = false;
382
      for(std::vector<int>::const_iterator it = _vertices.begin(); it != _vertices.end(); ++it) {
Jan Möbius's avatar
Jan Möbius committed
383
        if((*it) == fv_it->idx()) { onefound = true; break; }
384 385 386 387 388 389 390 391
      }
      if(!onefound) {
        allfound = false;
        break;
      }
    }
    if(allfound) {
      // all incident vertices are selected -> select face
Jan Möbius's avatar
Jan Möbius committed
392
      _mesh->status(*f_it).set_selected(true);
393 394
    }
  }
395 396
}

397 398 399 400
template< typename MeshT >
inline
void convertVertexToFaceSelection(MeshT* _mesh) {

401
  typename MeshT::FaceIter f_it, f_end = _mesh->faces_end();
402
  
403 404
  for (f_it = _mesh->faces_begin(); f_it != f_end; ++f_it) {

Jan Möbius's avatar
Jan Möbius committed
405
    typename MeshT::FaceVertexIter fv_it = _mesh->fv_iter(*f_it);
406 407
    // test if all incident vertices are selected
    bool allfound = true;
Jan Möbius's avatar
Jan Möbius committed
408 409
    for(; fv_it.is_valid(); ++fv_it) {
      if(!_mesh->status(*fv_it).selected()) {
410 411 412
        allfound = false;
        break;
      }
413
    }
414
    if(allfound)
Jan Möbius's avatar
Jan Möbius committed
415
      _mesh->status(*f_it).set_selected(true);
416
  }
417 418
}

419 420 421 422 423 424
template< typename MeshT >
inline
void convertVertexSelectionToFeatureVertices(MeshT* _mesh) {

    for (typename MeshT::VertexIter v_it = _mesh->vertices_begin(); v_it != _mesh->vertices_end(); ++v_it) {

Jan Möbius's avatar
Jan Möbius committed
425
        if (_mesh->status(*v_it).selected()) {
426

Jan Möbius's avatar
Jan Möbius committed
427
            _mesh->status(*v_it).set_feature(true);
428
        } else {
Jan Möbius's avatar
Jan Möbius committed
429
            _mesh->status(*v_it).set_feature(false);
430 431 432 433 434 435 436 437 438 439
        }
    }
}

template< typename MeshT >
inline
void convertFeatureVerticesToVertexSelection(MeshT* _mesh) {

    for (typename MeshT::VertexIter v_it = _mesh->vertices_begin(); v_it != _mesh->vertices_end(); ++v_it) {

Jan Möbius's avatar
Jan Möbius committed
440
        if (_mesh->status(*v_it).feature()) {
441

Jan Möbius's avatar
Jan Möbius committed
442
            _mesh->status(*v_it).set_selected(true);
443
        } else {
Jan Möbius's avatar
Jan Möbius committed
444
            _mesh->status(*v_it).set_selected(false);
445 446 447 448 449 450 451 452 453 454
        }
    }
}

template< typename MeshT >
inline
void clearFeatureVertices(MeshT* _mesh) {

    for (typename MeshT::VertexIter v_it = _mesh->vertices_begin(); v_it != _mesh->vertices_end(); ++v_it) {

Jan Möbius's avatar
Jan Möbius committed
455
        _mesh->status(*v_it).set_feature(false);
456 457 458
    }
}

459 460
//=========================================================
//== Modeling Regions =====================================
461 462 463
//=========================================================

template< typename MeshT >
464
inline
465
void setArea(MeshT* _mesh, const std::vector< int >& _vertices , unsigned int _type, bool _state) {
466 467
  for ( uint i = 0 ; i < _vertices.size() ; ++i ) {
    if ( _vertices[i] > (int)_mesh->n_vertices() )
468 469
      continue;

470 471 472 473 474 475
    typename MeshT::VertexHandle vh(_vertices[i]);
    _mesh->status(vh).change_bit(_type, _state);
  }
}

template< typename MeshT >
476
inline
477
void setArea(MeshT* _mesh , unsigned int _type, bool _state) {
478
  for ( typename MeshT::VertexIter v_it= _mesh->vertices_begin() ; v_it != _mesh->vertices_end() ; ++v_it )
Jan Möbius's avatar
Jan Möbius committed
479
    _mesh->status(*v_it).change_bit(_type,  _state);
480 481 482
}

template< typename MeshT >
483
inline
484 485
std::vector< int > getArea(MeshT* _mesh, unsigned int _type) {
  std::vector< int > selection;
486

487
  for ( typename MeshT::VertexIter v_it= _mesh->vertices_begin() ; v_it != _mesh->vertices_end() ; ++v_it )
Jan Möbius's avatar
Jan Möbius committed
488 489
    if ( _mesh->status(*v_it).is_bit_set( _type ) )
      selection.push_back( v_it->idx() );
490 491

  return selection;
492 493 494
}

template< typename MeshT >
495
inline
496 497
std::vector< int > getArea(MeshT* _mesh, unsigned int _type , bool& _invert) {
  std::vector< int > selection;
498

499
  int count = 0;
500

501
  for ( typename MeshT::VertexIter v_it= _mesh->vertices_begin() ; v_it != _mesh->vertices_end() ; ++v_it )
Jan Möbius's avatar
Jan Möbius committed
502
    if ( _mesh->status(*v_it).is_bit_set( _type ) )
503
      ++count;
504

505 506
  if ( count > (int)( _mesh->n_vertices() / 2) )
    _invert = true;
507
  else
508
    _invert = false;
509

510
  for ( typename MeshT::VertexIter v_it= _mesh->vertices_begin() ; v_it != _mesh->vertices_end() ; ++v_it )
Jan Möbius's avatar
Jan Möbius committed
511 512
    if ( _mesh->status(*v_it).is_bit_set( _type ) ^ _invert )
      selection.push_back( v_it->idx() );
513

514 515 516 517 518
  return selection;
}


//=========================================================
519 520 521
//== Edge Selection =====================================
//=========================================================

522
template< typename MeshT >
523
inline
524
void selectEdges(MeshT* _mesh, const std::vector< int >& _edges) {
525
  const int n_edges = (int)_mesh->n_edges();
526 527

  for ( uint i = 0 ; i < _edges.size() ; ++i )
528
    if ( (_edges[i] >= 0) && ( _edges[i] < n_edges ) )  {
529 530 531 532
      typename MeshT::EdgeHandle eh(_edges[i]);
      _mesh->status(eh).set_selected(true);
    }
}
533

534
//=========================================================
535

536
template< typename MeshT >
537
inline
538
void unselectEdges(MeshT* _mesh, const std::vector< int >& _edges) {
539
  const int n_edges = (int)_mesh->n_edges();
540 541

  for ( uint i = 0 ; i < _edges.size() ; ++i )
542
    if ( (_edges[i] >= 0) && ( _edges[i] < n_edges ) )  {
543 544 545
      typename MeshT::EdgeHandle eh(_edges[i]);
      _mesh->status(eh).set_selected(false);
    }
546 547
}

548
//=========================================================
549

550
template< typename MeshT >
551
inline
552 553
void selectAllEdges(MeshT* _mesh) {
  typename MeshT::EdgeIter e_it, e_end=_mesh->edges_end();
554 555

  for (e_it = _mesh->edges_begin(); e_it != e_end ; ++e_it)
Jan Möbius's avatar
Jan Möbius committed
556
  _mesh->status(*e_it).set_selected(true);
557
}
558 559 560 561

//=========================================================

template< typename MeshT >
562
inline
563 564 565
void clearEdgeSelection(MeshT* _mesh) {
  typename MeshT::EdgeIter e_it, e_end=_mesh->edges_end();

566
  for (e_it = _mesh->edges_begin(); e_it != e_end ; ++e_it)
Jan Möbius's avatar
Jan Möbius committed
567
    _mesh->status(*e_it).set_selected(false);
568
}
569 570 571 572

//=========================================================

template< typename MeshT >
573
inline
574 575 576
void invertEdgeSelection(MeshT* _mesh) {
  typename MeshT::EdgeIter e_it, e_end=_mesh->edges_end();

577
  for (e_it = _mesh->edges_begin(); e_it != e_end ; ++e_it)
Jan Möbius's avatar
Jan Möbius committed
578
    _mesh->status(*e_it).set_selected( ! _mesh->status(*e_it).selected());
579
}
580 581 582

//=========================================================

583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
template<typename MeshT>
inline
void growEdgeSelection(MeshT* _mesh) {
    std::set<typename MeshT::EdgeHandle> selectedEhs;
    for (typename MeshT::EdgeIter e_it = _mesh->edges_begin(), e_end = _mesh->edges_end();
            e_it != e_end; ++e_it) {

        if (!_mesh->status(*e_it).selected()) continue;

        const typename MeshT::HalfedgeHandle he = _mesh->halfedge_handle(*e_it, 0);
        const typename MeshT::VertexHandle vhs[] = { _mesh->from_vertex_handle(he),
                                                     _mesh->to_vertex_handle(he) };

        for (int i = 0; i < 2; ++i) {
            for (typename MeshT::VertexEdgeIter ve_it = _mesh->ve_begin(vhs[i]), ve_end = _mesh->ve_end(vhs[i]);
                    ve_it != ve_end; ++ve_it) {

Jan Möbius's avatar
Jan Möbius committed
600
                selectedEhs.insert(*ve_it);
601 602 603 604 605 606 607 608 609 610 611
            }
        }

    }

    for (typename std::set<typename MeshT::EdgeHandle>::const_iterator it = selectedEhs.begin(); it != selectedEhs.end(); ++it)
        _mesh->status(*it).set_selected(true);
}

//=========================================================

612

613 614 615 616 617
template< typename MeshT >
inline
void selectBoundaryEdges(MeshT* _mesh) {
  typename MeshT::EdgeIter e_it, e_end=_mesh->edges_end();

618
  for (e_it = _mesh->edges_begin(); e_it != e_end ; ++e_it)
Jan Möbius's avatar
Jan Möbius committed
619 620 621
    if ( _mesh->is_boundary( _mesh->halfedge_handle(*e_it,0) ) ||
         _mesh->is_boundary( _mesh->halfedge_handle(*e_it,1) ) )
      _mesh->status(*e_it).set_selected( true );
622 623
}

624
//=========================================================
625 626

template< typename MeshT >
627
inline
628 629
std::vector< int > getEdgeSelection(MeshT* _mesh) {
  std::vector< int > selection;
630

631
  for ( typename MeshT::EdgeIter e_it= _mesh->edges_begin() ; e_it != _mesh->edges_end() ; ++e_it )
Jan Möbius's avatar
Jan Möbius committed
632 633
    if ( _mesh->status(*e_it).selected() )
      selection.push_back( e_it->idx() );
634

635 636 637
  return selection;
}

638
//=========================================================
639 640

template< typename MeshT >
641
inline
642 643
std::vector< int > getEdgeSelection(MeshT* _mesh, bool& _invert) {
  std::vector< int > selection;
644

645
  int count = 0;
646

647
  for ( typename MeshT::VertexIter e_it= _mesh->edges_begin() ; e_it != _mesh->edges_end() ; ++e_it )
Jan Möbius's avatar
Jan Möbius committed
648
    if ( _mesh->status(*e_it).selected() )
649
      ++count;
650

651 652
  if ( count > (int)( _mesh->n_vertices() / 2) )
    _invert = true;
653
  else
654
    _invert = false;
655

656
  for ( typename MeshT::VertexIter e_it= _mesh->edges_begin() ; e_it != _mesh->edges_end() ; ++e_it )
Jan Möbius's avatar
Jan Möbius committed
657 658
    if ( _mesh->status(*e_it).selected() ^ _invert )
      selection.push_back( e_it->idx() );
659

660 661 662
  return selection;
}

663 664
template< typename MeshT >
inline
665
void convertEdgeToVertexSelection(MeshT* _mesh, const std::vector< int >& _edges) {
666

667
	for (std::vector<int>::const_iterator e = _edges.begin(); e != _edges.end(); ++e) {
668 669 670 671 672 673 674 675 676 677 678 679

		typename MeshT::EdgeHandle eh(*e);
		typename MeshT::HalfedgeHandle heh0 = _mesh->halfedge_handle(eh, 0);

		typename MeshT::VertexHandle vh0 = _mesh->to_vertex_handle(heh0);
		typename MeshT::VertexHandle vh1 = _mesh->from_vertex_handle(heh0);

		_mesh->status(vh0).set_selected(true);
		_mesh->status(vh1).set_selected(true);
	}
}

680 681 682 683 684 685
template< typename MeshT >
inline
void convertEdgeToVertexSelection(MeshT* _mesh) {

  for ( typename MeshT::EdgeIter e_it= _mesh->edges_begin() ; e_it != _mesh->edges_end() ; ++e_it )
    
Jan Möbius's avatar
Jan Möbius committed
686
    if ( _mesh->status(*e_it).selected() ){
687

Jan Möbius's avatar
Jan Möbius committed
688
      typename MeshT::HalfedgeHandle heh0 = _mesh->halfedge_handle(*e_it, 0);
689 690 691 692 693 694 695 696 697

      typename MeshT::VertexHandle vh0 = _mesh->to_vertex_handle(heh0);
      typename MeshT::VertexHandle vh1 = _mesh->from_vertex_handle(heh0);

      _mesh->status(vh0).set_selected(true);
      _mesh->status(vh1).set_selected(true);
    }
}

698 699
template< typename MeshT >
inline
700
void convertEdgeToFaceSelection(MeshT* _mesh, const std::vector< int >& _edges) {
701

702
  for(typename MeshT::FaceIter f_it = _mesh->faces_begin(); f_it != _mesh->faces_end(); ++f_it) {
Jan Möbius's avatar
Jan Möbius committed
703
    typename MeshT::FaceEdgeIter fe_it = _mesh->fe_iter(*f_it);
704 705
    // go over each edge of each face and test if it's selected
    bool allfound = true;
Jan Möbius's avatar
Jan Möbius committed
706
    for(; fe_it.is_valid(); ++fe_it) {
707 708
      // search fe_it in _edges
      bool onefound = false;
709
      for(std::vector<int>::const_iterator it = _edges.begin(); it != _edges.end(); ++it) {
Jan Möbius's avatar
Jan Möbius committed
710
        if((*it) == fe_it->idx()) { onefound = true; break; }
711 712 713 714 715 716 717 718
      }
      if(!onefound) {
        allfound = false;
        break;
      }
    }
    if(allfound) {
      // all incident vertices are selected -> select face
Jan Möbius's avatar
Jan Möbius committed
719
      _mesh->status(*f_it).set_selected(true);
720 721
    }
  }
722 723
}

724 725 726 727
template< typename MeshT >
inline
void convertEdgeToFaceSelection(MeshT* _mesh) {

728 729 730 731
  typename MeshT::FaceIter f_it, f_end = _mesh->faces_end();
  
  for (f_it = _mesh->faces_begin(); f_it != f_end; ++f_it) {

Jan Möbius's avatar
Jan Möbius committed
732
    typename MeshT::FaceEdgeIter fe_it = _mesh->fe_iter(*f_it);
733 734
    // test if all incident edges are selected
    bool allfound = true;
Jan Möbius's avatar
Jan Möbius committed
735 736
    for(; fe_it.is_valid(); ++fe_it) {
      if(!_mesh->status(*fe_it).selected()) {
737 738 739
        allfound = false;
        break;
      }
740
    }
741
    if(allfound)
Jan Möbius's avatar
Jan Möbius committed
742
      _mesh->status(*f_it).set_selected(true);
743
  }
744
}
745

746 747 748 749 750 751
template< typename MeshT >
inline
void convertEdgeToHalfedgeSelection(MeshT* _mesh) {

  for ( typename MeshT::EdgeIter e_it= _mesh->edges_begin() ; e_it != _mesh->edges_end() ; ++e_it )
    
Jan Möbius's avatar
Jan Möbius committed
752
    if ( _mesh->status(*e_it).selected() ){
753

Jan Möbius's avatar
Jan Möbius committed
754 755
      _mesh->status(_mesh->halfedge_handle(*e_it, 0)).set_selected(true);
      _mesh->status(_mesh->halfedge_handle(*e_it, 1)).set_selected(true);
756 757 758
    }
}

759 760
template< typename MeshT >
inline
761
void convertEdgeSelectionToFeatureEdges(MeshT* _mesh) {
762 763 764

    for (typename MeshT::EdgeIter e_it = _mesh->edges_begin(); e_it != _mesh->edges_end(); ++e_it) {

Jan Möbius's avatar
Jan Möbius committed
765
        if (_mesh->status(*e_it).selected()) {
766

Jan Möbius's avatar
Jan Möbius committed
767
            _mesh->status(*e_it).set_feature(true);
768
        } else {
Jan Möbius's avatar
Jan Möbius committed
769
            _mesh->status(*e_it).set_feature(false);
770 771 772 773 774 775
        }
    }
}

template< typename MeshT >
inline
776
void convertFeatureEdgesToEdgeSelection(MeshT* _mesh) {
777 778

    for (typename MeshT::EdgeIter e_it = _mesh->edges_begin(); e_it != _mesh->edges_end(); ++e_it) {
David Bommes's avatar
David Bommes committed
779

Jan Möbius's avatar
Jan Möbius committed
780
        if (_mesh->status(*e_it).feature()) {
781

Jan Möbius's avatar
Jan Möbius committed
782
            _mesh->status(*e_it).set_selected(true);
783
        } else {
Jan Möbius's avatar
Jan Möbius committed
784
            _mesh->status(*e_it).set_selected(false);
785 786 787 788 789 790
        }
    }
}

template< typename MeshT >
inline
791
void clearFeatureEdges(MeshT* _mesh) {
792 793 794

    for (typename MeshT::EdgeIter e_it = _mesh->edges_begin(); e_it != _mesh->edges_end(); ++e_it) {

Jan Möbius's avatar
Jan Möbius committed
795
        _mesh->status(*e_it).set_feature(false);
796 797
    }
}
David Bommes's avatar
David Bommes committed
798 799 800 801 802 803 804

//=========================================================
//== Halfedge Selection =====================================
//=========================================================

template< typename MeshT >
inline
805
void selectHalfedges(MeshT* _mesh, const std::vector< int >& _halfedges) {
David Bommes's avatar
David Bommes committed
806 807 808
  const int n_halfedges = (int)_mesh->n_halfedges();

  for ( uint i = 0 ; i < _halfedges.size() ; ++i )
809
    if ( (_halfedges[i] >= 0) && ( _halfedges[i] < n_halfedges ) )  {
David Bommes's avatar
David Bommes committed
810 811 812 813 814 815 816 817 818
      typename MeshT::HalfedgeHandle heh(_halfedges[i]);
      _mesh->status(heh).set_selected(true);
    }
}

//=========================================================

template< typename MeshT >
inline
819
void unselectHalfedges(MeshT* _mesh, const std::vector< int >& _halfedges) {
David Bommes's avatar
David Bommes committed
820 821 822
  const int n_halfedges = (int)_mesh->n_halfedges();

  for ( uint i = 0 ; i < _halfedges.size() ; ++i )
823
    if ( (_halfedges[i] >= 0) && ( _halfedges[i] < n_halfedges ) )  {
David Bommes's avatar
David Bommes committed
824 825 826 827 828 829 830 831 832 833 834 835 836
      typename MeshT::HalfedgeHandle heh(_halfedges[i]);
      _mesh->status(heh).set_selected(false);
    }
}

//=========================================================

template< typename MeshT >
inline
void selectAllHalfedges(MeshT* _mesh) {
  typename MeshT::HalfedgeIter he_it, he_end=_mesh->halfedges_end();

  for (he_it = _mesh->halfedges_begin(); he_it != he_end ; ++he_it)
Jan Möbius's avatar
Jan Möbius committed
837
  _mesh->status(*he_it).set_selected(true);
David Bommes's avatar
David Bommes committed
838 839 840 841 842 843 844 845 846 847
}

//=========================================================

template< typename MeshT >
inline
void clearHalfedgeSelection(MeshT* _mesh) {
  typename MeshT::HalfedgeIter he_it, he_end=_mesh->halfedges_end();

  for (he_it = _mesh->halfedges_begin(); he_it != he_end ; ++he_it)
Jan Möbius's avatar
Jan Möbius committed
848
    _mesh->status(*he_it).set_selected(false);
David Bommes's avatar
David Bommes committed
849 850 851 852 853 854 855 856 857 858
}

//=========================================================

template< typename MeshT >
inline
void invertHalfedgeSelection(MeshT* _mesh) {
  typename MeshT::HalfedgeIter he_it, he_end=_mesh->halfedges_end();

  for (he_it = _mesh->halfedges_begin(); he_it != he_end ; ++he_it)
Jan Möbius's avatar
Jan Möbius committed
859
    _mesh->status(*he_it).set_selected( ! _mesh->status(*he_it).selected());
David Bommes's avatar
David Bommes committed
860 861 862 863 864 865 866 867 868 869 870
}

//=========================================================


template< typename MeshT >
inline
void selectBoundaryHalfedges(MeshT* _mesh) {
  typename MeshT::HalfedgeIter he_it, he_end=_mesh->halfedges_end();

  for (he_it = _mesh->halfedges_begin(); he_it != he_end ; ++he_it)
Jan Möbius's avatar
Jan Möbius committed
871 872
    if ( _mesh->is_boundary( *he_it))
      _mesh->status(*he_it).set_selected( true );
David Bommes's avatar
David Bommes committed
873 874 875 876 877 878 879 880 881 882
}

//=========================================================

template< typename MeshT >
inline
std::vector< int > getHalfedgeSelection(MeshT* _mesh) {
  std::vector< int > selection;

  for ( typename MeshT::HalfedgeIter he_it= _mesh->halfedges_begin() ; he_it != _mesh->halfedges_end() ; ++he_it )
Jan Möbius's avatar
Jan Möbius committed
883 884
    if ( _mesh->status(*he_it).selected() )
      selection.push_back( he_it->idx() );
David Bommes's avatar
David Bommes committed
885 886 887 888

  return selection;
}

889 890 891 892 893 894
template< typename MeshT >
inline
void convertHalfedgeToVertexSelection(MeshT* _mesh) {
    
    for ( typename MeshT::HalfedgeIter he_it= _mesh->halfedges_begin() ; he_it != _mesh->halfedges_end() ; ++he_it ) {
        
Jan Möbius's avatar
Jan Möbius committed
895 896 897
        if(_mesh->status(*he_it).selected()) {
            _mesh->status(_mesh->to_vertex_handle(*he_it)).set_selected(true);
            _mesh->status(_mesh->from_vertex_handle(*he_it)).set_selected(true);
898 899 900 901 902 903 904 905 906 907
        }
    }
}

template< typename MeshT >
inline
void convertHalfedgeToEdgeSelection(MeshT* _mesh) {
    
    for ( typename MeshT::HalfedgeIter he_it= _mesh->halfedges_begin() ; he_it != _mesh->halfedges_end() ; ++he_it ) {
        
Jan Möbius's avatar
Jan Möbius committed
908 909
        if(_mesh->status(*he_it).selected()) {
            _mesh->status(_mesh->edge_handle(*he_it)).set_selected(true);
910 911 912 913 914 915 916
        }
    }
}

template< typename MeshT >
inline
void convertHalfedgeToFaceSelection(MeshT* _mesh) {
917 918 919 920
    // Note: A face is not only selected
    // iff all incident halfedges are selected but
    // at least one of them. This is, however,
    // desired in some cases.
921 922
    for ( typename MeshT::HalfedgeIter he_it= _mesh->halfedges_begin() ; he_it != _mesh->halfedges_end() ; ++he_it ) {
        
Jan Möbius's avatar
Jan Möbius committed
923 924
        if(_mesh->status(*he_it).selected()) {
            _mesh->status(_mesh->face_handle(*he_it)).set_selected(true);
925 926 927 928
        }
    }
}

929 930 931 932 933
//=========================================================
//== Face Selection =======================================
//=========================================================

template< typename MeshT >
934
inline
Jan Möbius's avatar
Jan Möbius committed
935
void selectFaces(MeshT* _mesh, const std::vector< int >& _faces) {
936
  const int n_faces = (int)_mesh->n_faces();
937 938

  for ( uint i = 0 ; i < _faces.size() ; ++i )
939
    if ( (_faces[i] >= 0) && ( _faces[i] < n_faces ) )  {
940 941 942 943
      typename MeshT::FaceHandle fh(_faces[i]);
      _mesh->status(fh).set_selected(true);
    }
}
944

945
//=========================================================
946

947
template< typename MeshT >
948
inline
Jan Möbius's avatar
Jan Möbius committed
949
void unselectFaces(MeshT* _mesh, const std::vector< int >& _faces) {
950
  const int n_faces = (int)_mesh->n_faces();
951 952

  for ( uint i = 0 ; i < _faces.size() ; ++i )
953
    if ( (_faces[i] >= 0) && ( _faces[i] < n_faces ) )  {
954 955 956
      typename MeshT::FaceHandle fh(_faces[i]);
      _mesh->status(fh).set_selected(false);
    }
957 958
}

959 960 961 962 963 964
//=========================================================

template< typename MeshT >
inline
void selectAllFaces(MeshT* _mesh) {
   typename MeshT::FaceIter f_it, f_end=_mesh->faces_end();
965 966

   for (f_it = _mesh->faces_begin(); f_it != f_end ; ++f_it)
Jan Möbius's avatar
Jan Möbius committed
967
      _mesh->status(*f_it).set_selected(true);
968 969 970 971 972 973 974 975 976
}

//=========================================================


template< typename MeshT >
inline
void clearFaceSelection(MeshT* _mesh) {
   typename MeshT::FaceIter f_it, f_end=_mesh->faces_end();
977 978

   for (f_it = _mesh->faces_begin(); f_it != f_end ; ++f_it)
Jan Möbius's avatar
Jan Möbius committed
979
      _mesh->status(*f_it).set_selected(false);
980 981 982 983 984 985
}

//-----------------------------------------------------------------------------


template< typename MeshT >
986
inline
987 988
void invertFaceSelection(MeshT* _mesh) {
   typename MeshT::FaceIter f_it, f_end=_mesh->faces_end();
989 990

   for (f_it = _mesh->faces_begin(); f_it != f_end ; ++f_it)
Jan Möbius's avatar
Jan Möbius committed
991
      _mesh->status(*f_it).set_selected( ! _mesh->status(*f_it).selected());
992 993 994 995 996 997 998 999
}

//=========================================================

template< typename MeshT >
inline
void selectBoundaryFaces(MeshT* _mesh) {
  typename MeshT::HalfedgeIter he_it, he_end=_mesh->halfedges_end();
1000 1001

  for (he_it = _mesh->halfedges_begin(); he_it != he_end ; ++he_it)
Jan Möbius's avatar
Jan Möbius committed
1002
    if (_mesh->is_boundary(*he_it) ) {
Jan Möbius's avatar
Jan Möbius committed
1003
        for (typename MeshT::VertexFaceIter vf_it(*_mesh ,_mesh->to_vertex_handle(*he_it) ) ; vf_it.is_valid() ; ++vf_it)
Jan Möbius's avatar
Jan Möbius committed
1004
          _mesh->status(*vf_it).set_selected(true);
Jan Möbius's avatar
Jan Möbius committed
1005
        for (typename MeshT::VertexFaceIter vf_it(*_mesh ,_mesh->from_vertex_handle(*he_it) ) ; vf_it.is_valid() ; ++vf_it)
Jan Möbius's avatar
Jan Möbius committed
1006
          _mesh->status(*vf_it).set_selected(true);
1007 1008 1009 1010 1011 1012 1013
    }
}

//=========================================================


template< typename MeshT >
1014
inline
1015 1016
void shrinkFaceSelection(MeshT* _mesh) {
   OpenMesh::FPropHandleT< bool > temp_shrink;
1017

1018
   _mesh->add_property( temp_shrink, "Temp property for Face selection shrinking" );
1019

1020
   typename MeshT::FaceIter f_it, f_end=_mesh->faces_end();
1021

1022
   // initialize property ( copy status to new property )
1023
   for (f_it = _mesh->faces_begin(); f_it != f_end ; ++f_it)
Jan Möbius's avatar
Jan Möbius committed
1024
      _mesh->property(temp_shrink,*f_it) = _mesh->status(*f_it).selected();
1025

1026
   // Shrink selection ( deselects all faces which are adjacent to a boundary vertex of the original selection)
1027
   for (f_it = _mesh->faces_begin(); f_it != f_end ; ++f_it)
Jan Möbius's avatar
Jan Möbius committed
1028
      if ( _mesh->property(temp_shrink,*f_it) ) {
1029
         bool boundary = false;
Jan Möbius's avatar
Jan Möbius committed
1030 1031
         for ( typename MeshT::FaceVertexIter fv_it(*_mesh,*f_it); fv_it.is_valid() ; ++fv_it) {
            for ( typename MeshT::VertexFaceIter vf_it(*_mesh,*fv_it); vf_it.is_valid() ; ++vf_it) {
Jan Möbius's avatar
Jan Möbius committed
1032
               if ( ! _mesh->property(temp_shrink,*vf_it) ) {
1033
                 boundary = true;
1034 1035 1036 1037 1038
               }
            }
            if ( boundary )
               break;
         }
1039

Jan Möbius's avatar
Jan Möbius committed
1040
         _mesh->status(*f_it).set_selected( !boundary );
1041
      }
1042

1043 1044 1045 1046 1047 1048
   _mesh->remove_property(temp_shrink);
}

//=========================================================

template< typename MeshT >
1049
inline
1050 1051
void growFaceSelection(