54 #include "PolyLinePlugin.hh"
56 #include <ACG/Scenegraph/ManipulatorNode.hh>
58 #if QT_VERSION >= 0x050000
69 GlutPrimitiveNode(
PolyLineObject* L, std::string name,
int _index = -1)
70 :
ACG::SceneGraph::GlutPrimitiveNode(
ACG::SceneGraph::GlutPrimitiveNode::SPHERE, L->manipulatorNode(), name)
88 :
ACG::SceneGraph::LineNode(LineSegmentsMode, L->manipulatorNode(), name)
110 pickToolBarActions_(0),
112 insertCircleAction_(0),
113 insertSplineAction_(0),
120 cutMultipleAction_(0),
122 cur_polyline_obj_(0),
125 create_point_ref_(0),
126 createCircle_CurrSelIndex_(-1),
127 createCircle_LastSelIndex_(-1),
128 moveCircle_SelNode_(0),
129 moveCircle_IsLocked(false),
130 moveCircle_IsFloating(false),
131 copyPaste_Action_(0),
132 copyPaste_ObjectId_(-1),
133 copyPaste_ActionType_(-1),
134 copyPaste_NewObjectId_(-1),
135 createSpline_CurrSelIndex_(-1),
136 createSpline_LastSelIndex_(-1),
137 moveBezSpline_SelNode_(0),
138 moveBezSpline_SelIndex_(-1),
139 moveBezSpline_SelSubIndex_(0),
141 smart_move_timer_(0),
142 cur_smart_move_obj_(0),
154 QSize size(100, 100);
156 tool_->setObjectName(
"PolyLineToolbar");
159 connect(
tool_->pb_subdivide,SIGNAL(clicked() ),
this,SLOT(slot_subdivide()));
160 connect(
tool_->subdivide_relative,SIGNAL(toggled(
bool) ),
this,SLOT(slot_subdivide_percent(
bool)));
161 connect(
tool_->pb_decimate,SIGNAL(clicked() ),
this,SLOT(slot_decimate()));
162 connect(
tool_->decimate_relative,SIGNAL(toggled(
bool) ),
this,SLOT(slot_decimate_percent(
bool)));
163 #ifdef EXTENDED_POLY_LINE
164 connect(
tool_->pb_resample_on_edges,SIGNAL(clicked() ),
this,SLOT(slot_resample_on_edges()));
166 tool_->pb_resample_on_edges->setDisabled(
true);
168 connect(
tool_->pb_smooth,SIGNAL(clicked() ),
this,SLOT(slot_smooth()));
169 connect(
tool_->pb_smooth,SIGNAL(clicked() ),
this,SIGNAL(updateView()));
170 connect(
tool_->pb_project,SIGNAL(clicked() ),
this,SLOT(slot_project()));
171 connect(
tool_->pb_project,SIGNAL(clicked() ),
this,SIGNAL(updateView()));
172 connect(
tool_->pb_smooth_project,SIGNAL(clicked() ),
this,SLOT(slot_smooth_project()));
173 connect(
tool_->pb_smooth_project,SIGNAL(clicked() ),
this,SIGNAL(updateView()));
175 connect(
tool_->rb_insert, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
176 connect(
tool_->rb_InsertCircle, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
177 connect(
tool_->rb_InsertSpline, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
178 connect(
tool_->rb_delete, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
179 connect(
tool_->rb_move, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
180 connect(
tool_->rb_smart_move, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
181 connect(
tool_->rb_merge, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
182 connect(
tool_->rb_split, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
184 connect(
tool_->sb_CirclePointNum, SIGNAL(valueChanged(
int)),
this, SLOT(slot_setCirclePointNum(
int)));
185 connect(
tool_->sb_SplineSegNum, SIGNAL(valueChanged(
int)),
this, SLOT(slot_setSplinePointNum(
int)));
187 tool_->rb_insert->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_insert.png") );
188 tool_->rb_InsertCircle->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_circle.png") );
189 tool_->rb_InsertSpline->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_bezier.png") );
190 tool_->rb_delete->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_delete.png") );
191 tool_->rb_move->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_move.png") );
192 tool_->rb_smart_move->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_move.png") );
193 tool_->rb_merge->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_merge.png") );
194 tool_->rb_split->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_split.png") );
201 QIcon* toolIcon =
new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"cut_polyline.png");
202 emit addToolbox( tr(
"PolyLine") ,
tool_, toolIcon );
211 slotMouseEvent( QMouseEvent* _event )
213 copyPaste_LastMouse = _event->pos();
216 if (_event->modifiers() & (Qt::ControlModifier))
220 && _event->button() != Qt::RightButton) {
227 case PL_INSERTCIRCLE:
228 me_insertCircle(_event);
231 case PL_INSERTSPLINE:
232 me_insertSpline(_event);
252 me_smart_move(_event);
256 me_copyPasteMouse(_event);
267 void PolyLinePlugin::slotKeyEvent(QKeyEvent* event) {
268 switch (event->key()) {
271 if(mode() == PL_INSERT && cur_polyline_obj_ && cur_insert_id_ != -1) {
274 if (event->modifiers() & (Qt::ShiftModifier))
280 cur_polyline_obj_ = 0;
281 create_point_ref_ = 0;
283 clearStatusMessage();
285 else if(mode() == PL_INSERTSPLINE) {
298 slotPickModeChanged(
const std::string& _mode)
301 cutAction_->setChecked( _mode == CREATE_CUT_POLYLINE );
314 emit addHiddenPickMode(
"PolyLine");
315 emit setPickModeMouseTracking(
"PolyLine",
true);
316 emit addHiddenPickMode( CREATE_CUT_POLYLINE );
317 emit addHiddenPickMode( CREATE_CUT_POLYLINES );
319 emit registerKey(Qt::Key_Return, Qt::NoModifier, tr(
"Terminate creation of poly line."),
true);
320 emit registerKey(Qt::Key_Return, Qt::ShiftModifier, tr(
"Terminate creation of poly line and create loop."),
true);
323 toolbar_ =
new QToolBar(tr(
"PolyLine Editing"));
324 toolbar_->setObjectName(
"PolyLineEditingToolbar");
332 polyLineAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_insert.png") );
337 cutAction_ =
new QAction(tr(
"&Create polyline at intersection with plane"),
this);
339 cutAction_->setStatusTip(tr(
"Create a polyline by specifying a plane with which the object is then intersected. The polyline will be created at the intersection."));
340 cutAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"cut_polyline.png") );
345 cutMultipleAction_ =
new QAction(tr(
"&Create polylines at intersection with plane"),
this);
347 cutMultipleAction_->setStatusTip(tr(
"Create polylines by specifying a plane with which the object is then intersected. The polylines will be created at the intersection."));
348 cutMultipleAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"cut_polylines.png") );
358 pickToolbar_->setObjectName(
"PolyLine_Editing_Toolbar");
359 pickToolbar_->setAttribute(Qt::WA_AlwaysShowToolTips,
true);
366 "Use <Doubleclick> to finish the line.\n"
367 "Hold <Shift> to close line on finish."));
368 insertAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_insert.png") );
375 "<Click> to select the center.\n"
376 "Drag to specify the radius."));
378 insertCircleAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_circle.png") );
385 "<Click> to select the points."));
387 insertSplineAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_bezier.png") );
392 deleteAction_->setStatusTip(tr(
"Delete a complete PolyLine."));
393 deleteAction_->setToolTip(tr(
"Delete a complete PolyLine.\n"
394 "<Click> on the lines you want to delete."));
395 deleteAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_delete.png") );
402 smartMoveAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_move.png") );
409 "Drag one endpoint of a PolyLine to the EndPoint of another one.\n"));
410 mergeAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_merge.png") );
415 splitAction_->setStatusTip(tr(
"Split a PolyLine at a given point."));
416 splitAction_->setToolTip(tr(
"Split a PolyLine at a given point.\n"
417 "<Click> on the vertex where you want to split the PolyLine and drag it away."));
418 splitAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_split.png") );
425 moveAction_->setStatusTip(tr(
"Move a Vertex of a PolyLine"));
426 moveAction_->setToolTip(tr(
"Move a single Vertex of a PolyLine."));
427 moveAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_move.png") );
436 smart_move_timer_ =
new QTimer(
this);
437 connect(smart_move_timer_, SIGNAL(timeout()),
this, SLOT(slot_smart_move_timer()));
442 connect(
planeSelect_, SIGNAL( updateViewProxy( ) ),
this, SIGNAL( updateView() ) );
443 connect(
planeSelect_, SIGNAL( nodeVisChangedProxy(
int) ),
this, SIGNAL(nodeVisibilityChanged(
int) ) );
446 copyPaste_Action_ =
new QAction(
"Duplicate", 0);
447 connect(copyPaste_Action_,SIGNAL(triggered() ),
this,SLOT(slot_duplicate()));
486 emit log(
"Cutting object " + object->
name());
489 emit log(
"Only Meshes are supported at the moment ");
500 QString command =
"generatePolyLineFromCut(" + QString::number(object->
id()) +
",Vector("
501 + QString::number(point[0]) +
"," + QString::number(point[1]) +
"," + QString::number(point[2]) +
"),Vector("
502 + QString::number(normal[0]) +
"," + QString::number(normal[1]) +
"," + QString::number(normal[2]) +
"));";
503 emit scriptInfo(command);
508 if (o_it->id() !=
object->id()) {
520 QString command =
"generatePolyLinesFromCut(" + QString::number(object->
id()) +
",Vector("
521 + QString::number(point[0]) +
"," + QString::number(point[1]) +
"," + QString::number(point[2]) +
"),Vector("
522 + QString::number(normal[0]) +
"," + QString::number(normal[1]) +
"," + QString::number(normal[2]) +
"));";
523 emit scriptInfo(command);
528 if (o_it->id() !=
object->id()) {
533 for (
unsigned int i = 0 ; i < objectIds.size() ; ++i ) {
535 if ( objectIds[i] != -1)
551 double max_length =
tool_->dsb_subdivide->value();
554 if (max_length == 0.0)
573 void PolyLinePlugin::slot_subdivide_percent(
bool _checked) {
577 double total_length = 0;
588 double v = total_length / double(n_active_pl);
593 if (n_active_pl > 0) {
594 double val_new =
tool_->dsb_subdivide->value() / v;
595 tool_->dsb_subdivide->setValue(val_new);
597 emit log(
LOGWARN,
"Could not find any active polyline!");
602 if (n_active_pl > 0) {
603 double val_new =
tool_->dsb_subdivide->value() * v;
604 tool_->dsb_subdivide->setValue(val_new);
606 emit log(
LOGWARN,
"Could not find any active polyline!");
620 double min_length =
tool_->dsb_decimate->value();
637 void PolyLinePlugin::slot_decimate_percent(
bool _checked)
642 double total_length = 0;
653 double v = total_length / double(n_active_pl);
658 if (n_active_pl > 0) {
659 double val_new =
tool_->dsb_subdivide->value() / v;
660 tool_->dsb_decimate->setValue(val_new);
662 emit log(
LOGWARN,
"Could not find any active polyline!");
667 if (n_active_pl > 0) {
668 double val_new =
tool_->dsb_subdivide->value() * v;
669 tool_->dsb_decimate->setValue(val_new);
671 emit log(
LOGWARN,
"Could not find any active polyline!");
679 #ifdef EXTENDED_POLY_LINE
683 slot_resample_on_edges()
687 unsigned int n_targetMeshes(0);
691 if( n_targetMeshes != 1)
693 std::cerr <<
"Warning: resample_on_edges needs exactly 1 target mesh! Otherwise no operation is performed! \n";
706 TriMesh* mesh = tmesh_obj->
mesh();
717 std::cerr <<
"resample " << o_it2->name().toStdString() << std::endl;
741 for(
int i=0; i<
tool_->sb_smooth_iter->value(); ++i)
742 if(
tool_->rb_smooth_c0->isChecked())
746 if(
tool_->rb_smooth_c1->isChecked())
750 if(
tool_->rb_smooth_c2->isChecked())
769 for (
int i = 0; i <
tool_->sb_smooth_iter->value(); ++i)
770 if (
tool_->rb_smooth_c0->isChecked())
773 else if (
tool_->rb_smooth_c1->isChecked())
776 else if (
tool_->rb_smooth_c2->isChecked())
792 std::vector<TriMesh*> meshes;
793 std::vector<OpenMeshTriangleBSPT<TriMesh>*> bsps;
802 meshes.push_back(tmesh_obj->
mesh());
829 std::vector<TriMesh*> meshes;
830 std::vector<OpenMeshTriangleBSPT<TriMesh>*> bsps;
840 meshes.push_back(tmesh_obj->
mesh());
857 slot_smooth_project()
859 int smooth_project_iter =
tool_->sb_smooth_project_iter->value();
861 for (
int i = 0, j = 1; i < smooth_project_iter; ++i, ++j) {
880 int smooth_project_iter =
tool_->sb_smooth_project_iter->value();
882 for (
int i = 0, j = 1; i < smooth_project_iter; ++i, ++j) {
899 slot_smart_move_timer()
901 int smooth_project_iter =
tool_->sb_smooth_project_iter->value();
903 if (smooth_project_iter)
904 slot_smooth_project(cur_smart_move_obj_);
906 slot_smooth(cur_smart_move_obj_);
914 PolyLinePlugin::slotObjectUpdated(
int _identifier,
const UpdateType &_type )
921 GlutPrimitiveNode* H = 0, *C = 0;
924 if(circleData && !C) {
925 createCircle_createUI(_identifier);
927 else if(splineData && !H) {
928 createSpline_createUI(_identifier);
938 if(copyPaste_ObjectId_ != -1 && copyPaste_ActionType_ != -1)
939 return PL_COPY_PASTE;
943 if(
tool_->rb_insert->isChecked() )
return PL_INSERT;
944 if(
tool_->rb_InsertCircle->isChecked() )
return PL_INSERTCIRCLE;
945 if(
tool_->rb_InsertSpline->isChecked() )
return PL_INSERTSPLINE;
946 else if(
tool_->rb_delete->isChecked() )
return PL_DELETE;
947 else if(
tool_->rb_move->isChecked() )
return PL_MOVE;
948 else if(
tool_->rb_split->isChecked() )
return PL_SPLIT;
949 else if(
tool_->rb_merge->isChecked() )
return PL_MERGE;
950 else if(
tool_->rb_smart_move->isChecked())
return PL_SMART_MOVE;
960 me_insert( QMouseEvent* _event )
962 if (_event->type() == QEvent::MouseMove) {
963 if (create_point_ref_) {
965 unsigned int node_idx, target_idx;
968 *create_point_ref_ = (PolyLine::Point) hit_point;
978 unsigned int node_idx, target_idx;
982 switch (_event->type()) {
984 case QEvent::MouseButtonPress: {
1004 cur_polyline_obj_->
line()->
add_point((PolyLine::Point) hit_point);
1006 emit showStatusMessage(tr(
"Double click/Enter to terminate poly line. Use with shift to create loop."));
1010 cur_polyline_obj_->
line()->
add_point((PolyLine::Point) hit_point);
1011 create_point_ref_ = &cur_polyline_obj_->
line()->
points().back();
1020 case QEvent::MouseButtonDblClick: {
1022 if (_event->modifiers() & (Qt::ShiftModifier)) {
1035 cur_insert_id_ = -1;
1036 cur_polyline_obj_ = 0;
1037 create_point_ref_ = 0;
1039 clearStatusMessage();
1052 double getRad(
int meshIdx)
1057 ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1058 ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1060 return 0.005*(bbMax-bbMin).norm();
1067 void PolyLinePlugin::
1068 createCircle_createUI(
int _polyLineObjectID)
1077 double rad = getRad(lineData->circleMeshIndex_);
1079 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Handle0");
1080 handle0->get_primitive(0).color =
ACG::Vec4f(1,0,0,1);
1081 handle0->set_size(rad);
1083 handle0->enablePicking(
true);
1084 handle0->set_position(lineData->circleCenter_ + lineData->circleMainAxis_ * lineData->circleMainRadius_);
1088 GlutPrimitiveNode* handle1 =
new GlutPrimitiveNode(lineObject,
"N_Handle1");
1089 handle1->get_primitive(0).color =
ACG::Vec4f(0,1,0,1);
1090 handle1->set_size(rad);
1092 handle1->enablePicking(
true);
1093 handle1->set_position(lineData->circleCenter_ + lineData->circleSideAxis_ * lineData->circleSideRadius_);
1097 GlutPrimitiveNode* cenNode =
new GlutPrimitiveNode(lineObject,
"N_Center");
1098 cenNode->get_primitive(0).color =
ACG::Vec4f(0,0,1,1);
1099 cenNode->set_size(rad);
1101 cenNode->enablePicking(
true);
1102 cenNode->set_position(lineData->circleCenter_);
1106 emit updatedObject(_polyLineObjectID,
UPDATE_ALL);
1111 void PolyLinePlugin::
1112 me_insertCircle(QMouseEvent* _event)
1115 TriMesh::FaceHandle fh;
1116 TriMesh::VertexHandle vh;
1118 if(!pick_triangle_mesh(_event->pos(), mesh, fh, vh, hit_point) && _event->type() != QEvent::MouseButtonRelease)
1127 const ACG::Vec3d n = circleData->circleNormal_, x0 = circleData->circleCenter_;
1128 const double t = ((n | x0) - (n | hit_point)) / n.sqrnorm();
1129 const ACG::Vec3d onPlane = hit_point + t * n, d = onPlane - x0;
1131 circleData->circleMainAxis_ = (onPlane - x0).normalize();
1132 circleData->circleSideRadius_ = circleData->circleMainRadius_ = d.norm();
1133 circleData->circleSideAxis_ = (circleData->circleMainAxis_ % n).normalize();
1149 if(!mesh->
mesh()->has_face_normals())
1150 mesh->
mesh()->request_face_normals();
1160 else if(_event->type() == QEvent::MouseButtonRelease ) {
1168 createCircle_CurrSelIndex_ = -1;
1174 void PolyLinePlugin::
1175 createSpline_createUI(
int _polyLineObjectID)
1186 GlutLineNode* lineN =
new GlutLineNode(lineObject,
"N_Line");
1188 lineN->enablePicking(
false);
1192 for(
unsigned int i = 0; i < splineData->points_.size(); i++) {
1193 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Control", i);
1194 handle0->get_primitive(0).color =
ACG::Vec4f(0,1,0,1);
1195 handle0->set_size(rad);
1197 handle0->set_position(splineData->points_[i].position);
1199 handle0->enablePicking(
true);
1203 for(
unsigned int i = 0; i < splineData->handles_.size(); i++) {
1205 const ACG::Vec3d hndlPos = splineData->handles_[i], ctrlPos = control.position;
1207 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Handle", i);
1208 handle0->get_primitive(0).color =
ACG::Vec4f(0,0,1,1);
1209 handle0->set_size(rad * 0.75);
1211 handle0->enablePicking(
true);
1212 handle0->set_position(hndlPos);
1216 GlutLineNode* lineN;
1218 lineN->add_line(ctrlPos, hndlPos);
1224 emit updatedObject(_polyLineObjectID,
UPDATE_ALL);
1243 ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1244 ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1250 GlutPrimitiveNode* control = 0;
1252 for(
unsigned int i = 0; i < splineData->points_.size(); i++) {
1254 control->enablePicking(
true);
1257 for(
unsigned int i = 0; i < splineData->handles_.size(); i++) {
1259 const ACG::Vec3d hndlPos = splineData->handles_[i], ctrlPos = control.position;
1261 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Handle", i);
1262 handle0->get_primitive(0).color =
ACG::Vec4f(0,0,1,1);
1263 handle0->set_size(0.004*sizeBB.norm());
1265 handle0->enablePicking(
true);
1266 handle0->set_position(hndlPos);
1270 GlutLineNode* lineN;
1272 lineN->add_line(ctrlPos, hndlPos);
1283 void PolyLinePlugin::
1284 me_insertSpline(QMouseEvent* _event)
1288 TriMesh::FaceHandle fh;
1289 TriMesh::VertexHandle vh;
1292 if(!pick_triangle_mesh(_event->pos(), mesh, fh, vh, hit_point))
1295 ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1296 ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1300 if(!mesh->
mesh()->has_face_normals())
1301 mesh->
mesh()->request_face_normals();
1305 if(_event->type() == QEvent::MouseButtonPress) {
1325 GlutLineNode* lineN =
new GlutLineNode(newLine,
"N_Line");
1327 lineN->enablePicking(
false);
1332 ACG::Vec3d insert_Point = hit_point + nor * 0.003 * sizeBB.norm();
1339 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Control", splineData->points_.size());
1340 handle0->get_primitive(0).color =
ACG::Vec4f(0,1,0,1);
1341 handle0->set_size(0.005*sizeBB.norm());
1343 handle0->set_position(insert_Point);
1345 handle0->enablePicking(
false);
1352 if(_event->type() == QEvent::MouseButtonDblClick) {
1361 me_delete( QMouseEvent* _event )
1364 if (_event->type() == QEvent::MouseButtonPress) {
1366 unsigned int node_idx, target_idx;
1376 emit deleteObject(obj->
id());
1392 if(moveCircle_SelNode_)
1395 if(moveCircle_SelNode_)
1400 _node_idx = obj->
id();
1406 if(!_moveCircle_SelNode_->
name().compare(
"N_Center"))
1408 _lineData->circleNormal_ = _nor;
1409 _lineData->circleCenter_ = _hit_point;
1410 _lineData->circleSideAxis_ = (_lineData->circleMainAxis_ % _lineData->circleNormal_).normalize();
1411 _lineData->circleMainAxis_ = (_lineData->circleNormal_ % _lineData->circleSideAxis_).normalize();
1415 const double cr = (_onPlane - _lineData->circleCenter_).norm();
1416 const ACG::Vec3d axisa = (_onPlane - _lineData->circleCenter_).normalize();
1417 if (!_moveCircle_SelNode_->
name().compare(
"N_Handle0")) {
1418 const ACG::Vec3d axisb = (axisa % _lineData->circleNormal_).normalize();
1419 _lineData->circleMainRadius_ = cr;
1422 _lineData->circleSideRadius_ = cr;
1424 _lineData->circleMainAxis_ = axisa;
1425 _lineData->circleSideAxis_ = axisb;
1427 const ACG::Vec3d axisb = (_lineData->circleNormal_ % axisa).normalize();
1428 _lineData->circleSideRadius_ = cr;
1431 _lineData->circleMainRadius_ = cr;
1433 _lineData->circleSideAxis_ = axisa;
1434 _lineData->circleMainAxis_ = axisb;
1442 me_move( QMouseEvent* _event )
1444 if((_event->modifiers() & Qt::ShiftModifier) != Qt::ShiftModifier && moveCircle_IsLocked)
1445 moveCircle_IsLocked = moveCircle_IsFloating =
false;
1448 if (_event->type() == QEvent::MouseButtonPress) {
1450 unsigned int node_idx, target_idx;
1455 GlutPrimitiveNode* glutNode =
dynamic_cast<GlutPrimitiveNode*
>(node);
1461 moveCircle_SelNode_ = glutNode;
1484 cur_move_id_ = cur_pol->
id();
1486 move_point_ref_ = &(cur_pol->
line()->
point(target_idx));
1493 if (_event->type() == QEvent::MouseMove){
1494 if (moveCircle_SelNode_) {
1500 unsigned int target_idx;
1501 bool hasHit = me_GetMeshHit(_event, moveCircle_SelNode_, hit_point, lineData->circleMeshIndex_, target_idx);
1502 if(lineData->circleMeshIndex_ == std::numeric_limits<unsigned int>::max())
return;
1503 if(!moveCircle_IsLocked && hasHit) {
1504 moveCircle_IsFloating =
false;
1505 ACG::Vec3d x0 = lineData->circleCenter_, n = lineData->circleNormal_;
1507 double t = ((n | x0) - (n | onMesh)) / n.sqrnorm();
1513 me_UpdateCircleData(onMesh, onPlane, mesh->
mesh()->normal(mesh->
mesh()->face_handle(target_idx)), moveCircle_SelNode_, lineData, (_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier);
1514 if (!moveCircle_SelNode_->
name().compare(
"N_Center")) {
1516 if((_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier) {
1517 moveCircle_IsLocked =
true;
1518 moveCircle_LastHitNor_ = lineData->circleNormal_;
1524 moveCircle_IsFloating =
true;
1533 : lineData->circleNormal_;
1534 const double t = ((x0 | n) - (cameraPos | n)) / (cameraDir | n);
1535 const ACG::Vec3d onPlane = cameraPos + cameraDir * t;
1537 me_UpdateCircleData(onPlane, onPlane, n, moveCircle_SelNode_, lineData, (_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier);
1549 unsigned int target_idx;
1551 if(lineData->
meshIndex_ == std::numeric_limits<unsigned int>::max())
1557 ACG::Vec3d onMesh = hit_point, onMeshNor = mesh->
mesh()->normal(mesh->
mesh()->face_handle(target_idx));
1561 lineData->points_[controlIndex].position = onMesh;
1562 lineData->points_[controlIndex].normal = onMeshNor;
1564 int handleIndex = 2 * controlIndex - 1;
1565 ACG::Vec3d dir = lineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
1567 lineData->handles_[handleIndex] = point;
1569 if(controlIndex != ((
int)lineData->points_.size() - 1)) {
1570 int handleIndex = 2 * controlIndex;
1571 ACG::Vec3d dir = lineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
1573 lineData->handles_[handleIndex] = point;
1584 double t = ((control.normal | control.position) - (control.normal | cameraPos)) / (control.normal | cameraDir);
1585 ACG::Vec3d onPlane = cameraPos + t * cameraDir;
1587 lineData->handles_[handleIndex] = onPlane;
1588 if(handleIndex % 2 == 1 && handleIndex != ((
int)lineData->handles_.size() - 1)) {
1589 double dist = (lineData->handles_[handleIndex + 1] - control.position).norm();
1590 if(_event->modifiers() & Qt::ShiftModifier)
1591 dist = (onPlane - control.position).norm();
1592 ACG::Vec3d dir = -(onPlane - control.position).normalize();
1593 lineData->handles_[handleIndex + 1] = control.position + dir * dist;
1595 if(handleIndex % 2 == 0 && handleIndex) {
1596 double dist = (lineData->handles_[handleIndex - 1] - control.position).norm();
1597 if(_event->modifiers() & Qt::ShiftModifier)
1598 dist = (onPlane - control.position).norm();
1599 ACG::Vec3d dir = -(onPlane - control.position).normalize();
1600 lineData->handles_[handleIndex - 1] = control.position + dir * dist;
1603 GlutLineNode* lineN;
1609 else if (move_point_ref_ != 0) {
1611 unsigned int node_idx, target_idx;
1613 (*move_point_ref_) = (PolyLine::Point) hit_point;
1621 if (_event->type() == QEvent::MouseButtonRelease) {
1622 if((_event->modifiers() & Qt::ShiftModifier) != Qt::ShiftModifier) {
1625 moveCircle_IsLocked = moveCircle_IsFloating =
false;
1629 moveCircle_IsLocked =
false;
1634 move_point_ref_ = 0;
1635 moveCircle_SelNode_ = 0;
1636 createCircle_CurrSelIndex_ = -1;
1646 me_split( QMouseEvent* _event )
1649 if (_event->type() == QEvent::MouseButtonPress) {
1651 move_point_ref_ = 0;
1653 unsigned int node_idx, target_idx;
1675 cur_move_id_ = cur_pol->
id();
1706 cur_move_id_ = cur_pol->
id();
1722 if (_event->type() == QEvent::MouseMove)
1723 if (move_point_ref_ != 0) {
1725 unsigned int node_idx, target_idx;
1729 (*move_point_ref_) = (PolyLine::Point) hit_point;
1738 if (_event->type() == QEvent::MouseButtonRelease) {
1740 if (cur_move_id_ != -1)
1743 move_point_ref_ = 0;
1754 me_merge( QMouseEvent* _event )
1757 if (_event->type() == QEvent::MouseButtonPress) {
1759 move_point_ref_ = 0;
1762 unsigned int node_idx, target_idx;
1777 if (target_idx == cur_pol->
line()->
n_vertices() - 1 || target_idx == 0) {
1778 if (target_idx == 0) {
1784 cur_merge_id_ = cur_pol->
id();
1797 if (_event->type() == QEvent::MouseMove && cur_merge_id_ != -1)
1798 if (move_point_ref_ != 0) {
1799 unsigned int node_idx, target_idx;
1803 (*move_point_ref_) = (PolyLine::Point) hit_point;
1812 if (_event->type() == QEvent::MouseButtonRelease && cur_merge_id_ != -1) {
1813 PolyLine::Point p_save;
1816 if (move_point_ref_ != 0) {
1828 move_point_ref_ = 0;
1831 unsigned int node_idx, target_idx;
1840 PluginFunctions::invalidatePickCaches();
1842 bool merged =
false;
1855 if ( target_idx < second_pol->line()->n_vertices() ) {
1858 unsigned int second_idx = target_idx;
1863 bool inv_first(
false), inv_second(
false);
1866 if (first_idx == 0) {
1878 if (first_idx == first_pol->
line()->
n_vertices() - 1 && second_idx == 0) {
1880 if (first_pol->
id() == second_pol->
id()) {
1897 emit deleteObject(second_pol->
id());
1908 PluginFunctions::invalidatePickCaches();
1921 if ( target_idx < second_pol->line()->n_vertices() ) {
1924 unsigned int second_idx = target_idx;
1930 if (first_idx == 0) {
1939 if (first_pol->
id() == second_pol->
id() && first_idx == first_pol->
line()->
n_vertices() - 1 && second_idx == 0) {
1964 move_point_ref_ = 0;
1976 me_smart_move( QMouseEvent* _event )
1979 if (_event->type() == QEvent::MouseButtonPress) {
1981 unsigned int node_idx, target_idx;
1994 cur_polyline_obj_ = cur_pol;
2001 cur_smart_move_obj_ = cur_pol;
2002 if (cur_pol->
line()->vertex_selections_available()) {
2003 if (!(_event->modifiers() & (Qt::ShiftModifier)))
2004 cur_pol->
line()->vertex_selection(target_idx) =
true;
2006 cur_pol->
line()->vertex_selection(target_idx) =
false;
2014 if (!(_event->modifiers() & (Qt::ShiftModifier)))
2015 smart_move_timer_->start(20);
2022 if( _event->type() == QEvent::MouseButtonRelease)
2024 smart_move_timer_->stop();
2025 cur_smart_move_obj_ = NULL;
2037 slotEditModeChanged()
2050 GlutPrimitiveNode* H0, *H1, *C;
2054 ACG::Vec3d h0 = circleData->circleCenter_ + circleData->circleMainAxis_ * circleData->circleMainRadius_,
2055 h1 = circleData->circleCenter_ + circleData->circleSideAxis_ * circleData->circleSideRadius_;
2057 C->set_position(circleData->circleCenter_);
2068 slot_setCirclePointNum(
int i)
2079 slot_setSplinePointNum(
int i)
2092 tool_->rb_insert->setChecked(
true);
2094 tool_->rb_InsertCircle->setChecked(
true);
2096 tool_->rb_InsertSpline->setChecked(
true);
2098 tool_->rb_delete->setChecked(
true);
2100 tool_->rb_move->setChecked(
true);
2102 tool_->rb_smart_move->setChecked(
true);
2104 tool_->rb_merge->setChecked(
true);
2106 tool_->rb_split->setChecked(
true);
2126 slotEnablePickMode(QString _name)
2133 if(_name ==
"INSERT")
2134 tool_->rb_insert->setChecked(
true);
2135 else if(_name ==
"DELETE")
2136 tool_->rb_delete->setChecked(
true);
2137 else if(_name ==
"MOVE")
2138 tool_->rb_move->setChecked(
true);
2139 else if(_name ==
"SPLIT")
2140 tool_->rb_split->setChecked(
true);
2141 else if(_name ==
"MERGE")
2142 tool_->rb_merge->setChecked(
true);
2143 else if( _name ==
"SMART_MOVE")
2144 tool_->rb_smart_move->setChecked(
true);
2152 pick_triangle_mesh( QPoint mPos,
2156 _fh = TriMesh::FaceHandle (-1);
2157 _vh = TriMesh::VertexHandle(-1);
2159 unsigned int target_idx = 0, node_idx = 0;
2177 _fh = m.face_handle(target_idx);
2179 TriMesh::FaceVertexIter fv_it(m,_fh);
2180 TriMesh::VertexHandle closest = *fv_it;
2181 float shortest_distance = (m.point(closest) - hit_point).sqrnorm();
2184 if ( (m.point(*fv_it ) - hit_point).sqrnorm() < shortest_distance ) {
2185 shortest_distance = (m.point(*fv_it ) - hit_point).sqrnorm();
2190 if ( (m.point(*fv_it ) - hit_point).sqrnorm() < shortest_distance ) {
2197 _hitPoint = hit_point;
2210 slotUpdateContextMenu(
int objectId)
2212 copyPaste_ObjectId_ = objectId;
2213 copyPaste_Action_->setVisible(
pickToolbar_->isVisible());
2218 me_copyPasteMouse(QMouseEvent* _event)
2225 copyPaste_ObjectId_ = copyPaste_ActionType_ - 1;
2228 unsigned int target_idx = 0, node_idx = 0;
2231 if(copyPaste_ActionType_ == 1) {
2241 GlutPrimitiveNode* glutNode =
dynamic_cast<GlutPrimitiveNode*
>(node);
2243 me_GetMeshHit(_event, glutNode, hit_point, circleData->circleMeshIndex_, target_idx);
2245 circleData-> circleCenter_ = hit_point;
2249 else if(oldSplineData) {
2250 for(
int i = 0; i < (int)splineData->points_.size(); i++) {
2251 ACG::Vec3d onMeshNor, oldPos = splineData->points_[i].position;
2253 splineData->points_[i].position = onMesh;
2254 splineData->points_[i].normal = onMeshNor;
2256 int handleIndex = 2 * i - 1;
2257 ACG::Vec3d dir = splineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
2259 splineData->handles_[handleIndex] = point;
2261 if(i != ((
int)splineData->points_.size() - 1)) {
2262 int handleIndex = 2 * i;
2263 ACG::Vec3d dir = splineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
2265 splineData->handles_[handleIndex] = point;
2268 GlutLineNode* lineN;
2276 newObj->
line()->
point(i) = hit_point + copyPaste_RelativePoints_[i];
2281 if(_event->type() == QEvent::MouseButtonPress) {
2282 copyPaste_ActionType_ = copyPaste_ObjectId_ = -1;
2285 else if(copyPaste_ActionType_ == 2) {
2299 unsigned int target_idx = 0, node_idx = 0;
2302 QPoint mPos = copyPaste_LastMouse;
2304 copyPaste_ActionType_ = 1;
2318 copyPaste_RelativePoints_.clear();
2323 createCircle_createUI(new_line_id);
2325 else if(splineData) {
2328 createSpline_createUI(new_line_id);
2331 for(
size_t i = 0; i < newData->points_.size(); i++)
2332 copyPaste_RelativePoints_.push_back(newData->points_[i].position - hit_point);
2339 copyPaste_RelativePoints_.push_back(obj->
line()->
point(i) - hit_point);
2343 copyPaste_NewObjectId_ = new_line_id;
2354 copyPaste_ActionType_ = 2;
2358 #if QT_VERSION < 0x050000
int createSpline_CurrSelIndex_
The index of the currently created spline.
QAction * deleteAction_
Called by pick Toolbar.
void smooth_uniform_laplace()
Laplacian smoothing.
void invert()
Invert polyline that first vertex becomes last.
PolyLinePlugin()
default constructor
void slotSetPolyLineMode(QAction *_action)
Called by Toolbar to enable pick mode.
void slotScissorLinesButton()
Scissor Button for multiple polylines was hit.
void enablePicking(bool _enable)
Enable or disable picking for this Object.
size_t n_vertices() const
Get number of vertices.
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
int createCircle_LastSelIndex_
Use this one to mark the last index to update the number of points.
MeshT * mesh()
return a pointer to the mesh
Namespace providing different geometric functions concerning angles.
void smooth_uniform_laplace3()
Cubic laplacian smoothing.
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
std::string name() const
Returns: name of node (needs not be unique)
int generatePolyLineFromCut(int _objectId, Vector _planePoint, Vector _planeNormal, int _polyLineId=-1)
Generates a polyLine of a plane intersection.
PerObjectData * objectData(QString _dataName)
Returns the object data pointer.
QString name() const
return the name of the object. The name defaults to NONAME if unset.
picks faces (should be implemented for all nodes)
pick any of the prior targets (should be implemented for all nodes)
PolyLineObject * polyLineObject(BaseObjectData *_object)
Cast an BaseObject to a PolyLineObject if possible.
Type for a MeshObject containing a triangle mesh.
void viewingDirection(const ACG::Vec3d &_dir, const ACG::Vec3d &_up, int _viewer)
Set the viewing direction.
bool getAdditionalNode(NodeT *&_node, QString _pluginName, QString _nodeName, int _id=0)
get an addition node from the object
void updatePolyEllipse(PolyLineObject *_lineObject, unsigned int _pointCount)
Generates points for the ellipse.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
QAction * polyLineAction_
Called by Toolbar to enable pick mode.
void set_random_color()
Generates a random color and sets it.
bool getObject(int _identifier, BSplineCurveObject *&_object)
void updatePolyBezierHandles(PolyLineObject *_lineObject, ACG::SceneGraph::LineNode *_line)
Updates all the handles on the PolyBezier.
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
void project_to_mesh(const MeshT &_mesh, SpatialSearchT *_ssearch=0)
Project polyline points to nearest surface points (use spatial search!!!)
MaterialNode * materialNode()
get a pointer to the materialnode
QAction * cutMultipleAction_
Called by pick Toolbar.
VectorT< float, 4 > Vec4f
OMTriangleBSP * requestTriangleBsp()
VectorT< double, 3 > Vec3d
QAction * splitAction_
Called by pick Toolbar.
bool is_closed() const
Check if the polyline is marked as closed.
QActionGroup * toolBarActions_
Called by Toolbar to enable pick mode.
void set_vertex_radius(const Scalar _r)
set ball-radius of vertices
const Vec3d get_position(int _idx=0) const
get position
void slotPickToolbarAction(QAction *_action)
Called by pick Toolbar.
EditMode
Edit Mode of PolyLinePlugin.
const QStringList TARGET_OBJECTS("target")
Iterable object range.
bool dataType(DataType _type) const
void delete_point(int _idx)
Delete point at _idx.
QToolBar * pickToolbar_
Called by pick Toolbar.
picks verices (may not be implemented for all nodes)
void addInterpolatePoint(ACG::Vec3d _position, ACG::Vec3d _normal)
Adds a point to the end of the list and inserts control points.
QAction * insertCircleAction_
Called by pick Toolbar.
void boundingBox(ACG::Vec3d &_bbMin, typename ACG::Vec3d &_bbMax)
Get the BoundingBox of this object.
void smooth_uniform_laplace2()
Squared laplacian smoothing.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
QAction * mergeAction_
Called by pick Toolbar.
void subdivide(Scalar _largest)
Subdivide polyline.
void updateHandles(PolyLineObject *_lineObject)
Updates the center, forward and side handle of the Poly ellipse.
const std::string pickMode()
Get the current Picking mode.
QAction * insertAction_
Called by pick Toolbar.
InterpolatePoint & getInterpolatePoint(unsigned int _handleIndex)
Retrieves the interpolate point based on the handle.
std::vector< Point > & points()
Get all points of the polyline.
void setObjectData(QString _dataName, PerObjectData *_data)
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
BaseObject * childExists(int _objectId)
Check if the element exists in the subtree of this element.
BaseObject *& objectRoot()
Get the root of the object structure.
void split(unsigned int _split_idx, PolyLineT< PointT > &_new_pl)
Split closed polyline at vertex with index _split_idx.
void updatePolyBezierSpline(PolyLineObject *_lineObject, unsigned int _pointsPerSegment)
Generates points for the spline, updates handles.
ACG::SceneGraph::BaseNode * getRootNode()
Get the root node for data objects.
void resize(unsigned int _n)
Resize current polyline.
void slotTriggerCutPlaneSelect()
Generate PolyLine after the cutPlane has been drawn.
QAction * moveAction_
Called by pick Toolbar.
bool finishSpline()
If possible calculates handles.
void set_closed(const bool _c)
Set if the polyline should be closed and therefore forms a loop.
Scalar length() const
Compute the length of the polyline (in future cached method)
ACG::SceneGraph::GlutPrimitiveNode * moveBezSpline_SelNode_
The handle which is being dragged.
double sceneRadius()
Returns the current scene radius from the active examiner widget.
Scalar vertex_radius() const
get ball-radius of vertices
TriMeshObject * triMeshObject(BaseObjectData *_object)
Cast an BaseObject to a TriMeshObject if possible.
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(1)<< 3)
Topology updated.
DrawMode POINTS_SHADED
draw shaded points (requires point normals)
IdList generatePolyLinesFromCut(int _objectId, Vector _planePoint, Vector _planeNormal)
Generates a polyLine of a plane intersection.
void get_viewport(int &_left, int &_bottom, int &_width, int &_height) const
get viewport
ACG::Vec3d createCircle_getHit(PolyLineCircleData *_circleData, ACG::Vec3d _hit_point)
Returns point on mesh or point on the normal plane.
QAction * insertSplineAction_
Called by pick Toolbar.
DrawMode WIREFRAME
draw wireframe
QtPlaneSelect * planeSelect_
Plane selection tool.
int createCircle_CurrSelIndex_
The object which is being modified(created, dragged)
The Menu will be shown when an object was picked.
void split_closed(unsigned int _split_idx)
Split closed polyline at vertex with index _split_idx.
void add_point(const Point &_p)
Append a point to the polyline.
int moveBezSpline_SelIndex_
The object which is being moved.
Point & point(unsigned int _i)
Get a point of the polyline.
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, unsigned int &_nodeIdx, unsigned int &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
ACG::SceneGraph::PolyLineNodeT< PolyLine > * lineNode()
Get the scenegraph Node.
void slotScissorButton()
Scissor Button was hit.
QAction * cutAction_
Called by pick Toolbar.
bool addAdditionalNode(NodeT *_node, QString _pluginName, QString _nodeName, int _id=0)
add an additional node to the object
Viewer::ActionMode actionMode()
Get the current Action mode.
PolyLineToolbarWidget * tool_
Widget for Toolbox.
void set_position(const Vec3d &_p, int _idx=0)
set position
void setObjectDrawMode(const ACG::SceneGraph::DrawModes::DrawMode &_mode, const bool &_force=false)
Set the draw mode for the object.
PolyLine * line()
return a pointer to the line
QActionGroup * pickToolBarActions_
Called by pick Toolbar.
Point & back()
Get last point of the polyline ( no range check!!!)
void append(const PolyLineT< PointT > &_pl)
Append second polyline _pl to this one.
ACG::GLState & glState()
Get the glState of the Viewer.
bool getPickedObject(const unsigned int _node_idx, BaseObjectData *&_object)
Get the picked mesh.
int createSpline_LastSelIndex_
Use this one to mark the last index to update the number of points.
#define DATA_TRIANGLE_MESH
QToolBar * toolbar_
Called by Toolbar to enable pick mode.
ACG::Vec3d getPointOnMesh(PolyLineBezierSplineData *_SplineData, ACG::Vec3d _point, ACG::Vec3d *_nor=0)
Returns the nearest point on the mesh or if none could be found the input.
ACG::Vec3d moveCircle_LastHitPos_
The last valid hit on the mesh.
void collapse(Scalar _smallest)
Collapse polyline.
void viewing_ray(int _x, int _y, Vec3d &_origin, Vec3d &_direction) const
QString name()
Name of the Plugin.
void enablePicking(bool _enable)
int moveBezSpline_SelSubIndex_
The index of the control or handle being moved.
unsigned int meshIndex_
Index of the corresponding mesh.
QAction * smartMoveAction_
Called by pick Toolbar.