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
45 #include <MeshTools/MeshNavigationT.hh>
46 #include <MeshTools/MeshSelectionT.hh>
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>
107 void MeshObjectSelectionPlugin::update_regions(MeshType* _mesh) {
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>
255 void MeshObjectSelectionPlugin::paintSphereSelection(MeshT* _mesh ,
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_)) {
319 update_dihedral_angle_threshold_from_ui();
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_) ) {
417 update_dihedral_angle_threshold_from_ui();
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
484 OpenMesh::VPropHandleT<bool> visited;
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>
556 void MeshObjectSelectionPlugin::floodFillSelection(
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>
645 void MeshObjectSelectionPlugin::componentsMeshSelection(
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
657 OpenMesh::VPropHandleT<bool> visited;
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
697 OpenMesh::FPropHandleT<bool> visited;
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
747 OpenMesh::FPropHandleT<bool> visited;
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 >
803 void MeshObjectSelectionPlugin::colorizeSelection(MeshT* _mesh,
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
881 OpenMesh::VPropHandleT<typename MeshT::VertexHandle> copyHandle;
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
LOGERR
Definition: LoggingInterface.hh:96
ACG::Geometry::distPointLineSquared
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
OpenMesh::VPropHandleT< bool >
DATA_TRIANGLE_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
DATA_POLY_MESH
#define DATA_POLY_MESH
Definition: PolyMesh.hh:59
MeshObjectSelectionPlugin::selectVerticesByValue
void selectVerticesByValue(int _objectId, QString _component, bool _greater, double _value)
Select vertices by their value.
Definition: VertexSelection.cc:584
ACG::GLState
Definition: GLState.hh:213
MeshNavigationT.hh
Functions for getting information about a mesh.
PluginFunctions::polyMesh
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
Definition: PluginFunctionsPolyMesh.cc:128
UPDATE_SELECTION_VERTICES
const UpdateType UPDATE_SELECTION_VERTICES(UpdateTypeSet(1)<< 5)
Vertex selection has changed.
UPDATE_SELECTION_HALFEDGES
const UpdateType UPDATE_SELECTION_HALFEDGES(UpdateTypeSet(1)<< 7)
Halfedge selection has changed.
MeshObjectSelectionPlugin::dihedral_angle_threshold_
double dihedral_angle_threshold_
Handle to selection environment.
Definition: MeshObjectSelectionPlugin.hh:626
ACG::GLState::project
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:640
PluginFunctions::getObject
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Definition: PluginFunctions.cc:296
OpenMesh::VectorT
Definition: Vector11T.hh:83
PluginFunctions::triMesh
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
Definition: PluginFunctionsTriangleMesh.cc:134
MeshObjectSelectionPlugin::deleteSelection
bool deleteSelection(MeshT *_mesh, PrimitiveType _primitiveType)
Delete all selected elements of a mesh.
Definition: MeshObjectSelectionPluginT_impl.hh:58
MeshObjectSelectionPlugin::faceType_
SelectionInterface::PrimitiveType faceType_
Handle to selection environment.
Definition: MeshObjectSelectionPlugin.hh:601
BaseObject::dataType
bool dataType(DataType _type) const
Definition: BaseObject.cc:221
IdList
std::vector< int > IdList
Standard Type for id Lists used for scripting.
Definition: DataTypes.hh:179
MeshObjectSelectionPlugin::vertexType_
SelectionInterface::PrimitiveType vertexType_
Primitive type handles:
Definition: MeshObjectSelectionPlugin.hh:598
OpenMesh::Attributes::Color
Add colors to mesh item (vertices/faces/edges)
Definition: Attributes.hh:83
MeshObjectSelectionPlugin::getFlightData
void getFlightData(MeshObjectT &_mesh_object, HandleT _handle, OpenMesh::Vec3d &center, OpenMesh::Vec3d &normal, bool &handle_valid)
set dihedral angle threshold for edge selection
Definition: MeshObjectSelectionPluginT_impl.hh:1015
MeshObjectSelectionPlugin::update_dihedral_angle_threshold_from_ui
void update_dihedral_angle_threshold_from_ui()
set dihedral angle threshold for edge selection
Definition: MeshObjectSelectionPlugin.cc:2377
OpenMesh::Vec4uc
VectorT< unsigned char, 4 > Vec4uc
Definition: Vector11T.hh:840
UPDATE_SELECTION_FACES
const UpdateType UPDATE_SELECTION_FACES(UpdateTypeSet(1)<< 8)
Face selection has changed.
PluginFunctions::polyMeshObject
PolyMeshObject * polyMeshObject(BaseObjectData *_object)
Cast an BaseObject to a PolyMeshObject if possible.
Definition: PluginFunctionsPolyMesh.cc:149
MeshSelectionT.hh
Functions for selection on a mesh.
PluginFunctions::triMeshObject
TriMeshObject * triMeshObject(BaseObjectData *_object)
Cast an BaseObject to a TriMeshObject if possible.
Definition: PluginFunctionsTriangleMesh.cc:156
BaseObjectData
Definition: BaseObjectData.hh:102
UpdateType
Update type class.
Definition: UpdateType.hh:60
UPDATE_SELECTION_EDGES
const UpdateType UPDATE_SELECTION_EDGES(UpdateTypeSet(1)<< 6)
Edge selection has changed.
MeshObjectSelectionPlugin::edgeType_
SelectionInterface::PrimitiveType edgeType_
Handle to selection environment.
Definition: MeshObjectSelectionPlugin.hh:599
MeshObjectSelectionPlugin::createMeshFromSelection
void createMeshFromSelection(MeshT &_mesh, MeshT &_newMesh, PrimitiveType _primitiveType)
Create a new mesh from the selection.
Definition: MeshObjectSelectionPluginT_impl.hh:877
MeshObjectSelectionPlugin::colorizeSelection
void colorizeSelection(MeshT *_mesh, PrimitiveType _primitiveTypes, int _red, int _green, int _blue, int _alpha)
Colorize the selection.
Definition: MeshObjectSelectionPluginT_impl.hh:803
MeshObjectSelectionPlugin::componentsMeshSelection
void componentsMeshSelection(MeshT *_mesh, int _objectId, uint _fh, ACG::Vec3d &_hit_point, PrimitiveType _primitiveType)
Connected component mesh selection.
Definition: MeshObjectSelectionPluginT_impl.hh:645
MeshObjectSelectionPlugin::selectElement
bool selectElement(int _objectId, HandleT _handle, bool _fly_to_element)
set dihedral angle threshold for edge selection
Definition: MeshObjectSelectionPluginT_impl.hh:979
MeshObjectSelectionPlugin::halfedgeType_
SelectionInterface::PrimitiveType halfedgeType_
Handle to selection environment.
Definition: MeshObjectSelectionPlugin.hh:600
OpenMesh::Vec4f
VectorT< float, 4 > Vec4f
Definition: Vector11T.hh:850
MeshObjectSelectionPlugin::closestBoundarySelection
void closestBoundarySelection(MeshT *_mesh, int _vh, PrimitiveType _primitiveTypes, bool _deselection)
Select all entities that are incident to closest boundary.
Definition: MeshObjectSelectionPluginT_impl.hh:474
OpenMesh::PolyMeshT::calc_centroid
Point calc_centroid(FaceHandle _fh) const
Computes and returns the average of the vertices defining _fh (same as calc_face_centroid) ...
Definition: PolyMeshT_impl.hh:267
MeshObjectSelectionPlugin::paintSphereSelection
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.
Definition: MeshObjectSelectionPluginT_impl.hh:255
MeshObjectSelectionPlugin::volumeSelection
bool volumeSelection(MeshT *_mesh, int _objectId, ACG::GLState &_state, QRegion *_region, PrimitiveType _primitiveTypes, bool _deselection)
Surface volume selection tool.
Definition: MeshObjectSelectionPluginT_impl.hh:391
OpenMesh::FPropHandleT< bool >
ACG::GLState::context_height
int context_height() const
get gl context height
Definition: GLState.hh:830
MeshObjectSelectionPlugin::toggleMeshSelection
void toggleMeshSelection(int _objectId, MeshT *_mesh, uint _fh, ACG::Vec3d &_hit_point, PrimitiveType _primitiveType)
Toggle mesh selection.
Definition: MeshObjectSelectionPluginT_impl.hh:147
UPDATE_NONE
const UpdateType UPDATE_NONE(UpdateTypeSet(0))
Empty update for empty initialization of update type.
MeshObjectSelectionPlugin::update_regions
void update_regions(MeshT *_mesh)
Update face selection to correspond to the vertex selection.
MeshObjectSelectionPlugin::floodFillSelection
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) ...
Definition: MeshObjectSelectionPluginT_impl.hh:556
OpenMesh::PolyMeshT::calc_normal
Normal calc_normal(FaceHandle _fh) const
same as calc_face_normal
Definition: PolyMeshT_impl.hh:187
PluginFunctions::flyTo
void flyTo(const ACG::Vec3d &_position, const ACG::Vec3d &_center, double _time)
Fly to point and viewing direction (animated).
Definition: PluginFunctions.cc:1057