43#include "MeshObjectSelectionPlugin.hh"
47#include <OpenMesh/Core/Geometry/MathDefs.hh>
57template<
typename MeshT>
64 for(
auto v_it : _mesh->vertices()) {
65 if(_mesh->status(v_it).selected()) {
74 for(
auto e_it : _mesh->edges()) {
75 if(_mesh->status(e_it).selected()) {
84 for(
auto f_it : _mesh->faces()) {
85 if(_mesh->status(f_it).selected()) {
92 _mesh->garbage_collection();
103template<
typename MeshType>
107 typename MeshType::FaceVertexIter fv_it;
108 typename MeshType::VertexHandle v0, v1, v2;
110 for(
auto f_it : _mesh->faces()) {
111 fv_it = _mesh->fv_iter(f_it);
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));
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))
127 _mesh->status(f_it).change_bit(AREA , a);
128 _mesh->status(f_it).change_bit(HANDLEAREA, h);
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();
158 if((_mesh->point(*fv_it)- _hit_point).sqrnorm()<shortest_distance) {
159 shortest_distance =(_mesh->point(*fv_it)- _hit_point).sqrnorm();
165 }
while( fv_it.is_valid() );
167 _mesh->status(closest).set_selected(!_mesh->status(closest).selected());
169 if(_mesh->status(closest).selected())
170 emit scriptInfo(
"selectVertices(ObjectId(" + QString::number(_objectId) +
") , [" + QString::number(closest.idx())+
"])");
172 emit scriptInfo(
"unselectVertices(ObjectId(" + QString::number(_objectId) +
") , [" + QString::number(closest.idx())+
"])");
180 typename MeshT::Scalar closest_dist(-1);
182 typename MeshT::Point pp =(
typename MeshT::Point)_hit_point;
189 typename MeshT::Point lp0 = _mesh->point(fhe_it.to());
190 typename MeshT::Point lp1 = _mesh->point(fhe_it.from());
194 if(dist_new <closest_dist || closest_dist == -1) {
197 closest_dist = dist_new;
202 typename MeshT::EdgeHandle closest_eh = closest.
edge();
206 _mesh->status(closest_eh).set_selected(!_mesh->status(closest_eh).selected());
208 if(_mesh->status(closest_eh).selected())
209 emit scriptInfo(
"selectEdges(ObjectId(" + QString::number(_objectId) +
") , [" + QString::number(closest_eh.idx())+
"])");
211 emit scriptInfo(
"unselectEdges(ObjectId(" + QString::number(_objectId) +
") , [" + QString::number(closest_eh.idx())+
"])");
214 _mesh->status(closest).set_selected(!_mesh->status(closest).selected());
216 if(_mesh->status(closest).selected())
217 emit scriptInfo(
"selectHalfedges(ObjectId(" + QString::number(_objectId) +
") , [" + QString::number(closest.
idx())+
"])");
219 emit scriptInfo(
"unselectHalfedges(ObjectId(" + QString::number(_objectId) +
") , [" + QString::number(closest.
idx())+
"])");
226 _mesh->status(fh).set_selected(!_mesh->status(fh).selected());
228 if(_mesh->status(fh).selected())
229 emit scriptInfo(
"selectFaces(ObjectId(" + QString::number(_objectId) +
") , [" + QString::number(fh.
idx())+
"])");
231 emit scriptInfo(
"unselectFaces(ObjectId(" + QString::number(_objectId) +
") , [" + QString::number(fh.
idx())+
"])");
248template <
class MeshT>
252 typename MeshT::Point _hitpoint,
254 PrimitiveType _primitiveType,
258 const float sqr_radius = _radius * _radius;
261 const bool sel = !_deselection;
264 std::set< typename MeshT::FaceHandle > visited;
271 visited.insert(hitface);
274 std::vector<typename OpenMesh::SmartFaceHandle> face_handles;
275 face_handles.reserve(50);
276 face_handles.push_back(hitface);
280 while(!face_handles.empty()) {
283 face_handles.pop_back();
287 unsigned int fVertices = 0;
290 std::vector<typename OpenMesh::SmartEdgeHandle> edge_handles;
294 const typename MeshT::VertexHandle vh = fh_it.from();
296 if((_mesh->point(vh) - _hitpoint).sqrnorm() <= sqr_radius) {
300 _mesh->status(vh).set_selected(sel);
302 if((_mesh->point(fh_it.to())- _hitpoint).sqrnorm()<= sqr_radius)
303 edge_handles.push_back(fh_it.edge());
314 for(
size_t i=0; i < edge_handles.size(); i++) {
316 if(!_mesh->has_face_normals() || std::abs(_mesh->calc_dihedral_angle_fast(edge_handles[i])) >=
dihedral_angle_threshold_)
318 _mesh->status( edge_handles[i].h0() ).set_selected(sel) ;
319 _mesh->status( edge_handles[i].h1() ).set_selected(sel) ;
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);
332 if( fh.
valence() == fVertices) {
333 _mesh->status(fh).set_selected(sel);
341 for(
auto ff_it : fh.
faces()) {
342 if ( visited.count(ff_it) == 0 )
343 face_handles.push_back(ff_it);
367 emit updatedObject(_objectId, update);
385 PrimitiveType _primitiveType,
bool _deselection) {
390 for(
auto v_it : _mesh->vertices())
391 _mesh->status(v_it).set_tagged(
false);
394 for(
auto v_it : _mesh->vertices()) {
396 proj = _state.
project(_mesh->point(v_it));
398 if(_region->contains(QPoint((
int)proj[0], _state.
context_height()- (
int)proj[1]))) {
400 _mesh->status(v_it).set_tagged(
true);
403 _mesh->status(v_it).set_selected(!_deselection);
410 for(
auto e_it : _mesh->edges()) {
412 if(_mesh->status(e_it.h0().to()).tagged()||
413 _mesh->status(e_it.h1().to()).tagged()) {
417 _mesh->status(e_it).set_selected(!_deselection);
422 _mesh->status(e_it.h0()).set_selected(!_deselection);
423 _mesh->status(e_it.h1()).set_selected(!_deselection);
430 for(
auto f_it : _mesh->faces()) {
433 for(
auto fv_it : f_it.vertices())
434 if(_mesh->status(fv_it).tagged())
438 _mesh->status(f_it).set_selected(!_deselection);
466 typename MeshT::VertexHandle vh = _mesh->vertex_handle(_vh);
475 if(!_mesh->get_property_handle(visited,
"Visited Vertices"))
476 _mesh->add_property(visited,
"Visited Vertices");
478 for(
auto v_it : _mesh->vertices())
479 _mesh->property(visited, v_it)=
false;
481 std::stack<typename OpenMesh::SmartVertexHandle> stack;
484 while(!stack.empty()) {
489 if(_mesh->property(visited,vh))
495 if(_mesh->is_boundary(_mesh->
edge_handle(voh_it))) {
497 stack.push(voh_it.to());
500 _mesh->status(voh_it.edge()).set_selected(!_deselection);
504 if(!heh.is_boundary()) heh = heh.opp();
505 _mesh->status(heh).set_selected(!_deselection);
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);
517 _mesh->property(visited,vh)=
true;
520 _mesh->status(vh).set_selected(!_deselection);
522 _mesh->remove_property(visited);
526 emit log(
LOGERR, tr(
"Unable to find boundary."));
529 emit log(
LOGERR, tr(
"Invalid vertex handle."));
546 MeshT* _mesh,
int _objectId, uint _fh,
double _maxAngle,
547 PrimitiveType _primitiveTypes,
bool _deselection) {
550 for (
auto face : _mesh->faces() )
551 _mesh->status(face).set_tagged(
false);
553 std::vector<typename MeshT::FaceHandle> face_handles;
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);
561 typename MeshT::Point n1 = _mesh->
normal(hitFace);
563 double maxAngle = OpenMesh::deg_to_rad(_maxAngle);
565 while (!face_handles.empty()) {
566 typename MeshT::FaceHandle fh = face_handles.back();
567 face_handles.pop_back();
569 for (
auto ff_it : _mesh->ff_range(fh)) {
572 if (_mesh->status(ff_it).tagged())
575 typename MeshT::Point n2 = _mesh->
normal(ff_it);
577 double angle = acos(n1 | n2);
579 if (angle <= maxAngle) {
580 _mesh->status(ff_it).set_tagged(
true);
581 face_handles.push_back(ff_it);
587 for (
auto face : _mesh->faces() ) {
588 if (_mesh->status(face).tagged()) {
591 for (
auto fv_it : face.vertices())
592 _mesh->status(fv_it).set_selected(!_deselection);
596 for (
auto fe_it : face.edges())
597 _mesh->status(fe_it).set_selected(!_deselection);
601 for (
auto fhe_it : face.halfedges())
602 _mesh->status(fhe_it).set_selected(!_deselection);
606 _mesh->status(face).set_selected(!_deselection);
635 PrimitiveType _primitiveType) {
646 _mesh->add_property(visited);
649 for (
auto v_it : _mesh->vertices())
650 _mesh->property(visited, v_it) =
false;
657 std::set<typename OpenMesh::SmartVertexHandle> unprocessed;
658 unprocessed.insert(current);
660 while( !unprocessed.empty() ) {
663 current = *unprocessed.begin();
664 _mesh->status(current).set_selected(!(_mesh->status(current)).selected());
665 _mesh->property(visited, current) =
true;
666 unprocessed.erase(current);
669 for(
auto vv_it : current.
vertices()) {
670 if(_mesh->property(visited, vv_it) ==
true)
continue;
671 unprocessed.insert(vv_it);
676 _mesh->remove_property(visited);
683 _mesh->add_property(visited);
686 for (
auto f_it : _mesh->faces())
687 _mesh->property(visited, f_it) =
false;
692 std::set<typename OpenMesh::SmartFaceHandle> unprocessed;
693 unprocessed.insert(current);
695 typename MeshT::EdgeHandle firstEdge = *(_mesh->fe_iter(fh));
696 if(!firstEdge.is_valid())
return;
697 bool selected = _mesh->status(firstEdge).selected();
699 while( !unprocessed.empty() ) {
702 current = *unprocessed.begin();
705 _mesh->status(fh_it).set_selected(!(_mesh->status(fh_it)).selected());
708 _mesh->status(fh_it.edge()).set_selected(!selected);
712 _mesh->property(visited, current) =
true;
713 unprocessed.erase(current);
716 for(
auto ff_it : current.
faces()) {
717 if(_mesh->property(visited, ff_it) ==
true)
continue;
718 unprocessed.insert(ff_it);
723 _mesh->remove_property(visited);
730 _mesh->add_property(visited);
733 for (
auto f_it : _mesh->faces())
734 _mesh->property(visited, f_it) =
false;
739 std::set<typename OpenMesh::SmartFaceHandle> unprocessed;
740 unprocessed.insert(current);
742 while( !unprocessed.empty() ) {
745 current = *unprocessed.begin();
746 _mesh->status(current).set_selected(!(_mesh->status(current)).selected());
747 _mesh->property(visited, current) =
true;
748 unprocessed.erase(current);
751 for(
auto ff_it : current.
faces()) {
752 if(_mesh->property(visited, ff_it) ==
true)
continue;
753 unprocessed.insert(ff_it);
758 _mesh->remove_property(visited);
781template<
typename MeshT >
783 PrimitiveType _primitiveTypes,
799 if ( !_mesh->has_vertex_colors() )
800 _mesh->request_vertex_colors();
802 for (
auto v_it : _mesh->vertices())
803 if ( _mesh->status(v_it).selected() )
804 _mesh->set_color(v_it, color);
810 if ( !_mesh->has_face_colors() )
811 _mesh->request_face_colors();
813 for (
auto f_it : _mesh->faces())
814 if ( _mesh->status(f_it).selected() )
815 _mesh->set_color(f_it, color);
820 if ( !_mesh->has_edge_colors() )
821 _mesh->request_edge_colors();
823 for (
auto e_it : _mesh->edges())
824 if ( _mesh->status(e_it).selected() )
825 _mesh->set_color(e_it, color);
831 if ( !_mesh->has_halfedge_colors() )
832 _mesh->request_halfedge_colors();
834 for (
auto h_it : _mesh->halfedges())
835 if ( _mesh->status(h_it).selected() )
836 _mesh->set_color(h_it, color);
856 _mesh.add_property(copyHandle,
"copyHandle Property");
859 for (
auto v_it : _mesh.vertices()) {
865 copy = _mesh.status(v_it).selected();
868 for (
auto voh_it : v_it.outgoing_halfedges())
869 if (_mesh.status(voh_it.edge()).selected()) {
875 for (
auto vf_it : v_it.faces())
876 if (_mesh.status(vf_it).selected()) {
884 _mesh.property(copyHandle, v_it) = _newMesh.
add_vertex(_mesh.point(v_it));
886 _mesh.property(copyHandle, v_it) =
typename MeshT::VertexHandle(-1);
892 for (
auto f_it : _mesh.faces()) {
894 std::vector<typename MeshT::VertexHandle> v;
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));
910 _newMesh.update_normals();
912 _mesh.remove_property(copyHandle);
921 for (
auto v_it : _mesh->vertices()) {
922 const typename MeshT::Point p = _mesh->point(v_it);
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);
933 emit log(
LOGERR,tr(
"selectVerticesByValue, undefined component ") + _component );
942 if ( ! _mesh->status(v_it).selected() )
943 _mesh->status(v_it).set_selected(select);
949template <
typename HandleT>
952 if (!_handle.is_valid())
957 emit log(
LOGERR,tr(
"selectElement: unable to get object"));
962 elementList.push_back(_handle.idx());
966 bool handle_valid =
false;
975 emit log(
LOGERR,tr(
"selectElement: Unsupported object Type"));
979 if (handle_valid && _fly_to_element)
985template <
typename MeshObjectT,
typename HandleT>
991 _mesh_object.boundingBox(bbMin, bbMax);
993 auto& mesh = *_mesh_object.mesh();
995 if (_handle.is_valid() &&
static_cast<size_t>(_handle.idx()) < mesh.template n_elements<HandleT>())
998 normal = 0.5 * (bbMax-bbMin).length() * mesh.
calc_normal(_handle);
1003 handle_valid =
false;
std::vector< int > IdList
Standard Type for id Lists used for scripting.
Functions for getting information about a mesh.
Functions for selection on a mesh.
#define DATA_TRIANGLE_MESH
int context_height() const
get gl context height
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
bool dataType(DataType _type) const
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 ¢er, 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.
int idx() const
Get the underlying index of this handle.
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.
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)
@ Color
Add colors to mesh item (vertices/faces/edges)
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())