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)
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) {
964 if (create_point_ref_) {
966 size_t node_idx, target_idx;
969 *create_point_ref_ = (PolyLine::Point) hit_point;
979 size_t node_idx, target_idx;
983 switch (_event->type()) {
985 case QEvent::MouseButtonPress: {
1005 cur_polyline_obj_->
line()->
add_point((PolyLine::Point) hit_point);
1007 emit showStatusMessage(tr(
"Double click/Enter to terminate poly line. Use with shift to create loop."));
1011 cur_polyline_obj_->
line()->
add_point((PolyLine::Point) hit_point);
1012 create_point_ref_ = &cur_polyline_obj_->
line()->
points().back();
1021 case QEvent::MouseButtonDblClick: {
1023 if (_event->modifiers() & (Qt::ShiftModifier)) {
1036 cur_insert_id_ = -1;
1037 cur_polyline_obj_ = 0;
1038 create_point_ref_ = 0;
1040 clearStatusMessage();
1053 double getRad(
int meshIdx)
1058 ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1059 ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1061 return 0.005*(bbMax-bbMin).norm();
1068 void PolyLinePlugin::
1069 createCircle_createUI(
int _polyLineObjectID)
1078 double rad = getRad(lineData->circleMeshIndex_);
1080 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Handle0");
1081 handle0->get_primitive(0).color =
ACG::Vec4f(1,0,0,1);
1082 handle0->set_size(rad);
1084 handle0->enablePicking(
true);
1085 handle0->set_position(lineData->circleCenter_ + lineData->circleMainAxis_ * lineData->circleMainRadius_);
1089 GlutPrimitiveNode* handle1 =
new GlutPrimitiveNode(lineObject,
"N_Handle1");
1090 handle1->get_primitive(0).color =
ACG::Vec4f(0,1,0,1);
1091 handle1->set_size(rad);
1093 handle1->enablePicking(
true);
1094 handle1->set_position(lineData->circleCenter_ + lineData->circleSideAxis_ * lineData->circleSideRadius_);
1098 GlutPrimitiveNode* cenNode =
new GlutPrimitiveNode(lineObject,
"N_Center");
1099 cenNode->get_primitive(0).color =
ACG::Vec4f(0,0,1,1);
1100 cenNode->set_size(rad);
1102 cenNode->enablePicking(
true);
1103 cenNode->set_position(lineData->circleCenter_);
1107 emit updatedObject(_polyLineObjectID,
UPDATE_ALL);
1112 void PolyLinePlugin::
1113 me_insertCircle(QMouseEvent* _event)
1116 TriMesh::FaceHandle fh;
1119 if(!pick_triangle_mesh(_event->pos(), mesh, fh, vh, hit_point) && _event->type() != QEvent::MouseButtonRelease)
1128 const ACG::Vec3d n = circleData->circleNormal_, x0 = circleData->circleCenter_;
1129 const double t = ((n | x0) - (n | hit_point)) / n.sqrnorm();
1130 const ACG::Vec3d onPlane = hit_point + t * n, d = onPlane - x0;
1132 circleData->circleMainAxis_ = (onPlane - x0).normalize();
1133 circleData->circleSideRadius_ = circleData->circleMainRadius_ = d.norm();
1134 circleData->circleSideAxis_ = (circleData->circleMainAxis_ % n).normalize();
1150 if(!mesh->
mesh()->has_face_normals())
1151 mesh->
mesh()->request_face_normals();
1161 else if(_event->type() == QEvent::MouseButtonRelease ) {
1169 createCircle_CurrSelIndex_ = -1;
1175 void PolyLinePlugin::
1176 createSpline_createUI(
int _polyLineObjectID)
1187 GlutLineNode* lineN =
new GlutLineNode(lineObject,
"N_Line");
1189 lineN->enablePicking(
false);
1193 for(
unsigned int i = 0; i < splineData->points_.size(); i++) {
1194 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Control", i);
1195 handle0->get_primitive(0).color =
ACG::Vec4f(0,1,0,1);
1196 handle0->set_size(rad);
1198 handle0->set_position(splineData->points_[i].position);
1200 handle0->enablePicking(
true);
1204 for(
unsigned int i = 0; i < splineData->handles_.size(); i++) {
1206 const ACG::Vec3d hndlPos = splineData->handles_[i], ctrlPos = control.position;
1208 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Handle", i);
1209 handle0->get_primitive(0).color =
ACG::Vec4f(0,0,1,1);
1210 handle0->set_size(rad * 0.75);
1212 handle0->enablePicking(
true);
1213 handle0->set_position(hndlPos);
1217 GlutLineNode* lineN;
1219 lineN->add_line(ctrlPos, hndlPos);
1225 emit updatedObject(_polyLineObjectID,
UPDATE_ALL);
1244 ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1245 ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1251 GlutPrimitiveNode* control = 0;
1253 for(
unsigned int i = 0; i < splineData->points_.size(); i++) {
1255 control->enablePicking(
true);
1258 for(
unsigned int i = 0; i < splineData->handles_.size(); i++) {
1260 const ACG::Vec3d hndlPos = splineData->handles_[i], ctrlPos = control.position;
1262 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Handle", i);
1263 handle0->get_primitive(0).color =
ACG::Vec4f(0,0,1,1);
1264 handle0->set_size(0.004*sizeBB.norm());
1266 handle0->enablePicking(
true);
1267 handle0->set_position(hndlPos);
1271 GlutLineNode* lineN;
1273 lineN->add_line(ctrlPos, hndlPos);
1284 void PolyLinePlugin::
1285 me_insertSpline(QMouseEvent* _event)
1289 TriMesh::FaceHandle fh;
1293 if(!pick_triangle_mesh(_event->pos(), mesh, fh, vh, hit_point))
1296 ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1297 ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1301 if(!mesh->
mesh()->has_face_normals())
1302 mesh->
mesh()->request_face_normals();
1306 if(_event->type() == QEvent::MouseButtonPress) {
1326 GlutLineNode* lineN =
new GlutLineNode(newLine,
"N_Line");
1328 lineN->enablePicking(
false);
1333 ACG::Vec3d insert_Point = hit_point + nor * 0.003 * sizeBB.norm();
1340 GlutPrimitiveNode* handle0 =
new GlutPrimitiveNode(lineObject,
"N_Control", splineData->points_.size());
1341 handle0->get_primitive(0).color =
ACG::Vec4f(0,1,0,1);
1342 handle0->set_size(0.005*sizeBB.norm());
1344 handle0->set_position(insert_Point);
1346 handle0->enablePicking(
false);
1353 if(_event->type() == QEvent::MouseButtonDblClick) {
1362 me_delete( QMouseEvent* _event )
1365 if (_event->type() == QEvent::MouseButtonPress) {
1367 size_t node_idx, target_idx;
1377 emit deleteObject(obj->
id());
1393 if(moveCircle_SelNode_)
1396 if(moveCircle_SelNode_)
1401 _node_idx = obj->
id();
1407 if(!_moveCircle_SelNode_->
name().compare(
"N_Center"))
1409 _lineData->circleNormal_ = _nor;
1410 _lineData->circleCenter_ = _hit_point;
1411 _lineData->circleSideAxis_ = (_lineData->circleMainAxis_ % _lineData->circleNormal_).normalize();
1412 _lineData->circleMainAxis_ = (_lineData->circleNormal_ % _lineData->circleSideAxis_).normalize();
1416 const double cr = (_onPlane - _lineData->circleCenter_).norm();
1417 const ACG::Vec3d axisa = (_onPlane - _lineData->circleCenter_).normalize();
1418 if (!_moveCircle_SelNode_->
name().compare(
"N_Handle0")) {
1419 const ACG::Vec3d axisb = (axisa % _lineData->circleNormal_).normalize();
1420 _lineData->circleMainRadius_ = cr;
1423 _lineData->circleSideRadius_ = cr;
1425 _lineData->circleMainAxis_ = axisa;
1426 _lineData->circleSideAxis_ = axisb;
1428 const ACG::Vec3d axisb = (_lineData->circleNormal_ % axisa).normalize();
1429 _lineData->circleSideRadius_ = cr;
1432 _lineData->circleMainRadius_ = cr;
1434 _lineData->circleSideAxis_ = axisa;
1435 _lineData->circleMainAxis_ = axisb;
1443 me_move( QMouseEvent* _event )
1445 if((_event->modifiers() & Qt::ShiftModifier) != Qt::ShiftModifier && moveCircle_IsLocked)
1446 moveCircle_IsLocked = moveCircle_IsFloating =
false;
1449 if (_event->type() == QEvent::MouseButtonPress) {
1451 size_t node_idx, target_idx;
1456 GlutPrimitiveNode* glutNode =
dynamic_cast<GlutPrimitiveNode*
>(node);
1462 moveCircle_SelNode_ = glutNode;
1485 cur_move_id_ = cur_pol->
id();
1487 move_point_ref_ = &(cur_pol->
line()->
point(target_idx));
1494 if (_event->type() == QEvent::MouseMove){
1495 if (moveCircle_SelNode_) {
1502 bool hasHit = me_GetMeshHit(_event, moveCircle_SelNode_, hit_point, lineData->circleMeshIndex_, target_idx);
1503 if(lineData->circleMeshIndex_ == std::numeric_limits<unsigned int>::max())
return;
1504 if(!moveCircle_IsLocked && hasHit) {
1505 moveCircle_IsFloating =
false;
1506 ACG::Vec3d x0 = lineData->circleCenter_, n = lineData->circleNormal_;
1508 double t = ((n | x0) - (n | onMesh)) / n.sqrnorm();
1514 me_UpdateCircleData(onMesh, onPlane, mesh->
mesh()->normal(mesh->
mesh()->face_handle(target_idx)), moveCircle_SelNode_, lineData, (_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier);
1515 if (!moveCircle_SelNode_->
name().compare(
"N_Center")) {
1517 if((_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier) {
1518 moveCircle_IsLocked =
true;
1519 moveCircle_LastHitNor_ = lineData->circleNormal_;
1525 moveCircle_IsFloating =
true;
1534 : lineData->circleNormal_;
1535 const double t = ((x0 | n) - (cameraPos | n)) / (cameraDir | n);
1536 const ACG::Vec3d onPlane = cameraPos + cameraDir * t;
1538 me_UpdateCircleData(onPlane, onPlane, n, moveCircle_SelNode_, lineData, (_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier);
1552 if(lineData->
meshIndex_ == std::numeric_limits<unsigned int>::max())
1558 ACG::Vec3d onMesh = hit_point, onMeshNor = mesh->
mesh()->normal(mesh->
mesh()->face_handle(target_idx));
1562 lineData->points_[controlIndex].position = onMesh;
1563 lineData->points_[controlIndex].normal = onMeshNor;
1565 int handleIndex = 2 * controlIndex - 1;
1566 ACG::Vec3d dir = lineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
1568 lineData->handles_[handleIndex] = point;
1570 if(controlIndex != ((
int)lineData->points_.size() - 1)) {
1571 int handleIndex = 2 * controlIndex;
1572 ACG::Vec3d dir = lineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
1574 lineData->handles_[handleIndex] = point;
1585 double t = ((control.normal | control.position) - (control.normal | cameraPos)) / (control.normal | cameraDir);
1586 ACG::Vec3d onPlane = cameraPos + t * cameraDir;
1588 lineData->handles_[handleIndex] = onPlane;
1589 if(handleIndex % 2 == 1 && handleIndex != ((
int)lineData->handles_.size() - 1)) {
1590 double dist = (lineData->handles_[handleIndex + 1] - control.position).norm();
1591 if(_event->modifiers() & Qt::ShiftModifier)
1592 dist = (onPlane - control.position).norm();
1593 ACG::Vec3d dir = -(onPlane - control.position).normalize();
1594 lineData->handles_[handleIndex + 1] = control.position + dir * dist;
1596 if(handleIndex % 2 == 0 && handleIndex) {
1597 double dist = (lineData->handles_[handleIndex - 1] - control.position).norm();
1598 if(_event->modifiers() & Qt::ShiftModifier)
1599 dist = (onPlane - control.position).norm();
1600 ACG::Vec3d dir = -(onPlane - control.position).normalize();
1601 lineData->handles_[handleIndex - 1] = control.position + dir * dist;
1604 GlutLineNode* lineN;
1610 else if (move_point_ref_ != 0) {
1612 size_t node_idx, target_idx;
1614 (*move_point_ref_) = (PolyLine::Point) hit_point;
1622 if (_event->type() == QEvent::MouseButtonRelease) {
1623 if((_event->modifiers() & Qt::ShiftModifier) != Qt::ShiftModifier) {
1626 moveCircle_IsLocked = moveCircle_IsFloating =
false;
1630 moveCircle_IsLocked =
false;
1635 move_point_ref_ = 0;
1636 moveCircle_SelNode_ = 0;
1637 createCircle_CurrSelIndex_ = -1;
1647 me_split( QMouseEvent* _event )
1650 if (_event->type() == QEvent::MouseButtonPress) {
1652 move_point_ref_ = 0;
1654 size_t node_idx, target_idx;
1676 cur_move_id_ = cur_pol->
id();
1707 cur_move_id_ = cur_pol->
id();
1723 if (_event->type() == QEvent::MouseMove)
1724 if (move_point_ref_ != 0) {
1726 size_t node_idx, target_idx;
1730 (*move_point_ref_) = (PolyLine::Point) hit_point;
1739 if (_event->type() == QEvent::MouseButtonRelease) {
1741 if (cur_move_id_ != -1)
1744 move_point_ref_ = 0;
1755 me_merge( QMouseEvent* _event )
1758 if (_event->type() == QEvent::MouseButtonPress) {
1760 move_point_ref_ = 0;
1763 size_t node_idx, target_idx;
1778 if (target_idx == cur_pol->
line()->
n_vertices() - 1 || target_idx == 0) {
1779 if (target_idx == 0) {
1785 cur_merge_id_ = cur_pol->
id();
1798 if (_event->type() == QEvent::MouseMove && cur_merge_id_ != -1)
1799 if (move_point_ref_ != 0) {
1800 size_t node_idx, target_idx;
1804 (*move_point_ref_) = (PolyLine::Point) hit_point;
1813 if (_event->type() == QEvent::MouseButtonRelease && cur_merge_id_ != -1) {
1814 PolyLine::Point p_save;
1817 if (move_point_ref_ != 0) {
1829 move_point_ref_ = 0;
1832 size_t node_idx, target_idx;
1841 PluginFunctions::invalidatePickCaches();
1843 bool merged =
false;
1856 if ( target_idx < second_pol->line()->n_vertices() ) {
1859 unsigned int second_idx = target_idx;
1864 bool inv_first(
false), inv_second(
false);
1867 if (first_idx == 0) {
1879 if (first_idx == first_pol->
line()->
n_vertices() - 1 && second_idx == 0) {
1881 if (first_pol->
id() == second_pol->
id()) {
1898 emit deleteObject(second_pol->
id());
1909 PluginFunctions::invalidatePickCaches();
1922 if ( target_idx < second_pol->line()->n_vertices() ) {
1925 unsigned int second_idx = target_idx;
1931 if (first_idx == 0) {
1940 if (first_pol->
id() == second_pol->
id() && first_idx == first_pol->
line()->
n_vertices() - 1 && second_idx == 0) {
1965 move_point_ref_ = 0;
1977 me_smart_move( QMouseEvent* _event )
1980 if (_event->type() == QEvent::MouseButtonPress) {
1982 size_t node_idx, target_idx;
1995 cur_polyline_obj_ = cur_pol;
2002 cur_smart_move_obj_ = cur_pol;
2003 if (cur_pol->
line()->vertex_selections_available()) {
2004 if (!(_event->modifiers() & (Qt::ShiftModifier)))
2005 cur_pol->
line()->vertex_selection(target_idx) =
true;
2007 cur_pol->
line()->vertex_selection(target_idx) =
false;
2015 if (!(_event->modifiers() & (Qt::ShiftModifier)))
2016 smart_move_timer_->start(20);
2023 if( _event->type() == QEvent::MouseButtonRelease)
2025 smart_move_timer_->stop();
2026 cur_smart_move_obj_ = NULL;
2038 slotEditModeChanged()
2051 GlutPrimitiveNode* H0, *H1, *C;
2055 ACG::Vec3d h0 = circleData->circleCenter_ + circleData->circleMainAxis_ * circleData->circleMainRadius_,
2056 h1 = circleData->circleCenter_ + circleData->circleSideAxis_ * circleData->circleSideRadius_;
2058 C->set_position(circleData->circleCenter_);
2069 slot_setCirclePointNum(
int i)
2080 slot_setSplinePointNum(
int i)
2093 tool_->rb_insert->setChecked(
true);
2095 tool_->rb_InsertCircle->setChecked(
true);
2097 tool_->rb_InsertSpline->setChecked(
true);
2099 tool_->rb_delete->setChecked(
true);
2101 tool_->rb_move->setChecked(
true);
2103 tool_->rb_smart_move->setChecked(
true);
2105 tool_->rb_merge->setChecked(
true);
2107 tool_->rb_split->setChecked(
true);
2127 slotEnablePickMode(QString _name)
2134 if(_name ==
"INSERT")
2135 tool_->rb_insert->setChecked(
true);
2136 else if(_name ==
"DELETE")
2137 tool_->rb_delete->setChecked(
true);
2138 else if(_name ==
"MOVE")
2139 tool_->rb_move->setChecked(
true);
2140 else if(_name ==
"SPLIT")
2141 tool_->rb_split->setChecked(
true);
2142 else if(_name ==
"MERGE")
2143 tool_->rb_merge->setChecked(
true);
2144 else if( _name ==
"SMART_MOVE")
2145 tool_->rb_smart_move->setChecked(
true);
2153 pick_triangle_mesh( QPoint mPos,
2157 _fh = TriMesh::FaceHandle (-1);
2160 size_t target_idx = 0, node_idx = 0;
2178 _fh = m.face_handle(target_idx);
2182 float shortest_distance = (m.point(closest) - hit_point).sqrnorm();
2185 if ( (m.point(*fv_it ) - hit_point).sqrnorm() < shortest_distance ) {
2186 shortest_distance = (m.point(*fv_it ) - hit_point).sqrnorm();
2191 if ( (m.point(*fv_it ) - hit_point).sqrnorm() < shortest_distance ) {
2198 _hitPoint = hit_point;
2211 slotUpdateContextMenu(
int objectId)
2213 copyPaste_ObjectId_ = objectId;
2214 copyPaste_Action_->setVisible(
pickToolbar_->isVisible());
2219 me_copyPasteMouse(QMouseEvent* _event)
2226 copyPaste_ObjectId_ = copyPaste_ActionType_ - 1;
2229 size_t target_idx = 0, node_idx = 0;
2232 if(copyPaste_ActionType_ == 1) {
2242 GlutPrimitiveNode* glutNode =
dynamic_cast<GlutPrimitiveNode*
>(node);
2244 me_GetMeshHit(_event, glutNode, hit_point, circleData->circleMeshIndex_, target_idx);
2246 circleData-> circleCenter_ = hit_point;
2250 else if(oldSplineData) {
2251 for(
int i = 0; i < (int)splineData->points_.size(); i++) {
2252 ACG::Vec3d onMeshNor, oldPos = splineData->points_[i].position;
2254 splineData->points_[i].position = onMesh;
2255 splineData->points_[i].normal = onMeshNor;
2257 int handleIndex = 2 * i - 1;
2258 ACG::Vec3d dir = splineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
2260 splineData->handles_[handleIndex] = point;
2262 if(i != ((
int)splineData->points_.size() - 1)) {
2263 int handleIndex = 2 * i;
2264 ACG::Vec3d dir = splineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
2266 splineData->handles_[handleIndex] = point;
2269 GlutLineNode* lineN;
2277 newObj->
line()->
point(i) = hit_point + copyPaste_RelativePoints_[i];
2282 if(_event->type() == QEvent::MouseButtonPress) {
2283 copyPaste_ActionType_ = copyPaste_ObjectId_ = -1;
2286 else if(copyPaste_ActionType_ == 2) {
2300 size_t target_idx = 0, node_idx = 0;
2303 QPoint mPos = copyPaste_LastMouse;
2305 copyPaste_ActionType_ = 1;
2319 copyPaste_RelativePoints_.clear();
2324 createCircle_createUI(new_line_id);
2326 else if(splineData) {
2329 createSpline_createUI(new_line_id);
2332 for(
size_t i = 0; i < newData->points_.size(); i++)
2333 copyPaste_RelativePoints_.push_back(newData->points_[i].position - hit_point);
2340 copyPaste_RelativePoints_.push_back(obj->
line()->
point(i) - hit_point);
2344 copyPaste_NewObjectId_ = new_line_id;
2355 copyPaste_ActionType_ = 2;
2359 #if QT_VERSION < 0x050000
QString name() const
return the name of the object. The name defaults to NONAME if unset.
int createSpline_CurrSelIndex_
The index of the currently created spline.
void add_point(const Point &_p)
Append a point to the polyline.
void invert()
Invert polyline that first vertex becomes last.
PerObjectData * objectData(QString _dataName)
Returns the object data pointer.
PolyLineObject * polyLineObject(BaseObjectData *_object)
Cast an BaseObject to a PolyLineObject if possible.
bool dataType(DataType _type) const
Scalar length() const
Compute the length of the polyline (in future cached method)
ACG::SceneGraph::PolyLineNodeT< PolyLine > * lineNode()
Get the scenegraph Node.
QtPlaneSelect * planeSelect_
Plane selection tool.
void slotScissorButton()
Scissor Button was hit.
bool getAdditionalNode(NodeT *&_node, QString _pluginName, QString _nodeName, int _id=0)
get an addition node from the object
int moveBezSpline_SelSubIndex_
The index of the control or handle being moved.
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.
BaseObject * childExists(int _objectId)
Check if the element exists in the subtree of this element.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
void resize(unsigned int _n)
Resize current polyline.
QActionGroup * pickToolBarActions_
Called by pick Toolbar.
QAction * cutMultipleAction_
Called by pick Toolbar.
DrawMode WIREFRAME
draw wireframe
void setObjectDrawMode(const ACG::SceneGraph::DrawModes::DrawMode &_mode, const bool &_force=false)
Set the draw mode for the object.
ACG::GLState & glState()
Get the glState of the Viewer.
void set_vertex_radius(const Scalar _r)
set ball-radius of vertices
Namespace providing different geometric functions concerning angles.
bool getObject(int _identifier, BSplineCurveObject *&_object)
QAction * mergeAction_
Called by pick Toolbar.
const Vec3d get_position(int _idx=0) const
get position
void smooth_uniform_laplace2()
Squared laplacian smoothing.
void split(unsigned int _split_idx, PolyLineT< PointT > &_new_pl)
Split closed polyline at vertex with index _split_idx.
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(1)<< 3)
Topology updated.
Type for a MeshObject containing a triangle mesh.
QAction * splitAction_
Called by pick Toolbar.
void setObjectData(QString _dataName, PerObjectData *_data)
pick any of the prior targets (should be implemented for all nodes)
Scalar vertex_radius() const
get ball-radius of vertices
bool addAdditionalNode(NodeT *_node, QString _pluginName, QString _nodeName, int _id=0)
add an additional node to the object
int createSpline_LastSelIndex_
Use this one to mark the last index to update the number of points.
bool finishSpline()
If possible calculates handles.
double sceneRadius()
Returns the current scene radius from the active examiner widget.
void smooth_uniform_laplace3()
Cubic laplacian smoothing.
void set_position(const Vec3d &_p, int _idx=0)
set position
QAction * insertCircleAction_
Called by pick Toolbar.
int generatePolyLineFromCut(int _objectId, Vector _planePoint, Vector _planeNormal, int _polyLineId=-1)
Generates a polyLine of a plane intersection.
Viewer::ActionMode actionMode()
Get the current Action mode.
void subdivide(Scalar _largest)
Subdivide polyline.
ACG::SceneGraph::BaseNode * getRootNode()
Get the root node for data objects.
void slotPickToolbarAction(QAction *_action)
Called by pick Toolbar.
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, size_t &_nodeIdx, size_t &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
void updatePolyBezierHandles(PolyLineObject *_lineObject, ACG::SceneGraph::LineNode *_line)
Updates all the handles on the PolyBezier.
void get_viewport(int &_left, int &_bottom, int &_width, int &_height) const
get viewport
IdList generatePolyLinesFromCut(int _objectId, Vector _planePoint, Vector _planeNormal)
Generates a polyLine of a plane intersection.
void addInterpolatePoint(ACG::Vec3d _position, ACG::Vec3d _normal)
Adds a point to the end of the list and inserts control points.
ACG::Vec3d createCircle_getHit(PolyLineCircleData *_circleData, ACG::Vec3d _hit_point)
Returns point on mesh or point on the normal plane.
QAction * polyLineAction_
Called by Toolbar to enable pick mode.
MaterialNode * materialNode()
get a pointer to the materialnode
std::vector< Point > & points()
Get all points of the polyline.
QString name()
Name of the Plugin.
Point & point(unsigned int _i)
Get a point of the polyline.
void enablePicking(bool _enable)
Enable or disable picking for this Object.
int createCircle_CurrSelIndex_
The object which is being modified(created, dragged)
void viewingDirection(const ACG::Vec3d &_dir, const ACG::Vec3d &_up, int _viewer)
Set the viewing direction.
QToolBar * toolbar_
Called by Toolbar to enable pick mode.
void boundingBox(ACG::Vec3d &_bbMin, typename ACG::Vec3d &_bbMax)
Get the BoundingBox of this object.
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
picks faces (should be implemented for all nodes)
#define DATA_TRIANGLE_MESH
size_t meshIndex_
Index of the corresponding mesh.
PolyLineToolbarWidget * tool_
Widget for Toolbox.
QActionGroup * toolBarActions_
Called by Toolbar to enable pick mode.
void slotTriggerCutPlaneSelect()
Generate PolyLine after the cutPlane has been drawn.
bool is_closed() const
Check if the polyline is marked as closed.
OMTriangleBSP * requestTriangleBsp()
QAction * insertAction_
Called by pick Toolbar.
void project_to_mesh(const MeshT &_mesh, SpatialSearchT *_ssearch=0)
Project polyline points to nearest surface points (use spatial search!!!)
EditMode
Edit Mode of PolyLinePlugin.
QAction * smartMoveAction_
Called by pick Toolbar.
TriMeshObject * triMeshObject(BaseObjectData *_object)
Cast an BaseObject to a TriMeshObject if possible.
void smooth_uniform_laplace()
Laplacian smoothing.
QAction * cutAction_
Called by pick Toolbar.
void updatePolyBezierSpline(PolyLineObject *_lineObject, unsigned int _pointsPerSegment)
Generates points for the spline, updates handles.
void enablePicking(bool _enable)
InterpolatePoint & getInterpolatePoint(unsigned int _handleIndex)
Retrieves the interpolate point based on the handle.
VectorT< float, 4 > Vec4f
size_t n_vertices() const
Get number of vertices.
void slotScissorLinesButton()
Scissor Button for multiple polylines was hit.
PolyLinePlugin()
default constructor
The Menu will be shown when an object was picked.
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
QAction * moveAction_
Called by pick Toolbar.
QAction * deleteAction_
Called by pick Toolbar.
void viewing_ray(int _x, int _y, Vec3d &_origin, Vec3d &_direction) const
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
void set_random_color()
Generates a random color and sets it.
void append(const PolyLineT< PointT > &_pl)
Append second polyline _pl to this one.
QToolBar * pickToolbar_
Called by pick Toolbar.
int moveBezSpline_SelIndex_
The object which is being moved.
int createCircle_LastSelIndex_
Use this one to mark the last index to update the number of points.
Point & back()
Get last point of the polyline ( no range check!!!)
void delete_point(int _idx)
Delete point at _idx.
std::string name() const
Returns: name of node (needs not be unique)
void updateHandles(PolyLineObject *_lineObject)
Updates the center, forward and side handle of the Poly ellipse.
ACG::SceneGraph::GlutPrimitiveNode * moveBezSpline_SelNode_
The handle which is being dragged.
ACG::Vec3d moveCircle_LastHitPos_
The last valid hit on the mesh.
VectorT< double, 3 > Vec3d
const std::string pickMode()
Get the current Picking mode.
const QStringList TARGET_OBJECTS("target")
Iterable object range.
BaseObject *& objectRoot()
Get the root of the object structure.
MeshT * mesh()
return a pointer to the mesh
void set_closed(const bool _c)
Set if the polyline should be closed and therefore forms a loop.
PolyLine * line()
return a pointer to the line
bool getPickedObject(const size_t _node_idx, BaseObjectData *&_object)
Get the picked mesh.
QAction * insertSplineAction_
Called by pick Toolbar.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
DrawMode POINTS_SHADED
draw shaded points (requires point normals)
void split_closed(unsigned int _split_idx)
Split closed polyline at vertex with index _split_idx.
void updatePolyEllipse(PolyLineObject *_lineObject, unsigned int _pointCount)
Generates points for the ellipse.
void collapse(Scalar _smallest)
Collapse polyline.
picks verices (may not be implemented for all nodes)
void slotSetPolyLineMode(QAction *_action)
Called by Toolbar to enable pick mode.
Kernel::FaceVertexIter FaceVertexIter
Circulator.