Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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
104 PolyLinePlugin::PolyLinePlugin() :
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
153 tool_ = new PolyLineToolbarWidget();
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
440 planeSelect_ = new QtPlaneSelect( PluginFunctions::viewerProperties().glState() );
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
456 void PolyLinePlugin::slotScissorButton( )
457 {
458 PluginFunctions::actionMode( Viewer::PickingMode );
459 PluginFunctions::pickMode( CREATE_CUT_POLYLINE );
460 }
461
462 //------------------------------------------------------------------------------
463
467 void PolyLinePlugin::slotScissorLinesButton( )
468 {
469 PluginFunctions::actionMode( Viewer::PickingMode );
470 PluginFunctions::pickMode( CREATE_CUT_POLYLINES );
471 }
472
473 //-----------------------------------------------------------------------------
474
478 void PolyLinePlugin::slotTriggerCutPlaneSelect( )
479 {
480
481 using ACG::SceneGraph::LineNode;
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
506 for (PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,
507 DataType(DATA_TRIANGLE_MESH | DATA_POLY_MESH)); o_it != PluginFunctions::objectsEnd(); ++o_it) {
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
526 for (PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,
527 DataType(DATA_TRIANGLE_MESH | DATA_POLY_MESH)); o_it != PluginFunctions::objectsEnd(); ++o_it) {
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
558 PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE);
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
580 PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE);
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
623 PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE);
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
645 PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE);
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
686 PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_TRIANGLE_MESH );
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
698 o_it = PluginFunctions::ObjectIterator(PluginFunctions::TARGET_OBJECTS, DATA_TRIANGLE_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
709 OpenMeshTriangleBSPT< TriMesh >* tbsp = tmesh_obj->requestTriangleBsp();
710 // OpenMeshTriangleBSPT< TriMesh >* tbsp = 0;
711
712 // iterate over all target polylines
713 PluginFunctions::ObjectIterator o_it2(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE );
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
737 PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE );
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
744 PluginFunctions::polyLineObject(*o_it)->line()->smooth_uniform_laplace();
745 else
746 if( tool_->rb_smooth_c1->isChecked())
747 // smooth polyline C1
748 PluginFunctions::polyLineObject(*o_it)->line()->smooth_uniform_laplace2();
749 else
750 if( tool_->rb_smooth_c2->isChecked())
751 // smooth polyline C2
752 PluginFunctions::polyLineObject(*o_it)->line()->smooth_uniform_laplace3();
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
795 PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_TRIANGLE_MESH);
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
808 PluginFunctions::ObjectIterator o_it2(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE);
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
832 PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_TRIANGLE_MESH);
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
934 PolyLinePlugin::EditMode
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 if (create_point_ref_) {
964 // Pick position
965 unsigned int node_idx, target_idx;
966 ACG::Vec3d hit_point;
967 if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
968 *create_point_ref_ = (PolyLine::Point) hit_point;
969
970 // update
971 emit updatedObject(cur_insert_id_, UPDATE_GEOMETRY);
972 }
973 }
974 return;
975 }
976
977 // Pick position
978 unsigned int node_idx, target_idx;
979 ACG::Vec3d hit_point;
980 if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
981
982 switch (_event->type()) {
983 // insert new point
984 case QEvent::MouseButtonPress: {
985 // new Polyline?
986 if (cur_insert_id_ == -1 || !PluginFunctions::objectRoot()->childExists(cur_insert_id_)) {
987 // add new polyline
988 emit addEmptyObject(DATA_POLY_LINE, cur_insert_id_);
989
990 // get current polylineobject
991 BaseObjectData *obj = 0;
992 PluginFunctions::getObject(cur_insert_id_, obj);
993 // default: set as target
994 obj->target(true);
995 // get polyline object
996 cur_polyline_obj_ = PluginFunctions::polyLineObject(obj);
997
998 cur_polyline_obj_->materialNode()->set_random_color();
999
1000 cur_polyline_obj_->line()->set_vertex_radius(PluginFunctions::sceneRadius()*0.012);
1001
1002 cur_polyline_obj_->lineNode()->drawMode(ACG::SceneGraph::DrawModes::DrawMode::getFromDescription("Points (as Spheres, constant screen size)") | ACG::SceneGraph::DrawModes::WIREFRAME);
1003
1004 cur_polyline_obj_->line()->add_point((PolyLine::Point) hit_point);
1005
1006 emit showStatusMessage(tr("Double click/Enter to terminate poly line. Use with shift to create loop."));
1007 }
1008
1009 // add new point
1010 cur_polyline_obj_->line()->add_point((PolyLine::Point) hit_point);
1011 create_point_ref_ = &cur_polyline_obj_->line()->points().back();
1012
1013 // update
1014 emit updatedObject(cur_insert_id_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
1015
1016 break;
1017 }
1018
1019 // finish polyline
1020 case QEvent::MouseButtonDblClick: {
1021 // close polyline
1022 if (_event->modifiers() & (Qt::ShiftModifier)) {
1023 cur_polyline_obj_->line()->set_closed(true);
1024 }
1025
1026 if (cur_polyline_obj_->line()->n_vertices() >= 2) {
1027
1028 cur_polyline_obj_->line()->delete_point(cur_polyline_obj_->line()->n_vertices() - 1);
1029 }
1030
1031 // update
1032 emit updatedObject(cur_insert_id_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
1033
1034 // reset current variables
1035 cur_insert_id_ = -1;
1036 cur_polyline_obj_ = 0;
1037 create_point_ref_ = 0;
1038
1039 clearStatusMessage();
1040
1041 break;
1042 }
1043
1044 default:
1045 break;
1046 }
1047 }
1048 }
1049
1050 //-----------------------------------------------------------------------------
1051
1052 double getRad(int meshIdx)
1053 {
1054 TriMeshObject* mesh;
1055 if(PluginFunctions::getObject(meshIdx, mesh)) {
1056 //use the size of the mesh to compute the handle radii
1057 ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1058 ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1059 mesh->boundingBox(bbMin, bbMax);
1060 return 0.005*(bbMax-bbMin).norm();
1061 }
1062 else {
1063 return PluginFunctions::sceneRadius()*0.01;//use double of the above cause it is the radius
1064 }
1065 }
1066
1067 void PolyLinePlugin::
1068 createCircle_createUI(int _polyLineObjectID)
1069 {
1070 PolyLineObject* lineObject;
1071 if (!PluginFunctions::getObject(_polyLineObjectID, lineObject) || !lineObject->objectData(CIRCLE_DATA))
1072 return;
1073 PolyLineCircleData* lineData = dynamic_cast<PolyLineCircleData*>(lineObject->objectData(CIRCLE_DATA));
1074
1075 lineObject->setObjectDrawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
1076
1077 double rad = getRad(lineData->circleMeshIndex_);
1078
1079 GlutPrimitiveNode* handle0 = new GlutPrimitiveNode(lineObject, "N_Handle0");
1080 handle0->get_primitive(0).color = ACG::Vec4f(1,0,0,1);
1081 handle0->set_size(rad);
1082 handle0->show();
1083 handle0->enablePicking(true);
1084 handle0->set_position(lineData->circleCenter_ + lineData->circleMainAxis_ * lineData->circleMainRadius_);
1085 lineObject->addAdditionalNode(handle0, name(), "handle0");
1086 handle0->drawMode(ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED);
1087
1088 GlutPrimitiveNode* handle1 = new GlutPrimitiveNode(lineObject, "N_Handle1");
1089 handle1->get_primitive(0).color = ACG::Vec4f(0,1,0,1);
1090 handle1->set_size(rad);
1091 handle1->show();
1092 handle1->enablePicking(true);
1093 handle1->set_position(lineData->circleCenter_ + lineData->circleSideAxis_ * lineData->circleSideRadius_);
1094 lineObject->addAdditionalNode(handle1, name(), "handle1");
1095 handle1->drawMode(ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED);
1096
1097 GlutPrimitiveNode* cenNode = new GlutPrimitiveNode(lineObject, "N_Center");
1098 cenNode->get_primitive(0).color = ACG::Vec4f(0,0,1,1);
1099 cenNode->set_size(rad);
1100 cenNode->show();
1101 cenNode->enablePicking(true);
1102 cenNode->set_position(lineData->circleCenter_);
1103 lineObject->addAdditionalNode(cenNode, name(), "circle");
1104 cenNode->drawMode(ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED);
1105
1106 emit updatedObject(_polyLineObjectID, UPDATE_ALL);
1107 }
1108
1109 //-----------------------------------------------------------------------------
1110
1111 void PolyLinePlugin::
1112 me_insertCircle(QMouseEvent* _event)
1113 {
1114 TriMeshObject* mesh;
1115 TriMesh::FaceHandle fh;
1116 TriMesh::VertexHandle vh;
1117 ACG::Vec3d hit_point;
1118 if(!pick_triangle_mesh(_event->pos(), mesh, fh, vh, hit_point) && _event->type() != QEvent::MouseButtonRelease)
1119 return;//can't generate a circle in empty space
1120
1121 if(_event->type() == QEvent::MouseMove && createCircle_CurrSelIndex_ != -1) {
1122 PolyLineObject* lineObject = 0;
1123 if(!PluginFunctions::getObject(createCircle_CurrSelIndex_, lineObject) || !lineObject->objectData(CIRCLE_DATA))
1124 return;
1125 PolyLineCircleData* circleData = dynamic_cast<PolyLineCircleData*>(lineObject->objectData(CIRCLE_DATA));
1126
1127 const ACG::Vec3d n = circleData->circleNormal_, x0 = circleData->circleCenter_;
1128 const double t = ((n | x0) - (n | hit_point)) / n.sqrnorm();
1129 const ACG::Vec3d onPlane = hit_point + t * n, d = onPlane - x0;
1130
1131 circleData->circleMainAxis_ = (onPlane - x0).normalize();
1132 circleData->circleSideRadius_ = circleData->circleMainRadius_ = d.norm();
1133 circleData->circleSideAxis_ = (circleData->circleMainAxis_ % n).normalize();
1134
1135 updatePolyEllipse(lineObject, tool_->sb_CirclePointNum->value());
1136 updateHandles(lineObject);
1137 }
1138 else if(_event->type() == QEvent::MouseButtonPress && createCircle_CurrSelIndex_ == -1) {
1139 int new_line_id;
1140 emit addEmptyObject(DATA_POLY_LINE, new_line_id);
1141 BaseObjectData *obj = 0;
1142 PluginFunctions::getObject(new_line_id, obj);
1143 obj->target(true);
1144 PolyLineObject* newLine = PluginFunctions::polyLineObject(obj);
1145 newLine->materialNode()->set_random_color();
1146
1147 newLine->line()->set_vertex_radius(PluginFunctions::sceneRadius()*0.012);
1148
1149 if(!mesh->mesh()->has_face_normals())
1150 mesh->mesh()->request_face_normals();
1151
1152 PolyLineCircleData* lineData = new PolyLineCircleData(hit_point, mesh->mesh()->normal(fh), ACG::Vec3d(), ACG::Vec3d(), 0, 0, mesh->id());
1153 newLine->setObjectData(CIRCLE_DATA, lineData);
1154 newLine->setObjectDrawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
1155
1156 emit updatedObject(new_line_id, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
1157 createCircle_LastSelIndex_ = createCircle_CurrSelIndex_ = newLine->id();
1158 createSpline_LastSelIndex_ = -1;
1159 }
1160 else if(_event->type() == QEvent::MouseButtonRelease ) {
1161 PolyLineObject* lineObject;
1162 if(PluginFunctions::getObject(createCircle_CurrSelIndex_, lineObject))
1163 {
1164 ACG::SceneGraph::GlutPrimitiveNode* N;
1165 if(lineObject->getAdditionalNode(N, name(), "handle0"))
1166 N->enablePicking(true);
1167 }
1168 createCircle_CurrSelIndex_ = -1;
1169 }
1170 }
1171
1172 //-------------------------------------------OpenFLipper/BasePlugin/----------------------------------
1173
1174 void PolyLinePlugin::
1175 createSpline_createUI(int _polyLineObjectID)
1176 {
1177 PolyLineObject* lineObject;
1178 if (!PluginFunctions::getObject(_polyLineObjectID, lineObject) || !lineObject->objectData(BEZSPLINE_DATA))
1179 return;
1180 PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(lineObject->objectData(BEZSPLINE_DATA));
1181
1182 lineObject->setObjectDrawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
1183
1184 double rad = getRad(splineData->meshIndex_);
1185
1186 GlutLineNode* lineN = new GlutLineNode(lineObject, "N_Line");
1187 lineN->show();
1188 lineN->enablePicking(false);
1189 lineObject->addAdditionalNode(lineN, name(), "line");
1190 lineN->drawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
1191
1192 for(unsigned int i = 0; i < splineData->points_.size(); i++) {
1193 GlutPrimitiveNode* handle0 = new GlutPrimitiveNode(lineObject, "N_Control", i);
1194 handle0->get_primitive(0).color = ACG::Vec4f(0,1,0,1);
1195 handle0->set_size(rad);
1196 handle0->show();
1197 handle0->set_position(splineData->points_[i].position);
1198 handle0->drawMode(ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED);
1199 handle0->enablePicking(true);
1200 lineObject->addAdditionalNode(handle0, name(), "control", i);
1201 }
1202
1203 for(unsigned int i = 0; i < splineData->handles_.size(); i++) {
1204 const PolyLineBezierSplineData::InterpolatePoint& control = splineData->getInterpolatePoint(i);
1205 const ACG::Vec3d hndlPos = splineData->handles_[i], ctrlPos = control.position;
1206
1207 GlutPrimitiveNode* handle0 = new GlutPrimitiveNode(lineObject, "N_Handle", i);
1208 handle0->get_primitive(0).color = ACG::Vec4f(0,0,1,1);
1209 handle0->set_size(rad * 0.75);
1210 handle0->show();
1211 handle0->enablePicking(true);
1212 handle0->set_position(hndlPos);
1213 lineObject->addAdditionalNode(handle0, name(), "handle", i);
1214 handle0->drawMode(ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED);
1215
1216 GlutLineNode* lineN;
1217 if(lineObject->getAdditionalNode(lineN, name(), "line")) {
1218 lineN->add_line(ctrlPos, hndlPos);
1219 lineN->add_color(ACG::Vec4f(1,0,0,1));
1220 }
1221 }
1222 updatePolyBezierSpline(lineObject, tool_->sb_SplineSegNum->value());
1223
1224 emit updatedObject(_polyLineObjectID, UPDATE_ALL);
1225 }
1226
1227 void
1228 PolyLinePlugin::
1229 finishSpline()
1230 {
1231 PolyLineObject* lineObject = 0;
1232
1233 if(!PluginFunctions::getObject(createSpline_CurrSelIndex_, lineObject))
1234 return;
1235
1236
1237 PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(lineObject->objectData(BEZSPLINE_DATA));
1238
1239 TriMeshObject* mesh;
1240 if(!PluginFunctions::getObject(splineData->meshIndex_, mesh))
1241 return;
1242
1243 ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1244 ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1245 mesh->boundingBox(bbMin, bbMax);
1246 const ACG::Vec3d sizeBB((bbMax-bbMin));
1247
1248 if(splineData->finishSpline()) {
1249
1250 GlutPrimitiveNode* control = 0;
1251
1252 for(unsigned int i = 0; i < splineData->points_.size(); i++) {
1253 lineObject->getAdditionalNode(control, name(), "control", i);
1254 control->enablePicking(true);
1255 }
1256
1257 for(unsigned int i = 0; i < splineData->handles_.size(); i++) {
1258 const PolyLineBezierSplineData::InterpolatePoint& control = splineData->getInterpolatePoint(i);
1259 const ACG::Vec3d hndlPos = splineData->handles_[i], ctrlPos = control.position;
1260
1261 GlutPrimitiveNode* handle0 = new GlutPrimitiveNode(lineObject, "N_Handle", i);
1262 handle0->get_primitive(0).color = ACG::Vec4f(0,0,1,1);
1263 handle0->set_size(0.004*sizeBB.norm());
1264 handle0->show();
1265 handle0->enablePicking(true);
1266 handle0->set_position(hndlPos);
1267 lineObject->addAdditionalNode(handle0, name(), "handle", i);
1268 handle0->drawMode(ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED);
1269
1270 GlutLineNode* lineN;
1271 if(lineObject->getAdditionalNode(lineN, name(), "line")) {
1272 lineN->add_line(ctrlPos, hndlPos);
1273 lineN->add_color(ACG::Vec4f(1,0,0,1));
1274 }
1275
1276 emit updatedObject(createSpline_CurrSelIndex_, UPDATE_ALL);
1277 }
1278 updatePolyBezierSpline(lineObject, tool_->sb_SplineSegNum->value());
1279 createSpline_CurrSelIndex_ = -1;
1280 }
1281 }
1282
1283 void PolyLinePlugin::
1284 me_insertSpline(QMouseEvent* _event)
1285 {
1286
1287 TriMeshObject* mesh;
1288 TriMesh::FaceHandle fh;
1289 TriMesh::VertexHandle vh;
1290 ACG::Vec3d hit_point;
1291
1292 if(!pick_triangle_mesh(_event->pos(), mesh, fh, vh, hit_point))
1293 return;//can't generate a circle in empty space
1294
1295 ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
1296 ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
1297 mesh->boundingBox(bbMin, bbMax);
1298 const ACG::Vec3d sizeBB((bbMax-bbMin));
1299
1300 if(!mesh->mesh()->has_face_normals())
1301 mesh->mesh()->request_face_normals();
1302
1303 ACG::Vec3d nor = mesh->mesh()->normal(fh);
1304
1305 if(_event->type() == QEvent::MouseButtonPress) {
1306
1307 if(createSpline_CurrSelIndex_ == -1) {
1308
1309 emit addEmptyObject(DATA_POLY_LINE, createSpline_CurrSelIndex_);
1310 createSpline_LastSelIndex_ = createSpline_CurrSelIndex_;
1311 createCircle_LastSelIndex_ = -1;
1312 BaseObjectData *obj = 0;
1313 PluginFunctions::getObject(createSpline_CurrSelIndex_, obj);
1314 obj->target(true);
1315 PolyLineObject* newLine = PluginFunctions::polyLineObject(obj);
1316 newLine->materialNode()->set_random_color();
1317 newLine->line()->set_vertex_radius(PluginFunctions::sceneRadius()*0.012);
1318
1319 newLine->lineNode()->drawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
1320 emit updatedObject(createSpline_CurrSelIndex_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
1321
1322 PolyLineBezierSplineData* lineData = new PolyLineBezierSplineData(mesh->id());
1323 newLine->setObjectData(BEZSPLINE_DATA, lineData);
1324
1325 GlutLineNode* lineN = new GlutLineNode(newLine, "N_Line");
1326 lineN->show();
1327 lineN->enablePicking(false);
1328 newLine->addAdditionalNode(lineN, name(), "line");
1329 lineN->drawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
1330 }
1331
1332 ACG::Vec3d insert_Point = hit_point + nor * 0.003 * sizeBB.norm();
1333 PolyLineObject* lineObject = 0;
1334
1335 if(!PluginFunctions::getObject(createSpline_CurrSelIndex_, lineObject))
1336 return;
1337
1338 PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(lineObject->objectData(BEZSPLINE_DATA));
1339 GlutPrimitiveNode* handle0 = new GlutPrimitiveNode(lineObject, "N_Control", splineData->points_.size());
1340 handle0->get_primitive(0).color = ACG::Vec4f(0,1,0,1);
1341 handle0->set_size(0.005*sizeBB.norm());
1342 handle0->show();
1343 handle0->set_position(insert_Point);
1344 handle0->drawMode(ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED);
1345 handle0->enablePicking(false);
1346 lineObject->addAdditionalNode(handle0, name(), "control", splineData->points_.size());
1347
1348 emit updatedObject(createSpline_CurrSelIndex_, UPDATE_ALL);
1349 splineData->addInterpolatePoint(insert_Point, nor);
1350
1351 }
1352 if(_event->type() == QEvent::MouseButtonDblClick) {
1353 finishSpline();
1354 }
1355 }
1356
1357 //-----------------------------------------------------------------------------
1358
1359 void
1360 PolyLinePlugin::
1361 me_delete( QMouseEvent* _event )
1362 {
1363 // MousePress ?
1364 if (_event->type() == QEvent::MouseButtonPress) {
1365
1366 unsigned int node_idx, target_idx;
1367 ACG::Vec3d hit_point;
1368 // pick
1369 if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point)) {
1370
1371 BaseObjectData* obj = 0;
1372
1373 if (PluginFunctions::getPickedObject(node_idx, obj))
1374 // is picked object polyline?
1375 if (PluginFunctions::polyLineObject(obj)) {
1376 emit deleteObject(obj->id());
1377 }
1378 }
1379
1380 }
1381
1382 }
1383
1384
1385 //-----------------------------------------------------------------------------
1386
1387 namespace {
1388
1389 bool me_GetMeshHit(QMouseEvent* _event, ACG::SceneGraph::GlutPrimitiveNode* moveCircle_SelNode_, ACG::Vec3d& _hit_point, unsigned int& _node_idx, unsigned int& _targetIdx)
1390 {
1391 unsigned int ndx;
1392 if(moveCircle_SelNode_)
1393 moveCircle_SelNode_->enablePicking(false);
1394 bool hasHit = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), ndx, _targetIdx, &_hit_point);
1395 if(moveCircle_SelNode_)
1396 moveCircle_SelNode_->enablePicking(true);
1397 BaseObjectData* obj;
1398 //if there is no current mesh use the newly found
1399 if(hasHit && PluginFunctions::getPickedObject(ndx, obj) && _node_idx == std::numeric_limits<unsigned int>::max())
1400 _node_idx = obj->id();
1401 return hasHit;
1402 }
1403
1404 void me_UpdateCircleData(ACG::Vec3d _hit_point, ACG::Vec3d _onPlane, ACG::Vec3d _nor, ACG::SceneGraph::GlutPrimitiveNode* _moveCircle_SelNode_, PolyLineCircleData* _lineData, bool _isShift)
1405 {
1406 if(!_moveCircle_SelNode_->name().compare("N_Center"))
1407 {
1408 _lineData->circleNormal_ = _nor;
1409 _lineData->circleCenter_ = _hit_point;
1410 _lineData->circleSideAxis_ = (_lineData->circleMainAxis_ % _lineData->circleNormal_).normalize();
1411 _lineData->circleMainAxis_ = (_lineData->circleNormal_ % _lineData->circleSideAxis_).normalize();
1412 }
1413 else
1414 {
1415 const double cr = (_onPlane - _lineData->circleCenter_).norm();
1416 const ACG::Vec3d axisa = (_onPlane - _lineData->circleCenter_).normalize();
1417 if (!_moveCircle_SelNode_->name().compare("N_Handle0")) {
1418 const ACG::Vec3d axisb = (axisa % _lineData->circleNormal_).normalize();
1419 _lineData->circleMainRadius_ = cr;
1420
1421 if (_isShift)
1422 _lineData->circleSideRadius_ = cr;
1423
1424 _lineData->circleMainAxis_ = axisa;
1425 _lineData->circleSideAxis_ = axisb;
1426 } else {
1427 const ACG::Vec3d axisb = (_lineData->circleNormal_ % axisa).normalize();
1428 _lineData->circleSideRadius_ = cr;
1429
1430 if (_isShift)
1431 _lineData->circleMainRadius_ = cr;
1432
1433 _lineData->circleSideAxis_ = axisa;
1434 _lineData->circleMainAxis_ = axisb;
1435 }
1436 }
1437 }
1438 }
1439
1440 void
1441 PolyLinePlugin::
1442 me_move( QMouseEvent* _event )
1443 {
1444 if((_event->modifiers() & Qt::ShiftModifier) != Qt::ShiftModifier && moveCircle_IsLocked)//alt was pressed but it isn't anymore
1445 moveCircle_IsLocked = moveCircle_IsFloating = false;
1446
1447 // MousePress ? -> get reference point
1448 if (_event->type() == QEvent::MouseButtonPress) {
1449
1450 unsigned int node_idx, target_idx;
1451 ACG::Vec3d hit_point;
1452 // this is for picking the handles on a circle or spline
1453 if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point)) {
1454 BaseNode* node = find_node( PluginFunctions::getRootNode(), node_idx );
1455 GlutPrimitiveNode* glutNode = dynamic_cast<GlutPrimitiveNode*>(node);
1456
1457 if(glutNode) {
1458 PolyLineCircleData* circleData = dynamic_cast<PolyLineCircleData*>(glutNode->line->objectData(CIRCLE_DATA));
1459 PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(glutNode->line->objectData(BEZSPLINE_DATA));
1460 if(circleData) {
1461 moveCircle_SelNode_ = glutNode;
1462 createCircle_LastSelIndex_ = createCircle_CurrSelIndex_ = glutNode->line->id();
1463 }
1464 if(splineData) {
1465 moveBezSpline_SelNode_ = glutNode;
1466 createSpline_LastSelIndex_ = moveBezSpline_SelIndex_ = glutNode->line->id();
1467 moveBezSpline_SelSubIndex_ = glutNode->index;
1468 }
1469 }
1470 }
1471 //this is for picking the normal poly lines
1472 if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_VERTEX, _event->pos(), node_idx, target_idx, &hit_point)) {
1473 BaseObjectData* obj = 0;
1474 if (PluginFunctions::getPickedObject(node_idx, obj)) {
1475 // is picked object polyline?
1476 PolyLineObject* cur_pol = PluginFunctions::polyLineObject(obj);
1477 if (cur_pol && !cur_pol->objectData(CIRCLE_DATA) && !cur_pol->objectData(BEZSPLINE_DATA)) {//no vertex dragging on circles!
1478
1479 // Check if we got a line segment or a vertex
1480 if ( target_idx >= cur_pol->line()->n_vertices() )
1481 return;
1482
1483 // save references
1484 cur_move_id_ = cur_pol->id();
1485
1486 move_point_ref_ = &(cur_pol->line()->point(target_idx));
1487 }
1488 }
1489 }
1490 }
1491
1492 // Move ? -> move reference point
1493 if (_event->type() == QEvent::MouseMove){
1494 if (moveCircle_SelNode_) {
1495 PolyLineObject* lineObject;
1496 if (!PluginFunctions::getObject(createCircle_CurrSelIndex_, lineObject) || !lineObject->objectData(CIRCLE_DATA))
1497 return;
1498 PolyLineCircleData* lineData = dynamic_cast<PolyLineCircleData*>(lineObject->objectData(CIRCLE_DATA));
1499 ACG::Vec3d hit_point;
1500 unsigned int target_idx;
1501 bool hasHit = me_GetMeshHit(_event, moveCircle_SelNode_, hit_point, lineData->circleMeshIndex_, target_idx);
1502 if(lineData->circleMeshIndex_ == std::numeric_limits<unsigned int>::max()) return;
1503 if(!moveCircle_IsLocked && hasHit) {
1504 moveCircle_IsFloating = false;
1505 ACG::Vec3d x0 = lineData->circleCenter_, n = lineData->circleNormal_;
1506 ACG::Vec3d onMesh = hit_point;
1507 double t = ((n | x0) - (n | onMesh)) / n.sqrnorm();
1508 ACG::Vec3d onPlane = onMesh + t * n;
1509 TriMeshObject* mesh;
1510 if (!PluginFunctions::getObject(lineData->circleMeshIndex_, mesh))
1511 return;
1512
1513 me_UpdateCircleData(onMesh, onPlane, mesh->mesh()->normal(mesh->mesh()->face_handle(target_idx)), moveCircle_SelNode_, lineData, (_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier);
1514 if (!moveCircle_SelNode_->name().compare("N_Center")) {
1515 moveCircle_LastHitPos_ = onMesh;
1516 if((_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier) {
1517 moveCircle_IsLocked = true;
1518 moveCircle_LastHitNor_ = lineData->circleNormal_;
1519 }
1520 }
1521 }
1522 else
1523 {
1524 moveCircle_IsFloating = true;
1525 ACG::Vec3d cameraPos, cameraDir;
1526 int l,b,w,h;
1527 PluginFunctions::viewerProperties(0).glState().get_viewport(l,b,w,h);
1528 PluginFunctions::viewerProperties(0).glState().viewing_ray(_event->pos().x(), h - 1 - _event->pos().y(), cameraPos, cameraDir);
1529 //intersect the camera ray with a plane located at moveCircle_LastHitPos_ facing moveCircle_LastHitNor_
1530 const ACG::Vec3d x0 = !moveCircle_SelNode_->name().compare("N_Center") ? moveCircle_LastHitPos_ : lineData->circleCenter_,
1531 //the side handles can only be moved on the normal plane
1532 n = !moveCircle_SelNode_->name().compare("N_Center") ? (moveCircle_IsLocked ? moveCircle_LastHitNor_ : PluginFunctions::viewingDirection())
1533 : lineData->circleNormal_;
1534 const double t = ((x0 | n) - (cameraPos | n)) / (cameraDir | n);
1535 const ACG::Vec3d onPlane = cameraPos + cameraDir * t;
1536
1537 me_UpdateCircleData(onPlane, onPlane, n, moveCircle_SelNode_, lineData, (_event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier);
1538
1539 }
1540 updateHandles(lineObject);
1541 updatePolyEllipse(lineObject, tool_->sb_CirclePointNum->value());
1542 }
1543 else if(moveBezSpline_SelNode_) {
1544 PolyLineObject* lineObject;
1545 if(!PluginFunctions::getObject(moveBezSpline_SelIndex_, lineObject) || !lineObject->objectData(BEZSPLINE_DATA))
1546 return;
1547 PolyLineBezierSplineData* lineData = dynamic_cast<PolyLineBezierSplineData*>(lineObject->objectData(BEZSPLINE_DATA));
1548 ACG::Vec3d hit_point;
1549 unsigned int target_idx;
1550 bool hasHit = me_GetMeshHit(_event, moveBezSpline_SelNode_, hit_point, lineData->meshIndex_, target_idx);
1551 if(lineData->meshIndex_ == std::numeric_limits<unsigned int>::max())
1552 return;
1553 if(!moveBezSpline_SelNode_->name().compare("N_Control") && hasHit) {
1554 TriMeshObject* mesh;
1555 if (!PluginFunctions::getObject(lineData->meshIndex_, mesh))
1556 return;
1557 ACG::Vec3d onMesh = hit_point, onMeshNor = mesh->mesh()->normal(mesh->mesh()->face_handle(target_idx));
1558 int controlIndex = moveBezSpline_SelSubIndex_;
1559 ACG::Vec3d oldPos = moveBezSpline_SelNode_->get_position();
1560 moveBezSpline_SelNode_->set_position(onMesh);
1561 lineData->points_[controlIndex].position = onMesh;
1562 lineData->points_[controlIndex].normal = onMeshNor;
1563 if(controlIndex) {
1564 int handleIndex = 2 * controlIndex - 1;
1565 ACG::Vec3d dir = lineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
1566 ACG::Vec3d point = forw + onMesh;
1567 lineData->handles_[handleIndex] = point;
1568 }
1569 if(controlIndex != ((int)lineData->points_.size() - 1)) {
1570 int handleIndex = 2 * controlIndex;
1571 ACG::Vec3d dir = lineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
1572 ACG::Vec3d point = forw + onMesh;
1573 lineData->handles_[handleIndex] = point;
1574 }
1575 }
1576 else if(!moveBezSpline_SelNode_->name().compare("N_Handle")) {
1577 int handleIndex = moveBezSpline_SelSubIndex_;
1578 const PolyLineBezierSplineData::InterpolatePoint& control = lineData->getInterpolatePoint(handleIndex);
1579 //we don't use the mesh location but instead the location on the normal plane!
1580 ACG::Vec3d cameraPos, cameraDir;
1581 int l,b,w,h;
1582 PluginFunctions::viewerProperties(0).glState().get_viewport(l,b,w,h);
1583 PluginFunctions::viewerProperties(0).glState().viewing_ray(_event->pos().x(), h - 1 - _event->pos().y(), cameraPos, cameraDir);
1584 double t = ((control.normal | control.position) - (control.normal | cameraPos)) / (control.normal | cameraDir);
1585 ACG::Vec3d onPlane = cameraPos + t * cameraDir;
1586
1587 lineData->handles_[handleIndex] = onPlane;
1588 if(handleIndex % 2 == 1 && handleIndex != ((int)lineData->handles_.size() - 1)) {
1589 double dist = (lineData->handles_[handleIndex + 1] - control.position).norm();
1590 if(_event->modifiers() & Qt::ShiftModifier)
1591 dist = (onPlane - control.position).norm();
1592 ACG::Vec3d dir = -(onPlane - control.position).normalize();
1593 lineData->handles_[handleIndex + 1] = control.position + dir * dist;
1594 }
1595 if(handleIndex % 2 == 0 && handleIndex) {
1596 double dist = (lineData->handles_[handleIndex - 1] - control.position).norm();
1597 if(_event->modifiers() & Qt::ShiftModifier)
1598 dist = (onPlane - control.position).norm();
1599 ACG::Vec3d dir = -(onPlane - control.position).normalize();
1600 lineData->handles_[handleIndex - 1] = control.position + dir * dist;
1601 }
1602 }
1603 GlutLineNode* lineN;
1604 if(!lineObject->getAdditionalNode(lineN, name(), "line", 0))
1605 return;
1606 updatePolyBezierHandles(lineObject, lineN);
1607 updatePolyBezierSpline(lineObject, tool_->sb_SplineSegNum->value());
1608 }
1609 else if (move_point_ref_ != 0) {
1610 ACG::Vec3d hit_point;
1611 unsigned int node_idx, target_idx;
1612 if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
1613 (*move_point_ref_) = (PolyLine::Point) hit_point;
1614 // update
1615 emit updatedObject(cur_move_id_, UPDATE_GEOMETRY);
1616 }
1617 }
1618 }
1619
1620 // Release ? -> release reference point
1621 if (_event->type() == QEvent::MouseButtonRelease) {
1622 if((_event->modifiers() & Qt::ShiftModifier) != Qt::ShiftModifier) {
1623 //in case we are not dragging the center and not pressing alt -> project to mesh
1624 // if(moveCircle_SelNode_ && moveCircle_SelNode_->name().compare("N_Center"))
1625 moveCircle_IsLocked = moveCircle_IsFloating = false;
1626 PolyLineObject* lineObject;
1627 if (PluginFunctions::getObject(createCircle_CurrSelIndex_, lineObject))
1628 {
1629 moveCircle_IsLocked = false;
1630 updateHandles(lineObject);
1631 updatePolyEllipse(lineObject, tool_->sb_CirclePointNum->value());
1632 }
1633 }
1634 move_point_ref_ = 0;
1635 moveCircle_SelNode_ = 0;
1636 createCircle_CurrSelIndex_ = -1;
1637 moveBezSpline_SelNode_ = 0;
1638 moveBezSpline_SelIndex_ = -1;
1639 }
1640 }
1641 //-----------------------------------------------------------------------------
1642
1643
1644 void
1645 PolyLinePlugin::
1646 me_split( QMouseEvent* _event )
1647 {
1648 // MousePress ?
1649 if (_event->type() == QEvent::MouseButtonPress) {
1650 // release old references
1651 move_point_ref_ = 0;
1652
1653 unsigned int node_idx, target_idx;
1654 ACG::Vec3d hit_point;
1655 // pick
1656 if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_VERTEX, _event->pos(), node_idx, target_idx, &hit_point)) {
1657
1658 BaseObjectData* obj = 0;
1659 if (PluginFunctions::getPickedObject(node_idx, obj)) {
1660
1661 // is picked object polyline?
1662 PolyLineObject* cur_pol = PluginFunctions::polyLineObject(obj);
1663
1664 if (cur_pol) {
1665
1666 // Check if we got a line segment or a vertex
1667 if ( target_idx >= cur_pol->line()->n_vertices() )
1668 return;
1669
1670 // splitting for CLOSED PolyLines
1671 if (cur_pol->line()->is_closed()) {
1672 cur_pol->line()->split_closed(target_idx);
1673
1674 // save references for moving
1675 cur_move_id_ = cur_pol->id();
1676 move_point_ref_ = &(cur_pol->line()->point(cur_pol->line()->n_vertices() - 1));
1677
1678 // emit changed objects
1679 emit updatedObject(cur_pol->id(), UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
1680 } else
1681 // splitting for OPEN PolyLines
1682 {
1683 // add new polyline
1684 int insert_id;
1685 emit addEmptyObject(DATA_POLY_LINE, insert_id);
1686
1687 // get current polylineobject
1688 BaseObjectData *obj2 = 0;
1689
1690 // get polyline object
1691 PluginFunctions::getObject(insert_id, obj2);
1692
1693 // default: mark as target
1694 obj2->target(true);
1695
1696 PolyLineObject* pol_obj2 = PluginFunctions::polyLineObject(obj2);
1697
1698 pol_obj2->materialNode()->set_random_color();
1699
1700 pol_obj2->line()->set_vertex_radius(cur_pol->line()->vertex_radius());
1701 pol_obj2->lineNode()->drawMode(cur_pol->lineNode()->drawMode());
1702
1703 cur_pol->line()->split(target_idx, *(pol_obj2->line()));
1704
1705 // save references for moving
1706 cur_move_id_ = cur_pol->id();
1707 move_point_ref_ = &(cur_pol->line()->point(cur_pol->line()->n_vertices() - 1));
1708
1709 // emit changed objects
1710 emit updatedObject(insert_id, UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
1711 emit updatedObject(cur_pol->id(), UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
1712 }
1713
1714 // update
1715 emit updateView();
1716 }
1717 }
1718 }
1719 }
1720
1721 // Move splitted ? -> move reference point
1722 if (_event->type() == QEvent::MouseMove)
1723 if (move_point_ref_ != 0) {
1724
1725 unsigned int node_idx, target_idx;
1726 ACG::Vec3d hit_point;
1727 // pick
1728 if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
1729 (*move_point_ref_) = (PolyLine::Point) hit_point;
1730
1731 // update
1732 emit updatedObject(cur_move_id_, UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
1733 emit updateView();
1734 }
1735 }
1736
1737 // Release splitted? -> release reference point
1738 if (_event->type() == QEvent::MouseButtonRelease) {
1739
1740 if (cur_move_id_ != -1)
1741 emit updatedObject(cur_move_id_, UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
1742
1743 move_point_ref_ = 0;
1744 cur_move_id_ = -1;
1745
1746 }
1747
1748 }
1749
1750 //-----------------------------------------------------------------------------
1751
1752 void
1753 PolyLinePlugin::
1754 me_merge( QMouseEvent* _event )
1755 {
1756 // Mouse PRESS ?
1757 if (_event->type() == QEvent::MouseButtonPress) {
1758 // release old references
1759 move_point_ref_ = 0;
1760 cur_merge_id_ = -1;
1761
1762 unsigned int node_idx, target_idx;
1763 ACG::Vec3d hit_point;
1764 // pick
1765 if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_VERTEX, _event->pos(), node_idx, target_idx, &hit_point)) {
1766 BaseObjectData* obj = 0;
1767 if (PluginFunctions::getPickedObject(node_idx, obj)) {
1768 // is picked object polyline?
1769 PolyLineObject* cur_pol = PluginFunctions::polyLineObject(obj);
1770 if (cur_pol) {
1771
1772 // Check if we got a line segment or a vertex
1773 if ( target_idx >= cur_pol->line()->n_vertices() ) {
1774 return;
1775 }
1776
1777 if (target_idx == cur_pol->line()->n_vertices() - 1 || target_idx == 0) {
1778 if (target_idx == 0) {
1779 cur_pol->line()->invert();
1780 //target_idx = cur_pol->line()->n_vertices() - 1;
1781 }
1782
1783 // save references
1784 cur_merge_id_ = cur_pol->id();
1785
1786 // save reference for moving
1787 // cur_pol->line()->add_point( cur_pol->line()->point( cur_pol->line()->n_vertices()-1));
1788 move_point_ref_ = &(cur_pol->line()->point(cur_pol->line()->n_vertices() - 1));
1789 }
1790 }
1791
1792 }
1793 }
1794 }
1795
1796 // Move ? -> move reference point
1797 if (_event->type() == QEvent::MouseMove && cur_merge_id_ != -1)
1798 if (move_point_ref_ != 0) {
1799 unsigned int node_idx, target_idx;
1800 ACG::Vec3d hit_point;
1801 // pick
1802 if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
1803 (*move_point_ref_) = (PolyLine::Point) hit_point;
1804
1805 // update
1806 emit updatedObject(cur_merge_id_, UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
1807 emit updateView();
1808 }
1809 }
1810
1811 // Mouse RELEASE ?
1812 if (_event->type() == QEvent::MouseButtonRelease && cur_merge_id_ != -1) {
1813 PolyLine::Point p_save;
1814
1815 // reset move references
1816 if (move_point_ref_ != 0) {
1817 // remove intermediate point
1818 // restore orig polyline
1819 BaseObjectData *obj = 0;
1820 PluginFunctions::getObject(cur_merge_id_, obj);
1821 PolyLineObject* opol = PluginFunctions::polyLineObject(obj);
1822
1823 // store position if merging fails
1824 p_save = opol->line()->back();
1825 opol->line()->resize(opol->line()->n_vertices() - 1);
1826
1827 // release reference
1828 move_point_ref_ = 0;
1829 }
1830
1831 unsigned int node_idx, target_idx;
1832 ACG::Vec3d hit_point;
1833
1834 // pick
1835 // restore first polyline
1836 BaseObjectData *obj2 = 0;
1837 PluginFunctions::getObject(cur_merge_id_, obj2);
1838 PolyLineObject* first_pol = PluginFunctions::polyLineObject(obj2);
1839 first_pol->enablePicking(false);
1840 PluginFunctions::invalidatePickCaches();
1841
1842 bool merged = false;
1843 if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_VERTEX, _event->pos(), node_idx, target_idx, &hit_point)) {
1844
1845 BaseObjectData* obj = 0;
1846
1847 if (PluginFunctions::getPickedObject(node_idx, obj)) {
1848
1849 // is picked object polyline? -> get second polyline
1850 PolyLineObject* second_pol = PluginFunctions::polyLineObject(obj);
1851
1852 if (second_pol) {
1853
1854 // Check if we got a line segment or a vertex
1855 if ( target_idx < second_pol->line()->n_vertices() ) {
1856 // get idxs
1857 unsigned int first_idx = first_pol->line()->n_vertices() - 1;
1858 unsigned int second_idx = target_idx;
1859
1860 // both polylines open?
1861 if (!first_pol->line()->is_closed() && !second_pol->line()->is_closed()) {
1862
1863 bool inv_first(false), inv_second(false);
1864
1865 // wrong ordering first Polyline?
1866 if (first_idx == 0) {
1867 inv_first = true;
1868 first_idx = first_pol->line()->n_vertices() - 1;
1869 }
1870
1871 // wrong ordering second Polyline?
1872 if (second_idx == second_pol->line()->n_vertices() - 1) {
1873 inv_second = true;
1874 second_idx = 0;
1875 }
1876
1877 // two endpoints available?
1878 if (first_idx == first_pol->line()->n_vertices() - 1 && second_idx == 0) {
1879 // same polyline?
1880 if (first_pol->id() == second_pol->id()) {
1881 // simply close line
1882 first_pol->line()->set_closed(true);
1883 } else {
1884 // invert if necessary
1885 if (inv_first)
1886 first_pol->line()->invert();
1887 if (inv_second)
1888 second_pol->line()->invert();
1889
1890 // append second polyline to first one
1891 first_pol->line()->append(*second_pol->line());
1892
1893 // set flag
1894 merged = true;
1895
1896 // delete appended
1897 emit deleteObject(second_pol->id());
1898 }
1899
1900 }
1901 }
1902 }
1903 }
1904 }
1905 }
1906
1907 first_pol->enablePicking(true);
1908 PluginFunctions::invalidatePickCaches();
1909
1910 //above can't try to close a line
1911 if(!merged && PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_VERTEX, _event->pos(), node_idx, target_idx, &hit_point)) {
1912 BaseObjectData* obj = 0;
1913 if (PluginFunctions::getPickedObject(node_idx, obj)) {
1914
1915 // is picked object polyline? -> get second polyline
1916 PolyLineObject* second_pol = PluginFunctions::polyLineObject(obj);
1917
1918 if (second_pol) {
1919
1920 // Check if we got a line segment or a vertex
1921 if ( target_idx < second_pol->line()->n_vertices() ) {
1922 // get idxs
1923 unsigned int first_idx = first_pol->line()->n_vertices() - 1;
1924 unsigned int second_idx = target_idx;
1925
1926 // both polylines open?
1927 if (!first_pol->line()->is_closed() && !second_pol->line()->is_closed()) {
1928
1929 // wrong ordering first Polyline?
1930 if (first_idx == 0) {
1931 first_idx = first_pol->line()->n_vertices() - 1;
1932 }
1933
1934 // wrong ordering second Polyline?
1935 if (second_idx == second_pol->line()->n_vertices() - 1) {
1936 second_idx = 0;
1937 }
1938
1939 if (first_pol->id() == second_pol->id() && first_idx == first_pol->line()->n_vertices() - 1 && second_idx == 0) {
1940 // simply close line
1941 first_pol->line()->set_closed(true);
1942 merged = true;
1943 }
1944 }
1945 }
1946 }
1947 }
1948 }
1949
1950 if (!merged) {
1951 // remove intermediate point
1952 // restore orig polyline
1953 BaseObjectData *obj = 0;
1954 PluginFunctions::getObject(cur_merge_id_, obj);
1955 PolyLineObject* opol = PluginFunctions::polyLineObject(obj);
1956
1957 opol->line()->add_point(p_save);
1958 }
1959
1960 // update
1961 emit updatedObject(cur_merge_id_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
1962
1963 // release old references
1964 move_point_ref_ = 0;
1965 cur_merge_id_ = -1;
1966 }
1967
1968 }
1969
1970
1971 //-----------------------------------------------------------------------------
1972
1973
1974 void
1975 PolyLinePlugin::
1976 me_smart_move( QMouseEvent* _event )
1977 {
1978 // MousePress ? -> select vertex and start timer
1979 if (_event->type() == QEvent::MouseButtonPress) {
1980
1981 unsigned int node_idx, target_idx;
1982 ACG::Vec3d hit_point;
1983
1984 // pick
1985 if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point)) {
1986
1987 BaseObjectData* obj = 0;
1988 if (PluginFunctions::getPickedObject(node_idx, obj)) {
1989
1990 // is picked object polyline?
1991 PolyLineObject* cur_pol = PluginFunctions::polyLineObject(obj);
1992 if (cur_pol) {
1993
1994 cur_polyline_obj_ = cur_pol;
1995
1996 // Check if we got a line segment or a vertex
1997 if ( target_idx >= cur_pol->line()->n_vertices() )
1998 return;
1999
2000 // save references
2001 cur_smart_move_obj_ = cur_pol;
2002 if (cur_pol->line()->vertex_selections_available()) {
2003 if (!(_event->modifiers() & (Qt::ShiftModifier)))
2004 cur_pol->line()->vertex_selection(target_idx) = true;
2005 else {
2006 cur_pol->line()->vertex_selection(target_idx) = false;
2007 emit updateView();
2008 }
2009 }
2010
2011 }
2012
2013 // start timer
2014 if (!(_event->modifiers() & (Qt::ShiftModifier)))
2015 smart_move_timer_->start(20);
2016 }
2017 }
2018 }
2019
2020
2021 // MouseRelease ? -> stop timer
2022 if( _event->type() == QEvent::MouseButtonRelease)
2023 {
2024 smart_move_timer_->stop();
2025 cur_smart_move_obj_ = NULL;
2026 }
2027
2028
2029 // call move event
2030 me_move( _event);
2031 }
2032
2033 //-----------------------------------------------------------------------------
2034
2035 void
2036 PolyLinePlugin::
2037 slotEditModeChanged()
2038 {
2039 PluginFunctions::pickMode("PolyLine");
2040 PluginFunctions::actionMode(Viewer::PickingMode);
2041 }
2042
2043 //-----------------------------------------------------------------------------
2044
2045 void
2046 PolyLinePlugin::
2047 updateHandles(PolyLineObject* _lineObject)
2048 {
2049 PolyLineCircleData* circleData = dynamic_cast<PolyLineCircleData*>(_lineObject->objectData(CIRCLE_DATA) );
2050 GlutPrimitiveNode* H0, *H1, *C;
2051 _lineObject->getAdditionalNode(C, name(), "circle");
2052 _lineObject->getAdditionalNode(H0, name(), "handle0");
2053 _lineObject->getAdditionalNode(H1, name(), "handle1");
2054 ACG::Vec3d h0 = circleData->circleCenter_ + circleData->circleMainAxis_ * circleData->circleMainRadius_,
2055 h1 = circleData->circleCenter_ + circleData->circleSideAxis_ * circleData->circleSideRadius_;
2056 if(C)
2057 C->set_position(circleData->circleCenter_);
2058 if(H0)
2059 H0->set_position(moveCircle_IsFloating ? h0 : createCircle_getHit(circleData, h0));
2060 if(H1)
2061 H1->set_position(moveCircle_IsFloating ? h1 : createCircle_getHit(circleData, h1));
2062 }
2063
2064 //-----------------------------------------------------------------------------
2065
2066 void
2067 PolyLinePlugin::
2068 slot_setCirclePointNum(int i)
2069 {
2070 PolyLineObject* _lineObject;
2071 if(createCircle_LastSelIndex_ != -1 && PluginFunctions::getObject(createCircle_LastSelIndex_, _lineObject))
2072 updatePolyEllipse(_lineObject, i);
2073 }
2074
2075 //-----------------------------------------------------------------------------
2076
2077 void
2078 PolyLinePlugin::
2079 slot_setSplinePointNum(int i)
2080 {
2081 PolyLineObject* _lineObject;
2082 if(createSpline_LastSelIndex_ != -1 && PluginFunctions::getObject(createSpline_LastSelIndex_, _lineObject))
2083 updatePolyBezierSpline(_lineObject, i);
2084 }
2085
2086 //-----------------------------------------------------------------------------
2087
2088 void
2089 PolyLinePlugin::
2090 slotPickToolbarAction(QAction* _action) {
2091 if ( _action == insertAction_ ) {
2092 tool_->rb_insert->setChecked(true);
2093 } else if ( _action == insertCircleAction_ ) {
2094 tool_->rb_InsertCircle->setChecked(true);
2095 } else if ( _action == insertSplineAction_ ) {
2096 tool_->rb_InsertSpline->setChecked(true);
2097 } else if ( _action == deleteAction_ ) {
2098 tool_->rb_delete->setChecked(true);
2099 } else if ( _action == moveAction_ ) {
2100 tool_->rb_move->setChecked(true);
2101 } else if ( _action == smartMoveAction_ ) {
2102 tool_->rb_smart_move->setChecked(true);
2103 } else if ( _action == mergeAction_ ) {
2104 tool_->rb_merge->setChecked(true);
2105 } else if ( _action == splitAction_ ) {
2106 tool_->rb_split->setChecked(true);
2107 }
2108 }
2109
2110 void
2111 PolyLinePlugin::
2112 slotSetPolyLineMode(QAction* _action) {
2113 if (_action == polyLineAction_ ){
2114 PluginFunctions::actionMode(Viewer::PickingMode);
2115 PluginFunctions::pickMode("PolyLine");
2116
2117 polyLineAction_->setChecked( true );
2118 }
2119 }
2120
2121 //-----------------------------------------------------------------------------
2122
2123
2124 void
2125 PolyLinePlugin::
2126 slotEnablePickMode(QString _name)
2127 {
2128 PluginFunctions::pickMode("PolyLine");
2129 PluginFunctions::actionMode(Viewer::PickingMode);
2130
2131 if(tool_ )
2132 {
2133 if(_name == "INSERT")
2134 tool_->rb_insert->setChecked(true);
2135 else if(_name == "DELETE")
2136 tool_->rb_delete->setChecked(true);
2137 else if(_name == "MOVE")
2138 tool_->rb_move->setChecked(true);
2139 else if(_name == "SPLIT")
2140 tool_->rb_split->setChecked(true);
2141 else if(_name == "MERGE")
2142 tool_->rb_merge->setChecked(true);
2143 else if( _name == "SMART_MOVE")
2144 tool_->rb_smart_move->setChecked(true);
2145 }
2146 }
2147
2148 //-----------------------------------------------------------------------------
2149
2150 bool
2151 PolyLinePlugin::
2152 pick_triangle_mesh( QPoint mPos,
2153 TriMeshObject*& _mesh_object_, TriMesh::FaceHandle& _fh, TriMesh::VertexHandle& _vh, ACG::Vec3d& _hitPoint)
2154 {
2155 // invalidate return values
2156 _fh = TriMesh::FaceHandle (-1);
2157 _vh = TriMesh::VertexHandle(-1);
2158
2159 unsigned int target_idx = 0, node_idx = 0;
2160 ACG::Vec3d hit_point;
2161
2162
2163
2164 if( PluginFunctions::scenegraphPick( ACG::SceneGraph::PICK_FACE, mPos, node_idx, target_idx, &hit_point ) )
2165 {
2166 // first check if a sphere was clicked
2167 BaseObjectData* object(0);
2168 if( PluginFunctions::getPickedObject( node_idx, object ) )
2169 {
2170 if( object->picked( node_idx ) && object->dataType(DATA_TRIANGLE_MESH) )
2171 {
2172 // get mesh object
2173 _mesh_object_ = dynamic_cast<TriMeshObject*>(object);
2174
2175 // get mesh and face handle
2176 TriMesh & m = *PluginFunctions::triMesh(object);
2177 _fh = m.face_handle(target_idx);
2178
2179 TriMesh::FaceVertexIter fv_it(m,_fh);
2180 TriMesh::VertexHandle closest = *fv_it;
2181 float shortest_distance = (m.point(closest) - hit_point).sqrnorm();
2182
2183 ++fv_it;
2184 if ( (m.point(*fv_it ) - hit_point).sqrnorm() < shortest_distance ) {
2185 shortest_distance = (m.point(*fv_it ) - hit_point).sqrnorm();
2186 closest = *fv_it;
2187 }
2188
2189 ++fv_it;
2190 if ( (m.point(*fv_it ) - hit_point).sqrnorm() < shortest_distance ) {
2191 // Unnecessary : shortest_distance = (m.point(*fv_it ) - hit_point).sqrnorm();
2192 closest = *fv_it;
2193 }
2194
2195 // stroe closest vh
2196 _vh = closest;
2197 _hitPoint = hit_point;
2198
2199 return true;
2200 }
2201 }
2202 }
2203 return false;
2204 }
2205
2206 //-----------------------------------------------------------------------------
2207
2208 void
2209 PolyLinePlugin::
2210 slotUpdateContextMenu(int objectId)
2211 {
2212 copyPaste_ObjectId_ = objectId;
2213 copyPaste_Action_->setVisible(pickToolbar_->isVisible());
2214 }
2215
2216 void
2217 PolyLinePlugin::
2218 me_copyPasteMouse(QMouseEvent* _event)
2219 {
2220 //get the object
2221 PolyLineObject* oldObj, *newObj;
2222 if(copyPaste_ObjectId_ == -1 || !PluginFunctions::getObject(copyPaste_ObjectId_, oldObj) || !PluginFunctions::getObject(copyPaste_NewObjectId_, newObj))
2223 {
2224 //something went wrong, leave the copying mode
2225 copyPaste_ObjectId_ = copyPaste_ActionType_ - 1;
2226 }
2227 //determine the world pos
2228 unsigned int target_idx = 0, node_idx = 0;
2229 ACG::Vec3d hit_point;
2230 if( PluginFunctions::scenegraphPick( ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point ) ) {
2231 if(copyPaste_ActionType_ == 1) {//duplicate
2232 //object being duplicated
2233 PolyLineCircleData* oldCircleData = dynamic_cast<PolyLineCircleData*>(oldObj->objectData(CIRCLE_DATA));
2234 PolyLineBezierSplineData* oldSplineData = dynamic_cast<PolyLineBezierSplineData*>(oldObj->objectData(BEZSPLINE_DATA));
2235 //newly created object
2236 PolyLineCircleData* circleData = dynamic_cast<PolyLineCircleData*>(newObj->objectData(CIRCLE_DATA));
2237 PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(newObj->objectData(BEZSPLINE_DATA));
2238
2239 if(oldCircleData) {
2240 BaseNode* node = find_node( PluginFunctions::getRootNode(), node_idx );
2241 GlutPrimitiveNode* glutNode = dynamic_cast<GlutPrimitiveNode*>(node);
2242 if(glutNode)//the hit_point is on the center handle
2243 me_GetMeshHit(_event, glutNode, hit_point, circleData->circleMeshIndex_, target_idx);
2244
2245 circleData-> circleCenter_ = hit_point;
2246 updatePolyEllipse(newObj, tool_->sb_CirclePointNum->value());
2247 updateHandles(newObj);
2248 }
2249 else if(oldSplineData) {
2250 for(int i = 0; i < (int)splineData->points_.size(); i++) {
2251 ACG::Vec3d onMeshNor, oldPos = splineData->points_[i].position;
2252 ACG::Vec3d onMesh = getPointOnMesh(splineData, copyPaste_RelativePoints_[i] + hit_point, &onMeshNor);
2253 splineData->points_[i].position = onMesh;
2254 splineData->points_[i].normal = onMeshNor;
2255 if(i) {
2256 int handleIndex = 2 * i - 1;
2257 ACG::Vec3d dir = splineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
2258 ACG::Vec3d point = forw + onMesh;
2259 splineData->handles_[handleIndex] = point;
2260 }
2261 if(i != ((int)splineData->points_.size() - 1)) {
2262 int handleIndex = 2 * i;
2263 ACG::Vec3d dir = splineData->handles_[handleIndex] - oldPos, side = dir % onMeshNor, forw = (onMeshNor % side).normalize() * dir.norm();
2264 ACG::Vec3d point = forw + onMesh;
2265 splineData->handles_[handleIndex] = point;
2266 }
2267 }
2268 GlutLineNode* lineN;
2269 if(!newObj->getAdditionalNode(lineN, name(), "line", 0))
2270 return;
2271 updatePolyBezierHandles(newObj, lineN);
2272 updatePolyBezierSpline(newObj, tool_->sb_SplineSegNum->value());
2273 }
2274 else {
2275 for(size_t i = 0; i < newObj->line()->n_vertices(); i++)
2276 newObj->line()->point(i) = hit_point + copyPaste_RelativePoints_[i];
2277 emit updatedObject(newObj->id(), UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
2278 }
2279
2280 //place the circle here and exit the copy paste state
2281 if(_event->type() == QEvent::MouseButtonPress) {
2282 copyPaste_ActionType_ = copyPaste_ObjectId_ = -1;
2283 }
2284 }
2285 else if(copyPaste_ActionType_ == 2) {//instanciate
2286
2287 }
2288 }
2289 }
2290
2291 void
2292 PolyLinePlugin::
2293 slot_duplicate()
2294 {
2295 PolyLineObject* obj;
2296 if(copyPaste_ObjectId_ == -1 || !PluginFunctions::getObject(copyPaste_ObjectId_, obj))
2297 return;
2298 //set mode for mouse move event
2299 unsigned int target_idx = 0, node_idx = 0;
2300 ACG::Vec3d hit_point;
2301 //determine the world coordinate of the mouse
2302 QPoint mPos = copyPaste_LastMouse;
2303 if( PluginFunctions::scenegraphPick( ACG::SceneGraph::PICK_ANYTHING, mPos, node_idx, target_idx, &hit_point ) ) {
2304 copyPaste_ActionType_ = 1;
2305
2306 PolyLineCircleData* circleData = dynamic_cast<PolyLineCircleData*>(obj->objectData(CIRCLE_DATA));
2307 PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(obj->objectData(BEZSPLINE_DATA));
2308
2309 //create the new object
2310 int new_line_id;
2311 emit addEmptyObject(DATA_POLY_LINE, new_line_id);
2312 BaseObjectData *newObj = 0;
2313 PluginFunctions::getObject(new_line_id, newObj);
2314 obj->target(true);
2315 PolyLineObject* newLine = PluginFunctions::polyLineObject(newObj);
2316 newLine->materialNode()->set_random_color();
2317 newLine->line()->set_vertex_radius(PluginFunctions::sceneRadius()*0.012);
2318 copyPaste_RelativePoints_.clear();
2319 if(circleData) {
2320 PolyLineCircleData* newData = new PolyLineCircleData(*circleData);//use a new instance!
2321 newLine->setObjectData(CIRCLE_DATA, newData);
2322 newLine->lineNode()->drawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
2323 createCircle_createUI(new_line_id);
2324 }
2325 else if(splineData) {
2326 PolyLineBezierSplineData* newData = new PolyLineBezierSplineData(*splineData);
2327 newLine->setObjectData(BEZSPLINE_DATA, newData);
2328 createSpline_createUI(new_line_id);
2329 newLine->lineNode()->drawMode(ACG::SceneGraph::DrawModes::WIREFRAME);
2330
2331 for(size_t i = 0; i < newData->points_.size(); i++)
2332 copyPaste_RelativePoints_.push_back(newData->points_[i].position - hit_point);
2333 }
2334 else {
2335 newLine->lineNode()->drawMode(ACG::SceneGraph::DrawModes::WIREFRAME|ACG::SceneGraph::DrawModes::POINTS_SHADED);
2336 newLine->line()->set_vertex_radius(obj->line()->vertex_radius());
2337 for(size_t i = 0; i < obj->line()->n_vertices(); i++) {
2338 newLine->line()->add_point(obj->line()->point(i));
2339 copyPaste_RelativePoints_.push_back(obj->line()->point(i) - hit_point);
2340 }
2341 }
2342 emit updatedObject(new_line_id, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
2343 copyPaste_NewObjectId_ = new_line_id;
2344 }
2345 }
2346
2347 void
2348 PolyLinePlugin::
2349 slot_instanciate()
2350 {
2351 PolyLineObject* obj;
2352 if(copyPaste_ObjectId_ == -1 || !PluginFunctions::getObject(copyPaste_ObjectId_, obj))
2353 return;
2354 copyPaste_ActionType_ = 2;
2355 //set mode for mouse move event
2356 }
2357
2358 #if QT_VERSION < 0x050000
2359 Q_EXPORT_PLUGIN2( PolyLinePlugin , PolyLinePlugin );
2360 #endif
2361
PolyLinePlugin::createSpline_CurrSelIndex_
int createSpline_CurrSelIndex_
The index of the currently created spline.
Definition: PolyLinePlugin.hh:492
PolyLinePlugin::deleteAction_
QAction * deleteAction_
Called by pick Toolbar.
Definition: PolyLinePlugin.hh:300
ACG::PolyLineT::smooth_uniform_laplace
void smooth_uniform_laplace()
Laplacian smoothing.
Definition: PolyLineT.cc:738
ACG::PolyLineT::invert
void invert()
Invert polyline that first vertex becomes last.
Definition: PolyLineT.cc:1357
PolyLinePlugin::PolyLinePlugin
PolyLinePlugin()
default constructor
Definition: PolyLinePlugin.cc:104
PolyLinePlugin::slotSetPolyLineMode
void slotSetPolyLineMode(QAction *_action)
Called by Toolbar to enable pick mode.
Definition: PolyLinePlugin.cc:2112
PolyLinePlugin::slotScissorLinesButton
void slotScissorLinesButton()
Scissor Button for multiple polylines was hit.
Definition: PolyLinePlugin.cc:467
PolyLineObject::enablePicking
void enablePicking(bool _enable)
Enable or disable picking for this Object.
Definition: PolyLineObject.cc:265
ACG::PolyLineT::n_vertices
size_t n_vertices() const
Get number of vertices.
Definition: PolyLineT.hh:122
PluginFunctions::viewerProperties
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
Definition: PluginFunctions.cc:613
PolyLinePlugin::createCircle_LastSelIndex_
int createCircle_LastSelIndex_
Use this one to mark the last index to update the number of points.
Definition: PolyLinePlugin.hh:373
MeshObject::mesh
MeshT * mesh()
return a pointer to the mesh
Definition: MeshObjectT.cc:351
ACG
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
ACG::PolyLineT::smooth_uniform_laplace3
void smooth_uniform_laplace3()
Cubic laplacian smoothing.
Definition: PolyLineT.cc:849
ACG::SceneGraph::BaseNode
Definition: BaseNode.hh:135
UPDATE_GEOMETRY
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
ACG::SceneGraph::ACG::SceneGraph::BaseNode::name
std::string name() const
Returns: name of node (needs not be unique)
Definition: MeshNode2T.cc:391
PolyLinePlugin::generatePolyLineFromCut
int generatePolyLineFromCut(int _objectId, Vector _planePoint, Vector _planeNormal, int _polyLineId=-1)
Generates a polyLine of a plane intersection.
Definition: PolyLineScripting.cc:55
BaseObject::objectData
PerObjectData * objectData(QString _dataName)
Returns the object data pointer.
Definition: BaseObject.cc:814
DATA_POLY_LINE
#define DATA_POLY_LINE
Definition: PolyLine.hh:70
BaseObjectData
Definition: BaseObjectData.hh:105
BaseObject::name
QString name() const
return the name of the object. The name defaults to NONAME if unset.
Definition: BaseObject.cc:741
ACG::SceneGraph::PICK_FACE
picks faces (should be implemented for all nodes)
Definition: BaseNode.hh:104
ACG::SceneGraph::PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
PluginFunctions::polyLineObject
PolyLineObject * polyLineObject(BaseObjectData *_object)
Cast an BaseObject to a PolyLineObject if possible.
Definition: PluginFunctionsPolyLine.cc:142
UpdateType
Update type class.
Definition: UpdateType.hh:70
TriMeshObject
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:73
PluginFunctions::viewingDirection
void viewingDirection(const ACG::Vec3d &_dir, const ACG::Vec3d &_up, int _viewer)
Set the viewing direction.
Definition: PluginFunctions.cc:691
BaseObjectData::getAdditionalNode
bool getAdditionalNode(NodeT *&_node, QString _pluginName, QString _nodeName, int _id=0)
get an addition node from the object
Definition: BaseObjectDataT.cc:91
PolyLinePlugin::updatePolyEllipse
void updatePolyEllipse(PolyLineObject *_lineObject, unsigned int _pointCount)
Generates points for the ellipse.
Definition: PolyLinePlugin_Circle.cc:138
UPDATE_ALL
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
PolyLinePlugin::polyLineAction_
QAction * polyLineAction_
Called by Toolbar to enable pick mode.
Definition: PolyLinePlugin.hh:276
ACG::SceneGraph::MaterialNode::set_random_color
void set_random_color()
Generates a random color and sets it.
Definition: MaterialNode.hh:399
PluginFunctions::getObject
bool getObject(int _identifier, BSplineCurveObject *&_object)
Definition: PluginFunctionsBSplineCurve.cc:75
PolyLinePlugin::updatePolyBezierHandles
void updatePolyBezierHandles(PolyLineObject *_lineObject, ACG::SceneGraph::LineNode *_line)
Updates all the handles on the PolyBezier.
Definition: PolyLinePlugin_BezierSpline.cc:82
ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition: DrawModes.cc:87
ACG::PolyLineT::project_to_mesh
void project_to_mesh(const MeshT &_mesh, SpatialSearchT *_ssearch=0)
Project polyline points to nearest surface points (use spatial search!!!)
Definition: PolyLineT.cc:937
BaseObjectData::materialNode
MaterialNode * materialNode()
get a pointer to the materialnode
Definition: BaseObjectData.cc:269
PolyLinePlugin::cutMultipleAction_
QAction * cutMultipleAction_
Called by pick Toolbar.
Definition: PolyLinePlugin.hh:306
ACG::Vec4f
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:144
MeshObject::requestTriangleBsp
OMTriangleBSP * requestTriangleBsp()
Definition: MeshObjectT.cc:756
ACG::Vec3d
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
PolyLinePlugin::splitAction_
QAction * splitAction_
Called by pick Toolbar.
Definition: PolyLinePlugin.hh:304
ACG::PolyLineT::is_closed
bool is_closed() const
Check if the polyline is marked as closed.
Definition: PolyLineT.hh:113
PolyLinePlugin::toolBarActions_
QActionGroup * toolBarActions_
Called by Toolbar to enable pick mode.
Definition: PolyLinePlugin.hh:277
ACG::PolyLineT::set_vertex_radius
void set_vertex_radius(const Scalar _r)
set ball-radius of vertices
Definition: PolyLineT.hh:351
ACG::SceneGraph::GlutPrimitiveNode::get_position
const Vec3d get_position(int _idx=0) const
get position
Definition: GlutPrimitiveNode.cc:116
PolyLineObject
Definition: PolyLineObject.hh:82
PolyLinePlugin::slotPickToolbarAction
void slotPickToolbarAction(QAction *_action)
Called by pick Toolbar.
Definition: PolyLinePlugin.cc:2090
PolyLinePlugin::EditMode
EditMode
Edit Mode of PolyLinePlugin.
Definition: PolyLinePlugin.hh:191
PluginFunctions::TARGET_OBJECTS
const QStringList TARGET_OBJECTS("target")
Iterable object range.
PolyLineCircleData
Definition: PolyLineCircleData.hh:58
BaseObject::dataType
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
ACG::PolyLineT::delete_point
void delete_point(int _idx)
Delete point at _idx.
Definition: PolyLineT.cc:417
PolyLinePlugin::pickToolbar_
QToolBar * pickToolbar_
Called by pick Toolbar.
Definition: PolyLinePlugin.hh:294
ACG::SceneGraph::PICK_VERTEX
picks verices (may not be implemented for all nodes)
Definition: BaseNode.hh:108
PolyLineBezierSplineData::addInterpolatePoint
void addInterpolatePoint(ACG::Vec3d _position, ACG::Vec3d _normal)
Adds a point to the end of the list and inserts control points.
Definition: PolyLineBezierSplineData.cc:66
PolyLinePlugin::insertCircleAction_
QAction * insertCircleAction_
Called by pick Toolbar.
Definition: PolyLinePlugin.hh:298
MeshObject::boundingBox
void boundingBox(ACG::Vec3d &_bbMin, typename ACG::Vec3d &_bbMax)
Get the BoundingBox of this object.
Definition: MeshObjectT.cc:637
LOGWARN
Definition: LoggingInterface.hh:106
ACG::PolyLineT::smooth_uniform_laplace2
void smooth_uniform_laplace2()
Squared laplacian smoothing.
Definition: PolyLineT.cc:792
PluginFunctions::triMesh
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
Definition: PluginFunctionsTriangleMesh.cc:140
PolyLinePlugin::mergeAction_
QAction * mergeAction_
Called by pick Toolbar.
Definition: PolyLinePlugin.hh:303
ACG::PolyLineT::subdivide
void subdivide(Scalar _largest)
Subdivide polyline.
Definition: PolyLineT.cc:619
PolyLinePlugin::updateHandles
void updateHandles(PolyLineObject *_lineObject)
Updates the center, forward and side handle of the Poly ellipse.
Definition: PolyLinePlugin.cc:2047
PluginFunctions::pickMode
const std::string pickMode()
Get the current Picking mode.
Definition: PluginFunctions.cc:579
PolyLinePlugin::insertAction_
QAction * insertAction_
Called by pick Toolbar.
Definition: PolyLinePlugin.hh:297
PolyLineBezierSplineData::getInterpolatePoint
InterpolatePoint & getInterpolatePoint(unsigned int _handleIndex)
Retrieves the interpolate point based on the handle.
Definition: PolyLineBezierSplineData.cc:111
ACG::PolyLineT::points
std::vector< Point > & points()
Get all points of the polyline.
Definition: PolyLineT.hh:154
BaseObject::setObjectData
void setObjectData(QString _dataName, PerObjectData *_data)
Definition: BaseObject.cc:792
PluginFunctions::ObjectIterator
Core Data Iterator.
Definition: PluginFunctions.hh:452
PluginFunctions::objectsEnd
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
Definition: PluginFunctionsIterator.cc:187
BaseObject::childExists
BaseObject * childExists(int _objectId)
Check if the element exists in the subtree of this element.
Definition: BaseObject.cc:527
PluginFunctions::objectRoot
BaseObject *& objectRoot()
Get the root of the object structure.
Definition: PluginFunctions.cc:1103
ACG::PolyLineT::split
void split(unsigned int _split_idx, PolyLineT< PointT > &_new_pl)
Split closed polyline at vertex with index _split_idx.
Definition: PolyLineT.cc:1463
PolyLineBezierSplineData
Definition: PolyLineBezierSplineData.hh:59
OpenMesh::VectorT
Definition: Vector11T.hh:83
PolyLinePlugin::updatePolyBezierSpline
void updatePolyBezierSpline(PolyLineObject *_lineObject, unsigned int _pointsPerSegment)
Generates points for the spline, updates handles.
Definition: PolyLinePlugin_BezierSpline.cc:105
PluginFunctions::getRootNode
ACG::SceneGraph::BaseNode * getRootNode()
Get the root node for data objects.
Definition: PluginFunctions.cc:965
ACG::PolyLineT::resize
void resize(unsigned int _n)
Resize current polyline.
Definition: PolyLineT.cc:231
PolyLinePlugin::slotTriggerCutPlaneSelect
void slotTriggerCutPlaneSelect()
Generate PolyLine after the cutPlane has been drawn.
Definition: PolyLinePlugin.cc:478
DATA_POLY_MESH
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
PolyLinePlugin::moveAction_
QAction * moveAction_
Called by pick Toolbar.
Definition: PolyLinePlugin.hh:301
PolyLineBezierSplineData::finishSpline
bool finishSpline()
If possible calculates handles.
Definition: PolyLineBezierSplineData.cc:75
ACG::PolyLineT::set_closed
void set_closed(const bool _c)
Set if the polyline should be closed and therefore forms a loop.
Definition: PolyLineT.hh:119
ACG::PolyLineT::length
Scalar length() const
Compute the length of the polyline (in future cached method)
Definition: PolyLineT.cc:484
PolyLineBezierSplineData::InterpolatePoint
Definition: PolyLineBezierSplineData.hh:64
PolyLinePlugin::moveBezSpline_SelNode_
ACG::SceneGraph::GlutPrimitiveNode * moveBezSpline_SelNode_
The handle which is being dragged.
Definition: PolyLinePlugin.hh:497
PluginFunctions::sceneRadius
double sceneRadius()
Returns the current scene radius from the active examiner widget.
Definition: PluginFunctions.cc:796
ACG::PolyLineT::vertex_radius
Scalar vertex_radius() const
get ball-radius of vertices
Definition: PolyLineT.hh:348
PluginFunctions::triMeshObject
TriMeshObject * triMeshObject(BaseObjectData *_object)
Cast an BaseObject to a TriMeshObject if possible.
Definition: PluginFunctionsTriangleMesh.cc:162
UPDATE_TOPOLOGY
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(1)<< 3)
Topology updated.
ACG::SceneGraph::DrawModes::POINTS_SHADED
DrawMode POINTS_SHADED
draw shaded points (requires point normals)
Definition: DrawModes.cc:81
PolyLinePlugin::generatePolyLinesFromCut
IdList generatePolyLinesFromCut(int _objectId, Vector _planePoint, Vector _planeNormal)
Generates a polyLine of a plane intersection.
Definition: PolyLineScripting.cc:163
ACG::GLState::get_viewport
void get_viewport(int &_left, int &_bottom, int &_width, int &_height) const
get viewport
Definition: GLState.hh:819
OpenMeshTriangleBSPT
Definition: TriangleBSPT.hh:206
PolyLinePlugin::createCircle_getHit
ACG::Vec3d createCircle_getHit(PolyLineCircleData *_circleData, ACG::Vec3d _hit_point)
Returns point on mesh or point on the normal plane.
Definition: PolyLinePlugin_Circle.cc:127
PolyLinePlugin::insertSplineAction_
QAction * insertSplineAction_
Called by pick Toolbar.
Definition: PolyLinePlugin.hh:299
ACG::SceneGraph::DrawModes::WIREFRAME
DrawMode WIREFRAME
draw wireframe
Definition: DrawModes.cc:84
PolyLinePlugin::planeSelect_
QtPlaneSelect * planeSelect_
Plane selection tool.
Definition: PolyLinePlugin.hh:510
PolyLinePlugin::createCircle_CurrSelIndex_
int createCircle_CurrSelIndex_
The object which is being modified(created, dragged)
Definition: PolyLinePlugin.hh:371
CONTEXTOBJECTMENU
The Menu will be shown when an object was picked.
Definition: ContextMenuInterface.hh:75
QtPlaneSelect
Definition: QtPlaneSelect.hh:67
ACG::PolyLineT::split_closed
void split_closed(unsigned int _split_idx)
Split closed polyline at vertex with index _split_idx.
Definition: PolyLineT.cc:1431
ACG::PolyLineT::add_point
void add_point(const Point &_p)
Append a point to the polyline.
Definition: PolyLineT.cc:288
PolyLinePlugin::moveBezSpline_SelIndex_
int moveBezSpline_SelIndex_
The object which is being moved.
Definition: PolyLinePlugin.hh:499
PolyLinePlugin
Definition: PolyLinePlugin.hh:101
ACG::SceneGraph::LineNode
Definition: LineNode.hh:90
ACG::PolyLineT::point
Point & point(unsigned int _i)
Get a point of the polyline.
Definition: PolyLineT.hh:148
PluginFunctions::scenegraphPick
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, unsigned int &_nodeIdx, unsigned int &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
Definition: PluginFunctions.cc:482
PolyLineObject::lineNode
ACG::SceneGraph::PolyLineNodeT< PolyLine > * lineNode()
Get the scenegraph Node.
Definition: PolyLineObject.cc:218
PolyLinePlugin::slotScissorButton
void slotScissorButton()
Scissor Button was hit.
Definition: PolyLinePlugin.cc:456
PolyLinePlugin::cutAction_
QAction * cutAction_
Called by pick Toolbar.
Definition: PolyLinePlugin.hh:305
BaseObjectData::addAdditionalNode
bool addAdditionalNode(NodeT *_node, QString _pluginName, QString _nodeName, int _id=0)
add an additional node to the object
Definition: BaseObjectDataT.cc:74
PolyLineToolbarWidget
Definition: PolyLineToolbarWidget.hh:51
DataType
Predefined datatypes.
Definition: DataTypes.hh:96
PluginFunctions::actionMode
Viewer::ActionMode actionMode()
Get the current Action mode.
Definition: PluginFunctions.cc:590
PolyLinePlugin::tool_
PolyLineToolbarWidget * tool_
Widget for Toolbox.
Definition: PolyLinePlugin.hh:266
ACG::SceneGraph::GlutPrimitiveNode::set_position
void set_position(const Vec3d &_p, int _idx=0)
set position
Definition: GlutPrimitiveNode.cc:106
BaseObjectData::setObjectDrawMode
void setObjectDrawMode(const ACG::SceneGraph::DrawModes::DrawMode &_mode, const bool &_force=false)
Set the draw mode for the object.
Definition: BaseObjectData.cc:300
PolyLineObject::line
PolyLine * line()
return a pointer to the line
Definition: PolyLineObject.cc:205
PolyLinePlugin::pickToolBarActions_
QActionGroup * pickToolBarActions_
Called by pick Toolbar.
Definition: PolyLinePlugin.hh:295
ACG::PolyLineT::back
Point & back()
Get last point of the polyline ( no range check!!!)
Definition: PolyLineT.hh:166
ACG::PolyLineT::append
void append(const PolyLineT< PointT > &_pl)
Append second polyline _pl to this one.
Definition: PolyLineT.cc:1387
Viewer::ViewerProperties::glState
ACG::GLState & glState()
Get the glState of the Viewer.
Definition: ViewerProperties.cc:329
PluginFunctions::getPickedObject
bool getPickedObject(const unsigned int _node_idx, BaseObjectData *&_object)
Get the picked mesh.
Definition: PluginFunctions.cc:263
PolyLinePlugin::createSpline_LastSelIndex_
int createSpline_LastSelIndex_
Use this one to mark the last index to update the number of points.
Definition: PolyLinePlugin.hh:494
BaseObject::target
bool target()
Definition: BaseObject.cc:284
DATA_TRIANGLE_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
PolyLinePlugin::toolbar_
QToolBar * toolbar_
Called by Toolbar to enable pick mode.
Definition: PolyLinePlugin.hh:279
PolyLinePlugin::getPointOnMesh
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.
Definition: PolyLinePlugin_BezierSpline.cc:63
PolyLinePlugin::moveCircle_LastHitPos_
ACG::Vec3d moveCircle_LastHitPos_
The last valid hit on the mesh.
Definition: PolyLinePlugin.hh:377
ACG::PolyLineT::collapse
void collapse(Scalar _smallest)
Collapse polyline.
Definition: PolyLineT.cc:672
ACG::GLState::viewing_ray
void viewing_ray(int _x, int _y, Vec3d &_origin, Vec3d &_direction) const
Definition: GLState.cc:926
PolyLinePlugin::name
QString name()
Name of the Plugin.
Definition: PolyLinePlugin.hh:209
ACG::SceneGraph::ACG::SceneGraph::BaseNode::enablePicking
void enablePicking(bool _enable)
Definition: MeshNode2T.cc:241
PolyLinePlugin::moveBezSpline_SelSubIndex_
int moveBezSpline_SelSubIndex_
The index of the control or handle being moved.
Definition: PolyLinePlugin.hh:501
PolyLineBezierSplineData::meshIndex_
unsigned int meshIndex_
Index of the corresponding mesh.
Definition: PolyLineBezierSplineData.hh:72
BaseObject::id
int id() const
Definition: BaseObject.cc:201
ACG::SceneGraph::GlutPrimitiveNode
Definition: GlutPrimitiveNode.hh:88
PolyLinePlugin::smartMoveAction_
QAction * smartMoveAction_
Called by pick Toolbar.
Definition: PolyLinePlugin.hh:302