75 emit addHiddenPickMode(EDGE_FLIP_POPUP);
76 emit addHiddenPickMode(EDGE_SPLIT_POPUP);
77 emit addHiddenPickMode(EDGE_COLLAPSE_POPUP);
78 emit addHiddenPickMode(FACE_ADD_POPUP);
79 emit addHiddenPickMode(FACE_SPLIT_POPUP);
80 emit addHiddenPickMode(FACE_DELETE_POPUP);
83 toolbar_ =
new QToolBar(
"Topology");
85 QActionGroup* group =
new QActionGroup(toolbar_);
87 QString iconPath = OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator();
89 const QString baseHelpURL =
"<a href='qthelp://org.openflipper.plugin-topology/Plugin-Topology/index.html";
90 const QString clickText = tr(
"Click for more information</a>");
93 edgeFlipAction_ = toolbar_->addAction( QIcon(iconPath +
"topology-edgeFlip.png"), EDGE_FLIP_POPUP );
94 edgeFlipAction_->setCheckable(
true);
95 edgeFlipAction_->setActionGroup(group);
96 edgeFlipAction_->setWhatsThis(tr(
"Flip edge. ") + baseHelpURL+
"#flip_edge'>" + clickText);
98 edgeSplitAction_ = toolbar_->addAction( QIcon(iconPath +
"topology-edgeSplit.png"), EDGE_SPLIT_POPUP );
99 edgeSplitAction_->setCheckable(
true);
100 edgeSplitAction_->setActionGroup(group);
101 edgeSplitAction_->setWhatsThis(tr(
"Split edge. ") + baseHelpURL+
"#split_edge'>" + clickText);
104 edgeCollapseAction_ = toolbar_->addAction( QIcon(iconPath +
"topology-edgeCollapse.png"), EDGE_COLLAPSE_POPUP );
105 edgeCollapseAction_->setCheckable(
true);
106 edgeCollapseAction_->setActionGroup(group);
107 edgeCollapseAction_->setWhatsThis(tr(
"Collapse edge. ") + baseHelpURL+
"#collapse_edge'>" + clickText);
110 toolbar_->addSeparator();
111 faceAddAction_ = toolbar_->addAction( QIcon(iconPath +
"topology-addFace.png"), FACE_ADD_POPUP );
112 faceAddAction_->setCheckable(
true);
113 faceAddAction_->setActionGroup(group);
114 faceAddAction_->setWhatsThis(tr(
"Add face.") + baseHelpURL+
"#add_face'>" + clickText);
117 faceDeleteAction_ = toolbar_->addAction( QIcon(iconPath +
"topology-deleteFace.png"), FACE_DELETE_POPUP );
118 faceDeleteAction_->setCheckable(
true);
119 faceDeleteAction_->setActionGroup(group);
120 faceDeleteAction_->setWhatsThis(tr(
"Delete face. ") + baseHelpURL+
"#delete_face'>" + clickText);
123 faceSplitAction_ = toolbar_->addAction( QIcon(iconPath +
"topology-splitFace.png"), FACE_SPLIT_POPUP );
124 faceSplitAction_->setCheckable(
true);
125 faceSplitAction_->setActionGroup(group);
126 faceSplitAction_->setWhatsThis(tr(
"Split face. ") + baseHelpURL+
"#split_face'>" + clickText);
128 group->setExclusive(
true);
130 connect( toolbar_, SIGNAL( actionTriggered(QAction*) ),
this, SLOT(
toolBarTriggered(QAction*) ));
132 emit addToolbar( toolbar_ );
238 if (( _event->type() != QEvent::MouseButtonPress) && (_event->type() != QEvent::MouseButtonDblClick))
241 size_t node_idx, target_idx;
256 float shortest_distance = (m.point(closest) - hit_point).sqrnorm();
259 if ( (m.point(*fv_it) - hit_point).sqrnorm() < shortest_distance ) {
260 shortest_distance = (m.point(*fv_it) - hit_point).sqrnorm();
265 if ( (m.point(*fv_it) - hit_point).sqrnorm() < shortest_distance ) {
271 std::pair<int,int> newVertex(object->
id(), closest.idx() );
273 for ( uint i = 0 ; i < addFaceVertices_.size() ; ++i ) {
274 if ( ( addFaceVertices_[i].first == newVertex.first ) &&
275 ( addFaceVertices_[i].second == newVertex.second ) ) {
276 addFaceVertices_.erase(addFaceVertices_.begin()+i);
277 m.status(closest).set_selected(
false);
285 addFaceVertices_.push_back( std::pair<int,int>(object->
id(), closest.idx() ) );
286 m.status(closest).set_selected(
true);
289 if ( addFaceVertices_.size() < 3 ) {
297 for ( uint i = 0 ; i < addFaceVertices_.size() ; ++i ) {
300 emit log(
LOGERR,
"Unable to get object for adding face");
305 if ( tmpObject->
dataType() != dt ) {
306 emit log(
LOGERR,
"Adding faces between different type of meshes is not supported!");
314 int objectId = addFaceVertices_[0].first;
315 for ( uint i = 0 ; i < addFaceVertices_.size() ; ++i ) {
316 if ( addFaceVertices_[i].first != objectId ) {
317 emit log(
LOGERR,
"Adding faces between different objects!");
328 bool errlog = omerr().is_enabled();
331 fh = m.add_face(vh0,vh1,vh2);
332 if ( !fh.is_valid() ) {
333 fh = m.add_face(vh2,vh1,vh0);
348 emit log(
LOGERR,
"Unable to add face!");
360 float shortest_distance = FLT_MAX;
363 float distance = (m.point( fv_it ) - hit_point).sqrnorm();
365 if (distance < shortest_distance){
366 shortest_distance = distance;
371 if (!closest.is_valid())
374 if (_event->type() != QEvent::MouseButtonDblClick){
376 std::pair<int,int> newVertex(object->
id(), closest.idx() );
378 for ( uint i = 0 ; i < addFaceVertices_.size() ; ++i ) {
379 if ( ( addFaceVertices_[i].first == newVertex.first ) &&
380 ( addFaceVertices_[i].second == newVertex.second ) ) {
381 addFaceVertices_.erase(addFaceVertices_.begin()+i);
382 m.status(closest).set_selected(
false);
390 addFaceVertices_.push_back( std::pair<int,int>(object->
id(), closest.idx() ) );
391 m.status(closest).set_selected(
true);
395 if ( (addFaceVertices_.size() < 3) || (_event->type() != QEvent::MouseButtonDblClick) ) {
403 for ( uint i = 0 ; i < addFaceVertices_.size() ; ++i ) {
406 emit log(
LOGERR,
"Unable to get object for adding face");
411 if ( tmpObject->
dataType() != dt ) {
412 emit log(
LOGERR,
"Adding faces between different type of meshes is not supported!");
420 int objectId = addFaceVertices_[0].first;
421 for ( uint i = 0 ; i < addFaceVertices_.size() ; ++i ) {
422 if ( addFaceVertices_[i].first != objectId ) {
423 emit log(
LOGERR,
"Adding faces between different objects!");
429 std::vector< PolyMesh::VertexHandle > vhs;
430 for ( uint i = 0 ; i < addFaceVertices_.size() ; ++i )
431 vhs.push_back( m.vertex_handle( addFaceVertices_[i].second ) );
434 bool errlog = omerr().is_enabled();
437 fh = m.add_face(vhs);
440 std::vector< PolyMesh::VertexHandle > rvhs;
442 while (!vhs.empty()){
443 rvhs.push_back( vhs.back() );
447 fh = m.add_face(rvhs);
463 emit log(
LOGERR,
"Unable to add face!");
478 if ( _event->type() != QEvent::MouseButtonPress )
492 emit log(
LOGOUT,
"Picked Face " + QString::number(fh.idx()) +
", normal (" +
493 QString::number(m.normal(fh)[0]) +
"," +
494 QString::number(m.normal(fh)[1]) +
"," +
495 QString::number(m.normal(fh)[2]) +
") ") ;
499 m.garbage_collection();
511 emit log(
LOGOUT,
"Picked Face " + QString::number(fh.idx()) +
", normal (" +
512 QString::number(m.normal(fh)[0]) +
"," +
513 QString::number(m.normal(fh)[1]) +
"," +
514 QString::number(m.normal(fh)[2]) +
") ") ;
518 m.garbage_collection();
537 if ( _event->type() != QEvent::MouseButtonPress )
540 size_t node_idx, target_idx;
550 emit log(
LOGOUT,
"Picked Face " + QString::number(fh.idx()) +
", normal (" +
551 QString::number(m.normal(fh)[0]) +
"," +
552 QString::number(m.normal(fh)[1]) +
"," +
553 QString::number(m.normal(fh)[2]) +
") ") ;
556 m.garbage_collection();
562 emit log(
LOGOUT,
"Picked Face " + QString::number(fh.idx()) +
", normal (" +
563 QString::number(m.normal(fh)[0]) +
"," +
564 QString::number(m.normal(fh)[1]) +
"," +
565 QString::number(m.normal(fh)[2]) +
") ") ;
568 m.garbage_collection();
586 if ( _event->type() != QEvent::MouseButtonPress )
589 size_t node_idx, target_idx;
612 if ( dist < min_dist ) {
614 closest_edge = m.edge_handle(e2);
618 if ( dist < min_dist) {
620 closest_edge = m.edge_handle(e3);
623 if ( m.is_flip_ok(closest_edge) )
624 m.flip(closest_edge);
626 emit log(
LOGERR,
"Flip is not allowed here!");
628 emit log(
LOGOUT,
"Picked Edge " + QString::number(closest_edge.idx()));
636 emit log(
LOGWARN,
"Edge Flips not supported for Poly Meshes");
651 if ( _event->type() != QEvent::MouseButtonPress )
654 size_t node_idx, target_idx;
677 if ( dist < min_dist ) {
679 closest_halfedge = e2;
683 if ( dist < min_dist) {
685 closest_halfedge = e3;
689 TriMesh::Point to = m.point( m.to_vertex_handle(closest_halfedge) );
690 TriMesh::Point from = m.point( m.from_vertex_handle(closest_halfedge) );
692 if ( (hit_point - to).sqrnorm() > (hit_point - from).sqrnorm() )
693 closest_halfedge = m.opposite_halfedge_handle(closest_halfedge);
695 if ( m.is_collapse_ok(closest_halfedge) ){
697 m.collapse(closest_halfedge );
698 m.garbage_collection();
700 emit log(
LOGERR,
"Collapse is not allowed here!");
702 emit log(
LOGOUT,
"Picked Edge " + QString::number(closest_halfedge.idx()));
716 double min_dist = FLT_MAX;
718 for(
auto fe_it : fh.
edges())
734 if ( (hit_point - to).sqrnorm() > (hit_point - from).sqrnorm() )
735 closest_edge = m.opposite_halfedge_handle(closest_edge);
739 m.collapse(closest_edge );
740 m.garbage_collection();
744 emit log(
LOGOUT,
"Picked Edge " + QString::number(closest_edge.idx()));
763 if ( _event->type() != QEvent::MouseButtonPress )
766 size_t node_idx, target_idx;
790 m.point(m.to_vertex_handle(e2)),
791 m.point(m.from_vertex_handle(e2)));
793 if (dist < min_dist) {
795 closest_edge = m.edge_handle(e2);
799 m.point(m.to_vertex_handle(e3)),
800 m.point(m.from_vertex_handle(e3)));
802 if (dist < min_dist) {
804 closest_edge = m.edge_handle(e3);
807 m.
split(closest_edge,hit_point);
809 emit log(
LOGOUT,
"Picked Edge " + QString::number(closest_edge.idx() ));
819 std::vector<OpenMesh::SmartHalfedgeHandle> halfEdgeHandles;
823 halfEdgeHandles.push_back(fh_it);
830 for (
auto iter : halfEdgeHandles)
835 closest_edge = iter.edge();
840 m.
split(closest_edge,hit_point);
842 emit log(
LOGOUT,
"Picked Edge " + QString::number(closest_edge.idx()) );