Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
PolyLinePlugin.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43  * *
44  * $Revision$ *
45  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 
51 //== INCLUDES =================================================================
52 
53 
54 #include "PolyLinePlugin.hh"
55 
56 #include <ACG/Scenegraph/ManipulatorNode.hh>
57 
58 #if QT_VERSION >= 0x050000
59 #else
60 #include <QtGui>
61 #endif
62 
63 namespace {
64 
65 class GlutPrimitiveNode : public ACG::SceneGraph::GlutPrimitiveNode {
66 
67  public:
68 
69  GlutPrimitiveNode(PolyLineObject* L, std::string name, int _index = -1)
70  : ACG::SceneGraph::GlutPrimitiveNode(ACG::SceneGraph::GlutPrimitiveNode::SPHERE, L->manipulatorNode(), name)
71  {
72  index = _index;
73  line = L;
74  }
75 
76  public:
77 
78  PolyLineObject* line;
79  int index;
80 
81 };
82 
83 class GlutLineNode : public ACG::SceneGraph::LineNode {
84 
85  public:
86 
87  GlutLineNode(PolyLineObject* L, std::string name)
88  : ACG::SceneGraph::LineNode(LineSegmentsMode, L->manipulatorNode(), name)
89  {
90  line = L;
91  }
92 
93  public:
94  PolyLineObject* line;
95 
96 };
97 
98 }
99 
100 
101 //== IMPLEMENTATION ==========================================================
102 
105  tool_(0),
106  polyLineAction_(0),
107  toolBarActions_(0),
108  toolbar_(0),
109  pickToolbar_(0),
110  pickToolBarActions_(0),
111  insertAction_(0),
112  insertCircleAction_(0),
113  insertSplineAction_(0),
114  deleteAction_(0),
115  moveAction_(0),
116  smartMoveAction_(0),
117  mergeAction_(0),
118  splitAction_(0),
119  cutAction_(0),
120  cutMultipleAction_(0),
121  cur_insert_id_(-1),
122  cur_polyline_obj_(0),
123  cur_move_id_(-1),
124  move_point_ref_(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),
140  cur_merge_id_(-1),
141  smart_move_timer_(0),
142  cur_smart_move_obj_(0),
143  planeSelect_(0)
144 {
145 }
146 
147 
148 void
149 PolyLinePlugin::
150 initializePlugin()
151 {
152  // Initialize the Toolbox
154  QSize size(100, 100);
155  tool_->resize(size);
156  tool_->setObjectName("PolyLineToolbar");
157 
158  // connect signals->slots
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()));
165 #else
166  tool_->pb_resample_on_edges->setDisabled(true);
167 #endif
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()));
174 
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() ));
183 
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)));
186  //add icons
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") );
195 // tool_->rb_smooth_c0->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_insert.svg") );
196 // tool_->rb_smooth_c1->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_c1.svg") );
197 // tool_->rb_smooth_c2->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_c2.svg") );
198 
199 
200  // Add the toolbox with the given icon
201  QIcon* toolIcon = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"cut_polyline.png");
202  emit addToolbox( tr("PolyLine") , tool_, toolIcon );
203 }
204 
205 
206 //-----------------------------------------------------------------------------
207 
208 
209 void
210 PolyLinePlugin::
211 slotMouseEvent( QMouseEvent* _event )
212 {
213  copyPaste_LastMouse = _event->pos();
214 
215  // control modifier is reserved for selcting target
216  if (_event->modifiers() & (Qt::ControlModifier))
217  return;
218 
219  if (PluginFunctions::pickMode() == ("PolyLine") && PluginFunctions::actionMode() == Viewer::PickingMode
220  && _event->button() != Qt::RightButton) {
221  // handle mouse events depending on current mode
222  switch (mode()) {
223  case PL_INSERT:
224  me_insert(_event);
225  break;
226 
227  case PL_INSERTCIRCLE:
228  me_insertCircle(_event);
229  break;
230 
231  case PL_INSERTSPLINE:
232  me_insertSpline(_event);
233  break;
234 
235  case PL_DELETE:
236  me_delete(_event);
237  break;
238 
239  case PL_MOVE:
240  me_move(_event);
241  break;
242 
243  case PL_SPLIT:
244  me_split(_event);
245  break;
246 
247  case PL_MERGE:
248  me_merge(_event);
249  break;
250 
251  case PL_SMART_MOVE:
252  me_smart_move(_event);
253  break;
254 
255  case PL_COPY_PASTE:
256  me_copyPasteMouse(_event);
257  break;
258 
259  default:
260  break;
261  }
262  } else if ( (PluginFunctions::pickMode() == CREATE_CUT_POLYLINE) || (PluginFunctions::pickMode() == CREATE_CUT_POLYLINES) ) {
263  planeSelect_->slotMouseEvent(_event);
264  }
265 }
266 
267 void PolyLinePlugin::slotKeyEvent(QKeyEvent* event) {
268  switch (event->key()) {
269  case Qt::Key_Return:
270  if (PluginFunctions::pickMode() == ("PolyLine") && PluginFunctions::actionMode() == Viewer::PickingMode) {
271  if(mode() == PL_INSERT && cur_polyline_obj_ && cur_insert_id_ != -1) {
272  cur_polyline_obj_->line()->delete_point(cur_polyline_obj_->line()->n_vertices() - 1);
273 
274  if (event->modifiers() & (Qt::ShiftModifier))
275  cur_polyline_obj_->line()->set_closed(true);
276 
277  emit updatedObject(cur_insert_id_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
278 
279  cur_insert_id_ = -1;
280  cur_polyline_obj_ = 0;
281  create_point_ref_ = 0;
282 
283  clearStatusMessage();
284  }
285  else if(mode() == PL_INSERTSPLINE) {
286  finishSpline();
287  }
288  }
289  break;
290  default:
291  break;
292  }
293 }
294 //-----------------------------------------------------------------------------
295 
296 void
297 PolyLinePlugin::
298 slotPickModeChanged( const std::string& _mode)
299 {
300  polyLineAction_->setChecked(_mode == "PolyLine");
301  cutAction_->setChecked( _mode == CREATE_CUT_POLYLINE );
302  cutMultipleAction_->setChecked( _mode == CREATE_CUT_POLYLINES );
303 }
304 
305 
306 //-----------------------------------------------------------------------------
307 
308 
309 void
310 PolyLinePlugin::
311 pluginsInitialized()
312 {
313  // Add the required Picking modes (Hidden, controlled only by the buttons)
314  emit addHiddenPickMode("PolyLine");
315  emit setPickModeMouseTracking("PolyLine", true);
316  emit addHiddenPickMode( CREATE_CUT_POLYLINE );
317  emit addHiddenPickMode( CREATE_CUT_POLYLINES );
318 
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);
321 
322  // TOOLBAR
323  toolbar_ = new QToolBar(tr("PolyLine Editing"));
324  toolbar_->setObjectName("PolyLineEditingToolbar");
325 
326 
327  toolBarActions_ = new QActionGroup(toolbar_);
328 
329  // icon which enables the Modeling toolbar
330  polyLineAction_ = new QAction(tr("Edit PolyLines"), toolBarActions_);
331  polyLineAction_->setStatusTip(tr("Edit and create PolyLines."));
332  polyLineAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"polyline_insert.png") );
333  polyLineAction_->setCheckable(true);
334  toolbar_->addAction(polyLineAction_);
335 
336  // icon for polyline cutting of objects
337  cutAction_ = new QAction(tr("&Create polyline at intersection with plane"), this);
338  cutAction_->setCheckable( true );
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") );
341  connect(cutAction_, SIGNAL(triggered()), this, SLOT(slotScissorButton()) );
342  toolbar_->addAction(cutAction_);
343 
344  // icon for polyline cutting of objects
345  cutMultipleAction_ = new QAction(tr("&Create polylines at intersection with plane"), this);
346  cutMultipleAction_->setCheckable( true );
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") );
349  connect(cutMultipleAction_, SIGNAL(triggered()), this, SLOT(slotScissorLinesButton()) );
350  toolbar_->addAction(cutMultipleAction_);
351 
352  connect(toolBarActions_, SIGNAL(triggered(QAction*)), this, SLOT(slotSetPolyLineMode(QAction*)) );
353 
354  emit addToolbar(toolbar_);
355 
356  // Pick Toolbar
357  pickToolbar_ = new QToolBar(tr("PolyLine Editing"));
358  pickToolbar_->setObjectName("PolyLine_Editing_Toolbar");
359  pickToolbar_->setAttribute(Qt::WA_AlwaysShowToolTips, true);
360  pickToolBarActions_ = new QActionGroup(pickToolbar_);
361  pickToolBarActions_->setExclusive (true);
362 
363  insertAction_ = new QAction(tr("Create PolyLine"), pickToolBarActions_);
364  insertAction_->setStatusTip(tr("Create a new PolyLine."));
365  insertAction_->setToolTip(tr("Create a new PolyLine.\n"
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") );
369  insertAction_->setCheckable(true);
370  pickToolbar_->addAction(insertAction_);
371 
372  insertCircleAction_ = new QAction(tr("Create PolyCircle"), pickToolBarActions_);
373  insertCircleAction_->setStatusTip(tr("Create a new PolyCircle."));
374  insertCircleAction_->setToolTip(tr("Create a new PolyCircle.\n"
375  "<Click> to select the center.\n"
376  "Drag to specify the radius."));
377 
378  insertCircleAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"polyline_circle.png") );
379  insertCircleAction_->setCheckable(true);
380  pickToolbar_->addAction(insertCircleAction_);
381 
382  insertSplineAction_ = new QAction(tr("Create PolySpline"), pickToolBarActions_);
383  insertSplineAction_->setStatusTip(tr("Create a new PolySpline."));
384  insertSplineAction_->setToolTip(tr("Create a new PolySpline.\n"
385  "<Click> to select the points."));
386 
387  insertSplineAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"polyline_bezier.png") );
388  insertSplineAction_->setCheckable(true);
389  pickToolbar_->addAction(insertSplineAction_);
390 
391  deleteAction_ = new QAction(tr("Delete PolyLine"), pickToolBarActions_);
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") );
396  deleteAction_->setCheckable(true);
397  pickToolbar_->addAction(deleteAction_);
398 
399  smartMoveAction_ = new QAction(tr("Move PolyLine"), pickToolBarActions_);
400  smartMoveAction_->setStatusTip(tr("Move the PolyLine."));
401  smartMoveAction_->setToolTip(tr("Move the polyline."));
402  smartMoveAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"polyline_move.png") );
403  smartMoveAction_->setCheckable(true);
404  pickToolbar_->addAction(smartMoveAction_);
405 
406  mergeAction_ = new QAction(tr("Merge PolyLines"), pickToolBarActions_);
407  mergeAction_->setStatusTip(tr("Merge two PolyLines."));
408  mergeAction_->setToolTip(tr("Merge two PolyLines.\n"
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") );
411  mergeAction_->setCheckable(true);
412  pickToolbar_->addAction(mergeAction_);
413 
414  splitAction_ = new QAction(tr("Split a PolyLine"), pickToolBarActions_);
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") );
419  splitAction_->setCheckable(true);
420  pickToolbar_->addAction(splitAction_);
421 
422  pickToolbar_->addSeparator ();
423 
424  moveAction_ = new QAction(tr("Move PolyLine Vertex"), pickToolBarActions_);
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") );
428  moveAction_->setCheckable(true);
429  pickToolbar_->addAction(moveAction_);
430 
431  emit setPickModeToolbar ("PolyLine", pickToolbar_);
432 
433  connect(pickToolBarActions_, SIGNAL(triggered(QAction*)), this, SLOT(slotPickToolbarAction(QAction*)) );
434 
435  // construct timer
436  smart_move_timer_ = new QTimer(this);
437  connect(smart_move_timer_, SIGNAL(timeout()), this, SLOT(slot_smart_move_timer()));
438 
439  // Instantiate plane select object
441  connect( planeSelect_, SIGNAL( signalTriggerCut( ) ), this, SLOT( slotTriggerCutPlaneSelect() ) );
442  connect( planeSelect_, SIGNAL( updateViewProxy( ) ), this, SIGNAL( updateView() ) );
443  connect( planeSelect_, SIGNAL( nodeVisChangedProxy(int) ), this, SIGNAL(nodeVisibilityChanged(int) ) );
444 
445  //create copy paste action in context menu
446  copyPaste_Action_ = new QAction("Duplicate", 0);
447  connect(copyPaste_Action_,SIGNAL(triggered() ),this,SLOT(slot_duplicate()));
448  emit addContextMenuItem(copyPaste_Action_ , DATA_POLY_LINE , CONTEXTOBJECTMENU );
449 }
450 
451 //------------------------------------------------------------------------------
452 
457 {
458  PluginFunctions::actionMode( Viewer::PickingMode );
459  PluginFunctions::pickMode( CREATE_CUT_POLYLINE );
460 }
461 
462 //------------------------------------------------------------------------------
463 
468 {
469  PluginFunctions::actionMode( Viewer::PickingMode );
470  PluginFunctions::pickMode( CREATE_CUT_POLYLINES );
471 }
472 
473 //-----------------------------------------------------------------------------
474 
479 {
480 
482 
483  // Iterate over all selected objects
484  BaseObjectData* object;
485  if (PluginFunctions::getPickedObject(planeSelect_->getNode(), object)) {
486  emit log("Cutting object " + object->name());
487 
488  if (!(object->dataType(DATA_TRIANGLE_MESH) || object->dataType(DATA_POLY_MESH))) {
489  emit log("Only Meshes are supported at the moment ");
490  return;
491  }
492 
493  ACG::Vec3d point = planeSelect_->getSourcePoint();
494  ACG::Vec3d normal = planeSelect_->getNormal();
495 
496  if ( PluginFunctions::pickMode() == CREATE_CUT_POLYLINE) {
497 
498  int objectId = generatePolyLineFromCut(object->id(), point, normal);
499 
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);
504 
505  //remove all other targets
508  if (o_it->id() != object->id()) {
509  o_it->target(false);
510  }
511  }
512 
513  // If we successfully created the polyline, we can inform the core about it.
514  if ( objectId != -1)
515  emit updatedObject(objectId,UPDATE_ALL);
516  } else {
517 
518  std::vector <int> objectIds = generatePolyLinesFromCut(object->id(), point, normal);
519 
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);
524 
525  //remove all other targets
528  if (o_it->id() != object->id()) {
529  o_it->target(false);
530  }
531  }
532 
533  for ( unsigned int i = 0 ; i < objectIds.size() ; ++i ) {
534  // If we successfully created the polyline, we can inform the core about it.
535  if ( objectIds[i] != -1)
536  emit updatedObject(objectIds[i],UPDATE_ALL);
537  }
538 
539  }
540  }
541 
542 }
543 
544 //-----------------------------------------------------------------------------
545 
546 void
547 PolyLinePlugin::
548 slot_subdivide()
549 {
550  // get subdivision value
551  double max_length = tool_->dsb_subdivide->value();
552 
553  // safety catch
554  if (max_length == 0.0)
555  max_length = 1e-4;
556 
557  // iterate over all target polylines
559 
560  for (; o_it != PluginFunctions::objectsEnd(); ++o_it) {
561  // subdivide polyline
562  PluginFunctions::polyLineObject(*o_it)->line()->subdivide(max_length);
563  }
564 
565  // update
566  emit updateView();
567 }
568 
569 
570 //-----------------------------------------------------------------------------
571 
572 
573 void PolyLinePlugin::slot_subdivide_percent(bool _checked) {
574 
575  // Get subdivision value
576  int n_active_pl = 0;
577  double total_length = 0;
578 
579  // Iterate over all target polylines
581 
582  for (; o_it != PluginFunctions::objectsEnd(); ++o_it) {
583  // Add polyline length
584  total_length += PluginFunctions::polyLineObject(*o_it)->line()->length();
585  ++n_active_pl;
586  }
587 
588  double v = total_length / double(n_active_pl);
589 
590  if (_checked) {
591 
592  // Compute current absolute length to relative portion
593  if (n_active_pl > 0) {
594  double val_new = tool_->dsb_subdivide->value() / v;
595  tool_->dsb_subdivide->setValue(val_new);
596  } else {
597  emit log(LOGWARN, "Could not find any active polyline!");
598  }
599  } else {
600 
601  // Compute relative portion to absolute value
602  if (n_active_pl > 0) {
603  double val_new = tool_->dsb_subdivide->value() * v;
604  tool_->dsb_subdivide->setValue(val_new);
605  } else {
606  emit log(LOGWARN, "Could not find any active polyline!");
607  }
608  }
609 }
610 
611 
612 //-----------------------------------------------------------------------------
613 
614 
615 void
616 PolyLinePlugin::
617 slot_decimate()
618 {
619  // get subdivision value
620  double min_length = tool_->dsb_decimate->value();
621 
622  // iterate over all target polylines
624 
625  for (; o_it != PluginFunctions::objectsEnd(); ++o_it) {
626  // decimate polyline
627  PluginFunctions::polyLineObject(*o_it)->line()->collapse(min_length);
628  }
629 
630  // update
631  emit updateView();
632 }
633 
634 //-----------------------------------------------------------------------------
635 
636 
637 void PolyLinePlugin::slot_decimate_percent(bool _checked)
638 {
639 
640  // Get decimation value
641  int n_active_pl = 0;
642  double total_length = 0;
643 
644  // Iterate over all target polylines
646 
647  for (; o_it != PluginFunctions::objectsEnd(); ++o_it) {
648  // Add polyline length
649  total_length += PluginFunctions::polyLineObject(*o_it)->line()->length();
650  ++n_active_pl;
651  }
652 
653  double v = total_length / double(n_active_pl);
654 
655  if (_checked) {
656 
657  // Compute current absolute length to relative portion
658  if (n_active_pl > 0) {
659  double val_new = tool_->dsb_subdivide->value() / v;
660  tool_->dsb_decimate->setValue(val_new);
661  } else {
662  emit log(LOGWARN, "Could not find any active polyline!");
663  }
664  } else {
665 
666  // Compute relative portion to absolute value
667  if (n_active_pl > 0) {
668  double val_new = tool_->dsb_subdivide->value() * v;
669  tool_->dsb_decimate->setValue(val_new);
670  } else {
671  emit log(LOGWARN, "Could not find any active polyline!");
672  }
673  }
674 }
675 
676 
677 //-----------------------------------------------------------------------------
678 
679 #ifdef EXTENDED_POLY_LINE
680 
681 void
682 PolyLinePlugin::
683 slot_resample_on_edges()
684 {
685  // count target meshes
687  unsigned int n_targetMeshes(0);
688  for(; o_it != PluginFunctions::objectsEnd(); ++o_it)
689  ++n_targetMeshes;
690 
691  if( n_targetMeshes != 1)
692  {
693  std::cerr << "Warning: resample_on_edges needs exactly 1 target mesh! Otherwise no operation is performed! \n";
694  return;
695  }
696 
697  // take first target mesh
699 
700  if(o_it != PluginFunctions::objectsEnd())
701  {
702  // get pointer to TriMeshObject
703  TriMeshObject* tmesh_obj = PluginFunctions::triMeshObject(*o_it);
704 
705  // get pointer to mesh
706  TriMesh* mesh = tmesh_obj->mesh();
707 
708  // get pointer to triangle bsp
710  // OpenMeshTriangleBSPT< TriMesh >* tbsp = 0;
711 
712  // iterate over all target polylines
714 
715  for (; o_it2 != PluginFunctions::objectsEnd(); ++o_it2)
716  {
717  std::cerr << "resample " << o_it2->name().toStdString() << std::endl;
718  // decimate polyline
719  PluginFunctions::polyLineObject(*o_it2)->line()->resample_on_mesh_edges( *mesh, tbsp );
720  }
721 
722  // update
723  emit updateView();
724  }
725 }
726 
727 #endif
728 
729 //-----------------------------------------------------------------------------
730 
731 
732 void
733 PolyLinePlugin::
734 slot_smooth()
735 {
736  // iterate over all target polylines
738 
739  for ( ; o_it != PluginFunctions::objectsEnd(); ++o_it)
740  {
741  for( int i=0; i<tool_->sb_smooth_iter->value(); ++i)
742  if( tool_->rb_smooth_c0->isChecked())
743  // smooth polyline C0
745  else
746  if( tool_->rb_smooth_c1->isChecked())
747  // smooth polyline C1
749  else
750  if( tool_->rb_smooth_c2->isChecked())
751  // smooth polyline C2
753 
754  emit updatedObject( o_it->id(), UPDATE_GEOMETRY);
755  }
756 
757 }
758 
759 
760 //-----------------------------------------------------------------------------
761 
762 
763 void
764 PolyLinePlugin::
765 slot_smooth( PolyLineObject*& _pol)
766 {
767  // if polyline object is valid
768  if (_pol) {
769  for (int i = 0; i < tool_->sb_smooth_iter->value(); ++i)
770  if (tool_->rb_smooth_c0->isChecked())
771  // smooth polyline C0
772  _pol->line()->smooth_uniform_laplace();
773  else if (tool_->rb_smooth_c1->isChecked())
774  // smooth polyline C1
775  _pol->line()->smooth_uniform_laplace2();
776  else if (tool_->rb_smooth_c2->isChecked())
777  // smooth polyline C2
778  _pol->line()->smooth_uniform_laplace3();
779 
780  emit updatedObject(_pol->id(), UPDATE_GEOMETRY);
781  }
782 }
783 
784 //-----------------------------------------------------------------------------
785 
786 
787 void
788 PolyLinePlugin::
789 slot_project()
790 {
791  // create meshe and bsp vectors
792  std::vector<TriMesh*> meshes;
793  std::vector<OpenMeshTriangleBSPT<TriMesh>*> bsps;
794 
796 
797  for (; o_it != PluginFunctions::objectsEnd(); ++o_it) {
798  // get pointer to TriMeshObject
799  TriMeshObject* tmesh_obj = PluginFunctions::triMeshObject(*o_it);
800 
801  // save meshes and bsps
802  meshes.push_back(tmesh_obj->mesh());
803  // bsps.push_back(0);
804  bsps.push_back(tmesh_obj->requestTriangleBsp());
805  }
806 
807  // iterate over all target polylines
809 
810  for (; o_it2 != PluginFunctions::objectsEnd(); ++o_it2) {
811  // project polyline
812  PluginFunctions::polyLineObject(*o_it2)->line()->project_to_mesh(meshes, &bsps);
813  emit updatedObject(o_it2->id(), UPDATE_GEOMETRY);
814  }
815 }
816 
817 
818 //-----------------------------------------------------------------------------
819 
820 
821 void
822 PolyLinePlugin::
823 slot_project( PolyLineObject*& _pol)
824 {
825  // check if polyline ok
826  if (_pol) {
827 
828  // create meshes and bsp vectors
829  std::vector<TriMesh*> meshes;
830  std::vector<OpenMeshTriangleBSPT<TriMesh>*> bsps;
831 
833 
834  for (; o_it != PluginFunctions::objectsEnd(); ++o_it) {
835 
836  // get pointer to TriMeshObject
837  TriMeshObject* tmesh_obj = PluginFunctions::triMeshObject(*o_it);
838 
839  // save meshes and bsps
840  meshes.push_back(tmesh_obj->mesh());
841  // bsps.push_back(0);
842  bsps.push_back(tmesh_obj->requestTriangleBsp());
843  }
844 
845  // only project given PolyLine
846  _pol->line()->project_to_mesh(meshes, &bsps);
847  }
848 
849 }
850 
851 
852 //-----------------------------------------------------------------------------
853 
854 
855 void
856 PolyLinePlugin::
857 slot_smooth_project()
858 {
859  int smooth_project_iter = tool_->sb_smooth_project_iter->value();
860 
861  for (int i = 0, j = 1; i < smooth_project_iter; ++i, ++j) {
862 
863  // n smoothing steps
864  slot_smooth();
865 
866  // projection step
867  slot_project();
868 
869  }
870 }
871 
872 
873 //-----------------------------------------------------------------------------
874 
875 
876 void
877 PolyLinePlugin::
878 slot_smooth_project(PolyLineObject*& _pol)
879 {
880  int smooth_project_iter = tool_->sb_smooth_project_iter->value();
881 
882  for (int i = 0, j = 1; i < smooth_project_iter; ++i, ++j) {
883 
884  // n smoothing steps
885  slot_smooth(_pol);
886 
887  // projection step
888  slot_project(_pol);
889 
890  }
891 }
892 
893 
894 //-----------------------------------------------------------------------------
895 
896 
897 void
898 PolyLinePlugin::
899 slot_smart_move_timer()
900 {
901  int smooth_project_iter = tool_->sb_smooth_project_iter->value();
902 
903  if (smooth_project_iter)
904  slot_smooth_project(cur_smart_move_obj_);
905  else // only smooth
906  slot_smooth(cur_smart_move_obj_);
907 
908  emit updateView();
909 }
910 
911 //-----------------------------------------------------------------------------
912 
913 void
914 PolyLinePlugin::slotObjectUpdated( int _identifier, const UpdateType &_type )
915 {
916  PolyLineObject* lineObject = 0;
917  if(!PluginFunctions::getObject(_identifier, lineObject))
918  return;
919  PolyLineCircleData* circleData = dynamic_cast<PolyLineCircleData*>(lineObject->objectData(CIRCLE_DATA));
920  PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(lineObject->objectData(BEZSPLINE_DATA));
921  GlutPrimitiveNode* H = 0, *C = 0;
922  lineObject->getAdditionalNode(C, name(), "circle");
923  lineObject->getAdditionalNode(H, name(), "control", 0);
924  if(circleData && !C) {
925  createCircle_createUI(_identifier);
926  }
927  else if(splineData && !H) {
928  createSpline_createUI(_identifier);
929  }
930 }
931 
932 //-----------------------------------------------------------------------------
933 
935 PolyLinePlugin::
936 mode()
937 {
938  if(copyPaste_ObjectId_ != -1 && copyPaste_ActionType_ != -1)//no matter what tool is selected
939  return PL_COPY_PASTE;
940 
941  if(tool_ )
942  {
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;
951  }
952 
953  return PL_NONE;
954 }
955 
956 //-----------------------------------------------------------------------------
957 
958 void
959 PolyLinePlugin::
960 me_insert( QMouseEvent* _event )
961 {
962  if (_event->type() == QEvent::MouseMove) {
963 
964  if (create_point_ref_) {
965  // Pick position
966  size_t node_idx, target_idx;
967  ACG::Vec3d hit_point;
968  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
969  *create_point_ref_ = (PolyLine::Point) hit_point;
970 
971  // update
972  emit updatedObject(cur_insert_id_, UPDATE_GEOMETRY);
973  }
974  }
975  return;
976  }
977 
978  // Pick position
979  size_t node_idx, target_idx;
980  ACG::Vec3d hit_point;
981  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
982 
983  switch (_event->type()) {
984  // insert new point
985  case QEvent::MouseButtonPress: {
986  // new Polyline?
987  if (cur_insert_id_ == -1 || !PluginFunctions::objectRoot()->childExists(cur_insert_id_)) {
988  // add new polyline
989  emit addEmptyObject(DATA_POLY_LINE, cur_insert_id_);
990 
991  // get current polylineobject
992  BaseObjectData *obj = 0;
993  PluginFunctions::getObject(cur_insert_id_, obj);
994  // default: set as target
995  obj->target(true);
996  // get polyline object
997  cur_polyline_obj_ = PluginFunctions::polyLineObject(obj);
998 
999  cur_polyline_obj_->materialNode()->set_random_color();
1000 
1001  cur_polyline_obj_->line()->set_vertex_radius(PluginFunctions::sceneRadius()*0.012);
1002 
1003  cur_polyline_obj_->lineNode()->drawMode(ACG::SceneGraph::DrawModes::DrawMode::getFromDescription("Points (as Spheres, constant screen size)") | ACG::SceneGraph::DrawModes::WIREFRAME);
1004 
1005  cur_polyline_obj_->line()->add_point((PolyLine::Point) hit_point);
1006 
1007  emit showStatusMessage(tr("Double click/Enter to terminate poly line. Use with shift to create loop."));
1008  }
1009 
1010  // add new point
1011  cur_polyline_obj_->line()->add_point((PolyLine::Point) hit_point);
1012  create_point_ref_ = &cur_polyline_obj_->line()->points().back();
1013 
1014  // update
1015  emit updatedObject(cur_insert_id_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
1016 
1017  break;
1018  }
1019 
1020  // finish polyline
1021  case QEvent::MouseButtonDblClick: {
1022  // close polyline
1023  if (_event->modifiers() & (Qt::ShiftModifier)) {
1024  cur_polyline_obj_->line()->set_closed(true);
1025  }
1026 
1027  if (cur_polyline_obj_->line()->n_vertices() >= 2) {
1028 
1029  cur_polyline_obj_->line()->delete_point(cur_polyline_obj_->line()->n_vertices() - 1);
1030  }
1031 
1032  // update
1033  emit updatedObject(cur_insert_id_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
1034 
1035  // reset current variables
1036  cur_insert_id_ = -1;
1037  cur_polyline_obj_ = 0;
1038  create_point_ref_ = 0;
1039 
1040  clearStatusMessage();
1041 
1042  break;
1043  }
1044 
1045  default:
1046  break;
1047  }
1048  }
1049 }
1050 
1051 //-----------------------------------------------------------------------------
1052 
1053 double getRad(int meshIdx)
1054 {
1055  TriMeshObject* mesh;
1056  if(PluginFunctions::getObject(meshIdx, mesh)) {
1057  //use the size of the mesh to compute the handle radii
1058  ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1059  ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1060  mesh->boundingBox(bbMin, bbMax);
1061  return 0.005*(bbMax-bbMin).norm();
1062  }
1063  else {
1064  return PluginFunctions::sceneRadius()*0.01;//use double of the above cause it is the radius
1065  }
1066 }
1067 
1068 void PolyLinePlugin::
1069 createCircle_createUI(int _polyLineObjectID)
1070 {
1071  PolyLineObject* lineObject;
1072  if (!PluginFunctions::getObject(_polyLineObjectID, lineObject) || !lineObject->objectData(CIRCLE_DATA))
1073  return;
1074  PolyLineCircleData* lineData = dynamic_cast<PolyLineCircleData*>(lineObject->objectData(CIRCLE_DATA));
1075 
1077 
1078  double rad = getRad(lineData->circleMeshIndex_);
1079 
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);
1083  handle0->show();
1084  handle0->enablePicking(true);
1085  handle0->set_position(lineData->circleCenter_ + lineData->circleMainAxis_ * lineData->circleMainRadius_);
1086  lineObject->addAdditionalNode(handle0, name(), "handle0");
1088 
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);
1092  handle1->show();
1093  handle1->enablePicking(true);
1094  handle1->set_position(lineData->circleCenter_ + lineData->circleSideAxis_ * lineData->circleSideRadius_);
1095  lineObject->addAdditionalNode(handle1, name(), "handle1");
1097 
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);
1101  cenNode->show();
1102  cenNode->enablePicking(true);
1103  cenNode->set_position(lineData->circleCenter_);
1104  lineObject->addAdditionalNode(cenNode, name(), "circle");
1106 
1107  emit updatedObject(_polyLineObjectID, UPDATE_ALL);
1108 }
1109 
1110 //-----------------------------------------------------------------------------
1111 
1112 void PolyLinePlugin::
1113 me_insertCircle(QMouseEvent* _event)
1114 {
1115  TriMeshObject* mesh;
1116  TriMesh::FaceHandle fh;
1118  ACG::Vec3d hit_point;
1119  if(!pick_triangle_mesh(_event->pos(), mesh, fh, vh, hit_point) && _event->type() != QEvent::MouseButtonRelease)
1120  return;//can't generate a circle in empty space
1121 
1122  if(_event->type() == QEvent::MouseMove && createCircle_CurrSelIndex_ != -1) {
1123  PolyLineObject* lineObject = 0;
1124  if(!PluginFunctions::getObject(createCircle_CurrSelIndex_, lineObject) || !lineObject->objectData(CIRCLE_DATA))
1125  return;
1126  PolyLineCircleData* circleData = dynamic_cast<PolyLineCircleData*>(lineObject->objectData(CIRCLE_DATA));
1127 
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;
1131 
1132  circleData->circleMainAxis_ = (onPlane - x0).normalize();
1133  circleData->circleSideRadius_ = circleData->circleMainRadius_ = d.norm();
1134  circleData->circleSideAxis_ = (circleData->circleMainAxis_ % n).normalize();
1135 
1136  updatePolyEllipse(lineObject, tool_->sb_CirclePointNum->value());
1137  updateHandles(lineObject);
1138  }
1139  else if(_event->type() == QEvent::MouseButtonPress && createCircle_CurrSelIndex_ == -1) {
1140  int new_line_id;
1141  emit addEmptyObject(DATA_POLY_LINE, new_line_id);
1142  BaseObjectData *obj = 0;
1143  PluginFunctions::getObject(new_line_id, obj);
1144  obj->target(true);
1146  newLine->materialNode()->set_random_color();
1147 
1149 
1150  if(!mesh->mesh()->has_face_normals())
1151  mesh->mesh()->request_face_normals();
1152 
1153  PolyLineCircleData* lineData = new PolyLineCircleData(hit_point, mesh->mesh()->normal(fh), ACG::Vec3d(), ACG::Vec3d(), 0, 0, mesh->id());
1154  newLine->setObjectData(CIRCLE_DATA, lineData);
1156 
1157  emit updatedObject(new_line_id, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
1158  createCircle_LastSelIndex_ = createCircle_CurrSelIndex_ = newLine->id();
1160  }
1161  else if(_event->type() == QEvent::MouseButtonRelease ) {
1162  PolyLineObject* lineObject;
1163  if(PluginFunctions::getObject(createCircle_CurrSelIndex_, lineObject))
1164  {
1166  if(lineObject->getAdditionalNode(N, name(), "handle0"))
1167  N->enablePicking(true);
1168  }
1169  createCircle_CurrSelIndex_ = -1;
1170  }
1171 }
1172 
1173 //-------------------------------------------OpenFLipper/BasePlugin/----------------------------------
1174 
1175 void PolyLinePlugin::
1176 createSpline_createUI(int _polyLineObjectID)
1177 {
1178  PolyLineObject* lineObject;
1179  if (!PluginFunctions::getObject(_polyLineObjectID, lineObject) || !lineObject->objectData(BEZSPLINE_DATA))
1180  return;
1181  PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(lineObject->objectData(BEZSPLINE_DATA));
1182 
1184 
1185  double rad = getRad(splineData->meshIndex_);
1186 
1187  GlutLineNode* lineN = new GlutLineNode(lineObject, "N_Line");
1188  lineN->show();
1189  lineN->enablePicking(false);
1190  lineObject->addAdditionalNode(lineN, name(), "line");
1191  lineN->drawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
1192 
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);
1197  handle0->show();
1198  handle0->set_position(splineData->points_[i].position);
1200  handle0->enablePicking(true);
1201  lineObject->addAdditionalNode(handle0, name(), "control", i);
1202  }
1203 
1204  for(unsigned int i = 0; i < splineData->handles_.size(); i++) {
1205  const PolyLineBezierSplineData::InterpolatePoint& control = splineData->getInterpolatePoint(i);
1206  const ACG::Vec3d hndlPos = splineData->handles_[i], ctrlPos = control.position;
1207 
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);
1211  handle0->show();
1212  handle0->enablePicking(true);
1213  handle0->set_position(hndlPos);
1214  lineObject->addAdditionalNode(handle0, name(), "handle", i);
1216 
1217  GlutLineNode* lineN;
1218  if(lineObject->getAdditionalNode(lineN, name(), "line")) {
1219  lineN->add_line(ctrlPos, hndlPos);
1220  lineN->add_color(ACG::Vec4f(1,0,0,1));
1221  }
1222  }
1223  updatePolyBezierSpline(lineObject, tool_->sb_SplineSegNum->value());
1224 
1225  emit updatedObject(_polyLineObjectID, UPDATE_ALL);
1226 }
1227 
1228 void
1229 PolyLinePlugin::
1230 finishSpline()
1231 {
1232  PolyLineObject* lineObject = 0;
1233 
1235  return;
1236 
1237 
1238  PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(lineObject->objectData(BEZSPLINE_DATA));
1239 
1240  TriMeshObject* mesh;
1241  if(!PluginFunctions::getObject(splineData->meshIndex_, mesh))
1242  return;
1243 
1244  ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1245  ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1246  mesh->boundingBox(bbMin, bbMax);
1247  const ACG::Vec3d sizeBB((bbMax-bbMin));
1248 
1249  if(splineData->finishSpline()) {
1250 
1251  GlutPrimitiveNode* control = 0;
1252 
1253  for(unsigned int i = 0; i < splineData->points_.size(); i++) {
1254  lineObject->getAdditionalNode(control, name(), "control", i);
1255  control->enablePicking(true);
1256  }
1257 
1258  for(unsigned int i = 0; i < splineData->handles_.size(); i++) {
1259  const PolyLineBezierSplineData::InterpolatePoint& control = splineData->getInterpolatePoint(i);
1260  const ACG::Vec3d hndlPos = splineData->handles_[i], ctrlPos = control.position;
1261 
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());
1265  handle0->show();
1266  handle0->enablePicking(true);
1267  handle0->set_position(hndlPos);
1268  lineObject->addAdditionalNode(handle0, name(), "handle", i);
1270 
1271  GlutLineNode* lineN;
1272  if(lineObject->getAdditionalNode(lineN, name(), "line")) {
1273  lineN->add_line(ctrlPos, hndlPos);
1274  lineN->add_color(ACG::Vec4f(1,0,0,1));
1275  }
1276 
1277  emit updatedObject(createSpline_CurrSelIndex_, UPDATE_ALL);
1278  }
1279  updatePolyBezierSpline(lineObject, tool_->sb_SplineSegNum->value());
1281  }
1282 }
1283 
1284 void PolyLinePlugin::
1285 me_insertSpline(QMouseEvent* _event)
1286 {
1287 
1288  TriMeshObject* mesh;
1289  TriMesh::FaceHandle fh;
1291  ACG::Vec3d hit_point;
1292 
1293  if(!pick_triangle_mesh(_event->pos(), mesh, fh, vh, hit_point))
1294  return;//can't generate a circle in empty space
1295 
1296  ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1297  ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1298  mesh->boundingBox(bbMin, bbMax);
1299  const ACG::Vec3d sizeBB((bbMax-bbMin));
1300 
1301  if(!mesh->mesh()->has_face_normals())
1302  mesh->mesh()->request_face_normals();
1303 
1304  ACG::Vec3d nor = mesh->mesh()->normal(fh);
1305 
1306  if(_event->type() == QEvent::MouseButtonPress) {
1307 
1308  if(createSpline_CurrSelIndex_ == -1) {
1309 
1310  emit addEmptyObject(DATA_POLY_LINE, createSpline_CurrSelIndex_);
1313  BaseObjectData *obj = 0;
1315  obj->target(true);
1317  newLine->materialNode()->set_random_color();
1319 
1320  newLine->lineNode()->drawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
1322 
1323  PolyLineBezierSplineData* lineData = new PolyLineBezierSplineData(mesh->id());
1324  newLine->setObjectData(BEZSPLINE_DATA, lineData);
1325 
1326  GlutLineNode* lineN = new GlutLineNode(newLine, "N_Line");
1327  lineN->show();
1328  lineN->enablePicking(false);
1329  newLine->addAdditionalNode(lineN, name(), "line");
1330  lineN->drawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
1331  }
1332 
1333  ACG::Vec3d insert_Point = hit_point + nor * 0.003 * sizeBB.norm();
1334  PolyLineObject* lineObject = 0;
1335 
1337  return;
1338 
1339  PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(lineObject->objectData(BEZSPLINE_DATA));
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());
1343  handle0->show();
1344  handle0->set_position(insert_Point);
1346  handle0->enablePicking(false);
1347  lineObject->addAdditionalNode(handle0, name(), "control", splineData->points_.size());
1348 
1349  emit updatedObject(createSpline_CurrSelIndex_, UPDATE_ALL);
1350  splineData->addInterpolatePoint(insert_Point, nor);
1351 
1352  }
1353  if(_event->type() == QEvent::MouseButtonDblClick) {
1354  finishSpline();
1355  }
1356 }
1357 
1358 //-----------------------------------------------------------------------------
1359 
1360 void
1361 PolyLinePlugin::
1362 me_delete( QMouseEvent* _event )
1363 {
1364  // MousePress ?
1365  if (_event->type() == QEvent::MouseButtonPress) {
1366 
1367  size_t node_idx, target_idx;
1368  ACG::Vec3d hit_point;
1369  // pick
1370  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point)) {
1371 
1372  BaseObjectData* obj = 0;
1373 
1374  if (PluginFunctions::getPickedObject(node_idx, obj))
1375  // is picked object polyline?
1377  emit deleteObject(obj->id());
1378  }
1379  }
1380 
1381  }
1382 
1383 }
1384 
1385 
1386 //-----------------------------------------------------------------------------
1387 
1388 namespace {
1389 
1390 bool me_GetMeshHit(QMouseEvent* _event, ACG::SceneGraph::GlutPrimitiveNode* moveCircle_SelNode_, ACG::Vec3d& _hit_point, size_t& _node_idx, size_t& _targetIdx)
1391 {
1392  size_t ndx;
1393  if(moveCircle_SelNode_)
1394  moveCircle_SelNode_->enablePicking(false);
1395  bool hasHit = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), ndx, _targetIdx, &_hit_point);
1396  if(moveCircle_SelNode_)
1397  moveCircle_SelNode_->enablePicking(true);
1398  BaseObjectData* obj;
1399  //if there is no current mesh use the newly found
1400  if(hasHit && PluginFunctions::getPickedObject(ndx, obj) && _node_idx == std::numeric_limits<unsigned int>::max())
1401  _node_idx = obj->id();
1402  return hasHit;
1403 }
1404 
1405 void me_UpdateCircleData(ACG::Vec3d _hit_point, ACG::Vec3d _onPlane, ACG::Vec3d _nor, ACG::SceneGraph::GlutPrimitiveNode* _moveCircle_SelNode_, PolyLineCircleData* _lineData, bool _isShift)
1406 {
1407  if(!_moveCircle_SelNode_->name().compare("N_Center"))
1408  {
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();
1413  }
1414  else
1415  {
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;
1421 
1422  if (_isShift)
1423  _lineData->circleSideRadius_ = cr;
1424 
1425  _lineData->circleMainAxis_ = axisa;
1426  _lineData->circleSideAxis_ = axisb;
1427  } else {
1428  const ACG::Vec3d axisb = (_lineData->circleNormal_ % axisa).normalize();
1429  _lineData->circleSideRadius_ = cr;
1430 
1431  if (_isShift)
1432  _lineData->circleMainRadius_ = cr;
1433 
1434  _lineData->circleSideAxis_ = axisa;
1435  _lineData->circleMainAxis_ = axisb;
1436  }
1437  }
1438 }
1439 }
1440 
1441 void
1442 PolyLinePlugin::
1443 me_move( QMouseEvent* _event )
1444 {
1445  if((_event->modifiers() & Qt::ShiftModifier) != Qt::ShiftModifier && moveCircle_IsLocked)//alt was pressed but it isn't anymore
1446  moveCircle_IsLocked = moveCircle_IsFloating = false;
1447 
1448  // MousePress ? -> get reference point
1449  if (_event->type() == QEvent::MouseButtonPress) {
1450 
1451  size_t node_idx, target_idx;
1452  ACG::Vec3d hit_point;
1453  // this is for picking the handles on a circle or spline
1454  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point)) {
1455  BaseNode* node = find_node( PluginFunctions::getRootNode(), node_idx );
1456  GlutPrimitiveNode* glutNode = dynamic_cast<GlutPrimitiveNode*>(node);
1457 
1458  if(glutNode) {
1459  PolyLineCircleData* circleData = dynamic_cast<PolyLineCircleData*>(glutNode->line->objectData(CIRCLE_DATA));
1460  PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(glutNode->line->objectData(BEZSPLINE_DATA));
1461  if(circleData) {
1462  moveCircle_SelNode_ = glutNode;
1463  createCircle_LastSelIndex_ = createCircle_CurrSelIndex_ = glutNode->line->id();
1464  }
1465  if(splineData) {
1466  moveBezSpline_SelNode_ = glutNode;
1467  createSpline_LastSelIndex_ = moveBezSpline_SelIndex_ = glutNode->line->id();
1468  moveBezSpline_SelSubIndex_ = glutNode->index;
1469  }
1470  }
1471  }
1472  //this is for picking the normal poly lines
1473  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_VERTEX, _event->pos(), node_idx, target_idx, &hit_point)) {
1474  BaseObjectData* obj = 0;
1475  if (PluginFunctions::getPickedObject(node_idx, obj)) {
1476  // is picked object polyline?
1478  if (cur_pol && !cur_pol->objectData(CIRCLE_DATA) && !cur_pol->objectData(BEZSPLINE_DATA)) {//no vertex dragging on circles!
1479 
1480  // Check if we got a line segment or a vertex
1481  if ( target_idx >= cur_pol->line()->n_vertices() )
1482  return;
1483 
1484  // save references
1485  cur_move_id_ = cur_pol->id();
1486 
1487  move_point_ref_ = &(cur_pol->line()->point(target_idx));
1488  }
1489  }
1490  }
1491  }
1492 
1493  // Move ? -> move reference point
1494  if (_event->type() == QEvent::MouseMove){
1495  if (moveCircle_SelNode_) {
1496  PolyLineObject* lineObject;
1497  if (!PluginFunctions::getObject(createCircle_CurrSelIndex_, lineObject) || !lineObject->objectData(CIRCLE_DATA))
1498  return;
1499  PolyLineCircleData* lineData = dynamic_cast<PolyLineCircleData*>(lineObject->objectData(CIRCLE_DATA));
1500  ACG::Vec3d hit_point;
1501  size_t target_idx;
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_;
1507  ACG::Vec3d onMesh = hit_point;
1508  double t = ((n | x0) - (n | onMesh)) / n.sqrnorm();
1509  ACG::Vec3d onPlane = onMesh + t * n;
1510  TriMeshObject* mesh;
1511  if (!PluginFunctions::getObject(lineData->circleMeshIndex_, mesh))
1512  return;
1513 
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")) {
1516  moveCircle_LastHitPos_ = onMesh;
1517  if((_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier) {
1518  moveCircle_IsLocked = true;
1519  moveCircle_LastHitNor_ = lineData->circleNormal_;
1520  }
1521  }
1522  }
1523  else
1524  {
1525  moveCircle_IsFloating = true;
1526  ACG::Vec3d cameraPos, cameraDir;
1527  int l,b,w,h;
1529  PluginFunctions::viewerProperties(0).glState().viewing_ray(_event->pos().x(), h - 1 - _event->pos().y(), cameraPos, cameraDir);
1530  //intersect the camera ray with a plane located at moveCircle_LastHitPos_ facing moveCircle_LastHitNor_
1531  const ACG::Vec3d x0 = !moveCircle_SelNode_->name().compare("N_Center") ? moveCircle_LastHitPos_ : lineData->circleCenter_,
1532  //the side handles can only be moved on the normal plane
1533  n = !moveCircle_SelNode_->name().compare("N_Center") ? (moveCircle_IsLocked ? moveCircle_LastHitNor_ : PluginFunctions::viewingDirection())
1534  : lineData->circleNormal_;
1535  const double t = ((x0 | n) - (cameraPos | n)) / (cameraDir | n);
1536  const ACG::Vec3d onPlane = cameraPos + cameraDir * t;
1537 
1538  me_UpdateCircleData(onPlane, onPlane, n, moveCircle_SelNode_, lineData, (_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier);
1539 
1540  }
1541  updateHandles(lineObject);
1542  updatePolyEllipse(lineObject, tool_->sb_CirclePointNum->value());
1543  }
1544  else if(moveBezSpline_SelNode_) {
1545  PolyLineObject* lineObject;
1546  if(!PluginFunctions::getObject(moveBezSpline_SelIndex_, lineObject) || !lineObject->objectData(BEZSPLINE_DATA))
1547  return;
1548  PolyLineBezierSplineData* lineData = dynamic_cast<PolyLineBezierSplineData*>(lineObject->objectData(BEZSPLINE_DATA));
1549  ACG::Vec3d hit_point;
1550  size_t target_idx;
1551  bool hasHit = me_GetMeshHit(_event, moveBezSpline_SelNode_, hit_point, lineData->meshIndex_, target_idx);
1552  if(lineData->meshIndex_ == std::numeric_limits<unsigned int>::max())
1553  return;
1554  if(!moveBezSpline_SelNode_->name().compare("N_Control") && hasHit) {
1555  TriMeshObject* mesh;
1556  if (!PluginFunctions::getObject(lineData->meshIndex_, mesh))
1557  return;
1558  ACG::Vec3d onMesh = hit_point, onMeshNor = mesh->mesh()->normal(mesh->mesh()->face_handle(target_idx));
1559  int controlIndex = moveBezSpline_SelSubIndex_;
1562  lineData->points_[controlIndex].position = onMesh;
1563  lineData->points_[controlIndex].normal = onMeshNor;
1564  if(controlIndex) {
1565  int handleIndex = 2 * controlIndex - 1;
1566  ACG::Vec3d dir = lineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
1567  ACG::Vec3d point = forw + onMesh;
1568  lineData->handles_[handleIndex] = point;
1569  }
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();
1573  ACG::Vec3d point = forw + onMesh;
1574  lineData->handles_[handleIndex] = point;
1575  }
1576  }
1577  else if(!moveBezSpline_SelNode_->name().compare("N_Handle")) {
1578  int handleIndex = moveBezSpline_SelSubIndex_;
1579  const PolyLineBezierSplineData::InterpolatePoint& control = lineData->getInterpolatePoint(handleIndex);
1580  //we don't use the mesh location but instead the location on the normal plane!
1581  ACG::Vec3d cameraPos, cameraDir;
1582  int l,b,w,h;
1584  PluginFunctions::viewerProperties(0).glState().viewing_ray(_event->pos().x(), h - 1 - _event->pos().y(), cameraPos, cameraDir);
1585  double t = ((control.normal | control.position) - (control.normal | cameraPos)) / (control.normal | cameraDir);
1586  ACG::Vec3d onPlane = cameraPos + t * cameraDir;
1587 
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;
1595  }
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;
1602  }
1603  }
1604  GlutLineNode* lineN;
1605  if(!lineObject->getAdditionalNode(lineN, name(), "line", 0))
1606  return;
1607  updatePolyBezierHandles(lineObject, lineN);
1608  updatePolyBezierSpline(lineObject, tool_->sb_SplineSegNum->value());
1609  }
1610  else if (move_point_ref_ != 0) {
1611  ACG::Vec3d hit_point;
1612  size_t node_idx, target_idx;
1613  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
1614  (*move_point_ref_) = (PolyLine::Point) hit_point;
1615  // update
1616  emit updatedObject(cur_move_id_, UPDATE_GEOMETRY);
1617  }
1618  }
1619  }
1620 
1621  // Release ? -> release reference point
1622  if (_event->type() == QEvent::MouseButtonRelease) {
1623  if((_event->modifiers() & Qt::ShiftModifier) != Qt::ShiftModifier) {
1624  //in case we are not dragging the center and not pressing alt -> project to mesh
1625  // if(moveCircle_SelNode_ && moveCircle_SelNode_->name().compare("N_Center"))
1626  moveCircle_IsLocked = moveCircle_IsFloating = false;
1627  PolyLineObject* lineObject;
1628  if (PluginFunctions::getObject(createCircle_CurrSelIndex_, lineObject))
1629  {
1630  moveCircle_IsLocked = false;
1631  updateHandles(lineObject);
1632  updatePolyEllipse(lineObject, tool_->sb_CirclePointNum->value());
1633  }
1634  }
1635  move_point_ref_ = 0;
1636  moveCircle_SelNode_ = 0;
1637  createCircle_CurrSelIndex_ = -1;
1640  }
1641 }
1642 //-----------------------------------------------------------------------------
1643 
1644 
1645 void
1646 PolyLinePlugin::
1647 me_split( QMouseEvent* _event )
1648 {
1649  // MousePress ?
1650  if (_event->type() == QEvent::MouseButtonPress) {
1651  // release old references
1652  move_point_ref_ = 0;
1653 
1654  size_t node_idx, target_idx;
1655  ACG::Vec3d hit_point;
1656  // pick
1657  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_VERTEX, _event->pos(), node_idx, target_idx, &hit_point)) {
1658 
1659  BaseObjectData* obj = 0;
1660  if (PluginFunctions::getPickedObject(node_idx, obj)) {
1661 
1662  // is picked object polyline?
1664 
1665  if (cur_pol) {
1666 
1667  // Check if we got a line segment or a vertex
1668  if ( target_idx >= cur_pol->line()->n_vertices() )
1669  return;
1670 
1671  // splitting for CLOSED PolyLines
1672  if (cur_pol->line()->is_closed()) {
1673  cur_pol->line()->split_closed(target_idx);
1674 
1675  // save references for moving
1676  cur_move_id_ = cur_pol->id();
1677  move_point_ref_ = &(cur_pol->line()->point(cur_pol->line()->n_vertices() - 1));
1678 
1679  // emit changed objects
1680  emit updatedObject(cur_pol->id(), UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
1681  } else
1682  // splitting for OPEN PolyLines
1683  {
1684  // add new polyline
1685  int insert_id;
1686  emit addEmptyObject(DATA_POLY_LINE, insert_id);
1687 
1688  // get current polylineobject
1689  BaseObjectData *obj2 = 0;
1690 
1691  // get polyline object
1692  PluginFunctions::getObject(insert_id, obj2);
1693 
1694  // default: mark as target
1695  obj2->target(true);
1696 
1698 
1699  pol_obj2->materialNode()->set_random_color();
1700 
1701  pol_obj2->line()->set_vertex_radius(cur_pol->line()->vertex_radius());
1702  pol_obj2->lineNode()->drawMode(cur_pol->lineNode()->drawMode());
1703 
1704  cur_pol->line()->split(target_idx, *(pol_obj2->line()));
1705 
1706  // save references for moving
1707  cur_move_id_ = cur_pol->id();
1708  move_point_ref_ = &(cur_pol->line()->point(cur_pol->line()->n_vertices() - 1));
1709 
1710  // emit changed objects
1711  emit updatedObject(insert_id, UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
1712  emit updatedObject(cur_pol->id(), UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
1713  }
1714 
1715  // update
1716  emit updateView();
1717  }
1718  }
1719  }
1720  }
1721 
1722  // Move splitted ? -> move reference point
1723  if (_event->type() == QEvent::MouseMove)
1724  if (move_point_ref_ != 0) {
1725 
1726  size_t node_idx, target_idx;
1727  ACG::Vec3d hit_point;
1728  // pick
1729  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
1730  (*move_point_ref_) = (PolyLine::Point) hit_point;
1731 
1732  // update
1733  emit updatedObject(cur_move_id_, UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
1734  emit updateView();
1735  }
1736  }
1737 
1738  // Release splitted? -> release reference point
1739  if (_event->type() == QEvent::MouseButtonRelease) {
1740 
1741  if (cur_move_id_ != -1)
1742  emit updatedObject(cur_move_id_, UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
1743 
1744  move_point_ref_ = 0;
1745  cur_move_id_ = -1;
1746 
1747  }
1748 
1749 }
1750 
1751 //-----------------------------------------------------------------------------
1752 
1753 void
1754 PolyLinePlugin::
1755 me_merge( QMouseEvent* _event )
1756 {
1757  // Mouse PRESS ?
1758  if (_event->type() == QEvent::MouseButtonPress) {
1759  // release old references
1760  move_point_ref_ = 0;
1761  cur_merge_id_ = -1;
1762 
1763  size_t node_idx, target_idx;
1764  ACG::Vec3d hit_point;
1765  // pick
1766  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_VERTEX, _event->pos(), node_idx, target_idx, &hit_point)) {
1767  BaseObjectData* obj = 0;
1768  if (PluginFunctions::getPickedObject(node_idx, obj)) {
1769  // is picked object polyline?
1771  if (cur_pol) {
1772 
1773  // Check if we got a line segment or a vertex
1774  if ( target_idx >= cur_pol->line()->n_vertices() ) {
1775  return;
1776  }
1777 
1778  if (target_idx == cur_pol->line()->n_vertices() - 1 || target_idx == 0) {
1779  if (target_idx == 0) {
1780  cur_pol->line()->invert();
1781  //target_idx = cur_pol->line()->n_vertices() - 1;
1782  }
1783 
1784  // save references
1785  cur_merge_id_ = cur_pol->id();
1786 
1787  // save reference for moving
1788  // cur_pol->line()->add_point( cur_pol->line()->point( cur_pol->line()->n_vertices()-1));
1789  move_point_ref_ = &(cur_pol->line()->point(cur_pol->line()->n_vertices() - 1));
1790  }
1791  }
1792 
1793  }
1794  }
1795  }
1796 
1797  // Move ? -> move reference point
1798  if (_event->type() == QEvent::MouseMove && cur_merge_id_ != -1)
1799  if (move_point_ref_ != 0) {
1800  size_t node_idx, target_idx;
1801  ACG::Vec3d hit_point;
1802  // pick
1803  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
1804  (*move_point_ref_) = (PolyLine::Point) hit_point;
1805 
1806  // update
1807  emit updatedObject(cur_merge_id_, UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
1808  emit updateView();
1809  }
1810  }
1811 
1812  // Mouse RELEASE ?
1813  if (_event->type() == QEvent::MouseButtonRelease && cur_merge_id_ != -1) {
1814  PolyLine::Point p_save;
1815 
1816  // reset move references
1817  if (move_point_ref_ != 0) {
1818  // remove intermediate point
1819  // restore orig polyline
1820  BaseObjectData *obj = 0;
1821  PluginFunctions::getObject(cur_merge_id_, obj);
1823 
1824  // store position if merging fails
1825  p_save = opol->line()->back();
1826  opol->line()->resize(opol->line()->n_vertices() - 1);
1827 
1828  // release reference
1829  move_point_ref_ = 0;
1830  }
1831 
1832  size_t node_idx, target_idx;
1833  ACG::Vec3d hit_point;
1834 
1835  // pick
1836  // restore first polyline
1837  BaseObjectData *obj2 = 0;
1838  PluginFunctions::getObject(cur_merge_id_, obj2);
1840  first_pol->enablePicking(false);
1841  PluginFunctions::invalidatePickCaches();
1842 
1843  bool merged = false;
1844  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_VERTEX, _event->pos(), node_idx, target_idx, &hit_point)) {
1845 
1846  BaseObjectData* obj = 0;
1847 
1848  if (PluginFunctions::getPickedObject(node_idx, obj)) {
1849 
1850  // is picked object polyline? -> get second polyline
1852 
1853  if (second_pol) {
1854 
1855  // Check if we got a line segment or a vertex
1856  if ( target_idx < second_pol->line()->n_vertices() ) {
1857  // get idxs
1858  unsigned int first_idx = first_pol->line()->n_vertices() - 1;
1859  unsigned int second_idx = target_idx;
1860 
1861  // both polylines open?
1862  if (!first_pol->line()->is_closed() && !second_pol->line()->is_closed()) {
1863 
1864  bool inv_first(false), inv_second(false);
1865 
1866  // wrong ordering first Polyline?
1867  if (first_idx == 0) {
1868  inv_first = true;
1869  first_idx = first_pol->line()->n_vertices() - 1;
1870  }
1871 
1872  // wrong ordering second Polyline?
1873  if (second_idx == second_pol->line()->n_vertices() - 1) {
1874  inv_second = true;
1875  second_idx = 0;
1876  }
1877 
1878  // two endpoints available?
1879  if (first_idx == first_pol->line()->n_vertices() - 1 && second_idx == 0) {
1880  // same polyline?
1881  if (first_pol->id() == second_pol->id()) {
1882  // simply close line
1883  first_pol->line()->set_closed(true);
1884  } else {
1885  // invert if necessary
1886  if (inv_first)
1887  first_pol->line()->invert();
1888  if (inv_second)
1889  second_pol->line()->invert();
1890 
1891  // append second polyline to first one
1892  first_pol->line()->append(*second_pol->line());
1893 
1894  // set flag
1895  merged = true;
1896 
1897  // delete appended
1898  emit deleteObject(second_pol->id());
1899  }
1900 
1901  }
1902  }
1903  }
1904  }
1905  }
1906  }
1907 
1908  first_pol->enablePicking(true);
1909  PluginFunctions::invalidatePickCaches();
1910 
1911  //above can't try to close a line
1912  if(!merged && PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_VERTEX, _event->pos(), node_idx, target_idx, &hit_point)) {
1913  BaseObjectData* obj = 0;
1914  if (PluginFunctions::getPickedObject(node_idx, obj)) {
1915 
1916  // is picked object polyline? -> get second polyline
1918 
1919  if (second_pol) {
1920 
1921  // Check if we got a line segment or a vertex
1922  if ( target_idx < second_pol->line()->n_vertices() ) {
1923  // get idxs
1924  unsigned int first_idx = first_pol->line()->n_vertices() - 1;
1925  unsigned int second_idx = target_idx;
1926 
1927  // both polylines open?
1928  if (!first_pol->line()->is_closed() && !second_pol->line()->is_closed()) {
1929 
1930  // wrong ordering first Polyline?
1931  if (first_idx == 0) {
1932  first_idx = first_pol->line()->n_vertices() - 1;
1933  }
1934 
1935  // wrong ordering second Polyline?
1936  if (second_idx == second_pol->line()->n_vertices() - 1) {
1937  second_idx = 0;
1938  }
1939 
1940  if (first_pol->id() == second_pol->id() && first_idx == first_pol->line()->n_vertices() - 1 && second_idx == 0) {
1941  // simply close line
1942  first_pol->line()->set_closed(true);
1943  merged = true;
1944  }
1945  }
1946  }
1947  }
1948  }
1949  }
1950 
1951  if (!merged) {
1952  // remove intermediate point
1953  // restore orig polyline
1954  BaseObjectData *obj = 0;
1955  PluginFunctions::getObject(cur_merge_id_, obj);
1957 
1958  opol->line()->add_point(p_save);
1959  }
1960 
1961  // update
1962  emit updatedObject(cur_merge_id_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
1963 
1964  // release old references
1965  move_point_ref_ = 0;
1966  cur_merge_id_ = -1;
1967  }
1968 
1969 }
1970 
1971 
1972 //-----------------------------------------------------------------------------
1973 
1974 
1975 void
1976 PolyLinePlugin::
1977 me_smart_move( QMouseEvent* _event )
1978 {
1979  // MousePress ? -> select vertex and start timer
1980  if (_event->type() == QEvent::MouseButtonPress) {
1981 
1982  size_t node_idx, target_idx;
1983  ACG::Vec3d hit_point;
1984 
1985  // pick
1986  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point)) {
1987 
1988  BaseObjectData* obj = 0;
1989  if (PluginFunctions::getPickedObject(node_idx, obj)) {
1990 
1991  // is picked object polyline?
1993  if (cur_pol) {
1994 
1995  cur_polyline_obj_ = cur_pol;
1996 
1997  // Check if we got a line segment or a vertex
1998  if ( target_idx >= cur_pol->line()->n_vertices() )
1999  return;
2000 
2001  // save references
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;
2006  else {
2007  cur_pol->line()->vertex_selection(target_idx) = false;
2008  emit updateView();
2009  }
2010  }
2011 
2012  }
2013 
2014  // start timer
2015  if (!(_event->modifiers() & (Qt::ShiftModifier)))
2016  smart_move_timer_->start(20);
2017  }
2018  }
2019  }
2020 
2021 
2022  // MouseRelease ? -> stop timer
2023  if( _event->type() == QEvent::MouseButtonRelease)
2024  {
2025  smart_move_timer_->stop();
2026  cur_smart_move_obj_ = NULL;
2027  }
2028 
2029 
2030  // call move event
2031  me_move( _event);
2032 }
2033 
2034 //-----------------------------------------------------------------------------
2035 
2036 void
2037 PolyLinePlugin::
2038 slotEditModeChanged()
2039 {
2040  PluginFunctions::pickMode("PolyLine");
2041  PluginFunctions::actionMode(Viewer::PickingMode);
2042 }
2043 
2044 //-----------------------------------------------------------------------------
2045 
2046 void
2049 {
2050  PolyLineCircleData* circleData = dynamic_cast<PolyLineCircleData*>(_lineObject->objectData(CIRCLE_DATA) );
2051  GlutPrimitiveNode* H0, *H1, *C;
2052  _lineObject->getAdditionalNode(C, name(), "circle");
2053  _lineObject->getAdditionalNode(H0, name(), "handle0");
2054  _lineObject->getAdditionalNode(H1, name(), "handle1");
2055  ACG::Vec3d h0 = circleData->circleCenter_ + circleData->circleMainAxis_ * circleData->circleMainRadius_,
2056  h1 = circleData->circleCenter_ + circleData->circleSideAxis_ * circleData->circleSideRadius_;
2057  if(C)
2058  C->set_position(circleData->circleCenter_);
2059  if(H0)
2060  H0->set_position(moveCircle_IsFloating ? h0 : createCircle_getHit(circleData, h0));
2061  if(H1)
2062  H1->set_position(moveCircle_IsFloating ? h1 : createCircle_getHit(circleData, h1));
2063 }
2064 
2065 //-----------------------------------------------------------------------------
2066 
2067 void
2068 PolyLinePlugin::
2069 slot_setCirclePointNum(int i)
2070 {
2071  PolyLineObject* _lineObject;
2073  updatePolyEllipse(_lineObject, i);
2074 }
2075 
2076 //-----------------------------------------------------------------------------
2077 
2078 void
2079 PolyLinePlugin::
2080 slot_setSplinePointNum(int i)
2081 {
2082  PolyLineObject* _lineObject;
2084  updatePolyBezierSpline(_lineObject, i);
2085 }
2086 
2087 //-----------------------------------------------------------------------------
2088 
2089 void
2091 slotPickToolbarAction(QAction* _action) {
2092  if ( _action == insertAction_ ) {
2093  tool_->rb_insert->setChecked(true);
2094  } else if ( _action == insertCircleAction_ ) {
2095  tool_->rb_InsertCircle->setChecked(true);
2096  } else if ( _action == insertSplineAction_ ) {
2097  tool_->rb_InsertSpline->setChecked(true);
2098  } else if ( _action == deleteAction_ ) {
2099  tool_->rb_delete->setChecked(true);
2100  } else if ( _action == moveAction_ ) {
2101  tool_->rb_move->setChecked(true);
2102  } else if ( _action == smartMoveAction_ ) {
2103  tool_->rb_smart_move->setChecked(true);
2104  } else if ( _action == mergeAction_ ) {
2105  tool_->rb_merge->setChecked(true);
2106  } else if ( _action == splitAction_ ) {
2107  tool_->rb_split->setChecked(true);
2108  }
2109 }
2110 
2111 void
2113 slotSetPolyLineMode(QAction* _action) {
2114  if (_action == polyLineAction_ ){
2115  PluginFunctions::actionMode(Viewer::PickingMode);
2116  PluginFunctions::pickMode("PolyLine");
2117 
2118  polyLineAction_->setChecked( true );
2119  }
2120 }
2121 
2122 //-----------------------------------------------------------------------------
2123 
2124 
2125 void
2126 PolyLinePlugin::
2127 slotEnablePickMode(QString _name)
2128 {
2129  PluginFunctions::pickMode("PolyLine");
2130  PluginFunctions::actionMode(Viewer::PickingMode);
2131 
2132  if(tool_ )
2133  {
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);
2146  }
2147 }
2148 
2149 //-----------------------------------------------------------------------------
2150 
2151 bool
2152 PolyLinePlugin::
2153 pick_triangle_mesh( QPoint mPos,
2154  TriMeshObject*& _mesh_object_, TriMesh::FaceHandle& _fh, TriMesh::VertexHandle& _vh, ACG::Vec3d& _hitPoint)
2155 {
2156  // invalidate return values
2157  _fh = TriMesh::FaceHandle (-1);
2158  _vh = TriMesh::VertexHandle(-1);
2159 
2160  size_t target_idx = 0, node_idx = 0;
2161  ACG::Vec3d hit_point;
2162 
2163 
2164 
2165  if( PluginFunctions::scenegraphPick( ACG::SceneGraph::PICK_FACE, mPos, node_idx, target_idx, &hit_point ) )
2166  {
2167  // first check if a sphere was clicked
2168  BaseObjectData* object(0);
2169  if( PluginFunctions::getPickedObject( node_idx, object ) )
2170  {
2171  if( object->picked( node_idx ) && object->dataType(DATA_TRIANGLE_MESH) )
2172  {
2173  // get mesh object
2174  _mesh_object_ = dynamic_cast<TriMeshObject*>(object);
2175 
2176  // get mesh and face handle
2177  TriMesh & m = *PluginFunctions::triMesh(object);
2178  _fh = m.face_handle(target_idx);
2179 
2180  TriMesh::FaceVertexIter fv_it(m,_fh);
2181  TriMesh::VertexHandle closest = *fv_it;
2182  float shortest_distance = (m.point(closest) - hit_point).sqrnorm();
2183 
2184  ++fv_it;
2185  if ( (m.point(*fv_it ) - hit_point).sqrnorm() < shortest_distance ) {
2186  shortest_distance = (m.point(*fv_it ) - hit_point).sqrnorm();
2187  closest = *fv_it;
2188  }
2189 
2190  ++fv_it;
2191  if ( (m.point(*fv_it ) - hit_point).sqrnorm() < shortest_distance ) {
2192  // Unnecessary : shortest_distance = (m.point(*fv_it ) - hit_point).sqrnorm();
2193  closest = *fv_it;
2194  }
2195 
2196  // stroe closest vh
2197  _vh = closest;
2198  _hitPoint = hit_point;
2199 
2200  return true;
2201  }
2202  }
2203  }
2204  return false;
2205 }
2206 
2207 //-----------------------------------------------------------------------------
2208 
2209 void
2210 PolyLinePlugin::
2211 slotUpdateContextMenu(int objectId)
2212 {
2213  copyPaste_ObjectId_ = objectId;
2214  copyPaste_Action_->setVisible(pickToolbar_->isVisible());
2215 }
2216 
2217 void
2218 PolyLinePlugin::
2219 me_copyPasteMouse(QMouseEvent* _event)
2220 {
2221  //get the object
2222  PolyLineObject* oldObj, *newObj;
2223  if(copyPaste_ObjectId_ == -1 || !PluginFunctions::getObject(copyPaste_ObjectId_, oldObj) || !PluginFunctions::getObject(copyPaste_NewObjectId_, newObj))
2224  {
2225  //something went wrong, leave the copying mode
2226  copyPaste_ObjectId_ = copyPaste_ActionType_ - 1;
2227  }
2228  //determine the world pos
2229  size_t target_idx = 0, node_idx = 0;
2230  ACG::Vec3d hit_point;
2231  if( PluginFunctions::scenegraphPick( ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point ) ) {
2232  if(copyPaste_ActionType_ == 1) {//duplicate
2233  //object being duplicated
2234  PolyLineCircleData* oldCircleData = dynamic_cast<PolyLineCircleData*>(oldObj->objectData(CIRCLE_DATA));
2235  PolyLineBezierSplineData* oldSplineData = dynamic_cast<PolyLineBezierSplineData*>(oldObj->objectData(BEZSPLINE_DATA));
2236  //newly created object
2237  PolyLineCircleData* circleData = dynamic_cast<PolyLineCircleData*>(newObj->objectData(CIRCLE_DATA));
2238  PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(newObj->objectData(BEZSPLINE_DATA));
2239 
2240  if(oldCircleData) {
2241  BaseNode* node = find_node( PluginFunctions::getRootNode(), node_idx );
2242  GlutPrimitiveNode* glutNode = dynamic_cast<GlutPrimitiveNode*>(node);
2243  if(glutNode)//the hit_point is on the center handle
2244  me_GetMeshHit(_event, glutNode, hit_point, circleData->circleMeshIndex_, target_idx);
2245 
2246  circleData-> circleCenter_ = hit_point;
2247  updatePolyEllipse(newObj, tool_->sb_CirclePointNum->value());
2248  updateHandles(newObj);
2249  }
2250  else if(oldSplineData) {
2251  for(int i = 0; i < (int)splineData->points_.size(); i++) {
2252  ACG::Vec3d onMeshNor, oldPos = splineData->points_[i].position;
2253  ACG::Vec3d onMesh = getPointOnMesh(splineData, copyPaste_RelativePoints_[i] + hit_point, &onMeshNor);
2254  splineData->points_[i].position = onMesh;
2255  splineData->points_[i].normal = onMeshNor;
2256  if(i) {
2257  int handleIndex = 2 * i - 1;
2258  ACG::Vec3d dir = splineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
2259  ACG::Vec3d point = forw + onMesh;
2260  splineData->handles_[handleIndex] = point;
2261  }
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();
2265  ACG::Vec3d point = forw + onMesh;
2266  splineData->handles_[handleIndex] = point;
2267  }
2268  }
2269  GlutLineNode* lineN;
2270  if(!newObj->getAdditionalNode(lineN, name(), "line", 0))
2271  return;
2272  updatePolyBezierHandles(newObj, lineN);
2273  updatePolyBezierSpline(newObj, tool_->sb_SplineSegNum->value());
2274  }
2275  else {
2276  for(size_t i = 0; i < newObj->line()->n_vertices(); i++)
2277  newObj->line()->point(i) = hit_point + copyPaste_RelativePoints_[i];
2278  emit updatedObject(newObj->id(), UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
2279  }
2280 
2281  //place the circle here and exit the copy paste state
2282  if(_event->type() == QEvent::MouseButtonPress) {
2283  copyPaste_ActionType_ = copyPaste_ObjectId_ = -1;
2284  }
2285  }
2286  else if(copyPaste_ActionType_ == 2) {//instanciate
2287 
2288  }
2289  }
2290 }
2291 
2292 void
2293 PolyLinePlugin::
2294 slot_duplicate()
2295 {
2296  PolyLineObject* obj;
2297  if(copyPaste_ObjectId_ == -1 || !PluginFunctions::getObject(copyPaste_ObjectId_, obj))
2298  return;
2299  //set mode for mouse move event
2300  size_t target_idx = 0, node_idx = 0;
2301  ACG::Vec3d hit_point;
2302  //determine the world coordinate of the mouse
2303  QPoint mPos = copyPaste_LastMouse;
2304  if( PluginFunctions::scenegraphPick( ACG::SceneGraph::PICK_ANYTHING, mPos, node_idx, target_idx, &hit_point ) ) {
2305  copyPaste_ActionType_ = 1;
2306 
2307  PolyLineCircleData* circleData = dynamic_cast<PolyLineCircleData*>(obj->objectData(CIRCLE_DATA));
2308  PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(obj->objectData(BEZSPLINE_DATA));
2309 
2310  //create the new object
2311  int new_line_id;
2312  emit addEmptyObject(DATA_POLY_LINE, new_line_id);
2313  BaseObjectData *newObj = 0;
2314  PluginFunctions::getObject(new_line_id, newObj);
2315  obj->target(true);
2317  newLine->materialNode()->set_random_color();
2319  copyPaste_RelativePoints_.clear();
2320  if(circleData) {
2321  PolyLineCircleData* newData = new PolyLineCircleData(*circleData);//use a new instance!
2322  newLine->setObjectData(CIRCLE_DATA, newData);
2323  newLine->lineNode()->drawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
2324  createCircle_createUI(new_line_id);
2325  }
2326  else if(splineData) {
2327  PolyLineBezierSplineData* newData = new PolyLineBezierSplineData(*splineData);
2328  newLine->setObjectData(BEZSPLINE_DATA, newData);
2329  createSpline_createUI(new_line_id);
2330  newLine->lineNode()->drawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
2331 
2332  for(size_t i = 0; i < newData->points_.size(); i++)
2333  copyPaste_RelativePoints_.push_back(newData->points_[i].position - hit_point);
2334  }
2335  else {
2337  newLine->line()->set_vertex_radius(obj->line()->vertex_radius());
2338  for(size_t i = 0; i < obj->line()->n_vertices(); i++) {
2339  newLine->line()->add_point(obj->line()->point(i));
2340  copyPaste_RelativePoints_.push_back(obj->line()->point(i) - hit_point);
2341  }
2342  }
2343  emit updatedObject(new_line_id, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
2344  copyPaste_NewObjectId_ = new_line_id;
2345  }
2346 }
2347 
2348 void
2349 PolyLinePlugin::
2350 slot_instanciate()
2351 {
2352  PolyLineObject* obj;
2353  if(copyPaste_ObjectId_ == -1 || !PluginFunctions::getObject(copyPaste_ObjectId_, obj))
2354  return;
2355  copyPaste_ActionType_ = 2;
2356  //set mode for mouse move event
2357 }
2358 
2359 #if QT_VERSION < 0x050000
2360  Q_EXPORT_PLUGIN2( PolyLinePlugin , PolyLinePlugin );
2361 #endif
2362 
QString name() const
return the name of the object. The name defaults to NONAME if unset.
Definition: BaseObject.cc:741
int createSpline_CurrSelIndex_
The index of the currently created spline.
void add_point(const Point &_p)
Append a point to the polyline.
Definition: PolyLineT.cc:288
void invert()
Invert polyline that first vertex becomes last.
Definition: PolyLineT.cc:1357
PerObjectData * objectData(QString _dataName)
Returns the object data pointer.
Definition: BaseObject.cc:814
PolyLineObject * polyLineObject(BaseObjectData *_object)
Cast an BaseObject to a PolyLineObject if possible.
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
Scalar length() const
Compute the length of the polyline (in future cached method)
Definition: PolyLineT.cc:484
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.
Definition: BaseObject.cc:527
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
void resize(unsigned int _n)
Resize current polyline.
Definition: PolyLineT.cc:231
QActionGroup * pickToolBarActions_
Called by pick Toolbar.
QAction * cutMultipleAction_
Called by pick Toolbar.
DrawMode WIREFRAME
draw wireframe
Definition: DrawModes.cc:84
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.
bool target()
Definition: BaseObject.cc:284
void set_vertex_radius(const Scalar _r)
set ball-radius of vertices
Definition: PolyLineT.hh:351
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
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.
Definition: PolyLineT.cc:792
void split(unsigned int _split_idx, PolyLineT< PointT > &_new_pl)
Split closed polyline at vertex with index _split_idx.
Definition: PolyLineT.cc:1463
int id() const
Definition: BaseObject.cc:201
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(1)<< 3)
Topology updated.
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:73
QAction * splitAction_
Called by pick Toolbar.
void setObjectData(QString _dataName, PerObjectData *_data)
Definition: BaseObject.cc:792
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
Scalar vertex_radius() const
get ball-radius of vertices
Definition: PolyLineT.hh:348
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.
Update type class.
Definition: UpdateType.hh:70
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.
Definition: PolyLineT.cc:849
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.
#define DATA_POLY_LINE
Definition: PolyLine.hh:70
void subdivide(Scalar _largest)
Subdivide polyline.
Definition: PolyLineT.cc:619
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
Definition: GLState.hh:819
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.
Definition: PolyLineT.hh:154
QString name()
Name of the Plugin.
Point & point(unsigned int _i)
Get a point of the polyline.
Definition: PolyLineT.hh:148
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
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.
Definition: MeshObjectT.cc:637
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)
Definition: BaseNode.hh:104
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
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.
Definition: PolyLineT.hh:113
OMTriangleBSP * requestTriangleBsp()
Definition: MeshObjectT.cc:756
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!!!)
Definition: PolyLineT.cc:937
EditMode
Edit Mode of PolyLinePlugin.
QAction * smartMoveAction_
Called by pick Toolbar.
TriMeshObject * triMeshObject(BaseObjectData *_object)
Cast an BaseObject to a TriMeshObject if possible.
Predefined datatypes.
Definition: DataTypes.hh:96
void smooth_uniform_laplace()
Laplacian smoothing.
Definition: PolyLineT.cc:738
QAction * cutAction_
Called by pick Toolbar.
void updatePolyBezierSpline(PolyLineObject *_lineObject, unsigned int _pointsPerSegment)
Generates points for the spline, updates handles.
InterpolatePoint & getInterpolatePoint(unsigned int _handleIndex)
Retrieves the interpolate point based on the handle.
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:144
size_t n_vertices() const
Get number of vertices.
Definition: PolyLineT.hh:122
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)
Definition: DrawModes.cc:87
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
Definition: GLState.cc:927
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.
Definition: PolyLineT.cc:1387
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!!!)
Definition: PolyLineT.hh:166
void delete_point(int _idx)
Delete point at _idx.
Definition: PolyLineT.cc:417
std::string name() const
Returns: name of node (needs not be unique)
Definition: MeshNode2T.cc:446
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
Definition: VectorT.hh:127
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
Definition: MeshObjectT.cc:351
void set_closed(const bool _c)
Set if the polyline should be closed and therefore forms a loop.
Definition: PolyLineT.hh:119
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.
Definition: PolyMeshT.hh:139
DrawMode POINTS_SHADED
draw shaded points (requires point normals)
Definition: DrawModes.cc:81
void split_closed(unsigned int _split_idx)
Split closed polyline at vertex with index _split_idx.
Definition: PolyLineT.cc:1431
void updatePolyEllipse(PolyLineObject *_lineObject, unsigned int _pointCount)
Generates points for the ellipse.
void collapse(Scalar _smallest)
Collapse polyline.
Definition: PolyLineT.cc:672
picks verices (may not be implemented for all nodes)
Definition: BaseNode.hh:108
void slotSetPolyLineMode(QAction *_action)
Called by Toolbar to enable pick mode.
Kernel::FaceVertexIter FaceVertexIter
Circulator.
Definition: PolyMeshT.hh:170