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
57template<typename MeshT>
58bool MeshObjectSelectionPlugin::deleteSelection(MeshT* _mesh, PrimitiveType _primitiveType) {
59
60 bool changed = false;
61
62 if(_primitiveType & vertexType_) {
63
64 for(auto v_it : _mesh->vertices()) {
65 if(_mesh->status(v_it).selected()) {
66 _mesh->delete_vertex(v_it);
67 changed = true;
68 }
69 }
70 }
71
72 if(_primitiveType & edgeType_) {
73
74 for(auto e_it : _mesh->edges()) {
75 if(_mesh->status(e_it).selected()) {
76 _mesh->delete_edge(e_it);
77 changed = true;
78 }
79 }
80 }
81
82 if(_primitiveType & faceType_) {;
83
84 for(auto f_it : _mesh->faces()) {
85 if(_mesh->status(f_it).selected()) {
86 _mesh->delete_face(f_it);
87 changed = true;
88 }
89 }
90 }
91
92 _mesh->garbage_collection();
93
94 return changed;
95}
96
97//***********************************************************************************
98
103template<typename MeshType>
105
106 // Set face status
107 typename MeshType::FaceVertexIter fv_it;
108 typename MeshType::VertexHandle v0, v1, v2;
109
110 for(auto f_it : _mesh->faces()) {
111 fv_it = _mesh->fv_iter(f_it);
112 v0 = *( fv_it);
113 v1 = *(++fv_it);
114 v2 = *(++fv_it);
115
116 const bool a =(_mesh->status(v0).is_bit_set(AREA)|| _mesh->status(v1).is_bit_set(AREA)|| _mesh->status(v2).is_bit_set(AREA));
117 bool h =(_mesh->status(v0).is_bit_set(HANDLEAREA)&&
118 _mesh->status(v1).is_bit_set(HANDLEAREA)&&
119 _mesh->status(v2).is_bit_set(HANDLEAREA));
120
121 if(!(a || h))
122 if(_mesh->status(v0).is_bit_set(HANDLEAREA)||
123 _mesh->status(v1).is_bit_set(HANDLEAREA)||
124 _mesh->status(v2).is_bit_set(HANDLEAREA))
125 h = true;
126
127 _mesh->status(f_it).change_bit(AREA , a);
128 _mesh->status(f_it).change_bit(HANDLEAREA, h);
129 }
130}
131
132//***********************************************************************************
133
142template<class MeshT>
143void MeshObjectSelectionPlugin::toggleMeshSelection(int _objectId, MeshT* _mesh, uint _fh, ACG::Vec3d& _hit_point, PrimitiveType _primitiveType) {
144
145 typename OpenMesh::SmartFaceHandle fh = make_smart(_mesh->face_handle(_fh), _mesh);
146
147 if(!fh.is_valid())
148 return;
149
150 //Vertex Selection
151 if(_primitiveType & vertexType_) {
152
153 typename MeshT::FaceVertexIter fv_it(*_mesh, fh);
154 typename MeshT::VertexHandle closest = *fv_it;
155 typename MeshT::Scalar shortest_distance =(_mesh->point(closest)- _hit_point).sqrnorm();
156
157 do {
158 if((_mesh->point(*fv_it)- _hit_point).sqrnorm()<shortest_distance) {
159 shortest_distance =(_mesh->point(*fv_it)- _hit_point).sqrnorm();
160 closest = *fv_it;
161 }
162
163 ++fv_it;
164
165 } while( fv_it.is_valid() );
166
167 _mesh->status(closest).set_selected(!_mesh->status(closest).selected());
168
169 if(_mesh->status(closest).selected())
170 emit scriptInfo("selectVertices(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(closest.idx())+ "])");
171 else
172 emit scriptInfo("unselectVertices(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(closest.idx())+ "])");
173 emit updatedObject(_objectId, UPDATE_SELECTION_VERTICES);
174 }
175
176 //Edge Selection
177 if( (_primitiveType & edgeType_) || (_primitiveType & halfedgeType_) ) {
178
179 typename OpenMesh::SmartHalfedgeHandle closest(-1);
180 typename MeshT::Scalar closest_dist(-1);
181
182 typename MeshT::Point pp =(typename MeshT::Point)_hit_point;
183
184 for(auto fhe_it : fh.halfedges()) {
185
186 // typename MeshT::HalfedgeHandle heh0 = _mesh->halfedge_handle(*fe_it, 0);
187 // typename MeshT::HalfedgeHandle heh1 = _mesh->halfedge_handle(*fe_it, 1);
188
189 typename MeshT::Point lp0 = _mesh->point(fhe_it.to());
190 typename MeshT::Point lp1 = _mesh->point(fhe_it.from());
191
192 double dist_new = ACG::Geometry::distPointLineSquared(pp, lp0, lp1);
193
194 if(dist_new <closest_dist || closest_dist == -1) {
195
196 // save closest Edge
197 closest_dist = dist_new;
198 closest = fhe_it;
199 }
200 }
201
202 typename MeshT::EdgeHandle closest_eh = closest.edge();
203
204 if(_primitiveType & edgeType_) {
205
206 _mesh->status(closest_eh).set_selected(!_mesh->status(closest_eh).selected());
207
208 if(_mesh->status(closest_eh).selected())
209 emit scriptInfo("selectEdges(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(closest_eh.idx())+ "])");
210 else
211 emit scriptInfo("unselectEdges(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(closest_eh.idx())+ "])");
212 emit updatedObject(_objectId, UPDATE_SELECTION_EDGES);
213 } else {
214 _mesh->status(closest).set_selected(!_mesh->status(closest).selected());
215
216 if(_mesh->status(closest).selected())
217 emit scriptInfo("selectHalfedges(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(closest.idx())+ "])");
218 else
219 emit scriptInfo("unselectHalfedges(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(closest.idx())+ "])");
220 emit updatedObject(_objectId, UPDATE_SELECTION_HALFEDGES);
221 }
222 }
223
224 //Face Selection
225 if(_primitiveType & faceType_) {
226 _mesh->status(fh).set_selected(!_mesh->status(fh).selected());
227
228 if(_mesh->status(fh).selected())
229 emit scriptInfo("selectFaces(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(fh.idx())+ "])");
230 else
231 emit scriptInfo("unselectFaces(ObjectId(" + QString::number(_objectId) + ") , [" + QString::number(fh.idx())+ "])");
232 emit updatedObject(_objectId, UPDATE_SELECTION_FACES);
233 }
234}
235
236//***********************************************************************************
237
248template <class MeshT>
250 int _objectId ,
251 int _target_idx ,
252 typename MeshT::Point _hitpoint,
253 double _radius,
254 PrimitiveType _primitiveType,
255 bool _deselection) {
256
257
258 const float sqr_radius = _radius * _radius;
259
260 // select or deselect primitives
261 const bool sel = !_deselection;
262
263 // TODO:: replace with unordered set if c++11 is our standard
264 std::set< typename MeshT::FaceHandle > visited;
265
266 typename OpenMesh::SmartFaceHandle hitface = make_smart(_mesh->face_handle(_target_idx), _mesh);
267
268 if(!hitface.is_valid())
269 return;
270
271 visited.insert(hitface);
272
273
274 std::vector<typename OpenMesh::SmartFaceHandle> face_handles;
275 face_handles.reserve(50);
276 face_handles.push_back(hitface);
277
278
279 // find primitives to be selected
280 while(!face_handles.empty()) {
281 typename OpenMesh::SmartFaceHandle fh = face_handles.back();
282 visited.insert(fh);
283 face_handles.pop_back();
284
285
286 // Check how many points of the new face lie inside the sphere
287 unsigned int fVertices = 0;
288
289 // Test the halfedges of this face:
290 std::vector<typename OpenMesh::SmartEdgeHandle> edge_handles;
291
292 for(auto fh_it : fh.halfedges()) {
293
294 const typename MeshT::VertexHandle vh = fh_it.from();
295
296 if((_mesh->point(vh) - _hitpoint).sqrnorm() <= sqr_radius) {
297
298 // Select one vertex here, the other vertex will be selected on one of the other halfedges
299 if(_primitiveType & vertexType_)
300 _mesh->status(vh).set_selected(sel);
301
302 if((_mesh->point(fh_it.to())- _hitpoint).sqrnorm()<= sqr_radius)
303 edge_handles.push_back(fh_it.edge());
304
305 fVertices++;
306 }
307
308 }
309
310
311 if( (_primitiveType & edgeType_) || (_primitiveType & halfedgeType_)) {
313
314 for( size_t i=0; i < edge_handles.size(); i++) {
315 if (_primitiveType & halfedgeType_)
316 if(!_mesh->has_face_normals() || std::abs(_mesh->calc_dihedral_angle_fast(edge_handles[i])) >= dihedral_angle_threshold_)
317 {
318 _mesh->status( edge_handles[i].h0() ).set_selected(sel) ;
319 _mesh->status( edge_handles[i].h1() ).set_selected(sel) ;
320 }
321
322 if (_primitiveType & edgeType_)
323 if(!_mesh->has_face_normals() || std::abs(_mesh->calc_dihedral_angle_fast(edge_handles[i])) >= dihedral_angle_threshold_)
324 _mesh->status(edge_handles[i]).set_selected(sel);
325 }
326
327 }
328
329 if(_primitiveType & faceType_) {
330
331 // If all vertices of the face are inside the sphere, we can select the face as well
332 if( fh.valence() == fVertices) {
333 _mesh->status(fh).set_selected(sel);
334 }
335 }
336
337 //if something was tagged also check the 1-ring
338 if( fVertices > 0) {
339
340 // _mesh->property(checkedProp, *ff_it)= true;
341 for(auto ff_it : fh.faces()) {
342 if ( visited.count(ff_it) == 0 )
343 face_handles.push_back(ff_it);
344 }
345
346 }
347
348 }
349
350 // Collect all updates into one update call
351 UpdateType update(UPDATE_NONE);
352
353 if(_primitiveType & vertexType_)
355
356
357 if(_primitiveType & edgeType_)
358 update |= UPDATE_SELECTION_EDGES;
359
360 if(_primitiveType & halfedgeType_)
362
363 if(_primitiveType & faceType_)
364 update |= UPDATE_SELECTION_FACES;
365
366 // Run the update
367 emit updatedObject(_objectId, update);
368
369}
370
371//***********************************************************************************
372
383template<class MeshT>
384bool MeshObjectSelectionPlugin::volumeSelection(MeshT* _mesh, int _objectId, ACG::GLState& _state, QRegion *_region,
385 PrimitiveType _primitiveType, bool _deselection) {
386 ACG::Vec3d proj;
387 bool rv = false;
388
389 //reset tagged status
390 for(auto v_it : _mesh->vertices())
391 _mesh->status(v_it).set_tagged(false);
392
393 //tag all vertices that are projected into region
394 for(auto v_it : _mesh->vertices()) {
395
396 proj = _state.project(_mesh->point(v_it));
397
398 if(_region->contains(QPoint((int)proj[0], _state.context_height()- (int)proj[1]))) {
399
400 _mesh->status(v_it).set_tagged(true);
401 rv = true;
402 if(_primitiveType & vertexType_) {
403 _mesh->status(v_it).set_selected(!_deselection);
404 }
405 }
406 }
407
408 if( (_primitiveType & edgeType_) || (_primitiveType & halfedgeType_) ) {
410 for(auto e_it : _mesh->edges()) {
411
412 if(_mesh->status(e_it.h0().to()).tagged()||
413 _mesh->status(e_it.h1().to()).tagged()) {
414
415 if(_primitiveType & edgeType_)
416 if(!_mesh->has_face_normals() || std::abs(_mesh->calc_dihedral_angle_fast(e_it)) >= dihedral_angle_threshold_)
417 _mesh->status(e_it).set_selected(!_deselection);
418
419 if(_primitiveType & halfedgeType_)
420 if(!_mesh->has_face_normals() || std::abs(_mesh->calc_dihedral_angle_fast(e_it)) >= dihedral_angle_threshold_)
421 {
422 _mesh->status(e_it.h0()).set_selected(!_deselection);
423 _mesh->status(e_it.h1()).set_selected(!_deselection);
424 }
425 }
426 }
427 }
428
429 if(_primitiveType & faceType_) {
430 for(auto f_it : _mesh->faces()) {
431
432 bool select = false;
433 for(auto fv_it : f_it.vertices())
434 if(_mesh->status(fv_it).tagged())
435 select = true;
436
437 if(select)
438 _mesh->status(f_it).set_selected(!_deselection);
439 }
440 }
441
442 if(_primitiveType & vertexType_)
443 emit updatedObject(_objectId, UPDATE_SELECTION_VERTICES);
444 if(_primitiveType & edgeType_)
445 emit updatedObject(_objectId, UPDATE_SELECTION_EDGES);
446 if(_primitiveType & halfedgeType_)
447 emit updatedObject(_objectId, UPDATE_SELECTION_HALFEDGES);
448 if(_primitiveType & faceType_)
449 emit updatedObject(_objectId, UPDATE_SELECTION_FACES);
450
451 return rv;
452}
453
454//***********************************************************************************
455
463template<class MeshT>
464void MeshObjectSelectionPlugin::closestBoundarySelection(MeshT* _mesh, int _vh, PrimitiveType _primitiveTypes, bool _deselection) {
465
466 typename MeshT::VertexHandle vh = _mesh->vertex_handle(_vh);
467
468 if(vh.is_valid()) {
469 //get boundary vertex
470 typename OpenMesh::SmartVertexHandle vhBound = make_smart(MeshNavigation::findClosestBoundary(_mesh , vh), _mesh);
471 if(vhBound.is_valid()) {
472
473 //walk around the boundary and select primitves
475 if(!_mesh->get_property_handle(visited,"Visited Vertices"))
476 _mesh->add_property(visited, "Visited Vertices");
477
478 for(auto v_it : _mesh->vertices())
479 _mesh->property(visited, v_it)= false;
480
481 std::stack<typename OpenMesh::SmartVertexHandle> stack;
482 stack.push(vhBound);
483
484 while(!stack.empty()) {
485
486 typename OpenMesh::SmartVertexHandle vh = stack.top();
487 stack.pop();
488
489 if(_mesh->property(visited,vh))
490 continue;
491
492 //find outgoing boundary-edges
493 for(auto voh_it : vh.outgoing_halfedges()) {
494
495 if(_mesh->is_boundary(_mesh->edge_handle(voh_it))) {
496
497 stack.push(voh_it.to());
498
499 if(_primitiveTypes & edgeType_)
500 _mesh->status(voh_it.edge()).set_selected(!_deselection);
501
502 if(_primitiveTypes & halfedgeType_) {
503 typename OpenMesh::SmartHalfedgeHandle heh = voh_it;
504 if(!heh.is_boundary()) heh = heh.opp();
505 _mesh->status(heh).set_selected(!_deselection);
506 }
507 }
508
509 if(_primitiveTypes & faceType_) {
510 typename MeshT::FaceHandle f1 = voh_it.face();
511 typename MeshT::FaceHandle f2 = voh_it.opp().face();
512 if(f1.is_valid())_mesh->status(f1).set_selected(!_deselection);
513 if(f2.is_valid())_mesh->status(f2).set_selected(!_deselection);
514 }
515 }
516
517 _mesh->property(visited,vh)= true;
518
519 if(_primitiveTypes & vertexType_)
520 _mesh->status(vh).set_selected(!_deselection);
521 }
522 _mesh->remove_property(visited);
523
524
525 } else {
526 emit log(LOGERR, tr("Unable to find boundary."));
527 }
528 } else {
529 emit log(LOGERR, tr("Invalid vertex handle."));
530 }
531}
532
533//***********************************************************************************
534
544template<class MeshT>
546 MeshT* _mesh, int _objectId, uint _fh, double _maxAngle,
547 PrimitiveType _primitiveTypes, bool _deselection) {
548
549 // reset tagged status
550 for ( auto face : _mesh->faces() )
551 _mesh->status(face).set_tagged(false);
552
553 std::vector<typename MeshT::FaceHandle> face_handles;
554
555
556 typename MeshT::FaceHandle hitFace = typename MeshT::FaceHandle(_fh);
557 face_handles.reserve(50);
558 face_handles.push_back(hitFace);
559 _mesh->status(hitFace).set_tagged(true);
560
561 typename MeshT::Point n1 = _mesh->normal(hitFace);
562
563 double maxAngle = OpenMesh::deg_to_rad(_maxAngle);
564
565 while (!face_handles.empty()) {
566 typename MeshT::FaceHandle fh = face_handles.back();
567 face_handles.pop_back();
568
569 for (auto ff_it : _mesh->ff_range(fh)) {
570
571 // Check if already tagged
572 if (_mesh->status(ff_it).tagged())
573 continue;
574
575 typename MeshT::Point n2 = _mesh->normal(ff_it);
576
577 double angle = acos(n1 | n2);
578
579 if (angle <= maxAngle) {
580 _mesh->status(ff_it).set_tagged(true);
581 face_handles.push_back(ff_it);
582 }
583 }
584 }
585
586 // now select all tagged primitives
587 for ( auto face : _mesh->faces() ) {
588 if (_mesh->status(face).tagged()) {
589
590 if(_primitiveTypes & vertexType_) {
591 for (auto fv_it : face.vertices())
592 _mesh->status(fv_it).set_selected(!_deselection);
593 }
594
595 if(_primitiveTypes & edgeType_) {
596 for (auto fe_it : face.edges())
597 _mesh->status(fe_it).set_selected(!_deselection);
598 }
599
600 if(_primitiveTypes & halfedgeType_) {
601 for (auto fhe_it : face.halfedges())
602 _mesh->status(fhe_it).set_selected(!_deselection);
603 }
604
605 if(_primitiveTypes & faceType_) {
606 _mesh->status(face).set_selected(!_deselection);
607 }
608 }
609 }
610
611
612 if(_primitiveTypes & vertexType_)
613 emit updatedObject(_objectId, UPDATE_SELECTION_VERTICES);
614 if(_primitiveTypes & edgeType_)
615 emit updatedObject(_objectId, UPDATE_SELECTION_EDGES);
616 if(_primitiveTypes & halfedgeType_)
617 emit updatedObject(_objectId, UPDATE_SELECTION_HALFEDGES);
618 if(_primitiveTypes & faceType_)
619 emit updatedObject(_objectId, UPDATE_SELECTION_FACES);
620}
621
622//***********************************************************************************
623
632template<class MeshT>
634 MeshT* _mesh, int _objectId, uint _fh, ACG::Vec3d& _hit_point,
635 PrimitiveType _primitiveType) {
636
637 typename OpenMesh::SmartFaceHandle fh = make_smart(_mesh->face_handle(_fh), _mesh);
638
639 if(!fh.is_valid())
640 return;
641
642 //Vertex Selection
643 if(_primitiveType & vertexType_) {
644
646 _mesh->add_property(visited);
647
648 // Initialize vertex tag
649 for (auto v_it : _mesh->vertices())
650 _mesh->property(visited, v_it) = false;
651
652 // Get some vertex incident to the clicked face
653 typename OpenMesh::SmartVertexHandle current = *(_mesh->fv_iter(fh));
654 if(!current.is_valid())
655 return;
656
657 std::set<typename OpenMesh::SmartVertexHandle> unprocessed;
658 unprocessed.insert(current);
659
660 while( !unprocessed.empty() ) {
661
662 // Select current vertex
663 current = *unprocessed.begin();
664 _mesh->status(current).set_selected(!(_mesh->status(current)).selected());
665 _mesh->property(visited, current) = true;
666 unprocessed.erase(current);
667
668 // Go over all neighbors
669 for(auto vv_it : current.vertices()) {
670 if(_mesh->property(visited, vv_it) == true) continue;
671 unprocessed.insert(vv_it);
672 }
673
674 }
675
676 _mesh->remove_property(visited);
677 }
678
679 //Edge Selection
680 if( (_primitiveType & edgeType_) || (_primitiveType & halfedgeType_ ) ) {
681
683 _mesh->add_property(visited);
684
685 // Initialize face tag
686 for (auto f_it : _mesh->faces())
687 _mesh->property(visited, f_it) = false;
688
689
690 typename OpenMesh::SmartFaceHandle current = fh;
691
692 std::set<typename OpenMesh::SmartFaceHandle> unprocessed;
693 unprocessed.insert(current);
694
695 typename MeshT::EdgeHandle firstEdge = *(_mesh->fe_iter(fh));
696 if(!firstEdge.is_valid()) return;
697 bool selected = _mesh->status(firstEdge).selected();
698
699 while( !unprocessed.empty() ) {
700
701 // Select all edges incident to current face
702 current = *unprocessed.begin();
703 for(auto fh_it : current.halfedges()) {
704 if(_primitiveType & halfedgeType_) {
705 _mesh->status(fh_it).set_selected(!(_mesh->status(fh_it)).selected());
706 }
707 if(_primitiveType & edgeType_) {
708 _mesh->status(fh_it.edge()).set_selected(!selected);
709 }
710 }
711
712 _mesh->property(visited, current) = true;
713 unprocessed.erase(current);
714
715 // Go over all neighbors
716 for(auto ff_it : current.faces()) {
717 if(_mesh->property(visited, ff_it) == true) continue;
718 unprocessed.insert(ff_it);
719 }
720
721 }
722
723 _mesh->remove_property(visited);
724 }
725
726 //Face Selection
727 if(_primitiveType & faceType_) {
728
730 _mesh->add_property(visited);
731
732 // Initialize face tag
733 for (auto f_it : _mesh->faces())
734 _mesh->property(visited, f_it) = false;
735
736
737 typename OpenMesh::SmartFaceHandle current = fh;
738
739 std::set<typename OpenMesh::SmartFaceHandle> unprocessed;
740 unprocessed.insert(current);
741
742 while( !unprocessed.empty() ) {
743
744 // Select all edges incident to current face
745 current = *unprocessed.begin();
746 _mesh->status(current).set_selected(!(_mesh->status(current)).selected());
747 _mesh->property(visited, current) = true;
748 unprocessed.erase(current);
749
750 // Go over all neighbors
751 for(auto ff_it : current.faces()) {
752 if(_mesh->property(visited, ff_it) == true) continue;
753 unprocessed.insert(ff_it);
754 }
755
756 }
757
758 _mesh->remove_property(visited);
759 }
760 if(_primitiveType & vertexType_)
761 emit updatedObject(_objectId, UPDATE_SELECTION_VERTICES);
762 if(_primitiveType & edgeType_)
763 emit updatedObject(_objectId, UPDATE_SELECTION_EDGES);
764 if(_primitiveType & halfedgeType_)
765 emit updatedObject(_objectId, UPDATE_SELECTION_HALFEDGES);
766 if(_primitiveType & faceType_)
767 emit updatedObject(_objectId, UPDATE_SELECTION_FACES);
768}
769
770//***********************************************************************************
771
781template< typename MeshT >
783 PrimitiveType _primitiveTypes,
784 int _red,
785 int _green,
786 int _blue,
787 int _alpha) {
788
789 typename MeshT::Color color = OpenMesh::color_cast<OpenMesh::Vec4f,OpenMesh::Vec4uc>(OpenMesh::Vec4uc(_red,_green,_blue,_alpha));
790 /*color[0] = _red;
791 color[1] = _green;
792 color[2] = _blue;
793 color[3] = _alpha;
794 */
795
796 if (_primitiveTypes & vertexType_) {
797
798 // Request vertex color attribute
799 if ( !_mesh->has_vertex_colors() )
800 _mesh->request_vertex_colors();
801
802 for (auto v_it : _mesh->vertices())
803 if ( _mesh->status(v_it).selected() )
804 _mesh->set_color(v_it, color);
805 }
806
807 if (_primitiveTypes & faceType_) {
808
809 // Request face color attribute
810 if ( !_mesh->has_face_colors() )
811 _mesh->request_face_colors();
812
813 for (auto f_it : _mesh->faces())
814 if ( _mesh->status(f_it).selected() )
815 _mesh->set_color(f_it, color);
816 }
817
818 if (_primitiveTypes & edgeType_) {
819 // Request edge color attribute
820 if ( !_mesh->has_edge_colors() )
821 _mesh->request_edge_colors();
822
823 for (auto e_it : _mesh->edges())
824 if ( _mesh->status(e_it).selected() )
825 _mesh->set_color(e_it, color);
826 }
827
828 if (_primitiveTypes & halfedgeType_) {
829
830 // Request halfedge color attribute
831 if ( !_mesh->has_halfedge_colors() )
832 _mesh->request_halfedge_colors();
833
834 for (auto h_it : _mesh->halfedges())
835 if ( _mesh->status(h_it).selected() )
836 _mesh->set_color(h_it, color);
837 }
838}
839
840//***********************************************************************************
841
842
850template<class MeshT>
851void MeshObjectSelectionPlugin::createMeshFromSelection(MeshT& _mesh, MeshT& _newMesh, PrimitiveType _primitiveType)
852{
853
854 // Tracking during copy action
856 _mesh.add_property(copyHandle, "copyHandle Property");
857
858 //first copy vertices
859 for (auto v_it : _mesh.vertices()) {
860
861 bool copy = false;
862
863 //if the vertex belongs to the selection copy it
864 if (_primitiveType & vertexType_)
865 copy = _mesh.status(v_it).selected();
866 else if (_primitiveType & edgeType_) {
867
868 for (auto voh_it : v_it.outgoing_halfedges())
869 if (_mesh.status(voh_it.edge()).selected()) {
870 copy = true;
871 break;
872 }
873
874 } else if (_primitiveType & faceType_) {
875 for (auto vf_it : v_it.faces())
876 if (_mesh.status(vf_it).selected()) {
877 copy = true;
878 break;
879 }
880 }
881
882 //copy it
883 if (copy) {
884 _mesh.property(copyHandle, v_it) = _newMesh.add_vertex(_mesh.point(v_it));
885 } else {
886 _mesh.property(copyHandle, v_it) = typename MeshT::VertexHandle(-1);
887 }
888 }
889
890 //now check all faces
891 //if all vertices of the face exist in the new mesh -> copy it
892 for (auto f_it : _mesh.faces()) {
893
894 std::vector<typename MeshT::VertexHandle> v;
895
896 bool skip = false;
897
898 for (auto fv_it : f_it.vertices())
899 if (_mesh.property(copyHandle, fv_it).is_valid())
900 v.push_back(_mesh.property(copyHandle, fv_it));
901 else {
902 skip = true;
903 break;
904 }
905
906 if (!skip)
907 _newMesh.add_face(v);
908 }
909
910 _newMesh.update_normals();
911
912 _mesh.remove_property(copyHandle);
913
914}
915
916template<class MeshT>
917void MeshObjectSelectionPlugin::selectVerticesByValue(MeshT* _mesh, QString _component, bool _greater, double _value)
918{
919
920 //first copy vertices
921 for (auto v_it : _mesh->vertices()) {
922 const typename MeshT::Point p = _mesh->point(v_it);
923
924 bool select = false;
925
926 if (_component.contains("x",Qt::CaseInsensitive) ) {
927 select = (p[0] > _value);
928 } else if (_component.contains("y",Qt::CaseInsensitive) ) {
929 select = (p[1] > _value);
930 } else if (_component.contains("z",Qt::CaseInsensitive) ) {
931 select = (p[2] > _value);
932 } else {
933 emit log(LOGERR,tr("selectVerticesByValue, undefined component ") + _component );
934 }
935
936
937 // invert if requested
938 if (! _greater )
939 select = !select;
940
941 // set selection status only if the vertex was previously unselected
942 if ( ! _mesh->status(v_it).selected() )
943 _mesh->status(v_it).set_selected(select);
944
945 }
946
947}
948
949template <typename HandleT>
950bool MeshObjectSelectionPlugin::selectElement(int _objectId, HandleT _handle, bool _fly_to_element)
951{
952 if (!_handle.is_valid())
953 return false;
954
955 BaseObjectData* object = nullptr;
956 if (!PluginFunctions::getObject(_objectId,object)) {
957 emit log(LOGERR,tr("selectElement: unable to get object"));
958 return false;
959 }
960
961 IdList elementList;
962 elementList.push_back(_handle.idx());
963
964 OpenMesh::Vec3d center;
965 OpenMesh::Vec3d normal;
966 bool handle_valid = false;
967
968 if (object->dataType() == DATA_TRIANGLE_MESH){
969 MeshSelection::selectElements(PluginFunctions::triMesh(object), elementList, HandleT());
970 getFlightData(*PluginFunctions::triMeshObject(object), _handle, center, normal, handle_valid);
971 } else if (object->dataType() == DATA_POLY_MESH) {
972 MeshSelection::selectElements(PluginFunctions::polyMesh(object), elementList, HandleT());
973 getFlightData(*PluginFunctions::polyMeshObject(object), _handle, center, normal, handle_valid);
974 } else {
975 emit log(LOGERR,tr("selectElement: Unsupported object Type"));
976 return false;
977 }
978
979 if (handle_valid && _fly_to_element)
980 PluginFunctions::flyTo(center + normal , center, 500.0);
981
982 return handle_valid;
983}
984
985template <typename MeshObjectT, typename HandleT>
986void MeshObjectSelectionPlugin::getFlightData(MeshObjectT& _mesh_object, HandleT _handle,
987 OpenMesh::Vec3d& center, OpenMesh::Vec3d& normal, bool& handle_valid)
988{
989 OpenMesh::Vec3d bbMin;
990 OpenMesh::Vec3d bbMax;
991 _mesh_object.boundingBox(bbMin, bbMax);
992
993 auto& mesh = *_mesh_object.mesh();
994
995 if (_handle.is_valid() && static_cast<size_t>(_handle.idx()) < mesh.template n_elements<HandleT>())
996 {
997 center = mesh.calc_centroid(_handle);
998 normal = 0.5 * (bbMax-bbMin).length() * mesh.calc_normal(_handle);
999 handle_valid = true;
1000 }
1001 else
1002 {
1003 handle_valid = false;
1004 }
1005}
1006
std::vector< int > IdList
Standard Type for id Lists used for scripting.
Definition: DataTypes.hh:181
@ LOGERR
Functions for getting information about a mesh.
Functions for selection on a mesh.
#define DATA_POLY_MESH
Definition: PolyMesh.hh:59
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
int context_height() const
get gl context height
Definition: GLState.hh:855
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:640
bool dataType(DataType _type) const
Definition: BaseObject.cc:219
void colorizeSelection(MeshT *_mesh, PrimitiveType _primitiveTypes, int _red, int _green, int _blue, int _alpha)
Colorize the selection.
void createMeshFromSelection(MeshT &_mesh, MeshT &_newMesh, PrimitiveType _primitiveType)
Create a new mesh from the selection.
bool selectElement(int _objectId, HandleT _handle, bool _fly_to_element)
set dihedral angle threshold for edge selection
SelectionInterface::PrimitiveType vertexType_
Primitive type handles:
double dihedral_angle_threshold_
Handle to selection environment.
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)
void toggleMeshSelection(int _objectId, MeshT *_mesh, uint _fh, ACG::Vec3d &_hit_point, PrimitiveType _primitiveType)
Toggle mesh selection.
void closestBoundarySelection(MeshT *_mesh, int _vh, PrimitiveType _primitiveTypes, bool _deselection)
Select all entities that are incident to closest boundary.
void update_regions(MeshT *_mesh)
Update face selection to correspond to the vertex selection.
bool volumeSelection(MeshT *_mesh, int _objectId, ACG::GLState &_state, QRegion *_region, PrimitiveType _primitiveTypes, bool _deselection)
Surface volume selection tool.
SelectionInterface::PrimitiveType edgeType_
Handle to selection environment.
void selectVerticesByValue(int _objectId, QString _component, bool _greater, double _value)
Select vertices by their value.
SelectionInterface::PrimitiveType halfedgeType_
Handle to selection environment.
void update_dihedral_angle_threshold_from_ui()
set dihedral angle threshold for edge selection
void getFlightData(MeshObjectT &_mesh_object, HandleT _handle, OpenMesh::Vec3d &center, OpenMesh::Vec3d &normal, bool &handle_valid)
set dihedral angle threshold for edge selection
void componentsMeshSelection(MeshT *_mesh, int _objectId, uint _fh, ACG::Vec3d &_hit_point, PrimitiveType _primitiveType)
Connected component mesh selection.
bool deleteSelection(MeshT *_mesh, PrimitiveType _primitiveType)
Delete all selected elements of a mesh.
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.
SelectionInterface::PrimitiveType faceType_
Handle to selection environment.
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
int idx() const
Get the underlying index of this handle.
Definition: Handles.hh:69
Point calc_centroid(FaceHandle _fh) const
Computes and returns the average of the vertices defining _fh (same as calc_face_centroid)
Normal calc_normal(FaceHandle _fh) const
same as calc_face_normal
VertexHandle add_vertex(const VecT &_p)
Add a geometric point to the mesh.
PointT normal(HalfFaceHandle _hfh) const
virtual VertexIter delete_vertex(VertexHandle _h)
Delete vertex from mesh.
bool is_valid(Handle _h) const
test is_valid and perform index range check
static EdgeHandle edge_handle(HalfEdgeHandle _h)
Handle conversion.
virtual FaceIter delete_face(FaceHandle _h)
Delete face from mesh.
virtual FaceHandle add_face(std::vector< HalfEdgeHandle > _halfedges, bool _topologyCheck=false)
Add face via incident edges.
virtual EdgeIter delete_edge(EdgeHandle _h)
Delete edge from mesh.
const Face & face(FaceHandle _faceHandle) const
Get face with handle _faceHandle.
Update type class.
Definition: UpdateType.hh:59
const UpdateType UPDATE_SELECTION_HALFEDGES(UpdateTypeSet(128))
Halfedge selection has changed.
const UpdateType UPDATE_SELECTION_VERTICES(UpdateTypeSet(32))
Vertex selection has changed.
const UpdateType UPDATE_SELECTION_EDGES(UpdateTypeSet(64))
Edge selection has changed.
const UpdateType UPDATE_SELECTION_FACES(UpdateTypeSet(256))
Face selection has changed.
const UpdateType UPDATE_NONE(UpdateTypeSet(0))
Empty update for empty initialization of update type.
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
@ Color
Add colors to mesh item (vertices/faces/edges)
Definition: Attributes.hh:83
TriMeshObject * triMeshObject(BaseObjectData *_object)
Cast an BaseObject to a TriMeshObject if possible.
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.
PolyMeshObject * polyMeshObject(BaseObjectData *_object)
Cast an BaseObject to a PolyMeshObject if possible.
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
void flyTo(const ACG::Vec3d &_position, const ACG::Vec3d &_center, double _time)
Fly to point and viewing direction (animated).
uint valence() const
Returns the valence of the face.
PolyConnectivity::ConstFaceFaceRange faces() const
Returns a range adjacent faces of the face (PolyConnectivity::ff_range())
PolyConnectivity::ConstFaceHalfedgeRange halfedges() const
Returns a range of halfedges of the face (PolyConnectivity::fh_range())
SmartEdgeHandle edge() const
Returns incident edge of halfedge.
Smart version of VertexHandle contains a pointer to the corresponding mesh and allows easier access t...
PolyConnectivity::ConstVertexVertexRange vertices() const
Returns a range of vertices adjacent to the vertex (PolyConnectivity::vv_range())
PolyConnectivity::ConstVertexOHalfedgeRange outgoing_halfedges() const
Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_range())