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  typename MeshT::FaceIter f_it, f_end(_mesh->faces_end());
562  for (f_it=_mesh->faces_begin(); f_it!=f_end; ++f_it)
563  _mesh->status(*f_it).set_tagged(false);
564 
565  std::vector<typename MeshT::FaceHandle> face_handles;
566 
567 
568  typename MeshT::FaceHandle hitFace = typename MeshT::FaceHandle(_fh);
569  face_handles.reserve(50);
570  face_handles.push_back(hitFace);
571  _mesh->status(hitFace).set_tagged(true);
572 
573  typename MeshT::Point n1 = _mesh->normal(hitFace);
574 
575  double maxAngle = OpenMesh::deg_to_rad(_maxAngle);
576 
577  while (!face_handles.empty()) {
578  typename MeshT::FaceHandle fh = face_handles.back();
579  face_handles.pop_back();
580 
581  for (typename MeshT::FaceFaceIter ff_it(*_mesh,fh) ; ff_it.is_valid() ; ++ff_it) {
582 
583  // Check if already tagged
584  if (_mesh->status(*ff_it).tagged())
585  continue;
586 
587  typename MeshT::Point n2 = _mesh->normal(*ff_it);
588 
589  double angle = acos(n1 | n2);
590 
591  if (angle <= maxAngle) {
592  _mesh->status(*ff_it).set_tagged(true);
593  face_handles.push_back(*ff_it);
594  }
595  }
596  }
597 
598  // now select all tagged primitives
599  for (f_it=_mesh->faces_begin(); f_it!=f_end; ++f_it) {
600  if (_mesh->status(*f_it).tagged()) {
601 
602  if(_primitiveTypes & vertexType_) {
603  for (typename MeshT::FaceVertexIter fv_it(*_mesh,*f_it) ; fv_it.is_valid(); ++fv_it)
604  _mesh->status(*fv_it).set_selected(!_deselection);
605  }
606 
607  if(_primitiveTypes & edgeType_) {
608  for (typename MeshT::FaceEdgeIter fe_it(*_mesh,*f_it) ; fe_it.is_valid(); ++fe_it)
609  _mesh->status(*fe_it).set_selected(!_deselection);
610  }
611 
612  if(_primitiveTypes & halfedgeType_) {
613  for (typename MeshT::FaceHalfedgeIter fhe_it(*_mesh,*f_it) ; fhe_it.is_valid(); ++fhe_it)
614  _mesh->status(*fhe_it).set_selected(!_deselection);
615  }
616 
617  if(_primitiveTypes & faceType_) {
618  _mesh->status(*f_it).set_selected(!_deselection);
619  }
620  }
621  }
622 
623 
624  if(_primitiveTypes & vertexType_)
625  emit updatedObject(_objectId, UPDATE_SELECTION_VERTICES);
626  if(_primitiveTypes & edgeType_)
627  emit updatedObject(_objectId, UPDATE_SELECTION_EDGES);
628  if(_primitiveTypes & halfedgeType_)
629  emit updatedObject(_objectId, UPDATE_SELECTION_HALFEDGES);
630  if(_primitiveTypes & faceType_)
631  emit updatedObject(_objectId, UPDATE_SELECTION_FACES);
632 }
633 
634 //***********************************************************************************
635 
644 template<class MeshT>
646  MeshT* _mesh, int _objectId, uint _fh, ACG::Vec3d& _hit_point,
647  PrimitiveType _primitiveType) {
648 
649  typename MeshT::FaceHandle fh = _mesh->face_handle(_fh);
650 
651  if(!fh.is_valid())
652  return;
653 
654  //Vertex Selection
655  if(_primitiveType & vertexType_) {
656 
658  _mesh->add_property(visited);
659 
660  typename MeshT::VertexIter v_it;
661  typename MeshT::VertexIter v_end = _mesh->vertices_end();
662 
663  // Initialize vertex tag
664  for (v_it = _mesh->vertices_begin(); v_it != v_end; ++v_it)
665  _mesh->property(visited, *v_it) = false;
666 
667  // Get some vertex incident to the clicked face
668  typename MeshT::VertexHandle current = *(_mesh->fv_iter(fh));
669  if(!current.is_valid())
670  return;
671 
672  std::set<typename MeshT::VertexHandle> unprocessed;
673  unprocessed.insert(current);
674 
675  while( !unprocessed.empty() ) {
676 
677  // Select current vertex
678  current = *unprocessed.begin();
679  _mesh->status(current).set_selected(!(_mesh->status(current)).selected());
680  _mesh->property(visited, current) = true;
681  unprocessed.erase(current);
682 
683  // Go over all neighbors
684  for(typename MeshT::VertexVertexIter vv_it = _mesh->vv_iter(current); vv_it.is_valid(); ++vv_it) {
685  if(_mesh->property(visited, *vv_it) == true) continue;
686  unprocessed.insert(*vv_it);
687  }
688 
689  }
690 
691  _mesh->remove_property(visited);
692  }
693 
694  //Edge Selection
695  if( (_primitiveType & edgeType_) || (_primitiveType & halfedgeType_ ) ) {
696 
698  _mesh->add_property(visited);
699 
700  typename MeshT::FaceIter f_it;
701  typename MeshT::FaceIter f_end = _mesh->faces_end();
702 
703  // Initialize face tag
704  for (f_it = _mesh->faces_begin(); f_it != f_end; ++f_it)
705  _mesh->property(visited, *f_it) = false;
706 
707 
708  typename MeshT::FaceHandle current = fh;
709 
710  std::set<typename MeshT::FaceHandle> unprocessed;
711  unprocessed.insert(current);
712 
713  typename MeshT::EdgeHandle firstEdge = *(_mesh->fe_iter(fh));
714  if(!firstEdge.is_valid()) return;
715  bool selected = _mesh->status(firstEdge).selected();
716 
717  while( !unprocessed.empty() ) {
718 
719  // Select all edges incident to current face
720  current = *unprocessed.begin();
721  for(typename MeshT::FaceHalfedgeIter fh_it = _mesh->fh_iter(current); fh_it.is_valid(); ++fh_it) {
722  if(_primitiveType & halfedgeType_) {
723  _mesh->status(*fh_it).set_selected(!(_mesh->status(*fh_it)).selected());
724  }
725  if(_primitiveType & edgeType_) {
726  _mesh->status(_mesh->edge_handle(*fh_it)).set_selected(!selected);
727  }
728  }
729 
730  _mesh->property(visited, current) = true;
731  unprocessed.erase(current);
732 
733  // Go over all neighbors
734  for(typename MeshT::FaceFaceIter ff_it = _mesh->ff_iter(current); ff_it.is_valid(); ++ff_it) {
735  if(_mesh->property(visited, *ff_it) == true) continue;
736  unprocessed.insert(*ff_it);
737  }
738 
739  }
740 
741  _mesh->remove_property(visited);
742  }
743 
744  //Face Selection
745  if(_primitiveType & faceType_) {
746 
748  _mesh->add_property(visited);
749 
750  typename MeshT::FaceIter f_it;
751  typename MeshT::FaceIter f_end = _mesh->faces_end();
752 
753  // Initialize face tag
754  for (f_it = _mesh->faces_begin(); f_it != f_end; ++f_it)
755  _mesh->property(visited, *f_it) = false;
756 
757 
758  typename MeshT::FaceHandle current = fh;
759 
760  std::set<typename MeshT::FaceHandle> unprocessed;
761  unprocessed.insert(current);
762 
763  while( !unprocessed.empty() ) {
764 
765  // Select all edges incident to current face
766  current = *unprocessed.begin();
767  _mesh->status(current).set_selected(!(_mesh->status(current)).selected());
768  _mesh->property(visited, current) = true;
769  unprocessed.erase(current);
770 
771  // Go over all neighbors
772  for(typename MeshT::FaceFaceIter ff_it = _mesh->ff_iter(current); ff_it.is_valid(); ++ff_it) {
773  if(_mesh->property(visited, *ff_it) == true) continue;
774  unprocessed.insert(*ff_it);
775  }
776 
777  }
778 
779  _mesh->remove_property(visited);
780  }
781  if(_primitiveType & vertexType_)
782  emit updatedObject(_objectId, UPDATE_SELECTION_VERTICES);
783  if(_primitiveType & edgeType_)
784  emit updatedObject(_objectId, UPDATE_SELECTION_EDGES);
785  if(_primitiveType & halfedgeType_)
786  emit updatedObject(_objectId, UPDATE_SELECTION_HALFEDGES);
787  if(_primitiveType & faceType_)
788  emit updatedObject(_objectId, UPDATE_SELECTION_FACES);
789 }
790 
791 //***********************************************************************************
792 
802 template< typename MeshT >
804  PrimitiveType _primitiveTypes,
805  int _red,
806  int _green,
807  int _blue,
808  int _alpha) {
809 
810  typename MeshT::Color color = OpenMesh::color_cast<OpenMesh::Vec4f,OpenMesh::Vec4uc>(OpenMesh::Vec4uc(_red,_green,_blue,_alpha));
811  /*color[0] = _red;
812  color[1] = _green;
813  color[2] = _blue;
814  color[3] = _alpha;
815  */
816 
817  if (_primitiveTypes & vertexType_) {
818  typename MeshT::VertexIter v_it, v_end=_mesh->vertices_end();
819 
820  // Request vertex color attribute
821  if ( !_mesh->has_vertex_colors() )
822  _mesh->request_vertex_colors();
823 
824  for (v_it=_mesh->vertices_begin(); v_it!=v_end; ++v_it)
825  if ( _mesh->status(*v_it).selected() )
826  _mesh->set_color(*v_it, color);
827  }
828 
829  if (_primitiveTypes & faceType_) {
830  typename MeshT::FaceIter f_it, f_end( _mesh->faces_end() );
831 
832  // Request face color attribute
833  if ( !_mesh->has_face_colors() )
834  _mesh->request_face_colors();
835 
836  for (f_it=_mesh->faces_begin(); f_it!=f_end; ++f_it)
837  if ( _mesh->status(*f_it).selected() )
838  _mesh->set_color(*f_it, color);
839  }
840 
841  if (_primitiveTypes & edgeType_) {
842  typename MeshT::EdgeIter e_it, e_end( _mesh->edges_end() );
843 
844  // Request edge color attribute
845  if ( !_mesh->has_edge_colors() )
846  _mesh->request_edge_colors();
847 
848  for (e_it=_mesh->edges_begin(); e_it!=e_end; ++e_it)
849  if ( _mesh->status(*e_it).selected() )
850  _mesh->set_color(*e_it, color);
851  }
852 
853  if (_primitiveTypes & halfedgeType_) {
854  typename MeshT::HalfedgeIter h_it, h_end( _mesh->halfedges_end() );
855 
856  // Request halfedge color attribute
857  if ( !_mesh->has_halfedge_colors() )
858  _mesh->request_halfedge_colors();
859 
860  for (h_it=_mesh->halfedges_begin(); h_it!=h_end; ++h_it)
861  if ( _mesh->status(*h_it).selected() )
862  _mesh->set_color(*h_it, color);
863  }
864 }
865 
866 //***********************************************************************************
867 
868 
876 template<class MeshT>
877 void MeshObjectSelectionPlugin::createMeshFromSelection(MeshT& _mesh, MeshT& _newMesh, PrimitiveType _primitiveType)
878 {
879 
880  // Tracking during copy action
882  _mesh.add_property(copyHandle, "copyHandle Property");
883 
884  //first copy vertices
885  typename MeshT::VertexIter v_it, v_end = _mesh.vertices_end();
886  for (v_it = _mesh.vertices_begin(); v_it != v_end; ++v_it) {
887 
888  bool copy = false;
889 
890  //if the vertex belongs to the selection copy it
891  if (_primitiveType & vertexType_)
892  copy = _mesh.status(*v_it).selected();
893  else if (_primitiveType & edgeType_) {
894 
895  for (typename MeshT::VertexOHalfedgeIter voh_it(_mesh, *v_it); voh_it.is_valid(); ++voh_it)
896  if (_mesh.status(_mesh.edge_handle(*voh_it)).selected()) {
897  copy = true;
898  break;
899  }
900 
901  } else if (_primitiveType & faceType_) {
902  for (typename MeshT::VertexFaceIter vf_it(_mesh, *v_it); vf_it.is_valid(); ++vf_it)
903  if (_mesh.status(*vf_it).selected()) {
904  copy = true;
905  break;
906  }
907  }
908 
909  //copy it
910  if (copy) {
911  _mesh.property(copyHandle, *v_it) = _newMesh.add_vertex(_mesh.point(*v_it));
912  } else {
913  _mesh.property(copyHandle, *v_it) = typename MeshT::VertexHandle(-1);
914  }
915  }
916 
917  //now check all faces
918  //if all vertices of the face exist in the new mesh -> copy it
919  typename MeshT::FaceIter f_it, f_end = _mesh.faces_end();
920  for (f_it = _mesh.faces_begin(); f_it != f_end; ++f_it) {
921 
922  std::vector<typename MeshT::VertexHandle> v;
923 
924  bool skip = false;
925 
926  for (typename MeshT::FaceVertexIter fv_it(_mesh, *f_it); fv_it.is_valid(); ++fv_it)
927  if (_mesh.property(copyHandle, *fv_it).is_valid())
928  v.push_back(_mesh.property(copyHandle, *fv_it));
929  else {
930  skip = true;
931  break;
932  }
933 
934  if (!skip)
935  _newMesh.add_face(v);
936  }
937 
938  _newMesh.update_normals();
939 
940  _mesh.remove_property(copyHandle);
941 
942 }
943 
944 template<class MeshT>
945 void MeshObjectSelectionPlugin::selectVerticesByValue(MeshT* _mesh, QString _component, bool _greater, double _value)
946 {
947 
948  //first copy vertices
949  typename MeshT::VertexIter v_it, v_end = _mesh->vertices_end();
950  for (v_it = _mesh->vertices_begin(); v_it != v_end; ++v_it) {
951  const typename MeshT::Point p = _mesh->point(*v_it);
952 
953  bool select = false;
954 
955  if (_component.contains("x",Qt::CaseInsensitive) ) {
956  select = (p[0] > _value);
957  } else if (_component.contains("y",Qt::CaseInsensitive) ) {
958  select = (p[1] > _value);
959  } else if (_component.contains("z",Qt::CaseInsensitive) ) {
960  select = (p[2] > _value);
961  } else {
962  emit log(LOGERR,tr("selectVerticesByValue, undefined component ") + _component );
963  }
964 
965 
966  // invert if requested
967  if (! _greater )
968  select = !select;
969 
970  // set selection status only if the vertex was previously unselected
971  if ( ! _mesh->status(*v_it).selected() )
972  _mesh->status(*v_it).set_selected(select);
973 
974  }
975 
976 }
977 
978 template <typename HandleT>
979 bool MeshObjectSelectionPlugin::selectElement(int _objectId, HandleT _handle, bool _fly_to_element)
980 {
981  if (!_handle.is_valid())
982  return false;
983 
984  BaseObjectData* object = nullptr;
985  if (!PluginFunctions::getObject(_objectId,object)) {
986  emit log(LOGERR,tr("selectElement: unable to get object"));
987  return false;
988  }
989 
990  IdList elementList;
991  elementList.push_back(_handle.idx());
992 
993  OpenMesh::Vec3d center;
994  OpenMesh::Vec3d normal;
995  bool handle_valid = false;
996 
997  if (object->dataType() == DATA_TRIANGLE_MESH){
998  MeshSelection::selectElements(PluginFunctions::triMesh(object), elementList, HandleT());
999  getFlightData(*PluginFunctions::triMeshObject(object), _handle, center, normal, handle_valid);
1000  } else if (object->dataType() == DATA_POLY_MESH) {
1001  MeshSelection::selectElements(PluginFunctions::polyMesh(object), elementList, HandleT());
1002  getFlightData(*PluginFunctions::polyMeshObject(object), _handle, center, normal, handle_valid);
1003  } else {
1004  emit log(LOGERR,tr("selectElement: Unsupported object Type"));
1005  return false;
1006  }
1007 
1008  if (handle_valid && _fly_to_element)
1009  PluginFunctions::flyTo(center + normal , center, 500.0);
1010 
1011  return handle_valid;
1012 }
1013 
1014 template <typename MeshObjectT, typename HandleT>
1015 void MeshObjectSelectionPlugin::getFlightData(MeshObjectT& _mesh_object, HandleT _handle,
1016  OpenMesh::Vec3d& center, OpenMesh::Vec3d& normal, bool& handle_valid)
1017 {
1018  OpenMesh::Vec3d bbMin;
1019  OpenMesh::Vec3d bbMax;
1020  _mesh_object.boundingBox(bbMin, bbMax);
1021 
1022  auto& mesh = *_mesh_object.mesh();
1023 
1024  if (_handle.is_valid() && static_cast<size_t>(_handle.idx()) < mesh.template n_elements<HandleT>())
1025  {
1026  center = mesh.calc_centroid(_handle);
1027  normal = 0.5 * (bbMax-bbMin).length() * mesh.calc_normal(_handle);
1028  handle_valid = true;
1029  }
1030  else
1031  {
1032  handle_valid = false;
1033  }
1034 }
1035 
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.
const UpdateType UPDATE_SELECTION_VERTICES(UpdateTypeSet(1)<< 5)
Vertex selection has changed.
const UpdateType UPDATE_SELECTION_HALFEDGES(UpdateTypeSet(1)<< 7)
Halfedge selection has changed.
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:179
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
void update_dihedral_angle_threshold_from_ui()
set dihedral angle threshold for edge selection
VectorT< unsigned char, 4 > Vec4uc
Definition: Vector11T.hh:840
const UpdateType UPDATE_SELECTION_FACES(UpdateTypeSet(1)<< 8)
Face selection has changed.
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:60
const UpdateType UPDATE_SELECTION_EDGES(UpdateTypeSet(1)<< 6)
Edge selection has changed.
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:850
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.
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:830
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
void flyTo(const ACG::Vec3d &_position, const ACG::Vec3d &_center, double _time)
Fly to point and viewing direction (animated).