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