Developer Documentation

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