Developer Documentation
MeshObjectSelectionPluginT_impl.hh
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright(C)2001-2010 by Computer Graphics Group, RWTH Aachen *
5  * www.openflipper.org *
6  * *
7  *---------------------------------------------------------------------------*
8  * This file is part of OpenFlipper. *
9  * *
10  * OpenFlipper is free software: you can redistribute it and/or modify *
11  * it under the terms of the GNU Lesser General Public License as *
12  * published by the Free Software Foundation, either version 3 of *
13  * the License, or(at your option)any later version with the *
14  * following exceptions: *
15  * *
16  * If other files instantiate templates or use macros *
17  * or inline functions from this file, or you compile this file and *
18  * link it with other files to produce an executable, this file does *
19  * not by itself cause the resulting executable to be covered by the *
20  * GNU Lesser General Public License. This exception does not however *
21  * invalidate any other reasons why the executable file might be *
22  * covered by the GNU Lesser General Public License. *
23  * *
24  * OpenFlipper is distributed in the hope that it will be useful, *
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27  * GNU Lesser General Public License for more details. *
28  * *
29  * You should have received a copy of the GNU LesserGeneral Public *
30  * License along with OpenFlipper. If not, *
31  * see <http://www.gnu.org/licenses/>. *
32  * *
33 \*===========================================================================*/
34 
35 /*===========================================================================*\
36  * *
37  * $Revision$ *
38  * $Author$ *
39  * $Date: 2010-09-24 14:05:45 +0200(Fri, 24 Sep 2010)$ *
40  * *
41 \*===========================================================================*/
42 
43 #include "MeshObjectSelectionPlugin.hh"
44 
47 #include <OpenMesh/Core/Geometry/MathDefs.hh>
48 
49 #include <set>
50 
57 template<typename MeshT>
58 bool MeshObjectSelectionPlugin::deleteSelection(MeshT* _mesh, PrimitiveType _primitiveType) {
59 
60  bool changed = false;
61 
62  if(_primitiveType & vertexType_) {
63  typename MeshT::VertexIter v_it, v_end=_mesh->vertices_end();
64 
65  for(v_it=_mesh->vertices_begin(); v_it!=v_end; ++v_it) {
66  if(_mesh->status(*v_it).selected()) {
67  _mesh->delete_vertex(*v_it);
68  changed = true;
69  }
70  }
71  }
72 
73  if(_primitiveType & edgeType_) {
74  typename MeshT::EdgeIter e_it, e_end(_mesh->edges_end());
75 
76  for(e_it=_mesh->edges_begin(); e_it!=e_end; ++e_it) {
77  if(_mesh->status(*e_it).selected()) {
78  _mesh->delete_edge(*e_it);
79  changed = true;
80  }
81  }
82  }
83 
84  if(_primitiveType & faceType_) {
85  typename MeshT::FaceIter f_it, f_end(_mesh->faces_end());
86 
87  for(f_it=_mesh->faces_begin(); f_it!=f_end; ++f_it) {
88  if(_mesh->status(*f_it).selected()) {
89  _mesh->delete_face(*f_it);
90  changed = true;
91  }
92  }
93  }
94 
95  _mesh->garbage_collection();
96 
97  return changed;
98 }
99 
100 //***********************************************************************************
101 
106 template<typename MeshType>
108 
109  // Set face status
110  typename MeshType::FaceIter f_it, f_end=_mesh->faces_end();
111  typename MeshType::FaceVertexIter fv_it;
112  typename MeshType::VertexHandle v0, v1, v2;
113 
114  for(f_it=_mesh->faces_begin(); f_it!=f_end; ++f_it) {
115  fv_it = _mesh->fv_iter(*f_it);
116  v0 = *( fv_it);
117  v1 = *(++fv_it);
118  v2 = *(++fv_it);
119 
120  const bool a =(_mesh->status(v0).is_bit_set(AREA)|| _mesh->status(v1).is_bit_set(AREA)|| _mesh->status(v2).is_bit_set(AREA));
121  bool h =(_mesh->status(v0).is_bit_set(HANDLEAREA)&&
122  _mesh->status(v1).is_bit_set(HANDLEAREA)&&
123  _mesh->status(v2).is_bit_set(HANDLEAREA));
124 
125  if(!(a || h))
126  if(_mesh->status(v0).is_bit_set(HANDLEAREA)||
127  _mesh->status(v1).is_bit_set(HANDLEAREA)||
128  _mesh->status(v2).is_bit_set(HANDLEAREA))
129  h = true;
130 
131  _mesh->status(*f_it).change_bit(AREA , a);
132  _mesh->status(*f_it).change_bit(HANDLEAREA, h);
133  }
134 }
135 
136 //***********************************************************************************
137 
146 template<class MeshT>
147 void MeshObjectSelectionPlugin::toggleMeshSelection(int _objectId, MeshT* _mesh, uint _fh, ACG::Vec3d& _hit_point, PrimitiveType _primitiveType) {
148 
149  typename MeshT::FaceHandle fh = _mesh->face_handle(_fh);
150 
151  if(!fh.is_valid())
152  return;
153 
154  //Vertex Selection
155  if(_primitiveType & vertexType_) {
156 
157  typename MeshT::FaceVertexIter fv_it(*_mesh, fh);
158  typename MeshT::VertexHandle closest = *fv_it;
159  typename MeshT::Scalar shortest_distance =(_mesh->point(closest)- _hit_point).sqrnorm();
160 
161  do {
162  if((_mesh->point(*fv_it)- _hit_point).sqrnorm()<shortest_distance) {
163  shortest_distance =(_mesh->point(*fv_it)- _hit_point).sqrnorm();
164  closest = *fv_it;
165  }
166 
167  ++fv_it;
168 
169  } while( fv_it.is_valid() );
170 
171  _mesh->status(closest).set_selected(!_mesh->status(closest).selected());
172 
173  if(_mesh->status(closest).selected())
174  emit scriptInfo("selectVertices(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(closest.idx())+ "])");
175  else
176  emit scriptInfo("unselectVertices(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(closest.idx())+ "])");
177  emit updatedObject(_objectId, UPDATE_SELECTION_VERTICES);
178  }
179 
180  //Edge Selection
181  if( (_primitiveType & edgeType_) || (_primitiveType & halfedgeType_) ) {
182 
183  typename MeshT::FaceHalfedgeIter fhe_it(*_mesh, fh);
184 
185  typename MeshT::HalfedgeHandle closest(-1);
186  typename MeshT::Scalar closest_dist(-1);
187 
188  typename MeshT::Point pp =(typename MeshT::Point)_hit_point;
189 
190  for(; fhe_it.is_valid(); ++fhe_it) {
191 
192  // typename MeshT::HalfedgeHandle heh0 = _mesh->halfedge_handle(*fe_it, 0);
193  // typename MeshT::HalfedgeHandle heh1 = _mesh->halfedge_handle(*fe_it, 1);
194 
195  typename MeshT::Point lp0 = _mesh->point(_mesh->to_vertex_handle (*fhe_it));
196  typename MeshT::Point lp1 = _mesh->point(_mesh->from_vertex_handle(*fhe_it));
197 
198  double dist_new = ACG::Geometry::distPointLineSquared(pp, lp0, lp1);
199 
200  if(dist_new <closest_dist || closest_dist == -1) {
201 
202  // save closest Edge
203  closest_dist = dist_new;
204  closest = *fhe_it;
205  }
206  }
207 
208  typename MeshT::EdgeHandle closest_eh = _mesh->edge_handle(closest);
209 
210  if(_primitiveType & edgeType_) {
211 
212  _mesh->status(closest_eh).set_selected(!_mesh->status(closest_eh).selected());
213 
214  if(_mesh->status(closest_eh).selected())
215  emit scriptInfo("selectEdges(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(closest_eh.idx())+ "])");
216  else
217  emit scriptInfo("unselectEdges(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(closest_eh.idx())+ "])");
218  emit updatedObject(_objectId, UPDATE_SELECTION_EDGES);
219  } else {
220  _mesh->status(closest).set_selected(!_mesh->status(closest).selected());
221 
222  if(_mesh->status(closest).selected())
223  emit scriptInfo("selectHalfedges(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(closest.idx())+ "])");
224  else
225  emit scriptInfo("unselectHalfedges(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(closest.idx())+ "])");
226  emit updatedObject(_objectId, UPDATE_SELECTION_HALFEDGES);
227  }
228  }
229 
230  //Face Selection
231  if(_primitiveType & faceType_) {
232  _mesh->status(fh).set_selected(!_mesh->status(fh).selected());
233 
234  if(_mesh->status(fh).selected())
235  emit scriptInfo("selectFaces(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(fh.idx())+ "])");
236  else
237  emit scriptInfo("unselectFaces(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(fh.idx())+ "])");
238  emit updatedObject(_objectId, UPDATE_SELECTION_FACES);
239  }
240 }
241 
242 //***********************************************************************************
243 
254 template <class MeshT>
256  int _objectId ,
257  int _target_idx ,
258  typename MeshT::Point _hitpoint,
259  double _radius,
260  PrimitiveType _primitiveType,
261  bool _deselection) {
262 
263 
264  const float sqr_radius = _radius * _radius;
265 
266  // select or deselect primitives
267  const bool sel = !_deselection;
268 
269  // TODO:: replace with unordered set if c++11 is our standard
270  std::set< typename MeshT::FaceHandle > visited;
271 
272  typename MeshT::FaceHandle hitface = _mesh->face_handle(_target_idx);
273 
274  if(!hitface.is_valid())
275  return;
276 
277  visited.insert(hitface);
278 
279 
280  std::vector<typename MeshT::FaceHandle> face_handles;
281  face_handles.reserve(50);
282  face_handles.push_back(hitface);
283 
284 
285  // find primitives to be selected
286  while(!face_handles.empty()) {
287  typename MeshT::FaceHandle fh = face_handles.back();
288  visited.insert(fh);
289  face_handles.pop_back();
290 
291 
292  // Check how many points of the new face lie inside the sphere
293  unsigned int fVertices = 0;
294 
295  // Test the halfedges of this face:
296  std::vector<typename MeshT::EdgeHandle> edge_handles;
297 
298  for(typename MeshT::FaceHalfedgeIter fh_it(*_mesh,fh); fh_it.is_valid(); ++fh_it) {
299 
300  const typename MeshT::VertexHandle vh = _mesh->from_vertex_handle(*fh_it);
301 
302  if((_mesh->point(vh) - _hitpoint).sqrnorm() <= sqr_radius) {
303 
304  // Select one vertex here, the other vertex will be selected on one of the other halfedges
305  if(_primitiveType & vertexType_)
306  _mesh->status(vh).set_selected(sel);
307 
308 
309  if((_mesh->point(_mesh->to_vertex_handle(*fh_it))- _hitpoint).sqrnorm()<= sqr_radius)
310  edge_handles.push_back(_mesh->edge_handle(*fh_it));
311 
312  fVertices++;
313  }
314 
315  }
316 
317 
318  if( (_primitiveType & edgeType_) || (_primitiveType & halfedgeType_)) {
320 
321  for( size_t i=0; i < edge_handles.size(); i++) {
322  if (_primitiveType & halfedgeType_)
323  if(!_mesh->has_face_normals() || std::abs(_mesh->calc_dihedral_angle_fast(edge_handles[i])) >= dihedral_angle_threshold_)
324  {
325  _mesh->status( _mesh->halfedge_handle(edge_handles[i],0) ).set_selected(sel) ;
326  _mesh->status( _mesh->halfedge_handle(edge_handles[i],1) ).set_selected(sel) ;
327  }
328 
329  if (_primitiveType & edgeType_)
330  if(!_mesh->has_face_normals() || std::abs(_mesh->calc_dihedral_angle_fast(edge_handles[i])) >= dihedral_angle_threshold_)
331  _mesh->status(edge_handles[i]).set_selected(sel);
332  }
333 
334  }
335 
336  if(_primitiveType & faceType_) {
337 
338  // If all vertices of the face are inside the sphere, we can select the face as well
339  if( _mesh->valence(fh ) == fVertices) {
340  _mesh->status(fh).set_selected(sel);
341  }
342  }
343 
344  //if something was tagged also check the 1-ring
345  if( fVertices > 0) {
346 
347  // _mesh->property(checkedProp, *ff_it)= true;
348  for(typename MeshT::FaceFaceIter ff_it(*_mesh,fh); ff_it.is_valid(); ++ff_it) {
349  if ( visited.count(*ff_it) == 0 )
350  face_handles.push_back(*ff_it);
351  }
352 
353  }
354 
355  }
356 
357  // Collect all updates into one update call
358  UpdateType update(UPDATE_NONE);
359 
360  if(_primitiveType & vertexType_)
361  update |= UPDATE_SELECTION_VERTICES;
362 
363 
364  if(_primitiveType & edgeType_)
365  update |= UPDATE_SELECTION_EDGES;
366 
367  if(_primitiveType & halfedgeType_)
368  update |= UPDATE_SELECTION_HALFEDGES;
369 
370  if(_primitiveType & faceType_)
371  update |= UPDATE_SELECTION_FACES;
372 
373  // Run the update
374  emit updatedObject(_objectId, update);
375 
376 }
377 
378 //***********************************************************************************
379 
390 template<class MeshT>
391 bool MeshObjectSelectionPlugin::volumeSelection(MeshT* _mesh, int _objectId, ACG::GLState& _state, QRegion *_region,
392  PrimitiveType _primitiveType, bool _deselection) {
393  ACG::Vec3d proj;
394  bool rv = false;
395 
396  //reset tagged status
397  typename MeshT::VertexIter v_it, v_end(_mesh->vertices_end());
398  for(v_it=_mesh->vertices_begin(); v_it!=v_end; ++v_it)
399  _mesh->status(*v_it).set_tagged(false);
400 
401  //tag all vertices that are projected into region
402  for(v_it=_mesh->vertices_begin(); v_it!=v_end; ++v_it) {
403 
404  proj = _state.project(_mesh->point(*v_it));
405 
406  if(_region->contains(QPoint((int)proj[0], _state.context_height()- (int)proj[1]))) {
407 
408  _mesh->status(*v_it).set_tagged(true);
409  rv = true;
410  if(_primitiveType & vertexType_) {
411  _mesh->status(*v_it).set_selected(!_deselection);
412  }
413  }
414  }
415 
416  if( (_primitiveType & edgeType_) || (_primitiveType & halfedgeType_) ) {
418  typename MeshT::EdgeIter e_it, e_end(_mesh->edges_end());
419  for(e_it=_mesh->edges_begin(); e_it!=e_end; ++e_it) {
420 
421  if(_mesh->status(_mesh->to_vertex_handle(_mesh->halfedge_handle(*e_it, 0))).tagged()||
422  _mesh->status(_mesh->to_vertex_handle(_mesh->halfedge_handle(*e_it, 1))).tagged()) {
423 
424  if(_primitiveType & edgeType_)
425  if(!_mesh->has_face_normals() || std::abs(_mesh->calc_dihedral_angle_fast(*e_it)) >= dihedral_angle_threshold_)
426  _mesh->status(*e_it).set_selected(!_deselection);
427 
428  if(_primitiveType & halfedgeType_)
429  if(!_mesh->has_face_normals() || std::abs(_mesh->calc_dihedral_angle_fast(*e_it)) >= dihedral_angle_threshold_)
430  {
431  _mesh->status(_mesh->halfedge_handle(*e_it,0)).set_selected(!_deselection);
432  _mesh->status(_mesh->halfedge_handle(*e_it,1)).set_selected(!_deselection);
433  }
434  }
435  }
436  }
437 
438  if(_primitiveType & faceType_) {
439  typename MeshT::FaceIter f_it, f_end(_mesh->faces_end());
440  for(f_it=_mesh->faces_begin(); f_it!=f_end; ++f_it) {
441 
442  bool select = false;
443  for(typename MeshT::FaceVertexIter fv_it(*_mesh,*f_it); fv_it.is_valid(); ++fv_it)
444  if(_mesh->status(*fv_it).tagged())
445  select = true;
446 
447  if(select)
448  _mesh->status(*f_it).set_selected(!_deselection);
449  }
450  }
451 
452  if(_primitiveType & vertexType_)
453  emit updatedObject(_objectId, UPDATE_SELECTION_VERTICES);
454  if(_primitiveType & edgeType_)
455  emit updatedObject(_objectId, UPDATE_SELECTION_EDGES);
456  if(_primitiveType & halfedgeType_)
457  emit updatedObject(_objectId, UPDATE_SELECTION_HALFEDGES);
458  if(_primitiveType & faceType_)
459  emit updatedObject(_objectId, UPDATE_SELECTION_FACES);
460 
461  return rv;
462 }
463 
464 //***********************************************************************************
465 
473 template<class MeshT>
474 void MeshObjectSelectionPlugin::closestBoundarySelection(MeshT* _mesh, int _vh, PrimitiveType _primitiveTypes, bool _deselection) {
475 
476  typename MeshT::VertexHandle vh = _mesh->vertex_handle(_vh);
477 
478  if(vh.is_valid()) {
479  //get boundary vertex
480  typename MeshT::VertexHandle vhBound = MeshNavigation::findClosestBoundary(_mesh , vh);
481  if(vhBound.is_valid()) {
482 
483  //walk around the boundary and select primitves
485  if(!_mesh->get_property_handle(visited,"Visited Vertices"))
486  _mesh->add_property(visited, "Visited Vertices");
487 
488  typename MeshT::VertexIter v_it, v_end = _mesh->vertices_end();
489  for(v_it = _mesh->vertices_begin(); v_it != v_end; ++v_it)
490  _mesh->property(visited, *v_it)= false;
491 
492  std::stack<typename MeshT::VertexHandle> stack;
493  stack.push(vhBound);
494 
495  while(!stack.empty()) {
496 
497  typename MeshT::VertexHandle vh = stack.top();
498  stack.pop();
499 
500  if(_mesh->property(visited,vh))
501  continue;
502 
503  //find outgoing boundary-edges
504  for(typename MeshT::VertexOHalfedgeIter voh_it(*_mesh,vh); voh_it.is_valid(); ++voh_it) {
505 
506  if(_mesh->is_boundary(_mesh->edge_handle(*voh_it))) {
507 
508  stack.push(_mesh->to_vertex_handle(*voh_it));
509 
510  if(_primitiveTypes & edgeType_)
511  _mesh->status(_mesh->edge_handle(*voh_it)).set_selected(!_deselection);
512 
513  if(_primitiveTypes & halfedgeType_) {
514  typename MeshT::HalfedgeHandle heh = *voh_it;
515  if(!_mesh->is_boundary(heh))heh = _mesh->opposite_halfedge_handle(heh);
516  _mesh->status(heh).set_selected(!_deselection);
517  }
518  }
519 
520  if(_primitiveTypes & faceType_) {
521  typename MeshT::FaceHandle f1 = _mesh->face_handle(*voh_it);
522  typename MeshT::FaceHandle f2 = _mesh->face_handle(_mesh->opposite_halfedge_handle(*voh_it));
523  if(f1.is_valid())_mesh->status(f1).set_selected(!_deselection);
524  if(f2.is_valid())_mesh->status(f2).set_selected(!_deselection);
525  }
526  }
527 
528  _mesh->property(visited,vh)= true;
529 
530  if(_primitiveTypes & vertexType_)
531  _mesh->status(vh).set_selected(!_deselection);
532  }
533  _mesh->remove_property(visited);
534 
535 
536  } else {
537  emit log(LOGERR, tr("Unable to find boundary."));
538  }
539  } else {
540  emit log(LOGERR, tr("Invalid vertex handle."));
541  }
542 }
543 
544 //***********************************************************************************
545 
555 template<class MeshT>
557  MeshT* _mesh, int _objectId, uint _fh, double _maxAngle,
558  PrimitiveType _primitiveTypes, bool _deselection) {
559 
560  // reset tagged status
561  for ( auto face : _mesh->faces() )
562  _mesh->status(face).set_tagged(false);
563 
564  std::vector<typename MeshT::FaceHandle> face_handles;
565 
566 
567  typename MeshT::FaceHandle hitFace = typename MeshT::FaceHandle(_fh);
568  face_handles.reserve(50);
569  face_handles.push_back(hitFace);
570  _mesh->status(hitFace).set_tagged(true);
571 
572  typename MeshT::Point n1 = _mesh->normal(hitFace);
573 
574  double maxAngle = OpenMesh::deg_to_rad(_maxAngle);
575 
576  while (!face_handles.empty()) {
577  typename MeshT::FaceHandle fh = face_handles.back();
578  face_handles.pop_back();
579 
580  for (auto ff_it : _mesh->ff_range(fh)) {
581 
582  // Check if already tagged
583  if (_mesh->status(ff_it).tagged())
584  continue;
585 
586  typename MeshT::Point n2 = _mesh->normal(ff_it);
587 
588  double angle = acos(n1 | n2);
589 
590  if (angle <= maxAngle) {
591  _mesh->status(ff_it).set_tagged(true);
592  face_handles.push_back(ff_it);
593  }
594  }
595  }
596 
597  // now select all tagged primitives
598  for ( auto face : _mesh->faces() ) {
599  if (_mesh->status(face).tagged()) {
600 
601  if(_primitiveTypes & vertexType_) {
602  for (typename MeshT::FaceVertexIter fv_it(*_mesh,face) ; fv_it.is_valid(); ++fv_it)
603  _mesh->status(*fv_it).set_selected(!_deselection);
604  }
605 
606  if(_primitiveTypes & edgeType_) {
607  for (typename MeshT::FaceEdgeIter fe_it(*_mesh,face) ; fe_it.is_valid(); ++fe_it)
608  _mesh->status(*fe_it).set_selected(!_deselection);
609  }
610 
611  if(_primitiveTypes & halfedgeType_) {
612  for (typename MeshT::FaceHalfedgeIter fhe_it(*_mesh,face) ; fhe_it.is_valid(); ++fhe_it)
613  _mesh->status(*fhe_it).set_selected(!_deselection);
614  }
615 
616  if(_primitiveTypes & faceType_) {
617  _mesh->status(face).set_selected(!_deselection);
618  }
619  }
620  }
621 
622 
623  if(_primitiveTypes & vertexType_)
624  emit updatedObject(_objectId, UPDATE_SELECTION_VERTICES);
625  if(_primitiveTypes & edgeType_)
626  emit updatedObject(_objectId, UPDATE_SELECTION_EDGES);
627  if(_primitiveTypes & halfedgeType_)
628  emit updatedObject(_objectId, UPDATE_SELECTION_HALFEDGES);
629  if(_primitiveTypes & faceType_)
630  emit updatedObject(_objectId, UPDATE_SELECTION_FACES);
631 }
632 
633 //***********************************************************************************
634 
643 template<class MeshT>
645  MeshT* _mesh, int _objectId, uint _fh, ACG::Vec3d& _hit_point,
646  PrimitiveType _primitiveType) {
647 
648  typename MeshT::FaceHandle fh = _mesh->face_handle(_fh);
649 
650  if(!fh.is_valid())
651  return;
652 
653  //Vertex Selection
654  if(_primitiveType & vertexType_) {
655 
657  _mesh->add_property(visited);
658 
659  typename MeshT::VertexIter v_it;
660  typename MeshT::VertexIter v_end = _mesh->vertices_end();
661 
662  // Initialize vertex tag
663  for (v_it = _mesh->vertices_begin(); v_it != v_end; ++v_it)
664  _mesh->property(visited, *v_it) = false;
665 
666  // Get some vertex incident to the clicked face
667  typename MeshT::VertexHandle current = *(_mesh->fv_iter(fh));
668  if(!current.is_valid())
669  return;
670 
671  std::set<typename MeshT::VertexHandle> unprocessed;
672  unprocessed.insert(current);
673 
674  while( !unprocessed.empty() ) {
675 
676  // Select current vertex
677  current = *unprocessed.begin();
678  _mesh->status(current).set_selected(!(_mesh->status(current)).selected());
679  _mesh->property(visited, current) = true;
680  unprocessed.erase(current);
681 
682  // Go over all neighbors
683  for(typename MeshT::VertexVertexIter vv_it = _mesh->vv_iter(current); vv_it.is_valid(); ++vv_it) {
684  if(_mesh->property(visited, *vv_it) == true) continue;
685  unprocessed.insert(*vv_it);
686  }
687 
688  }
689 
690  _mesh->remove_property(visited);
691  }
692 
693  //Edge Selection
694  if( (_primitiveType & edgeType_) || (_primitiveType & halfedgeType_ ) ) {
695 
697  _mesh->add_property(visited);
698 
699  typename MeshT::FaceIter f_it;
700  typename MeshT::FaceIter f_end = _mesh->faces_end();
701 
702  // Initialize face tag
703  for (f_it = _mesh->faces_begin(); f_it != f_end; ++f_it)
704  _mesh->property(visited, *f_it) = false;
705 
706 
707  typename MeshT::FaceHandle current = fh;
708 
709  std::set<typename MeshT::FaceHandle> unprocessed;
710  unprocessed.insert(current);
711 
712  typename MeshT::EdgeHandle firstEdge = *(_mesh->fe_iter(fh));
713  if(!firstEdge.is_valid()) return;
714  bool selected = _mesh->status(firstEdge).selected();
715 
716  while( !unprocessed.empty() ) {
717 
718  // Select all edges incident to current face
719  current = *unprocessed.begin();
720  for(typename MeshT::FaceHalfedgeIter fh_it = _mesh->fh_iter(current); fh_it.is_valid(); ++fh_it) {
721  if(_primitiveType & halfedgeType_) {
722  _mesh->status(*fh_it).set_selected(!(_mesh->status(*fh_it)).selected());
723  }
724  if(_primitiveType & edgeType_) {
725  _mesh->status(_mesh->edge_handle(*fh_it)).set_selected(!selected);
726  }
727  }
728 
729  _mesh->property(visited, current) = true;
730  unprocessed.erase(current);
731 
732  // Go over all neighbors
733  for(typename MeshT::FaceFaceIter ff_it = _mesh->ff_iter(current); ff_it.is_valid(); ++ff_it) {
734  if(_mesh->property(visited, *ff_it) == true) continue;
735  unprocessed.insert(*ff_it);
736  }
737 
738  }
739 
740  _mesh->remove_property(visited);
741  }
742 
743  //Face Selection
744  if(_primitiveType & faceType_) {
745 
747  _mesh->add_property(visited);
748 
749  typename MeshT::FaceIter f_it;
750  typename MeshT::FaceIter f_end = _mesh->faces_end();
751 
752  // Initialize face tag
753  for (f_it = _mesh->faces_begin(); f_it != f_end; ++f_it)
754  _mesh->property(visited, *f_it) = false;
755 
756 
757  typename MeshT::FaceHandle current = fh;
758 
759  std::set<typename MeshT::FaceHandle> unprocessed;
760  unprocessed.insert(current);
761 
762  while( !unprocessed.empty() ) {
763 
764  // Select all edges incident to current face
765  current = *unprocessed.begin();
766  _mesh->status(current).set_selected(!(_mesh->status(current)).selected());
767  _mesh->property(visited, current) = true;
768  unprocessed.erase(current);
769 
770  // Go over all neighbors
771  for(typename MeshT::FaceFaceIter ff_it = _mesh->ff_iter(current); ff_it.is_valid(); ++ff_it) {
772  if(_mesh->property(visited, *ff_it) == true) continue;
773  unprocessed.insert(*ff_it);
774  }
775 
776  }
777 
778  _mesh->remove_property(visited);
779  }
780  if(_primitiveType & vertexType_)
781  emit updatedObject(_objectId, UPDATE_SELECTION_VERTICES);
782  if(_primitiveType & edgeType_)
783  emit updatedObject(_objectId, UPDATE_SELECTION_EDGES);
784  if(_primitiveType & halfedgeType_)
785  emit updatedObject(_objectId, UPDATE_SELECTION_HALFEDGES);
786  if(_primitiveType & faceType_)
787  emit updatedObject(_objectId, UPDATE_SELECTION_FACES);
788 }
789 
790 //***********************************************************************************
791 
801 template< typename MeshT >
803  PrimitiveType _primitiveTypes,
804  int _red,
805  int _green,
806  int _blue,
807  int _alpha) {
808 
809  typename MeshT::Color color = OpenMesh::color_cast<OpenMesh::Vec4f,OpenMesh::Vec4uc>(OpenMesh::Vec4uc(_red,_green,_blue,_alpha));
810  /*color[0] = _red;
811  color[1] = _green;
812  color[2] = _blue;
813  color[3] = _alpha;
814  */
815 
816  if (_primitiveTypes & vertexType_) {
817  typename MeshT::VertexIter v_it, v_end=_mesh->vertices_end();
818 
819  // Request vertex color attribute
820  if ( !_mesh->has_vertex_colors() )
821  _mesh->request_vertex_colors();
822 
823  for (v_it=_mesh->vertices_begin(); v_it!=v_end; ++v_it)
824  if ( _mesh->status(*v_it).selected() )
825  _mesh->set_color(*v_it, color);
826  }
827 
828  if (_primitiveTypes & faceType_) {
829  typename MeshT::FaceIter f_it, f_end( _mesh->faces_end() );
830 
831  // Request face color attribute
832  if ( !_mesh->has_face_colors() )
833  _mesh->request_face_colors();
834 
835  for (f_it=_mesh->faces_begin(); f_it!=f_end; ++f_it)
836  if ( _mesh->status(*f_it).selected() )
837  _mesh->set_color(*f_it, color);
838  }
839 
840  if (_primitiveTypes & edgeType_) {
841  typename MeshT::EdgeIter e_it, e_end( _mesh->edges_end() );
842 
843  // Request edge color attribute
844  if ( !_mesh->has_edge_colors() )
845  _mesh->request_edge_colors();
846 
847  for (e_it=_mesh->edges_begin(); e_it!=e_end; ++e_it)
848  if ( _mesh->status(*e_it).selected() )
849  _mesh->set_color(*e_it, color);
850  }
851 
852  if (_primitiveTypes & halfedgeType_) {
853  typename MeshT::HalfedgeIter h_it, h_end( _mesh->halfedges_end() );
854 
855  // Request halfedge color attribute
856  if ( !_mesh->has_halfedge_colors() )
857  _mesh->request_halfedge_colors();
858 
859  for (h_it=_mesh->halfedges_begin(); h_it!=h_end; ++h_it)
860  if ( _mesh->status(*h_it).selected() )
861  _mesh->set_color(*h_it, color);
862  }
863 }
864 
865 //***********************************************************************************
866 
867 
875 template<class MeshT>
876 void MeshObjectSelectionPlugin::createMeshFromSelection(MeshT& _mesh, MeshT& _newMesh, PrimitiveType _primitiveType)
877 {
878 
879  // Tracking during copy action
881  _mesh.add_property(copyHandle, "copyHandle Property");
882 
883  //first copy vertices
884  typename MeshT::VertexIter v_it, v_end = _mesh.vertices_end();
885  for (v_it = _mesh.vertices_begin(); v_it != v_end; ++v_it) {
886 
887  bool copy = false;
888 
889  //if the vertex belongs to the selection copy it
890  if (_primitiveType & vertexType_)
891  copy = _mesh.status(*v_it).selected();
892  else if (_primitiveType & edgeType_) {
893 
894  for (typename MeshT::VertexOHalfedgeIter voh_it(_mesh, *v_it); voh_it.is_valid(); ++voh_it)
895  if (_mesh.status(_mesh.edge_handle(*voh_it)).selected()) {
896  copy = true;
897  break;
898  }
899 
900  } else if (_primitiveType & faceType_) {
901  for (typename MeshT::VertexFaceIter vf_it(_mesh, *v_it); vf_it.is_valid(); ++vf_it)
902  if (_mesh.status(*vf_it).selected()) {
903  copy = true;
904  break;
905  }
906  }
907 
908  //copy it
909  if (copy) {
910  _mesh.property(copyHandle, *v_it) = _newMesh.add_vertex(_mesh.point(*v_it));
911  } else {
912  _mesh.property(copyHandle, *v_it) = typename MeshT::VertexHandle(-1);
913  }
914  }
915 
916  //now check all faces
917  //if all vertices of the face exist in the new mesh -> copy it
918  typename MeshT::FaceIter f_it, f_end = _mesh.faces_end();
919  for (f_it = _mesh.faces_begin(); f_it != f_end; ++f_it) {
920 
921  std::vector<typename MeshT::VertexHandle> v;
922 
923  bool skip = false;
924 
925  for (typename MeshT::FaceVertexIter fv_it(_mesh, *f_it); fv_it.is_valid(); ++fv_it)
926  if (_mesh.property(copyHandle, *fv_it).is_valid())
927  v.push_back(_mesh.property(copyHandle, *fv_it));
928  else {
929  skip = true;
930  break;
931  }
932 
933  if (!skip)
934  _newMesh.add_face(v);
935  }
936 
937  _newMesh.update_normals();
938 
939  _mesh.remove_property(copyHandle);
940 
941 }
942 
943 template<class MeshT>
944 void MeshObjectSelectionPlugin::selectVerticesByValue(MeshT* _mesh, QString _component, bool _greater, double _value)
945 {
946 
947  //first copy vertices
948  typename MeshT::VertexIter v_it, v_end = _mesh->vertices_end();
949  for (v_it = _mesh->vertices_begin(); v_it != v_end; ++v_it) {
950  const typename MeshT::Point p = _mesh->point(*v_it);
951 
952  bool select = false;
953 
954  if (_component.contains("x",Qt::CaseInsensitive) ) {
955  select = (p[0] > _value);
956  } else if (_component.contains("y",Qt::CaseInsensitive) ) {
957  select = (p[1] > _value);
958  } else if (_component.contains("z",Qt::CaseInsensitive) ) {
959  select = (p[2] > _value);
960  } else {
961  emit log(LOGERR,tr("selectVerticesByValue, undefined component ") + _component );
962  }
963 
964 
965  // invert if requested
966  if (! _greater )
967  select = !select;
968 
969  // set selection status only if the vertex was previously unselected
970  if ( ! _mesh->status(*v_it).selected() )
971  _mesh->status(*v_it).set_selected(select);
972 
973  }
974 
975 }
976 
977 template <typename HandleT>
978 bool MeshObjectSelectionPlugin::selectElement(int _objectId, HandleT _handle, bool _fly_to_element)
979 {
980  if (!_handle.is_valid())
981  return false;
982 
983  BaseObjectData* object = nullptr;
984  if (!PluginFunctions::getObject(_objectId,object)) {
985  emit log(LOGERR,tr("selectElement: unable to get object"));
986  return false;
987  }
988 
989  IdList elementList;
990  elementList.push_back(_handle.idx());
991 
992  OpenMesh::Vec3d center;
993  OpenMesh::Vec3d normal;
994  bool handle_valid = false;
995 
996  if (object->dataType() == DATA_TRIANGLE_MESH){
997  MeshSelection::selectElements(PluginFunctions::triMesh(object), elementList, HandleT());
998  getFlightData(*PluginFunctions::triMeshObject(object), _handle, center, normal, handle_valid);
999  } else if (object->dataType() == DATA_POLY_MESH) {
1000  MeshSelection::selectElements(PluginFunctions::polyMesh(object), elementList, HandleT());
1001  getFlightData(*PluginFunctions::polyMeshObject(object), _handle, center, normal, handle_valid);
1002  } else {
1003  emit log(LOGERR,tr("selectElement: Unsupported object Type"));
1004  return false;
1005  }
1006 
1007  if (handle_valid && _fly_to_element)
1008  PluginFunctions::flyTo(center + normal , center, 500.0);
1009 
1010  return handle_valid;
1011 }
1012 
1013 template <typename MeshObjectT, typename HandleT>
1014 void MeshObjectSelectionPlugin::getFlightData(MeshObjectT& _mesh_object, HandleT _handle,
1015  OpenMesh::Vec3d& center, OpenMesh::Vec3d& normal, bool& handle_valid)
1016 {
1017  OpenMesh::Vec3d bbMin;
1018  OpenMesh::Vec3d bbMax;
1019  _mesh_object.boundingBox(bbMin, bbMax);
1020 
1021  auto& mesh = *_mesh_object.mesh();
1022 
1023  if (_handle.is_valid() && static_cast<size_t>(_handle.idx()) < mesh.template n_elements<HandleT>())
1024  {
1025  center = mesh.calc_centroid(_handle);
1026  normal = 0.5 * (bbMax-bbMin).length() * mesh.calc_normal(_handle);
1027  handle_valid = true;
1028  }
1029  else
1030  {
1031  handle_valid = false;
1032  }
1033 }
1034 
Vec::value_type distPointLineSquared(const Vec &_p, const Vec &_v0, const Vec &_v1, Vec *_min_v)
squared distance from point _p to line segment (_v0,_v1)
Definition: Algorithms.cc:290
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
#define DATA_POLY_MESH
Definition: PolyMesh.hh:59
void selectVerticesByValue(int _objectId, QString _component, bool _greater, double _value)
Select vertices by their value.
Functions for getting information about a mesh.
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
double dihedral_angle_threshold_
Handle to selection environment.
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:640
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
bool deleteSelection(MeshT *_mesh, PrimitiveType _primitiveType)
Delete all selected elements of a mesh.
SelectionInterface::PrimitiveType faceType_
Handle to selection environment.
bool dataType(DataType _type) const
Definition: BaseObject.cc:221
std::vector< int > IdList
Standard Type for id Lists used for scripting.
Definition: DataTypes.hh:181
SelectionInterface::PrimitiveType vertexType_
Primitive type handles:
Add colors to mesh item (vertices/faces/edges)
Definition: Attributes.hh:83
void getFlightData(MeshObjectT &_mesh_object, HandleT _handle, OpenMesh::Vec3d &center, OpenMesh::Vec3d &normal, bool &handle_valid)
set dihedral angle threshold for edge selection
const UpdateType UPDATE_SELECTION_HALFEDGES(UpdateTypeSet(128))
Halfedge selection has changed.
void update_dihedral_angle_threshold_from_ui()
set dihedral angle threshold for edge selection
VectorT< unsigned char, 4 > Vec4uc
Definition: Vector11T.hh:859
PolyMeshObject * polyMeshObject(BaseObjectData *_object)
Cast an BaseObject to a PolyMeshObject if possible.
Functions for selection on a mesh.
TriMeshObject * triMeshObject(BaseObjectData *_object)
Cast an BaseObject to a TriMeshObject if possible.
Update type class.
Definition: UpdateType.hh:59
SelectionInterface::PrimitiveType edgeType_
Handle to selection environment.
void createMeshFromSelection(MeshT &_mesh, MeshT &_newMesh, PrimitiveType _primitiveType)
Create a new mesh from the selection.
void colorizeSelection(MeshT *_mesh, PrimitiveType _primitiveTypes, int _red, int _green, int _blue, int _alpha)
Colorize the selection.
void componentsMeshSelection(MeshT *_mesh, int _objectId, uint _fh, ACG::Vec3d &_hit_point, PrimitiveType _primitiveType)
Connected component mesh selection.
bool selectElement(int _objectId, HandleT _handle, bool _fly_to_element)
set dihedral angle threshold for edge selection
SelectionInterface::PrimitiveType halfedgeType_
Handle to selection environment.
VectorT< float, 4 > Vec4f
Definition: Vector11T.hh:869
const UpdateType UPDATE_SELECTION_EDGES(UpdateTypeSet(64))
Edge selection has changed.
void closestBoundarySelection(MeshT *_mesh, int _vh, PrimitiveType _primitiveTypes, bool _deselection)
Select all entities that are incident to closest boundary.
Point calc_centroid(FaceHandle _fh) const
Computes and returns the average of the vertices defining _fh (same as calc_face_centroid) ...
void paintSphereSelection(MeshT *_mesh, int _objectId, int _target_idx, typename MeshT::Point _hitpoint, double _radius, PrimitiveType _primitiveTypes, bool _deselection)
Use the event to paint selection with a sphere.
const UpdateType UPDATE_SELECTION_FACES(UpdateTypeSet(256))
Face selection has changed.
bool volumeSelection(MeshT *_mesh, int _objectId, ACG::GLState &_state, QRegion *_region, PrimitiveType _primitiveTypes, bool _deselection)
Surface volume selection tool.
int context_height() const
get gl context height
Definition: GLState.hh:855
void toggleMeshSelection(int _objectId, MeshT *_mesh, uint _fh, ACG::Vec3d &_hit_point, PrimitiveType _primitiveType)
Toggle mesh selection.
const UpdateType UPDATE_NONE(UpdateTypeSet(0))
Empty update for empty initialization of update type.
void update_regions(MeshT *_mesh)
Update face selection to correspond to the vertex selection.
void floodFillSelection(MeshT *_mesh, int _objectId, uint _fh, double _maxAngle, PrimitiveType _primitiveTypes, bool _deselection)
Select all entities that are connected (and do not exceed the maximum dihedral angle) ...
Normal calc_normal(FaceHandle _fh) const
same as calc_face_normal
const UpdateType UPDATE_SELECTION_VERTICES(UpdateTypeSet(32))
Vertex selection has changed.
void flyTo(const ACG::Vec3d &_position, const ACG::Vec3d &_center, double _time)
Fly to point and viewing direction (animated).