54 #include "PolyLinePlugin.hh" 56 #include <ACG/Scenegraph/ManipulatorNode.hh> 57 #include <ACG/Scenegraph/LineNode.hh> 58 #include <ACG/Scenegraph/GlutPrimitiveNode.hh> 59 #include <ACG/QtScenegraph/QtTranslationManipulatorNode.hh> 67 GlutPrimitiveNode(
PolyLineObject* L, std::string name,
int _index = -1)
86 :
ACG::
SceneGraph::LineNode(LineSegmentsMode, L->manipulatorNode(), name)
108 pickToolBarActions_(0),
110 insertCircleAction_(0),
111 insertSplineAction_(0),
118 cutMultipleAction_(0),
120 cur_polyline_obj_(0),
123 create_point_ref_(0),
124 createCircle_CurrSelIndex_(-1),
125 createCircle_LastSelIndex_(-1),
126 moveCircle_SelNode_(0),
127 moveCircle_IsLocked(false),
128 moveCircle_IsFloating(false),
129 copyPaste_Action_(0),
130 copyPaste_ObjectId_(-1),
131 copyPaste_ActionType_(-1),
132 copyPaste_NewObjectId_(-1),
133 createSpline_CurrSelIndex_(-1),
134 createSpline_LastSelIndex_(-1),
135 moveBezSpline_SelNode_(0),
136 moveBezSpline_SelIndex_(-1),
137 moveBezSpline_SelSubIndex_(0),
139 smart_move_timer_(0),
140 cur_smart_move_obj_(0),
152 QSize size(100, 100);
154 tool_->setObjectName(
"PolyLineToolbar");
157 connect(
tool_->pb_subdivide,SIGNAL(clicked() ),
this,SLOT(slot_subdivide()));
158 connect(
tool_->subdivide_relative,SIGNAL(toggled(
bool) ),
this,SLOT(slot_subdivide_percent(
bool)));
159 connect(
tool_->pb_decimate,SIGNAL(clicked() ),
this,SLOT(slot_decimate()));
160 connect(
tool_->decimate_relative,SIGNAL(toggled(
bool) ),
this,SLOT(slot_decimate_percent(
bool)));
161 #ifdef EXTENDED_POLY_LINE 162 connect(
tool_->pb_resample_on_edges,SIGNAL(clicked() ),
this,SLOT(slot_resample_on_edges()));
164 tool_->pb_resample_on_edges->setDisabled(
true);
166 connect(
tool_->pb_smooth,SIGNAL(clicked() ),
this,SLOT(slot_smooth()));
167 connect(
tool_->pb_smooth,SIGNAL(clicked() ),
this,SIGNAL(updateView()));
168 connect(
tool_->pb_project,SIGNAL(clicked() ),
this,SLOT(slot_project()));
169 connect(
tool_->pb_project,SIGNAL(clicked() ),
this,SIGNAL(updateView()));
170 connect(
tool_->pb_smooth_project,SIGNAL(clicked() ),
this,SLOT(slot_smooth_project()));
171 connect(
tool_->pb_smooth_project,SIGNAL(clicked() ),
this,SIGNAL(updateView()));
173 connect(
tool_->rb_insert, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
174 connect(
tool_->rb_InsertCircle, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
175 connect(
tool_->rb_InsertSpline, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
176 connect(
tool_->rb_delete, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
177 connect(
tool_->rb_move, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
178 connect(
tool_->rb_smart_move, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
179 connect(
tool_->rb_merge, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
180 connect(
tool_->rb_split, SIGNAL( clicked() ),
this, SLOT( slotEditModeChanged() ));
182 connect(
tool_->sb_CirclePointNum, SIGNAL(valueChanged(
int)),
this, SLOT(slot_setCirclePointNum(
int)));
183 connect(
tool_->sb_SplineSegNum, SIGNAL(valueChanged(
int)),
this, SLOT(slot_setSplinePointNum(
int)));
185 tool_->rb_insert->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_insert.png") );
186 tool_->rb_InsertCircle->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_circle.png") );
187 tool_->rb_InsertSpline->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_bezier.png") );
188 tool_->rb_delete->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_delete.png") );
189 tool_->rb_move->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_move.png") );
190 tool_->rb_smart_move->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_move.png") );
191 tool_->rb_merge->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_merge.png") );
192 tool_->rb_split->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() +
"polyline_split.png") );
199 QIcon* toolIcon =
new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"cut_polyline.png");
200 emit addToolbox( tr(
"PolyLine") ,
tool_, toolIcon );
209 slotMouseEvent( QMouseEvent* _event )
211 copyPaste_LastMouse = _event->pos();
214 if (_event->modifiers() & (Qt::ControlModifier))
218 && _event->button() != Qt::RightButton) {
225 case PL_INSERTCIRCLE:
226 me_insertCircle(_event);
229 case PL_INSERTSPLINE:
230 me_insertSpline(_event);
250 me_smart_move(_event);
254 me_copyPasteMouse(_event);
265 void PolyLinePlugin::slotKeyEvent(QKeyEvent* event) {
266 switch (event->key()) {
269 if(mode() == PL_INSERT && cur_polyline_obj_ && cur_insert_id_ != -1) {
272 if (event->modifiers() & (Qt::ShiftModifier))
278 cur_polyline_obj_ = 0;
279 create_point_ref_ = 0;
281 clearStatusMessage();
283 else if(mode() == PL_INSERTSPLINE) {
296 slotPickModeChanged(
const std::string& _mode)
299 cutAction_->setChecked( _mode == CREATE_CUT_POLYLINE );
312 emit addHiddenPickMode(
"PolyLine");
313 emit setPickModeMouseTracking(
"PolyLine",
true);
314 emit addHiddenPickMode( CREATE_CUT_POLYLINE );
315 emit addHiddenPickMode( CREATE_CUT_POLYLINES );
317 emit registerKey(Qt::Key_Return, Qt::NoModifier, tr(
"Terminate creation of poly line."),
true);
318 emit registerKey(Qt::Key_Return, Qt::ShiftModifier, tr(
"Terminate creation of poly line and create loop."),
true);
321 toolbar_ =
new QToolBar(tr(
"PolyLine Editing"));
322 toolbar_->setObjectName(
"PolyLineEditingToolbar");
330 polyLineAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_insert.png") );
335 cutAction_ =
new QAction(tr(
"&Create polyline at intersection with plane"),
this);
337 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."));
338 cutAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"cut_polyline.png") );
343 cutMultipleAction_ =
new QAction(tr(
"&Create polylines at intersection with plane"),
this);
345 cutMultipleAction_->setStatusTip(tr(
"Create polylines by specifying a plane with which the object is then intersected. The polylines will be created at the intersection."));
346 cutMultipleAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"cut_polylines.png") );
356 pickToolbar_->setObjectName(
"PolyLine_Editing_Toolbar");
357 pickToolbar_->setAttribute(Qt::WA_AlwaysShowToolTips,
true);
364 "Use <Doubleclick> to finish the line.\n" 365 "Hold <Shift> to close line on finish."));
366 insertAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_insert.png") );
373 "<Click> to select the center.\n" 374 "Drag to specify the radius."));
376 insertCircleAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_circle.png") );
383 "<Click> to select the points."));
385 insertSplineAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_bezier.png") );
390 deleteAction_->setStatusTip(tr(
"Delete a complete PolyLine."));
391 deleteAction_->setToolTip(tr(
"Delete a complete PolyLine.\n" 392 "<Click> on the lines you want to delete."));
393 deleteAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_delete.png") );
400 smartMoveAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_move.png") );
407 "Drag one endpoint of a PolyLine to the EndPoint of another one.\n"));
408 mergeAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_merge.png") );
413 splitAction_->setStatusTip(tr(
"Split a PolyLine at a given point."));
414 splitAction_->setToolTip(tr(
"Split a PolyLine at a given point.\n" 415 "<Click> on the vertex where you want to split the PolyLine and drag it away."));
416 splitAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_split.png") );
423 moveAction_->setStatusTip(tr(
"Move a Vertex of a PolyLine"));
424 moveAction_->setToolTip(tr(
"Move a single Vertex of a PolyLine."));
425 moveAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"polyline_move.png") );
434 smart_move_timer_ =
new QTimer(
this);
435 connect(smart_move_timer_, SIGNAL(timeout()),
this, SLOT(slot_smart_move_timer()));
440 connect(
planeSelect_, SIGNAL( updateViewProxy( ) ),
this, SIGNAL( updateView() ) );
441 connect(
planeSelect_, SIGNAL( nodeVisChangedProxy(
int) ),
this, SIGNAL(nodeVisibilityChanged(
int) ) );
444 copyPaste_Action_ =
new QAction(
"Duplicate", 0);
445 connect(copyPaste_Action_,SIGNAL(triggered() ),
this,SLOT(slot_duplicate()));
484 emit log(
"Cutting object " + object->
name());
487 emit log(
"Only Meshes are supported at the moment ");
498 QString command =
"generatePolyLineFromCut(" + QString::number(object->
id()) +
",Vector(" 499 + QString::number(point[0]) +
"," + QString::number(point[1]) +
"," + QString::number(point[2]) +
"),Vector(" 500 + QString::number(normal[0]) +
"," + QString::number(normal[1]) +
"," + QString::number(normal[2]) +
"));";
501 emit scriptInfo(command);
506 if (o_it->id() !=
object->id()) {
518 QString command =
"generatePolyLinesFromCut(" + QString::number(object->
id()) +
",Vector(" 519 + QString::number(point[0]) +
"," + QString::number(point[1]) +
"," + QString::number(point[2]) +
"),Vector(" 520 + QString::number(normal[0]) +
"," + QString::number(normal[1]) +
"," + QString::number(normal[2]) +
"));";
521 emit scriptInfo(command);
526 if (o_it->id() !=
object->id()) {
531 for (
unsigned int i = 0 ; i < objectIds.size() ; ++i ) {
533 if ( objectIds[i] != -1)
549 double max_length =
tool_->dsb_subdivide->value();
552 if (max_length == 0.0)
571 void PolyLinePlugin::slot_subdivide_percent(
bool _checked) {
575 double total_length = 0;
586 double v = total_length / double(n_active_pl);
591 if (n_active_pl > 0) {
592 double val_new =
tool_->dsb_subdivide->value() / v;
593 tool_->dsb_subdivide->setValue(val_new);
595 emit log(
LOGWARN,
"Could not find any active polyline!");
600 if (n_active_pl > 0) {
601 double val_new =
tool_->dsb_subdivide->value() * v;
602 tool_->dsb_subdivide->setValue(val_new);
604 emit log(
LOGWARN,
"Could not find any active polyline!");
618 double min_length =
tool_->dsb_decimate->value();
635 void PolyLinePlugin::slot_decimate_percent(
bool _checked)
640 double total_length = 0;
651 double v = total_length / double(n_active_pl);
656 if (n_active_pl > 0) {
657 double val_new =
tool_->dsb_subdivide->value() / v;
658 tool_->dsb_decimate->setValue(val_new);
660 emit log(
LOGWARN,
"Could not find any active polyline!");
665 if (n_active_pl > 0) {
666 double val_new =
tool_->dsb_subdivide->value() * v;
667 tool_->dsb_decimate->setValue(val_new);
669 emit log(
LOGWARN,
"Could not find any active polyline!");
677 #ifdef EXTENDED_POLY_LINE 681 slot_resample_on_edges()
685 unsigned int n_targetMeshes(0);
689 if( n_targetMeshes != 1)
691 std::cerr <<
"Warning: resample_on_edges needs exactly 1 target mesh! Otherwise no operation is performed! \n";
715 std::cerr <<
"resample " << o_it2->
name().toStdString() << std::endl;
739 for(
int i=0; i<
tool_->sb_smooth_iter->value(); ++i)
740 if(
tool_->rb_smooth_c0->isChecked())
744 if(
tool_->rb_smooth_c1->isChecked())
748 if(
tool_->rb_smooth_c2->isChecked())
767 for (
int i = 0; i <
tool_->sb_smooth_iter->value(); ++i)
768 if (
tool_->rb_smooth_c0->isChecked())
771 else if (
tool_->rb_smooth_c1->isChecked())
774 else if (
tool_->rb_smooth_c2->isChecked())
790 std::vector<TriMesh*> meshes;
791 std::vector<OpenMeshTriangleBSPT<TriMesh>*> bsps;
800 meshes.push_back(tmesh_obj->
mesh());
827 std::vector<TriMesh*> meshes;
828 std::vector<OpenMeshTriangleBSPT<TriMesh>*> bsps;
838 meshes.push_back(tmesh_obj->
mesh());
855 slot_smooth_project()
857 int smooth_project_iter =
tool_->sb_smooth_project_iter->value();
859 for (
int i = 0, j = 1; i < smooth_project_iter; ++i, ++j) {
878 int smooth_project_iter =
tool_->sb_smooth_project_iter->value();
880 for (
int i = 0, j = 1; i < smooth_project_iter; ++i, ++j) {
897 slot_smart_move_timer()
899 int smooth_project_iter =
tool_->sb_smooth_project_iter->value();
901 if (smooth_project_iter)
902 slot_smooth_project(cur_smart_move_obj_);
904 slot_smooth(cur_smart_move_obj_);
912 PolyLinePlugin::slotObjectUpdated(
int _identifier,
const UpdateType &_type )
919 GlutPrimitiveNode* H = 0, *C = 0;
922 if(circleData && !C) {
923 createCircle_createUI(_identifier);
925 else if(splineData && !H) {
926 createSpline_createUI(_identifier);
936 if(copyPaste_ObjectId_ != -1 && copyPaste_ActionType_ != -1)
937 return PL_COPY_PASTE;
941 if(
tool_->rb_insert->isChecked() )
return PL_INSERT;
942 if(
tool_->rb_InsertCircle->isChecked() )
return PL_INSERTCIRCLE;
943 if(
tool_->rb_InsertSpline->isChecked() )
return PL_INSERTSPLINE;
944 else if(
tool_->rb_delete->isChecked() )
return PL_DELETE;
945 else if(
tool_->rb_move->isChecked() )
return PL_MOVE;
946 else if(
tool_->rb_split->isChecked() )
return PL_SPLIT;
947 else if(
tool_->rb_merge->isChecked() )
return PL_MERGE;
948 else if(
tool_->rb_smart_move->isChecked())
return PL_SMART_MOVE;
958 me_insert( QMouseEvent* _event )
960 if (_event->type() == QEvent::MouseMove) {
962 if (create_point_ref_) {
964 size_t node_idx, target_idx;
967 *create_point_ref_ = (PolyLine::Point) hit_point;
977 size_t node_idx, target_idx;
981 switch (_event->type()) {
983 case QEvent::MouseButtonPress: {
1003 cur_polyline_obj_->
line()->
add_point((PolyLine::Point) hit_point);
1005 emit showStatusMessage(tr(
"Double click/Enter to terminate poly line. Use with shift to create loop."));
1009 cur_polyline_obj_->
line()->
add_point((PolyLine::Point) hit_point);
1010 create_point_ref_ = &cur_polyline_obj_->
line()->
points().back();
1019 case QEvent::MouseButtonDblClick: {
1021 if (_event->modifiers() & (Qt::ShiftModifier)) {
1034 cur_insert_id_ = -1;
1035 cur_polyline_obj_ = 0;
1036 create_point_ref_ = 0;
1038 clearStatusMessage();
1051 double getRad(
int meshIdx)
1056 ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1057 ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1059 return 0.005*(bbMax-bbMin).norm();
1066 void PolyLinePlugin::
1067 createCircle_createUI(
int _polyLineObjectID)
1076 double rad = getRad(lineData->circleMeshIndex_);
1078 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Handle0");
1079 handle0->get_primitive(0).color =
ACG::Vec4f(1,0,0,1);
1080 handle0->set_size(rad);
1082 handle0->enablePicking(
true);
1083 handle0->set_position(lineData->circleCenter_ + lineData->circleMainAxis_ * lineData->circleMainRadius_);
1087 GlutPrimitiveNode* handle1 =
new GlutPrimitiveNode(lineObject,
"N_Handle1");
1088 handle1->get_primitive(0).color =
ACG::Vec4f(0,1,0,1);
1089 handle1->set_size(rad);
1091 handle1->enablePicking(
true);
1092 handle1->set_position(lineData->circleCenter_ + lineData->circleSideAxis_ * lineData->circleSideRadius_);
1096 GlutPrimitiveNode* cenNode =
new GlutPrimitiveNode(lineObject,
"N_Center");
1097 cenNode->get_primitive(0).color =
ACG::Vec4f(0,0,1,1);
1098 cenNode->set_size(rad);
1100 cenNode->enablePicking(
true);
1101 cenNode->set_position(lineData->circleCenter_);
1105 emit updatedObject(_polyLineObjectID,
UPDATE_ALL);
1110 void PolyLinePlugin::
1111 me_insertCircle(QMouseEvent* _event)
1114 TriMesh::FaceHandle fh;
1115 TriMesh::VertexHandle vh;
1117 if(!pick_triangle_mesh(_event->pos(), mesh, fh, vh, hit_point) && _event->type() != QEvent::MouseButtonRelease)
1126 const ACG::Vec3d n = circleData->circleNormal_, x0 = circleData->circleCenter_;
1127 const double t = ((n | x0) - (n | hit_point)) / n.
sqrnorm();
1128 const ACG::Vec3d onPlane = hit_point + t * n, d = onPlane - x0;
1130 circleData->circleMainAxis_ = (onPlane - x0).normalize();
1131 circleData->circleSideRadius_ = circleData->circleMainRadius_ = d.norm();
1132 circleData->circleSideAxis_ = (circleData->circleMainAxis_ % n).normalize();
1148 if(!mesh->
mesh()->has_face_normals())
1149 mesh->
mesh()->request_face_normals();
1159 else if(_event->type() == QEvent::MouseButtonRelease ) {
1167 createCircle_CurrSelIndex_ = -1;
1173 void PolyLinePlugin::
1174 createSpline_createUI(
int _polyLineObjectID)
1185 GlutLineNode* lineN =
new GlutLineNode(lineObject,
"N_Line");
1187 lineN->enablePicking(
false);
1191 for(
unsigned int i = 0; i < splineData->points_.size(); i++) {
1192 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Control", i);
1193 handle0->get_primitive(0).color =
ACG::Vec4f(0,1,0,1);
1194 handle0->set_size(rad);
1196 handle0->set_position(splineData->points_[i].position);
1198 handle0->enablePicking(
true);
1202 for(
unsigned int i = 0; i < splineData->handles_.size(); i++) {
1204 const ACG::Vec3d hndlPos = splineData->handles_[i], ctrlPos = control.position;
1206 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Handle", i);
1207 handle0->get_primitive(0).color =
ACG::Vec4f(0,0,1,1);
1208 handle0->set_size(rad * 0.75);
1210 handle0->enablePicking(
true);
1211 handle0->set_position(hndlPos);
1215 GlutLineNode* lineN;
1217 lineN->add_line(ctrlPos, hndlPos);
1223 emit updatedObject(_polyLineObjectID,
UPDATE_ALL);
1242 ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1243 ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1249 GlutPrimitiveNode* control = 0;
1251 for(
unsigned int i = 0; i < splineData->points_.size(); i++) {
1253 control->enablePicking(
true);
1256 for(
unsigned int i = 0; i < splineData->handles_.size(); i++) {
1258 const ACG::Vec3d hndlPos = splineData->handles_[i], ctrlPos = control.position;
1260 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Handle", i);
1261 handle0->get_primitive(0).color =
ACG::Vec4f(0,0,1,1);
1262 handle0->set_size(0.004*sizeBB.
norm());
1264 handle0->enablePicking(
true);
1265 handle0->set_position(hndlPos);
1269 GlutLineNode* lineN;
1271 lineN->add_line(ctrlPos, hndlPos);
1282 void PolyLinePlugin::
1283 me_insertSpline(QMouseEvent* _event)
1287 TriMesh::FaceHandle fh;
1288 TriMesh::VertexHandle vh;
1291 if(!pick_triangle_mesh(_event->pos(), mesh, fh, vh, hit_point))
1294 ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1295 ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1299 if(!mesh->
mesh()->has_face_normals())
1300 mesh->
mesh()->request_face_normals();
1304 if(_event->type() == QEvent::MouseButtonPress) {
1324 GlutLineNode* lineN =
new GlutLineNode(newLine,
"N_Line");
1326 lineN->enablePicking(
false);
1331 ACG::Vec3d insert_Point = hit_point + nor * 0.003 * sizeBB.
norm();
1338 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Control", splineData->points_.size());
1339 handle0->get_primitive(0).color =
ACG::Vec4f(0,1,0,1);
1340 handle0->set_size(0.005*sizeBB.
norm());
1342 handle0->set_position(insert_Point);
1344 handle0->enablePicking(
false);
1351 if(_event->type() == QEvent::MouseButtonDblClick) {
1360 me_delete( QMouseEvent* _event )
1363 if (_event->type() == QEvent::MouseButtonPress) {
1365 size_t node_idx, target_idx;
1375 emit deleteObject(obj->
id());
1391 if(moveCircle_SelNode_)
1394 if(moveCircle_SelNode_)
1399 _node_idx = obj->
id();
1405 if(!_moveCircle_SelNode_->
name().compare(
"N_Center"))
1407 _lineData->circleNormal_ = _nor;
1408 _lineData->circleCenter_ = _hit_point;
1409 _lineData->circleSideAxis_ = (_lineData->circleMainAxis_ % _lineData->circleNormal_).normalize();
1410 _lineData->circleMainAxis_ = (_lineData->circleNormal_ % _lineData->circleSideAxis_).normalize();
1414 const double cr = (_onPlane - _lineData->circleCenter_).norm();
1415 const ACG::Vec3d axisa = (_onPlane - _lineData->circleCenter_).normalize();
1416 if (!_moveCircle_SelNode_->
name().compare(
"N_Handle0")) {
1417 const ACG::Vec3d axisb = (axisa % _lineData->circleNormal_).normalize();
1418 _lineData->circleMainRadius_ = cr;
1421 _lineData->circleSideRadius_ = cr;
1423 _lineData->circleMainAxis_ = axisa;
1424 _lineData->circleSideAxis_ = axisb;
1426 const ACG::Vec3d axisb = (_lineData->circleNormal_ % axisa).normalize();
1427 _lineData->circleSideRadius_ = cr;
1430 _lineData->circleMainRadius_ = cr;
1432 _lineData->circleSideAxis_ = axisa;
1433 _lineData->circleMainAxis_ = axisb;
1441 me_move( QMouseEvent* _event )
1443 if((_event->modifiers() & Qt::ShiftModifier) != Qt::ShiftModifier && moveCircle_IsLocked)
1444 moveCircle_IsLocked = moveCircle_IsFloating =
false;
1447 if (_event->type() == QEvent::MouseButtonPress) {
1449 size_t node_idx, target_idx;
1454 GlutPrimitiveNode* glutNode =
dynamic_cast<GlutPrimitiveNode*
>(node);
1483 cur_move_id_ = cur_pol->
id();
1485 move_point_ref_ = &(cur_pol->
line()->
point(target_idx));
1492 if (_event->type() == QEvent::MouseMove){
1500 bool hasHit = me_GetMeshHit(_event,
moveCircle_SelNode_, hit_point, lineData->circleMeshIndex_, target_idx);
1501 if(lineData->circleMeshIndex_ == std::numeric_limits<unsigned int>::max())
return;
1502 if(!moveCircle_IsLocked && hasHit) {
1503 moveCircle_IsFloating =
false;
1504 ACG::Vec3d x0 = lineData->circleCenter_, n = lineData->circleNormal_;
1506 double t = ((n | x0) - (n | onMesh)) / n.
sqrnorm();
1512 me_UpdateCircleData(onMesh, onPlane, mesh->
mesh()->normal(mesh->
mesh()->face_handle(target_idx)),
moveCircle_SelNode_, lineData, (_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier);
1515 if((_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier) {
1516 moveCircle_IsLocked =
true;
1517 moveCircle_LastHitNor_ = lineData->circleNormal_;
1523 moveCircle_IsFloating =
true;
1532 : lineData->circleNormal_;
1533 const double t = ((x0 | n) - (cameraPos | n)) / (cameraDir | n);
1534 const ACG::Vec3d onPlane = cameraPos + cameraDir * t;
1536 me_UpdateCircleData(onPlane, onPlane, n,
moveCircle_SelNode_, lineData, (_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier);
1550 if(lineData->
meshIndex_ == std::numeric_limits<unsigned int>::max())
1556 ACG::Vec3d onMesh = hit_point, onMeshNor = mesh->
mesh()->normal(mesh->
mesh()->face_handle(target_idx));
1560 lineData->points_[controlIndex].position = onMesh;
1561 lineData->points_[controlIndex].normal = onMeshNor;
1563 int handleIndex = 2 * controlIndex - 1;
1564 ACG::Vec3d dir = lineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.
norm();
1566 lineData->handles_[handleIndex] = point;
1568 if(controlIndex != ((
int)lineData->points_.size() - 1)) {
1569 int handleIndex = 2 * controlIndex;
1570 ACG::Vec3d dir = lineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.
norm();
1572 lineData->handles_[handleIndex] = point;
1583 double t = ((control.normal | control.position) - (control.normal | cameraPos)) / (control.normal | cameraDir);
1584 ACG::Vec3d onPlane = cameraPos + t * cameraDir;
1586 lineData->handles_[handleIndex] = onPlane;
1587 if(handleIndex % 2 == 1 && handleIndex != ((
int)lineData->handles_.size() - 1)) {
1588 double dist = (lineData->handles_[handleIndex + 1] - control.position).norm();
1589 if(_event->modifiers() & Qt::ShiftModifier)
1590 dist = (onPlane - control.position).norm();
1591 ACG::Vec3d dir = -(onPlane - control.position).normalize();
1592 lineData->handles_[handleIndex + 1] = control.position + dir * dist;
1594 if(handleIndex % 2 == 0 && handleIndex) {
1595 double dist = (lineData->handles_[handleIndex - 1] - control.position).norm();
1596 if(_event->modifiers() & Qt::ShiftModifier)
1597 dist = (onPlane - control.position).norm();
1598 ACG::Vec3d dir = -(onPlane - control.position).normalize();
1599 lineData->handles_[handleIndex - 1] = control.position + dir * dist;
1602 GlutLineNode* lineN;
1608 else if (move_point_ref_ != 0) {
1610 size_t node_idx, target_idx;
1612 (*move_point_ref_) = (PolyLine::Point) hit_point;
1620 if (_event->type() == QEvent::MouseButtonRelease) {
1621 if((_event->modifiers() & Qt::ShiftModifier) != Qt::ShiftModifier) {
1624 moveCircle_IsLocked = moveCircle_IsFloating =
false;
1628 moveCircle_IsLocked =
false;
1633 move_point_ref_ = 0;
1645 me_split( QMouseEvent* _event )
1648 if (_event->type() == QEvent::MouseButtonPress) {
1650 move_point_ref_ = 0;
1652 size_t node_idx, target_idx;
1674 cur_move_id_ = cur_pol->
id();
1705 cur_move_id_ = cur_pol->
id();
1721 if (_event->type() == QEvent::MouseMove)
1722 if (move_point_ref_ != 0) {
1724 size_t node_idx, target_idx;
1728 (*move_point_ref_) = (PolyLine::Point) hit_point;
1737 if (_event->type() == QEvent::MouseButtonRelease) {
1739 if (cur_move_id_ != -1)
1742 move_point_ref_ = 0;
1753 me_merge( QMouseEvent* _event )
1756 if (_event->type() == QEvent::MouseButtonPress) {
1758 move_point_ref_ = 0;
1761 size_t node_idx, target_idx;
1776 if (target_idx == cur_pol->
line()->
n_vertices() - 1 || target_idx == 0) {
1777 if (target_idx == 0) {
1783 cur_merge_id_ = cur_pol->
id();
1796 if (_event->type() == QEvent::MouseMove && cur_merge_id_ != -1)
1797 if (move_point_ref_ != 0) {
1798 size_t node_idx, target_idx;
1802 (*move_point_ref_) = (PolyLine::Point) hit_point;
1811 if (_event->type() == QEvent::MouseButtonRelease && cur_merge_id_ != -1) {
1812 PolyLine::Point p_save;
1815 if (move_point_ref_ != 0) {
1827 move_point_ref_ = 0;
1830 size_t node_idx, target_idx;
1839 PluginFunctions::invalidatePickCaches();
1841 bool merged =
false;
1854 if ( target_idx < second_pol->line()->n_vertices() ) {
1857 unsigned int second_idx = target_idx;
1862 bool inv_first(
false), inv_second(
false);
1865 if (first_idx == 0) {
1877 if (first_idx == first_pol->
line()->
n_vertices() - 1 && second_idx == 0) {
1879 if (first_pol->
id() == second_pol->
id()) {
1896 emit deleteObject(second_pol->
id());
1907 PluginFunctions::invalidatePickCaches();
1920 if ( target_idx < second_pol->line()->n_vertices() ) {
1923 unsigned int second_idx = target_idx;
1929 if (first_idx == 0) {
1938 if (first_pol->
id() == second_pol->
id() && first_idx == first_pol->
line()->
n_vertices() - 1 && second_idx == 0) {
1963 move_point_ref_ = 0;
1975 me_smart_move( QMouseEvent* _event )
1978 if (_event->type() == QEvent::MouseButtonPress) {
1980 size_t node_idx, target_idx;
1993 cur_polyline_obj_ = cur_pol;
2000 cur_smart_move_obj_ = cur_pol;
2001 if (cur_pol->
line()->vertex_selections_available()) {
2002 if (!(_event->modifiers() & (Qt::ShiftModifier)))
2003 cur_pol->
line()->vertex_selection(target_idx) =
true;
2005 cur_pol->
line()->vertex_selection(target_idx) =
false;
2013 if (!(_event->modifiers() & (Qt::ShiftModifier)))
2014 smart_move_timer_->start(20);
2021 if( _event->type() == QEvent::MouseButtonRelease)
2023 smart_move_timer_->stop();
2024 cur_smart_move_obj_ = NULL;
2036 slotEditModeChanged()
2049 GlutPrimitiveNode* H0, *H1, *C;
2053 ACG::Vec3d h0 = circleData->circleCenter_ + circleData->circleMainAxis_ * circleData->circleMainRadius_,
2054 h1 = circleData->circleCenter_ + circleData->circleSideAxis_ * circleData->circleSideRadius_;
2056 C->set_position(circleData->circleCenter_);
2067 slot_setCirclePointNum(
int i)
2078 slot_setSplinePointNum(
int i)
2091 tool_->rb_insert->setChecked(
true);
2093 tool_->rb_InsertCircle->setChecked(
true);
2095 tool_->rb_InsertSpline->setChecked(
true);
2097 tool_->rb_delete->setChecked(
true);
2099 tool_->rb_move->setChecked(
true);
2101 tool_->rb_smart_move->setChecked(
true);
2103 tool_->rb_merge->setChecked(
true);
2105 tool_->rb_split->setChecked(
true);
2125 slotEnablePickMode(QString _name)
2132 if(_name ==
"INSERT")
2133 tool_->rb_insert->setChecked(
true);
2134 else if(_name ==
"DELETE")
2135 tool_->rb_delete->setChecked(
true);
2136 else if(_name ==
"MOVE")
2137 tool_->rb_move->setChecked(
true);
2138 else if(_name ==
"SPLIT")
2139 tool_->rb_split->setChecked(
true);
2140 else if(_name ==
"MERGE")
2141 tool_->rb_merge->setChecked(
true);
2142 else if( _name ==
"SMART_MOVE")
2143 tool_->rb_smart_move->setChecked(
true);
2151 pick_triangle_mesh( QPoint mPos,
2155 _fh = TriMesh::FaceHandle (-1);
2156 _vh = TriMesh::VertexHandle(-1);
2158 size_t target_idx = 0, node_idx = 0;
2176 _fh = m.face_handle(target_idx);
2179 TriMesh::VertexHandle closest = *fv_it;
2180 float shortest_distance = (m.point(closest) - hit_point).sqrnorm();
2183 if ( (m.point(*fv_it ) - hit_point).sqrnorm() < shortest_distance ) {
2184 shortest_distance = (m.point(*fv_it ) - hit_point).sqrnorm();
2189 if ( (m.point(*fv_it ) - hit_point).sqrnorm() < shortest_distance ) {
2196 _hitPoint = hit_point;
2209 slotUpdateContextMenu(
int objectId)
2211 copyPaste_ObjectId_ = objectId;
2212 copyPaste_Action_->setVisible(
pickToolbar_->isVisible());
2217 me_copyPasteMouse(QMouseEvent* _event)
2224 copyPaste_ObjectId_ = copyPaste_ActionType_ - 1;
2227 size_t target_idx = 0, node_idx = 0;
2230 if(copyPaste_ActionType_ == 1) {
2240 GlutPrimitiveNode* glutNode =
dynamic_cast<GlutPrimitiveNode*
>(node);
2242 me_GetMeshHit(_event, glutNode, hit_point, circleData->circleMeshIndex_, target_idx);
2244 circleData-> circleCenter_ = hit_point;
2248 else if(oldSplineData) {
2249 for(
int i = 0; i < (int)splineData->points_.size(); i++) {
2250 ACG::Vec3d onMeshNor, oldPos = splineData->points_[i].position;
2252 splineData->points_[i].position = onMesh;
2253 splineData->points_[i].normal = onMeshNor;
2255 int handleIndex = 2 * i - 1;
2256 ACG::Vec3d dir = splineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.
norm();
2258 splineData->handles_[handleIndex] = point;
2260 if(i != ((
int)splineData->points_.size() - 1)) {
2261 int handleIndex = 2 * i;
2262 ACG::Vec3d dir = splineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.
norm();
2264 splineData->handles_[handleIndex] = point;
2267 GlutLineNode* lineN;
2275 newObj->
line()->
point(i) = hit_point + copyPaste_RelativePoints_[i];
2280 if(_event->type() == QEvent::MouseButtonPress) {
2281 copyPaste_ActionType_ = copyPaste_ObjectId_ = -1;
2284 else if(copyPaste_ActionType_ == 2) {
2298 size_t target_idx = 0, node_idx = 0;
2301 QPoint mPos = copyPaste_LastMouse;
2303 copyPaste_ActionType_ = 1;
2317 copyPaste_RelativePoints_.clear();
2322 createCircle_createUI(new_line_id);
2324 else if(splineData) {
2327 createSpline_createUI(new_line_id);
2330 for(
size_t i = 0; i < newData->points_.size(); i++)
2331 copyPaste_RelativePoints_.push_back(newData->points_[i].position - hit_point);
2338 copyPaste_RelativePoints_.push_back(obj->
line()->
point(i) - hit_point);
2342 copyPaste_NewObjectId_ = new_line_id;
2353 copyPaste_ActionType_ = 2;
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, size_t &_nodeIdx, size_t &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
QtPlaneSelect * planeSelect_
Plane selection tool.
void slotSetPolyLineMode(QAction *_action)
Called by Toolbar to enable pick mode.
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(8))
Topology updated.
QAction * mergeAction_
Called by pick Toolbar.
PolyLinePlugin()
default constructor
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.
int moveBezSpline_SelIndex_
The object which is being moved.
#define DATA_TRIANGLE_MESH
OMTriangleBSP * requestTriangleBsp()
QActionGroup * toolBarActions_
Called by Toolbar to enable pick mode.
void updatePolyEllipse(PolyLineObject *_lineObject, unsigned int _pointCount)
Generates points for the ellipse.
const Vec3d get_position(int _idx=0) const
get position
bool getAdditionalNode(NodeT *&_node, QString _pluginName, QString _nodeName, int _id=0)
get an addition node from the object
virtual bool picked(uint _node_idx)
detect if the node has been picked
QToolBar * pickToolbar_
Called by pick Toolbar.
void split_closed(unsigned int _split_idx)
Split closed polyline at vertex with index _split_idx.
void updateHandles(PolyLineObject *_lineObject)
Updates the center, forward and side handle of the Poly ellipse.
Point & back()
Get last point of the polyline ( no range check!!!)
void viewingDirection(const ACG::Vec3d &_dir, const ACG::Vec3d &_up, int _viewer)
Set the viewing direction.
void collapse(Scalar _smallest)
Collapse polyline.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
void setObjectData(QString _dataName, PerObjectData *_data)
void resize(unsigned int _n)
Resize current polyline.
picks faces (should be implemented for all nodes)
void smooth_uniform_laplace()
Laplacian smoothing.
std::vector< Point > & points()
Get all points of the polyline.
Kernel::FaceVertexIter FaceVertexIter
Circulator.
ACG::SceneGraph::BaseNode * getRootNode()
Get the root node for data objects.
std::string name() const
Returns: name of node (needs not be unique)
void updatePolyBezierSpline(PolyLineObject *_lineObject, unsigned int _pointsPerSegment)
Generates points for the spline, updates handles.
QToolBar * toolbar_
Called by Toolbar to enable pick mode.
Namespace providing different geometric functions concerning angles.
QAction * insertAction_
Called by pick Toolbar.
void add_point(const Point &_p)
Append a point to the polyline.
ACG::SceneGraph::GlutPrimitiveNode * moveBezSpline_SelNode_
The handle which is being dragged.
PolyLineObject * polyLineObject(BaseObjectData *_object)
Cast an BaseObject to a PolyLineObject if possible.
void append(const PolyLineT< PointT > &_pl)
Append second polyline _pl to this one.
VectorT< float, 4 > Vec4f
void split(unsigned int _split_idx, PolyLineT< PointT > &_new_pl)
Split closed polyline at vertex with index _split_idx.
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
BaseObject *& objectRoot()
Get the root of the object structure.
size_t meshIndex_
Index of the corresponding mesh.
void get_viewport(int &_left, int &_bottom, int &_width, int &_height) const
get viewport
void smooth_uniform_laplace2()
Squared laplacian smoothing.
PolyLineToolbarWidget * tool_
Widget for Toolbox.
void addInterpolatePoint(ACG::Vec3d _position, ACG::Vec3d _normal)
Adds a point to the end of the list and inserts control points.
void smooth_uniform_laplace3()
Cubic laplacian smoothing.
void enablePicking(bool _enable)
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
void set_random_color()
Generates a random color and sets it.
Scalar length() const
Compute the length of the polyline (in future cached method)
int createCircle_LastSelIndex_
Use this one to mark the last index to update the number of points.
ACG::Vec3d moveCircle_LastHitPos_
The last valid hit on the mesh.
QActionGroup * pickToolBarActions_
Called by pick Toolbar.
QAction * insertCircleAction_
Called by pick Toolbar.
MeshT * mesh()
return a pointer to the mesh
void subdivide(Scalar _largest)
Subdivide polyline.
int createCircle_CurrSelIndex_
The object which is being modified(created, dragged)
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(4))
Geometry updated.
EditMode
Edit Mode of PolyLinePlugin.
BaseObject * childExists(int _objectId)
Check if the element exists in the subtree of this element.
bool dataType(DataType _type) const
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
void set_vertex_radius(const Scalar _r)
set ball-radius of vertices
int moveBezSpline_SelSubIndex_
The index of the control or handle being moved.
void set_position(const Vec3d &_p, int _idx=0)
set position
QAction * deleteAction_
Called by pick Toolbar.
InterpolatePoint & getInterpolatePoint(unsigned int _handleIndex)
Retrieves the interpolate point based on the handle.
void slotScissorButton()
Scissor Button was hit.
QAction * moveAction_
Called by pick Toolbar.
Scalar vertex_radius() const
get ball-radius of vertices
Viewer::ActionMode actionMode()
Get the current Action mode.
pick any of the prior targets (should be implemented for all nodes)
Point & point(unsigned int _i)
Get a point of the polyline.
void setObjectDrawMode(const ACG::SceneGraph::DrawModes::DrawMode &_mode, const bool &_force=false)
Set the draw mode for the object.
double sceneRadius()
Returns the current scene radius from the active examiner widget.
picks verices (may not be implemented for all nodes)
void slotTriggerCutPlaneSelect()
Generate PolyLine after the cutPlane has been drawn.
QAction * polyLineAction_
Called by Toolbar to enable pick mode.
int generatePolyLineFromCut(int _objectId, Vector _planePoint, Vector _planeNormal, int _polyLineId=-1)
Generates a polyLine of a plane intersection.
QString name() const
return the name of the object. The name defaults to NONAME if unset.
void slotMouseEvent(QMouseEvent *_event)
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM >>().sqrnorm()))
compute euclidean norm
QAction * splitAction_
Called by pick Toolbar.
QAction * smartMoveAction_
Called by pick Toolbar.
TriMeshObject * triMeshObject(BaseObjectData *_object)
Cast an BaseObject to a TriMeshObject if possible.
Type for a MeshObject containing a triangle mesh.
const std::string pickMode()
Get the current Picking mode.
int createSpline_CurrSelIndex_
The index of the currently created spline.
PolyLine * line()
return a pointer to the line
bool addAdditionalNode(NodeT *_node, QString _pluginName, QString _nodeName, int _id=0)
add an additional node to the object
void delete_point(int _idx)
Delete point at _idx.
void updatePolyBezierHandles(PolyLineObject *_lineObject, ACG::SceneGraph::LineNode *_line)
Updates all the handles on the PolyBezier.
const QStringList TARGET_OBJECTS("target")
Iterable object range.
void invert()
Invert polyline that first vertex becomes last.
MaterialNode * materialNode()
get a pointer to the materialnode
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
size_t n_vertices() const
Get number of vertices.
ACG::Vec3d createCircle_getHit(PolyLineCircleData *_circleData, ACG::Vec3d _hit_point)
Returns point on mesh or point on the normal plane.
QString name()
Name of the Plugin.
QAction * cutMultipleAction_
Called by pick Toolbar.
void viewing_ray(int _x, int _y, Vec3d &_origin, Vec3d &_direction) const
void slotScissorLinesButton()
Scissor Button for multiple polylines was hit.
DrawMode WIREFRAME
draw wireframe
int createSpline_LastSelIndex_
Use this one to mark the last index to update the number of points.
QAction * cutAction_
Called by pick Toolbar.
PerObjectData * objectData(QString _dataName)
Returns the object data pointer.
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
void set_closed(const bool _c)
Set if the polyline should be closed and therefore forms a loop.
decltype(std::declval< S >() *std::declval< S >()) sqrnorm() const
compute squared euclidean norm
bool is_closed() const
Check if the polyline is marked as closed.
QAction * insertSplineAction_
Called by pick Toolbar.
void boundingBox(ACG::Vec3d &_bbMin, typename ACG::Vec3d &_bbMax)
Get the BoundingBox of this object.
void project_to_mesh(const MeshT &_mesh, SpatialSearchT *_ssearch=0)
Project polyline points to nearest surface points (use spatial search!!!)
ACG::SceneGraph::PolyLineNodeT< PolyLine > * lineNode()
Get the scenegraph Node.
void enablePicking(bool _enable)
Enable or disable picking for this Object.
void slotPickToolbarAction(QAction *_action)
Called by pick Toolbar.
ACG::SceneGraph::GlutPrimitiveNode * moveCircle_SelNode_
The handle which is being dragged.
DrawMode POINTS_SHADED
draw shaded points (requires point normals)
IdList generatePolyLinesFromCut(int _objectId, Vector _planePoint, Vector _planeNormal)
Generates a polyLine of a plane intersection.
bool getPickedObject(const size_t _node_idx, BaseObjectData *&_object)
Get the picked mesh.
bool finishSpline()
If possible calculates handles.
VectorT< double, 3 > Vec3d
ACG::GLState & glState()
Get the glState of the Viewer.