PolyLinePlugin.cc 50.4 KB
Newer Older
Jan Möbius's avatar
 
Jan Möbius committed
1 2 3 4 5 6 7 8 9
//=============================================================================
//
//  CLASS PolyLinePlugin - IMPLEMENTATION
//
//=============================================================================


//== INCLUDES =================================================================

Matthias Möller's avatar
Matthias Möller committed
10 11 12 13 14 15 16

#if QT_VERSION >= 0x050000 
  #include <QtWidgets>
#else
  #include <QtGui>
#endif

Jan Möbius's avatar
 
Jan Möbius committed
17 18 19 20 21 22 23 24 25 26 27 28

#include "PolyLinePlugin.hh"

#include <iostream>
#include <ACG/GL/GLState.hh>
#include <QStringList>
#include <ACG/Scenegraph/ManipulatorNode.hh>

#include <OpenFlipper/BasePlugin/PluginFunctions.hh>

#include <OpenFlipper/common/GlobalOptions.hh>

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
#include <ACG/Geometry/bsp/BSPImplT.hh>

namespace {

class GlutObjectNode : public ACG::SceneGraph::GlutPrimitiveNode{
	public:
		GlutObjectNode(PolyLineObject* L, BaseNode* M, std::string name)
			: ACG::SceneGraph::GlutPrimitiveNode(ACG::SceneGraph::GlutPrimitiveNode::SPHERE, M, name)
		{
			line = L;
		}
	public:
		PolyLineObject* line;
};


}

Jan Möbius's avatar
 
Jan Möbius committed
47 48 49 50 51 52 53 54 55 56 57 58

//== IMPLEMENTATION ==========================================================

/// default constructor
PolyLinePlugin::PolyLinePlugin() :
        tool_(0),
        polyLineAction_(0),
        toolBarActions_(0),
        toolbar_(0),
        pickToolbar_(0),
        pickToolBarActions_(0),
        insertAction_(0),
59
        insertCircleAction_(0),
Jan Möbius's avatar
 
Jan Möbius committed
60 61 62 63 64 65 66 67 68 69
        deleteAction_(0),
        moveAction_(0),
        smartMoveAction_(0),
        mergeAction_(0),
        splitAction_(0),
        cutAction_(0),
        cur_insert_id_(-1),
        cur_polyline_obj_(0),
        cur_move_id_(-1),
        move_point_ref_(0),
70
        create_point_ref_(0),
71 72
        createCircle_CurrSelIndex_(-1),
        moveCircle_SelNode_(0),
Jan Möbius's avatar
 
Jan Möbius committed
73 74 75
        cur_merge_id_(-1),
        smart_move_timer_(0),
        cur_smart_move_obj_(0),
76
        planeSelect_(0)
Jan Möbius's avatar
 
Jan Möbius committed
77 78 79 80 81 82 83 84
{
}


void
PolyLinePlugin::
initializePlugin()
{
Jan Möbius's avatar
Jan Möbius committed
85
  // Initialize the Toolbox
Jan Möbius's avatar
 
Jan Möbius committed
86 87 88
  tool_ = new PolyLineToolbarWidget();
  QSize size(100, 100);
  tool_->resize(size);
Jan Möbius's avatar
Jan Möbius committed
89
  tool_->setObjectName("PolyLineToolbar");
Jan Möbius's avatar
 
Jan Möbius committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108

  // connect signals->slots
  connect(tool_->pb_subdivide,SIGNAL(clicked() ),this,SLOT(slot_subdivide()));
  connect(tool_->subdivide_relative,SIGNAL(toggled(bool) ),this,SLOT(slot_subdivide_percent(bool)));
  connect(tool_->pb_decimate,SIGNAL(clicked() ),this,SLOT(slot_decimate()));
  connect(tool_->decimate_relative,SIGNAL(toggled(bool) ),this,SLOT(slot_decimate_percent(bool)));
#ifdef EXTENDED_POLY_LINE
  connect(tool_->pb_resample_on_edges,SIGNAL(clicked() ),this,SLOT(slot_resample_on_edges()));
#else
  tool_->pb_resample_on_edges->setDisabled(true);
#endif
  connect(tool_->pb_smooth,SIGNAL(clicked() ),this,SLOT(slot_smooth()));
  connect(tool_->pb_smooth,SIGNAL(clicked() ),this,SIGNAL(updateView()));
  connect(tool_->pb_project,SIGNAL(clicked() ),this,SLOT(slot_project()));
  connect(tool_->pb_project,SIGNAL(clicked() ),this,SIGNAL(updateView()));
  connect(tool_->pb_smooth_project,SIGNAL(clicked() ),this,SLOT(slot_smooth_project()));
  connect(tool_->pb_smooth_project,SIGNAL(clicked() ),this,SIGNAL(updateView()));

  connect(tool_->rb_insert, SIGNAL( clicked() ), this, SLOT( slotEditModeChanged() ));
109
  connect(tool_->rb_InsertCircle, SIGNAL( clicked() ), this, SLOT( slotEditModeChanged() ));
Jan Möbius's avatar
 
Jan Möbius committed
110 111 112 113 114 115
  connect(tool_->rb_delete, SIGNAL( clicked() ), this, SLOT( slotEditModeChanged() ));
  connect(tool_->rb_move,   SIGNAL( clicked() ), this, SLOT( slotEditModeChanged() ));
  connect(tool_->rb_smart_move, SIGNAL( clicked() ), this, SLOT( slotEditModeChanged() ));
  connect(tool_->rb_merge,  SIGNAL( clicked() ), this, SLOT( slotEditModeChanged() ));
  connect(tool_->rb_split,  SIGNAL( clicked() ), this, SLOT( slotEditModeChanged() ));

116 117
  connect(tool_->sb_CirclePointNum, SIGNAL(valueChanged(int)), this, SLOT(slot_setCirclePointNum(int)));

Jan Möbius's avatar
 
Jan Möbius committed
118 119
  //add icons
  tool_->rb_insert->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_insert.png") );
120
  tool_->rb_InsertCircle->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_circle.png") );
Jan Möbius's avatar
 
Jan Möbius committed
121 122 123 124 125 126 127 128
  tool_->rb_delete->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_delete.png") );
  tool_->rb_move->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_move.png") );
  tool_->rb_smart_move->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_move.png") );
  tool_->rb_merge->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_merge.png") );
  tool_->rb_split->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_split.png") );
//   tool_->rb_smooth_c0->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_insert.svg") );
//   tool_->rb_smooth_c1->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_c1.svg") );
//   tool_->rb_smooth_c2->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "polyline_c2.svg") );
129 130 131 132 133


  // Add the toolbox with the given icon
  QIcon* toolIcon = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"cut_polyline.png");
  emit addToolbox( tr("PolyLine") , tool_, toolIcon );
Jan Möbius's avatar
 
Jan Möbius committed
134 135 136 137 138 139 140 141 142 143 144
}


//-----------------------------------------------------------------------------


void
PolyLinePlugin::
slotMouseEvent( QMouseEvent* _event )
{
  // control modifier is reserved for selcting target
Jan Möbius's avatar
Jan Möbius committed
145
  if (_event->modifiers() & (Qt::ControlModifier))
Jan Möbius's avatar
 
Jan Möbius committed
146 147
    return;

Jan Möbius's avatar
Jan Möbius committed
148 149
  if (PluginFunctions::pickMode() == ("PolyLine") && PluginFunctions::actionMode() == Viewer::PickingMode
      && _event->button() != Qt::RightButton) {
Jan Möbius's avatar
 
Jan Möbius committed
150
    // handle mouse events depending on current mode
Jan Möbius's avatar
Jan Möbius committed
151
    switch (mode()) {
Jan Möbius's avatar
 
Jan Möbius committed
152
      case PL_INSERT:
Jan Möbius's avatar
Jan Möbius committed
153 154
        me_insert(_event);
        break;
Jan Möbius's avatar
 
Jan Möbius committed
155

156 157 158 159
      case PL_INSERTCIRCLE:
        me_insertCircle(_event);
        break;

Jan Möbius's avatar
 
Jan Möbius committed
160
      case PL_DELETE:
Jan Möbius's avatar
Jan Möbius committed
161 162
        me_delete(_event);
        break;
Jan Möbius's avatar
 
Jan Möbius committed
163 164

      case PL_MOVE:
Jan Möbius's avatar
Jan Möbius committed
165 166
        me_move(_event);
        break;
Jan Möbius's avatar
 
Jan Möbius committed
167 168

      case PL_SPLIT:
Jan Möbius's avatar
Jan Möbius committed
169 170
        me_split(_event);
        break;
Jan Möbius's avatar
 
Jan Möbius committed
171 172

      case PL_MERGE:
Jan Möbius's avatar
Jan Möbius committed
173 174
        me_merge(_event);
        break;
Jan Möbius's avatar
 
Jan Möbius committed
175 176

      case PL_SMART_MOVE:
Jan Möbius's avatar
Jan Möbius committed
177 178
        me_smart_move(_event);
        break;
Jan Möbius's avatar
 
Jan Möbius committed
179 180

      default:
Jan Möbius's avatar
Jan Möbius committed
181
        break;
Jan Möbius's avatar
 
Jan Möbius committed
182
    }
Jan Möbius's avatar
Jan Möbius committed
183 184
  } else if (PluginFunctions::pickMode() == CREATE_CUT_POLYLINE) {
    planeSelect_->slotMouseEvent(_event);
Jan Möbius's avatar
 
Jan Möbius committed
185 186 187
  }
}

188
void PolyLinePlugin::slotKeyEvent(QKeyEvent* event) {
189
    if (!cur_polyline_obj_ || cur_insert_id_ == -1) return;
190 191 192
    switch (event->key()) {
        case Qt::Key_Return:
            if (PluginFunctions::pickMode() == ("PolyLine") && PluginFunctions::actionMode() == Viewer::PickingMode && mode() == PL_INSERT) {
Jan Möbius's avatar
 
Jan Möbius committed
193

194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
                cur_polyline_obj_->line()->delete_point(cur_polyline_obj_->line()->n_vertices() - 1);

                if (event->modifiers() & (Qt::ShiftModifier))
                  cur_polyline_obj_->line()->set_closed(true);

                emit updatedObject(cur_insert_id_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);

                cur_insert_id_ = -1;
                cur_polyline_obj_ = 0;
                create_point_ref_ = 0;

                clearStatusMessage();
            }
            break;
        default:
            break;
    }
}
Jan Möbius's avatar
 
Jan Möbius committed
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
//-----------------------------------------------------------------------------

void
PolyLinePlugin::
slotPickModeChanged( const std::string& _mode)
{
  polyLineAction_->setChecked(_mode == "PolyLine");
  cutAction_->setChecked( _mode == CREATE_CUT_POLYLINE );
}


//-----------------------------------------------------------------------------


void
PolyLinePlugin::
pluginsInitialized()
{
Jan Möbius's avatar
Jan Möbius committed
230 231
  // Add the required Picking modes (Hidden, controlled only by the buttons)
  emit addHiddenPickMode("PolyLine");
232
  emit setPickModeMouseTracking("PolyLine", true);
Jan Möbius's avatar
Jan Möbius committed
233
  emit addHiddenPickMode( CREATE_CUT_POLYLINE );
234 235 236

  emit registerKey(Qt::Key_Return, Qt::NoModifier, tr("Terminate creation of poly line."), true);
  emit registerKey(Qt::Key_Return, Qt::ShiftModifier, tr("Terminate creation of poly line and create loop."), true);
Jan Möbius's avatar
 
Jan Möbius committed
237
  
Jan Möbius's avatar
Jan Möbius committed
238
  // TOOLBAR
Jan Möbius's avatar
 
Jan Möbius committed
239
  toolbar_ = new QToolBar(tr("PolyLine Editing"));
Jan Möbius's avatar
Jan Möbius committed
240 241
  toolbar_->setObjectName("PolyLineEditingToolbar");

Jan Möbius's avatar
 
Jan Möbius committed
242 243 244
  
  toolBarActions_ = new QActionGroup(toolbar_);
  
Jan Möbius's avatar
Jan Möbius committed
245
  // icon which enables the Modeling toolbar
Jan Möbius's avatar
 
Jan Möbius committed
246 247 248 249 250 251
  polyLineAction_ = new QAction(tr("Edit PolyLines"), toolBarActions_);
  polyLineAction_->setStatusTip(tr("Edit and create PolyLines."));
  polyLineAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"polyline_insert.png") );
  polyLineAction_->setCheckable(true);
  toolbar_->addAction(polyLineAction_);
  
Jan Möbius's avatar
Jan Möbius committed
252
  // icon for polyline cutting of objects
Jan Möbius's avatar
 
Jan Möbius committed
253 254 255 256 257 258 259 260 261 262 263 264 265
  cutAction_ = new QAction(tr("&Create polyline at intersection with plane"), this);
  cutAction_->setCheckable( true );
  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."));
  cutAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"cut_polyline.png") );
  connect(cutAction_, SIGNAL(triggered()), this, SLOT(slotScissorButton()) );
  toolbar_->addAction(cutAction_);
  
  connect(toolBarActions_, SIGNAL(triggered(QAction*)), this, SLOT(slotSetPolyLineMode(QAction*)) );
  
  emit addToolbar(toolbar_);
  
  // Pick Toolbar
  pickToolbar_ = new QToolBar(tr("PolyLine Editing"));
Jan Möbius's avatar
Jan Möbius committed
266
  pickToolbar_->setObjectName("PolyLine_Editing_Toolbar");
Jan Möbius's avatar
 
Jan Möbius committed
267 268 269 270 271 272 273 274 275 276 277 278 279
  pickToolbar_->setAttribute(Qt::WA_AlwaysShowToolTips, true);
  pickToolBarActions_ = new QActionGroup(pickToolbar_);
  pickToolBarActions_->setExclusive (true);
  
  insertAction_ = new QAction(tr("Create PolyLine"), pickToolBarActions_);
  insertAction_->setStatusTip(tr("Create a new PolyLine."));
  insertAction_->setToolTip(tr("Create a new PolyLine.\n"
                               "Use <Doubleclick> to finish the line.\n"
                               "Hold <Shift> to close line on finish."));
  insertAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"polyline_insert.png") );
  insertAction_->setCheckable(true);
  pickToolbar_->addAction(insertAction_);
  
280 281 282 283 284 285 286 287 288 289
  insertCircleAction_ = new QAction(tr("Create PolyCircle"), pickToolBarActions_);
  insertCircleAction_->setStatusTip(tr("Create a new PolyCircle."));
  insertCircleAction_->setToolTip(tr("Create a new PolyCircle.\n"
		  	  	  	  	  	  	  	 "<Click> to select the center.\n"
		  	  	  	  	  	  	  	 "Drag to specify the radius."));

  insertCircleAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"polyline_circle.png") );
  insertCircleAction_->setCheckable(true);
  pickToolbar_->addAction(insertCircleAction_);

Jan Möbius's avatar
 
Jan Möbius committed
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
  deleteAction_ = new QAction(tr("Delete PolyLine"), pickToolBarActions_);
  deleteAction_->setStatusTip(tr("Delete a complete PolyLine."));
  deleteAction_->setToolTip(tr( "Delete a complete PolyLine.\n"
                                "<Click> on the lines you want to delete."));
  deleteAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"polyline_delete.png") );
  deleteAction_->setCheckable(true);
  pickToolbar_->addAction(deleteAction_);  

  smartMoveAction_ = new QAction(tr("Move PolyLine"), pickToolBarActions_);
  smartMoveAction_->setStatusTip(tr("Move the PolyLine."));
  smartMoveAction_->setToolTip(tr("Move the polyline."));
  smartMoveAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"polyline_move.png") );
  smartMoveAction_->setCheckable(true);
  pickToolbar_->addAction(smartMoveAction_);
  
  mergeAction_ = new QAction(tr("Merge PolyLines"), pickToolBarActions_);
  mergeAction_->setStatusTip(tr("Merge two PolyLines."));
  mergeAction_->setToolTip(tr("Merge two PolyLines.\n"
                              "Drag one endpoint of a PolyLine to the EndPoint of another one.\n"));
  mergeAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"polyline_merge.png") );
  mergeAction_->setCheckable(true);
  pickToolbar_->addAction(mergeAction_);  
  
  splitAction_ = new QAction(tr("Split a PolyLine"), pickToolBarActions_);
  splitAction_->setStatusTip(tr("Split a PolyLine at a given point."));
  splitAction_->setToolTip(tr("Split a PolyLine at a given point.\n"
                              "<Click> on the vertex where you want to split the PolyLine and drag it away."));
  splitAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"polyline_split.png") );
  splitAction_->setCheckable(true);
  pickToolbar_->addAction(splitAction_);  
  
  pickToolbar_->addSeparator ();
  
  moveAction_ = new QAction(tr("Move PolyLine Vertex"), pickToolBarActions_);
  moveAction_->setStatusTip(tr("Move a Vertex of a PolyLine"));
  moveAction_->setToolTip(tr("Move a single Vertex of a PolyLine."));
  moveAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"polyline_move.png") );
  moveAction_->setCheckable(true);
  pickToolbar_->addAction(moveAction_);
  
  emit setPickModeToolbar ("PolyLine", pickToolbar_);
  
  connect(pickToolBarActions_, SIGNAL(triggered(QAction*)), this, SLOT(slotPickToolbarAction(QAction*)) );

  // construct timer
  smart_move_timer_ = new QTimer(this);
  connect(smart_move_timer_, SIGNAL(timeout()), this, SLOT(slot_smart_move_timer()));
  
Jan Möbius's avatar
Jan Möbius committed
338
  // Instantiate plane select object
Jan Möbius's avatar
 
Jan Möbius committed
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
  planeSelect_ = new QtPlaneSelect( PluginFunctions::viewerProperties().glState() );
  connect( planeSelect_, SIGNAL( signalTriggerCut( ) ), this, SLOT( slotTriggerCutPlaneSelect() ) );
  connect( planeSelect_, SIGNAL( updateViewProxy( ) ), this, SIGNAL( updateView() ) );
}

//------------------------------------------------------------------------------

/** \brief Scissor Button was hit
*
*/
void PolyLinePlugin::slotScissorButton( )
{
    PluginFunctions::actionMode( Viewer::PickingMode );
    PluginFunctions::pickMode( CREATE_CUT_POLYLINE );
}

//-----------------------------------------------------------------------------

/** \brief Generate PolyLine after the cutPlane has been drawn
*
*/
void PolyLinePlugin::slotTriggerCutPlaneSelect( )
{
    using ACG::SceneGraph::LineNode;
Jan Möbius's avatar
Jan Möbius committed
363 364 365 366 367 368 369 370 371

  // Iterate over all selected objects
  BaseObjectData* object;
  if (PluginFunctions::getPickedObject(planeSelect_->getNode(), object)) {
    emit log("Cutting object " + object->name());

    if (!(object->dataType(DATA_TRIANGLE_MESH) || object->dataType(DATA_POLY_MESH))) {
      emit log("Only Meshes are supported at the moment ");
      return;
Jan Möbius's avatar
 
Jan Möbius committed
372
    }
Jan Möbius's avatar
Jan Möbius committed
373 374 375 376

    ACG::Vec3d point = planeSelect_->getSourcePoint();
    ACG::Vec3d normal = planeSelect_->getNormal();

377
    int objectId = generatePolyLineFromCut(object->id(), point, normal);
Jan Möbius's avatar
Jan Möbius committed
378 379 380 381 382 383 384 385

    QString command = "generatePolyLineFromCut(" + QString::number(object->id()) + ",Vector("
        + QString::number(point[0]) + "," + QString::number(point[1]) + "," + QString::number(point[2]) + "),Vector("
        + QString::number(normal[0]) + "," + QString::number(normal[1]) + "," + QString::number(normal[2]) + "));";
    emit scriptInfo(command);

    //remove all other targets
    for (PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,
386
         DataType(DATA_TRIANGLE_MESH | DATA_POLY_MESH)); o_it != PluginFunctions::objectsEnd(); ++o_it) {
Jan Möbius's avatar
Jan Möbius committed
387 388 389
      if (o_it->id() != object->id()) {
        o_it->target(false);
      }
390 391 392 393 394 395
    }

    // If we successfully created the polyline, we can inform the core about it.
    if ( objectId != -1)
      emit updatedObject(objectId,UPDATE_ALL);

Jan Möbius's avatar
Jan Möbius committed
396 397
  }

Jan Möbius's avatar
 
Jan Möbius committed
398 399 400 401 402 403 404 405 406 407
}

//-----------------------------------------------------------------------------

void
PolyLinePlugin::
slot_subdivide()
{
  // get subdivision value
  double max_length = tool_->dsb_subdivide->value();
Jan Möbius's avatar
Jan Möbius committed
408

Jan Möbius's avatar
 
Jan Möbius committed
409
  // safety catch
Jan Möbius's avatar
Jan Möbius committed
410
  if (max_length == 0.0)
Jan Möbius's avatar
 
Jan Möbius committed
411 412 413
    max_length = 1e-4;

  // iterate over all target polylines
Jan Möbius's avatar
Jan Möbius committed
414
  PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE);
Jan Möbius's avatar
 
Jan Möbius committed
415

Jan Möbius's avatar
Jan Möbius committed
416
  for (; o_it != PluginFunctions::objectsEnd(); ++o_it) {
Jan Möbius's avatar
 
Jan Möbius committed
417
    // subdivide polyline
Jan Möbius's avatar
Jan Möbius committed
418
    PluginFunctions::polyLineObject(*o_it)->line()->subdivide(max_length);
Jan Möbius's avatar
 
Jan Möbius committed
419 420 421 422 423 424 425 426 427 428 429 430
  }

  // update
  emit updateView();
}


//-----------------------------------------------------------------------------


void PolyLinePlugin::slot_subdivide_percent(bool _checked) {

Jan Möbius's avatar
Jan Möbius committed
431 432 433
  // Get subdivision value
  int n_active_pl = 0;
  double total_length = 0;
Jan Möbius's avatar
 
Jan Möbius committed
434

Jan Möbius's avatar
Jan Möbius committed
435 436
  // Iterate over all target polylines
  PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE);
Jan Möbius's avatar
 
Jan Möbius committed
437

Jan Möbius's avatar
Jan Möbius committed
438 439 440 441 442
  for (; o_it != PluginFunctions::objectsEnd(); ++o_it) {
    // Add polyline length
    total_length += PluginFunctions::polyLineObject(*o_it)->line()->length();
    ++n_active_pl;
  }
Jan Möbius's avatar
 
Jan Möbius committed
443

Jan Möbius's avatar
Jan Möbius committed
444
  double v = total_length / double(n_active_pl);
Jan Möbius's avatar
 
Jan Möbius committed
445

Jan Möbius's avatar
Jan Möbius committed
446
  if (_checked) {
Jan Möbius's avatar
 
Jan Möbius committed
447

Jan Möbius's avatar
Jan Möbius committed
448 449 450 451
    // Compute current absolute length to relative portion
    if (n_active_pl > 0) {
      double val_new = tool_->dsb_subdivide->value() / v;
      tool_->dsb_subdivide->setValue(val_new);
Jan Möbius's avatar
 
Jan Möbius committed
452
    } else {
Jan Möbius's avatar
Jan Möbius committed
453 454 455
      emit log(LOGWARN, "Could not find any active polyline!");
    }
  } else {
Jan Möbius's avatar
 
Jan Möbius committed
456

Jan Möbius's avatar
Jan Möbius committed
457 458 459 460 461 462
    // Compute relative portion to absolute value
    if (n_active_pl > 0) {
      double val_new = tool_->dsb_subdivide->value() * v;
      tool_->dsb_subdivide->setValue(val_new);
    } else {
      emit log(LOGWARN, "Could not find any active polyline!");
Jan Möbius's avatar
 
Jan Möbius committed
463
    }
Jan Möbius's avatar
Jan Möbius committed
464
  }
Jan Möbius's avatar
 
Jan Möbius committed
465 466 467 468 469 470 471 472 473 474 475 476 477 478
}


//-----------------------------------------------------------------------------


void
PolyLinePlugin::
slot_decimate()
{
  // get subdivision value
  double min_length = tool_->dsb_decimate->value();

  // iterate over all target polylines
Jan Möbius's avatar
Jan Möbius committed
479
  PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE);
Jan Möbius's avatar
 
Jan Möbius committed
480

Jan Möbius's avatar
Jan Möbius committed
481
  for (; o_it != PluginFunctions::objectsEnd(); ++o_it) {
Jan Möbius's avatar
 
Jan Möbius committed
482
    // decimate polyline
Jan Möbius's avatar
Jan Möbius committed
483
    PluginFunctions::polyLineObject(*o_it)->line()->collapse(min_length);
Jan Möbius's avatar
 
Jan Möbius committed
484 485 486 487 488 489 490 491 492
  }

  // update
  emit updateView();
}

//-----------------------------------------------------------------------------


Jan Möbius's avatar
Jan Möbius committed
493 494
void PolyLinePlugin::slot_decimate_percent(bool _checked)
{
Jan Möbius's avatar
 
Jan Möbius committed
495

Jan Möbius's avatar
Jan Möbius committed
496 497 498
  // Get decimation value
  int n_active_pl = 0;
  double total_length = 0;
Jan Möbius's avatar
 
Jan Möbius committed
499

Jan Möbius's avatar
Jan Möbius committed
500 501
  // Iterate over all target polylines
  PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE);
Jan Möbius's avatar
 
Jan Möbius committed
502

Jan Möbius's avatar
Jan Möbius committed
503 504 505 506 507
  for (; o_it != PluginFunctions::objectsEnd(); ++o_it) {
    // Add polyline length
    total_length += PluginFunctions::polyLineObject(*o_it)->line()->length();
    ++n_active_pl;
  }
Jan Möbius's avatar
 
Jan Möbius committed
508

Jan Möbius's avatar
Jan Möbius committed
509
  double v = total_length / double(n_active_pl);
Jan Möbius's avatar
 
Jan Möbius committed
510

Jan Möbius's avatar
Jan Möbius committed
511
  if (_checked) {
Jan Möbius's avatar
 
Jan Möbius committed
512

Jan Möbius's avatar
Jan Möbius committed
513 514 515 516
    // Compute current absolute length to relative portion
    if (n_active_pl > 0) {
      double val_new = tool_->dsb_subdivide->value() / v;
      tool_->dsb_decimate->setValue(val_new);
Jan Möbius's avatar
 
Jan Möbius committed
517
    } else {
Jan Möbius's avatar
Jan Möbius committed
518 519 520
      emit log(LOGWARN, "Could not find any active polyline!");
    }
  } else {
Jan Möbius's avatar
 
Jan Möbius committed
521

Jan Möbius's avatar
Jan Möbius committed
522 523 524 525 526 527
    // Compute relative portion to absolute value
    if (n_active_pl > 0) {
      double val_new = tool_->dsb_subdivide->value() * v;
      tool_->dsb_decimate->setValue(val_new);
    } else {
      emit log(LOGWARN, "Could not find any active polyline!");
Jan Möbius's avatar
 
Jan Möbius committed
528
    }
Jan Möbius's avatar
Jan Möbius committed
529
  }
Jan Möbius's avatar
 
Jan Möbius committed
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
}


//-----------------------------------------------------------------------------

#ifdef EXTENDED_POLY_LINE

void
PolyLinePlugin::
slot_resample_on_edges()
{
  // count target meshes
  PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_TRIANGLE_MESH );
  unsigned int n_targetMeshes(0);
  for(; o_it != PluginFunctions::objectsEnd(); ++o_it)
    ++n_targetMeshes;

  if( n_targetMeshes != 1)
  {
    std::cerr << "Warning: resample_on_edges needs exactly 1 target mesh! Otherwise no operation is performed! \n";
    return;
  }

  // take first target mesh
  o_it = PluginFunctions::ObjectIterator(PluginFunctions::TARGET_OBJECTS, DATA_TRIANGLE_MESH );

  if(o_it != PluginFunctions::objectsEnd())
  {
    // get pointer to TriMeshObject
    TriMeshObject* tmesh_obj = PluginFunctions::triMeshObject(*o_it);

    // get pointer to mesh
    TriMesh* mesh = tmesh_obj->mesh();

    // get pointer to triangle bsp
    OpenMeshTriangleBSPT< TriMesh >* tbsp = tmesh_obj->requestTriangleBsp();
    //    OpenMeshTriangleBSPT< TriMesh >* tbsp = 0;

    // iterate over all target polylines
    PluginFunctions::ObjectIterator o_it2(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE );

Jan Möbius's avatar
Jan Möbius committed
571
    for (; o_it2 != PluginFunctions::objectsEnd(); ++o_it2)
Jan Möbius's avatar
 
Jan Möbius committed
572
    {
573
      std::cerr << "resample " << o_it2->name().toStdString() << std::endl;
Jan Möbius's avatar
 
Jan Möbius committed
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
      // decimate polyline
      PluginFunctions::polyLineObject(*o_it2)->line()->resample_on_mesh_edges( *mesh, tbsp );
    }

    // update
    emit updateView();
  }
}

#endif

//-----------------------------------------------------------------------------


void
PolyLinePlugin::
slot_smooth()
{
  // iterate over all target polylines
  PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE );

  for (  ; o_it != PluginFunctions::objectsEnd(); ++o_it)
  {
    for( int i=0; i<tool_->sb_smooth_iter->value(); ++i)
      if( tool_->rb_smooth_c0->isChecked())
	// smooth polyline C0
	PluginFunctions::polyLineObject(*o_it)->line()->smooth_uniform_laplace();
      else
	if( tool_->rb_smooth_c1->isChecked())
	  // smooth polyline C1
	  PluginFunctions::polyLineObject(*o_it)->line()->smooth_uniform_laplace2();
	else
	  if( tool_->rb_smooth_c2->isChecked())
	    // smooth polyline C2
	    PluginFunctions::polyLineObject(*o_it)->line()->smooth_uniform_laplace3();

    emit updatedObject( o_it->id(), UPDATE_GEOMETRY);
  }

}


//-----------------------------------------------------------------------------


void
PolyLinePlugin::
slot_smooth( PolyLineObject*& _pol)
{
  // if polyline object is valid
Jan Möbius's avatar
Jan Möbius committed
624 625 626
  if (_pol) {
    for (int i = 0; i < tool_->sb_smooth_iter->value(); ++i)
      if (tool_->rb_smooth_c0->isChecked())
Jan Möbius's avatar
 
Jan Möbius committed
627 628
        // smooth polyline C0
        _pol->line()->smooth_uniform_laplace();
Jan Möbius's avatar
Jan Möbius committed
629 630 631 632 633 634 635 636
      else if (tool_->rb_smooth_c1->isChecked())
        // smooth polyline C1
        _pol->line()->smooth_uniform_laplace2();
      else if (tool_->rb_smooth_c2->isChecked())
        // smooth polyline C2
        _pol->line()->smooth_uniform_laplace3();

    emit updatedObject(_pol->id(), UPDATE_GEOMETRY);
Jan Möbius's avatar
 
Jan Möbius committed
637 638 639 640 641 642 643 644 645 646 647
  }
}

//-----------------------------------------------------------------------------


void
PolyLinePlugin::
slot_project()
{
  // create meshe and bsp vectors
Jan Möbius's avatar
Jan Möbius committed
648 649
  std::vector<TriMesh*> meshes;
  std::vector<OpenMeshTriangleBSPT<TriMesh>*> bsps;
Jan Möbius's avatar
 
Jan Möbius committed
650

Jan Möbius's avatar
Jan Möbius committed
651
  PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_TRIANGLE_MESH);
Jan Möbius's avatar
 
Jan Möbius committed
652

Jan Möbius's avatar
Jan Möbius committed
653
  for (; o_it != PluginFunctions::objectsEnd(); ++o_it) {
Jan Möbius's avatar
 
Jan Möbius committed
654 655 656 657
    // get pointer to TriMeshObject
    TriMeshObject* tmesh_obj = PluginFunctions::triMeshObject(*o_it);

    // save meshes and bsps
Jan Möbius's avatar
Jan Möbius committed
658
    meshes.push_back(tmesh_obj->mesh());
Jan Möbius's avatar
 
Jan Möbius committed
659
    //    bsps.push_back(0);
Jan Möbius's avatar
Jan Möbius committed
660
    bsps.push_back(tmesh_obj->requestTriangleBsp());
Jan Möbius's avatar
 
Jan Möbius committed
661 662 663
  }

  // iterate over all target polylines
Jan Möbius's avatar
Jan Möbius committed
664
  PluginFunctions::ObjectIterator o_it2(PluginFunctions::TARGET_OBJECTS, DATA_POLY_LINE);
Jan Möbius's avatar
 
Jan Möbius committed
665

Jan Möbius's avatar
Jan Möbius committed
666
  for (; o_it2 != PluginFunctions::objectsEnd(); ++o_it2) {
Jan Möbius's avatar
 
Jan Möbius committed
667
    // project polyline
Jan Möbius's avatar
Jan Möbius committed
668 669
    PluginFunctions::polyLineObject(*o_it2)->line()->project_to_mesh(meshes, &bsps);
    emit updatedObject(o_it2->id(), UPDATE_GEOMETRY);
Jan Möbius's avatar
 
Jan Möbius committed
670 671 672 673 674 675 676 677 678 679 680 681
  }
}


//-----------------------------------------------------------------------------


void 
PolyLinePlugin::
slot_project( PolyLineObject*& _pol)
{
  // check if polyline ok
Jan Möbius's avatar
Jan Möbius committed
682 683
  if (_pol) {

Jan Möbius's avatar
 
Jan Möbius committed
684
    // create meshes and bsp vectors
Jan Möbius's avatar
Jan Möbius committed
685 686
    std::vector<TriMesh*> meshes;
    std::vector<OpenMeshTriangleBSPT<TriMesh>*> bsps;
Jan Möbius's avatar
 
Jan Möbius committed
687

Jan Möbius's avatar
Jan Möbius committed
688 689 690
    PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_TRIANGLE_MESH);

    for (; o_it != PluginFunctions::objectsEnd(); ++o_it) {
Jan Möbius's avatar
 
Jan Möbius committed
691 692 693 694 695

      // get pointer to TriMeshObject
      TriMeshObject* tmesh_obj = PluginFunctions::triMeshObject(*o_it);

      // save meshes and bsps
Jan Möbius's avatar
Jan Möbius committed
696
      meshes.push_back(tmesh_obj->mesh());
Jan Möbius's avatar
 
Jan Möbius committed
697
      //    bsps.push_back(0);
Jan Möbius's avatar
Jan Möbius committed
698
      bsps.push_back(tmesh_obj->requestTriangleBsp());
Jan Möbius's avatar
 
Jan Möbius committed
699 700 701
    }

    // only project given PolyLine
Jan Möbius's avatar
Jan Möbius committed
702
    _pol->line()->project_to_mesh(meshes, &bsps);
Jan Möbius's avatar
 
Jan Möbius committed
703 704 705 706 707 708 709 710 711 712 713 714 715 716
  }

}


//-----------------------------------------------------------------------------


void
PolyLinePlugin::
slot_smooth_project()
{
  int smooth_project_iter = tool_->sb_smooth_project_iter->value();

Jan Möbius's avatar
Jan Möbius committed
717 718
  for (int i = 0, j = 1; i < smooth_project_iter; ++i, ++j) {

Jan Möbius's avatar
 
Jan Möbius committed
719 720 721 722 723
    // n smoothing steps
    slot_smooth();

    // projection step
    slot_project();
Jan Möbius's avatar
Jan Möbius committed
724

Jan Möbius's avatar
 
Jan Möbius committed
725 726 727 728 729 730 731 732 733
  }
}


//-----------------------------------------------------------------------------


void
PolyLinePlugin::
Jan Möbius's avatar
Jan Möbius committed
734
slot_smooth_project(PolyLineObject*& _pol)
Jan Möbius's avatar
 
Jan Möbius committed
735 736 737
{
  int smooth_project_iter = tool_->sb_smooth_project_iter->value();

Jan Möbius's avatar
Jan Möbius committed
738 739
  for (int i = 0, j = 1; i < smooth_project_iter; ++i, ++j) {

Jan Möbius's avatar
 
Jan Möbius committed
740
    // n smoothing steps
Jan Möbius's avatar
Jan Möbius committed
741
    slot_smooth(_pol);
Jan Möbius's avatar
 
Jan Möbius committed
742 743

    // projection step
Jan Möbius's avatar
Jan Möbius committed
744 745
    slot_project(_pol);

Jan Möbius's avatar
 
Jan Möbius committed
746 747 748 749 750 751 752 753 754 755 756 757 758
  }
}


//-----------------------------------------------------------------------------


void
PolyLinePlugin::
slot_smart_move_timer()
{
  int smooth_project_iter = tool_->sb_smooth_project_iter->value();

Jan Möbius's avatar
Jan Möbius committed
759 760 761 762
  if (smooth_project_iter)
    slot_smooth_project(cur_smart_move_obj_);
  else // only smooth
    slot_smooth(cur_smart_move_obj_);
Jan Möbius's avatar
 
Jan Möbius committed
763 764 765 766 767 768 769

  emit updateView();
}




770 771
//-----------------------------------------------------------------------------

Jan Möbius's avatar
 
Jan Möbius committed
772 773 774 775 776 777 778
PolyLinePlugin::EditMode
PolyLinePlugin::
mode()
{
  if(tool_ )
  {
    if( tool_->rb_insert->isChecked()         ) return PL_INSERT;
779
    if( tool_->rb_InsertCircle->isChecked()	  ) return PL_INSERTCIRCLE;
Jan Möbius's avatar
 
Jan Möbius committed
780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
    else if( tool_->rb_delete->isChecked()    ) return PL_DELETE;
    else if( tool_->rb_move->isChecked()      ) return PL_MOVE;
    else if( tool_->rb_split->isChecked()     ) return PL_SPLIT;
    else if( tool_->rb_merge->isChecked()     ) return PL_MERGE;
    else if( tool_->rb_smart_move->isChecked()) return PL_SMART_MOVE;
  }

  return PL_NONE;
}

//-----------------------------------------------------------------------------

void
PolyLinePlugin::
me_insert( QMouseEvent* _event )
{
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
    if (_event->type() == QEvent::MouseMove) {
        if (create_point_ref_) {
            // Pick position
            unsigned int node_idx, target_idx;
            ACG::Vec3d hit_point;
            if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
                *create_point_ref_ = (PolyLine::Point) hit_point;

                // update
                emit updatedObject(cur_insert_id_, UPDATE_GEOMETRY);
            }
        }
        return;
    }

Jan Möbius's avatar
 
Jan Möbius committed
811
  // Pick position
Jan Möbius's avatar
Jan Möbius committed
812 813 814
  unsigned int node_idx, target_idx;
  ACG::Vec3d hit_point;
  if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
Jan Möbius's avatar
 
Jan Möbius committed
815

Jan Möbius's avatar
Jan Möbius committed
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832
    switch (_event->type()) {
      // insert new point
      case QEvent::MouseButtonPress: {
        // new Polyline?
        if (cur_insert_id_ == -1 || !PluginFunctions::objectRoot()->childExists(cur_insert_id_)) {
          // add new polyline
          emit addEmptyObject(DATA_POLY_LINE, cur_insert_id_);

          // get current polylineobject
          BaseObjectData *obj = 0;
          PluginFunctions::getObject(cur_insert_id_, obj);
          // default: set as target
          obj->target(true);
          // get polyline object
          cur_polyline_obj_ = PluginFunctions::polyLineObject(obj);

          cur_polyline_obj_->materialNode()->set_random_color();
833 834 835 836

          cur_polyline_obj_->line()->add_point((PolyLine::Point) hit_point);

          emit showStatusMessage(tr("Double click/Enter to terminate poly line. Use with shift to create loop."));
Jan Möbius's avatar
Jan Möbius committed
837
        }
Jan Möbius's avatar
 
Jan Möbius committed
838

Jan Möbius's avatar
Jan Möbius committed
839 840
        // add new point
        cur_polyline_obj_->line()->add_point((PolyLine::Point) hit_point);
841
        create_point_ref_ = &cur_polyline_obj_->line()->points().back();
Jan Möbius's avatar
 
Jan Möbius committed
842

Jan Möbius's avatar
Jan Möbius committed
843 844
        // update
        emit updatedObject(cur_insert_id_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
Jan Möbius's avatar
 
Jan Möbius committed
845

Jan Möbius's avatar
Jan Möbius committed
846 847
        break;
      }
Jan Möbius's avatar
 
Jan Möbius committed
848

Jan Möbius's avatar
Jan Möbius committed
849 850
      // finish polyline
      case QEvent::MouseButtonDblClick: {
Jan Möbius's avatar
 
Jan Möbius committed
851

Jan Möbius's avatar
Jan Möbius committed
852 853 854 855
        // close polyline
        if (_event->modifiers() & (Qt::ShiftModifier)) {
          cur_polyline_obj_->line()->set_closed(true);
        }
Jan Möbius's avatar
 
Jan Möbius committed
856

857 858 859 860 861 862 863 864 865 866 867 868
        if (cur_polyline_obj_->line()->n_vertices() >= 2) {
            const PolyLine::Point &p1 = cur_polyline_obj_->line()->point(cur_polyline_obj_->line()->n_vertices() - 1),
                    &p2 = cur_polyline_obj_->line()->point(cur_polyline_obj_->line()->n_vertices() - 2);

            /*
             * Remove duplicate created as a move sentinel.
             */
            if ((p2 - p1).sqrnorm() < 1e-6) {
                cur_polyline_obj_->line()->delete_point(cur_polyline_obj_->line()->n_vertices() - 1);
            }
        }

Jan Möbius's avatar
Jan Möbius committed
869 870
        // update
        emit updatedObject(cur_insert_id_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
Jan Möbius's avatar
 
Jan Möbius committed
871

Jan Möbius's avatar
Jan Möbius committed
872 873 874
        // reset current variables
        cur_insert_id_ = -1;
        cur_polyline_obj_ = 0;
875 876 877
        create_point_ref_ = 0;

        clearStatusMessage();
Jan Möbius's avatar
 
Jan Möbius committed
878

Jan Möbius's avatar
Jan Möbius committed
879
        break;
Jan Möbius's avatar
 
Jan Möbius committed
880 881 882
      }

      default:
Jan Möbius's avatar
Jan Möbius committed
883
        break;
Jan Möbius's avatar
 
Jan Möbius committed
884 885 886 887 888 889
    }
  }
}

//-----------------------------------------------------------------------------

890 891 892 893 894 895 896 897 898
void PolyLinePlugin::
me_insertCircle(QMouseEvent* _event)
{
	TriMeshObject* mesh;
	TriMesh::FaceHandle fh;
	TriMesh::VertexHandle vh;
	ACG::Vec3d hit_point;
	if(!pick_triangle_mesh(_event->pos(), mesh, fh, vh, hit_point))
		return;//can't generate a circle in empty space
899 900

	if(_event->type() == QEvent::MouseMove && createCircle_CurrSelIndex_ != -1) {
Jan Möbius's avatar
Jan Möbius committed
901 902
		PolyLineObject* lineObject = 0;
		if(!PluginFunctions::getObject(createCircle_CurrSelIndex_, lineObject))
903 904
			return;

905
		const ACG::Vec3d n = createCircle_Normal_, x0 = createCircle_Point_;
Jan Möbius's avatar
Jan Möbius committed
906
		const double t = ((n | x0) - (n | hit_point)) / n.sqrnorm();
907 908 909 910
		const ACG::Vec3d onPlane = hit_point + t * n,  d = onPlane - x0;
		const double r = d.norm();
		const ACG::Vec3d mainAxis = (onPlane - x0).normalize(), sideAxis = (mainAxis % n).normalize();

Jan Möbius's avatar
Jan Möbius committed
911 912 913 914
		PolyLineCircleData* lineData = new PolyLineCircleData(x0, n, mainAxis, sideAxis, r, r, mesh->id());
		lineObject->setObjectData(CIRCLE_DATA, lineData);
		updatePolyEllipse(lineObject, tool_->sb_CirclePointNum->value());
		updateHandles(lineObject);
915 916 917 918 919 920
	}
	else if(_event->type() == QEvent::MouseButtonPress) {
		emit addEmptyObject(DATA_POLY_LINE, cur_insert_id_);
		BaseObjectData *obj = 0;
		PluginFunctions::getObject(cur_insert_id_, obj);
		obj->target(true);
921 922
		PolyLineObject* newLine = PluginFunctions::polyLineObject(obj);
		newLine->materialNode()->set_random_color();
923 924 925 926

		createCircle_Point_ = hit_point;
		if(!mesh->mesh()->has_face_normals())
			mesh->mesh()->request_face_normals();
927
		createCircle_Normal_ = mesh->mesh()->normal(fh);
928
		emit updatedObject(cur_insert_id_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
Jan Möbius's avatar
Jan Möbius committed
929
		createCircle_LastSelIndex_ = createCircle_CurrSelIndex_ = newLine->id();
930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963

		ACG::Vec3d bbMin( FLT_MAX, FLT_MAX, FLT_MAX);
		ACG::Vec3d bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX);
		mesh->boundingBox(bbMin, bbMax);
		const ACG::Vec3d sizeBB((bbMax-bbMin));

		GlutObjectNode* handle0 = new GlutObjectNode(newLine, obj->manipulatorNode(), "N_Handle0");
		handle0->get_primitive(0).color = ACG::Vec4f(1,0,0,1);
		handle0->set_size(0.005*sizeBB.norm());
		handle0->show();
		handle0->enablePicking(false);
		handle0->set_position(hit_point);
		newLine->addAdditionalNode(handle0, name(), "handle0");
		handle0->drawMode(ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED);

		GlutObjectNode* handle1 = new GlutObjectNode(newLine, obj->manipulatorNode(), "N_Handle1");
		handle1->get_primitive(0).color = ACG::Vec4f(0,1,0,1);
		handle1->set_size(0.005*sizeBB.norm());
		handle1->show();
		handle1->enablePicking(true);
		handle1->set_position(hit_point);
		newLine->addAdditionalNode(handle1, name(), "handle1");
		handle1->drawMode(ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED);

		GlutObjectNode* cenNode = new GlutObjectNode(newLine, obj->manipulatorNode(), "N_Center");
		cenNode->get_primitive(0).color = ACG::Vec4f(0,0,1,1);
		cenNode->set_size(0.005*sizeBB.norm());
		cenNode->show();
		cenNode->enablePicking(true);
		cenNode->set_position(hit_point);
		newLine->addAdditionalNode(cenNode, name(), "circle");
		cenNode->drawMode(ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED);

		emit updatedObject(newLine->id(), UPDATE_ALL);
964 965
	}
	else if(_event->type() == QEvent::MouseButtonRelease) {
Jan Möbius's avatar
Jan Möbius committed
966 967
		PolyLineObject* lineObject;
		if(!PluginFunctions::getObject(createCircle_CurrSelIndex_, lineObject))
968 969
			return;
		ACG::SceneGraph::GlutPrimitiveNode* N;
Jan Möbius's avatar
Jan Möbius committed
970
		if(lineObject->getAdditionalNode(N, name(), "handle0"))
971 972
			N->enablePicking(true);
		createCircle_CurrSelIndex_ = -1;
973 974 975 976
	}
}

//-----------------------------------------------------------------------------
Jan Möbius's avatar
 
Jan Möbius committed
977 978 979 980 981 982

void
PolyLinePlugin::
me_delete( QMouseEvent* _event )
{
  // MousePress ?
Jan Möbius's avatar
Jan Möbius committed
983 984 985 986
  if (_event->type() == QEvent::MouseButtonPress) {

    unsigned int node_idx, target_idx;
    ACG::Vec3d hit_point;
Jan Möbius's avatar
 
Jan Möbius committed
987
    // pick
Jan Möbius's avatar
Jan Möbius committed
988 989
    if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point)) {

Jan Möbius's avatar
 
Jan Möbius committed
990
      BaseObjectData* obj = 0;
Jan Möbius's avatar
Jan Möbius committed
991 992

      if (PluginFunctions::getPickedObject(node_idx, obj))
Jan Möbius's avatar
 
Jan Möbius committed
993
        // is picked object polyline?
Jan Möbius's avatar
Jan Möbius committed
994
        if (PluginFunctions::polyLineObject(obj)) {
Jan Möbius's avatar
 
Jan Möbius committed
995 996 997
          emit deleteObject(obj->id());
        }
    }
Jan Möbius's avatar
Jan Möbius committed
998

Jan Möbius's avatar
 
Jan Möbius committed
999
  }
Jan Möbius's avatar
Jan Möbius committed
1000

Jan Möbius's avatar
 
Jan Möbius committed
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
}


//-----------------------------------------------------------------------------


void
PolyLinePlugin::
me_move( QMouseEvent* _event )
{
1011
  // MousePress ? -> get reference point
Jan Möbius's avatar
Jan Möbius committed
1012 1013 1014 1015
  if (_event->type() == QEvent::MouseButtonPress) {

    unsigned int node_idx, target_idx;
    ACG::Vec3d hit_point;
Jan Möbius's avatar
 
Jan Möbius committed
1016
    // pick
1017
    if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point)) {
Jan Möbius's avatar
Jan Möbius committed
1018

1019 1020 1021 1022
      BaseNode* node = find_node( PluginFunctions::getRootNode(), node_idx );
      GlutObjectNode* glutNode = dynamic_cast<GlutObjectNode*>(node);
      if(glutNode) {
        moveCircle_SelNode_        = glutNode;
Jan Möbius's avatar
Jan Möbius committed
1023
        createCircle_LastSelIndex_ = createCircle_CurrSelIndex_ = glutNode->line->id();
1024 1025
      }

Jan Möbius's avatar
 
Jan Möbius committed
1026
      BaseObjectData* obj = 0;
Jan Möbius's avatar
Jan Möbius committed
1027 1028 1029
      if (PluginFunctions::getPickedObject(node_idx, obj)) {
        // is picked object polyline?
        PolyLineObject* cur_pol = PluginFunctions::polyLineObject(obj);
1030
        if (cur_pol && !cur_pol->objectData(CIRCLE_DATA)) {//no vertex dragging on circles!
1031 1032 1033 1034 1035

          // Check if we got a line segment or a vertex
          if ( target_idx >= cur_pol->line()->n_vertices() )
            return;

Jan Möbius's avatar
Jan Möbius committed
1036 1037
          // save references
          cur_move_id_ = cur_pol->id();
1038

Jan Möbius's avatar
Jan Möbius committed
1039 1040
          move_point_ref_ = &(cur_pol->line()->point(target_idx));
        }
Jan Möbius's avatar
 
Jan Möbius committed
1041 1042 1043 1044 1045
      }
    }
  }

  // Move ? -> move reference point
1046
  if (_event->type() == QEvent::MouseMove){
Jan Möbius's avatar
Jan Möbius committed
1047

1048 1049
    unsigned int node_idx, target_idx;
    ACG::Vec3d hit_point;
Jan Möbius's avatar
Jan Möbius committed
1050

1051 1052 1053
    if(moveCircle_SelNode_) {
      if(PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point) ) {

Jan Möbius's avatar
Jan Möbius committed
1054 1055
        PolyLineObject* lineObject;
        if(!PluginFunctions::getObject(createCircle_CurrSelIndex_, lineObject))
1056 1057
          return;

Jan Möbius's avatar
Jan Möbius committed
1058
        PolyLineCircleData* lineData = dynamic_cast<PolyLineCircleData*>(lineObject->objectData(CIRCLE_DATA));
1059 1060
        double cr;
        ACG::Vec3d onPlane;
Jan Möbius's avatar
Jan Möbius committed
1061
        const ACG::Vec3d x0 = lineData->circleCenter_, n = lineData->circleNormal_;
1062

Jan Möbius's avatar
Jan Möbius committed
1063
        createCircle_getHitInfo(lineData, hit_point, &hit_point, &cr, &onPlane);
1064 1065

        if(!moveCircle_SelNode_->name().compare("N_Center")) {
Jan Möbius's avatar
Jan Möbius committed
1066
        	lineData->circleCenter_ = hit_point;
1067 1068 1069 1070 1071
        }
        else {
          ACG::Vec3d axisa = (onPlane - x0).normalize();
          if(!moveCircle_SelNode_->name().compare("N_Handle0")) {
            ACG::Vec3d axisb = (axisa % n).normalize();
Jan Möbius's avatar
Jan Möbius committed
1072 1073 1074
            lineData->circleMainRadius_ = cr;
            lineData->circleMainAxis_ = axisa;
            lineData->circleSideAxis_ = axisb;
1075 1076
          } else {
            ACG::Vec3d axisb = (n % axisa).normalize();
Jan Möbius's avatar
Jan Möbius committed
1077 1078 1079
            lineData->circleSideRadius_ = cr;
            lineData->circleSideAxis_ = axisa;
            lineData->circleMainAxis_ = axisb;
1080 1081
          }
        }
Jan Möbius's avatar
Jan Möbius committed
1082 1083
        updateHandles(lineObject);
        updatePolyEllipse(lineObject, tool_->sb_CirclePointNum->value());
1084 1085 1086
      }
    }
    else if (move_point_ref_ != 0) {
Jan Möbius's avatar
Jan Möbius committed
1087 1088 1089 1090
      if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {
        (*move_point_ref_) = (PolyLine::Point) hit_point;
        // update
        emit updatedObject(cur_move_id_, UPDATE_GEOMETRY);
Jan Möbius's avatar
 
Jan Möbius committed
1091 1092
      }
    }
1093
  }
Jan Möbius's avatar
 
Jan Möbius committed
1094 1095

  // Release ? -> release reference point
1096 1097 1098 1099 1100
  if (_event->type() == QEvent::MouseButtonRelease) {
	  move_point_ref_ = 0;
	  moveCircle_SelNode_ = 0;
	  createCircle_CurrSelIndex_ = -1;
  }
Jan Möbius's avatar
 
Jan Möbius committed
1101 1102 1103 1104 1105 1106 1107 1108 1109
}
//-----------------------------------------------------------------------------


void
PolyLinePlugin::
me_split( QMouseEvent* _event )
{
  // MousePress ?
Jan Möbius's avatar
Jan Möbius committed
1110
  if (_event->type() == QEvent::MouseButtonPress) {
Jan Möbius's avatar
 
Jan Möbius committed
1111 1112 1113
    // release old references
    move_point_ref_ = 0;

Jan Möbius's avatar
Jan Möbius committed
1114 1115
    unsigned int node_idx, target_idx;
    ACG::Vec3d hit_point;
Jan Möbius's avatar
 
Jan Möbius committed
1116
    // pick
1117 1118
    if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point)) {

Jan Möbius's avatar
 
Jan Möbius committed
1119
      BaseObjectData* obj = 0;
Jan Möbius's avatar
Jan Möbius committed
1120 1121 1122
      if (PluginFunctions::getPickedObject(node_idx, obj)) {
        // is picked object polyline?
        PolyLineObject* cur_pol = PluginFunctions::polyLineObject(obj);
1123

Jan Möbius's avatar
Jan Möbius committed
1124
        if (cur_pol) {
1125 1126 1127 1128 1129

          // Check if we got a line segment or a vertex
          if ( target_idx >= cur_pol->line()->n_vertices() )
            return;

Jan Möbius's avatar
Jan Möbius committed
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
          // splitting for CLOSED PolyLines
          if (cur_pol->line()->is_closed()) {
            cur_pol->line()->split_closed(target_idx);

            // save references for moving
            cur_move_id_ = cur_pol->id();
            move_point_ref_ = &(cur_pol->line()->point(cur_pol->line()->n_vertices() - 1));

            // emit changed objects
            emit updatedObject(cur_pol->id(), UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
          } else
          // splitting for OPEN PolyLines
          {
            // add new polyline
            int insert_id;
            emit addEmptyObject(DATA_POLY_LINE, insert_id);

            // get current polylineobject
            BaseObjectData *obj2 = 0;

            // get polyline object
            PluginFunctions::getObject(insert_id, obj2);

            // default: mark as target
            obj2->target(true);

            PolyLineObject* pol_obj2 = PluginFunctions::polyLineObject(obj2);

            pol_obj2->materialNode()->set_random_color();

            cur_pol->line()->split(target_idx, *(pol_obj2->line()));

            // save references for moving
            cur_move_id_ = cur_pol->id();
            move_point_ref_ = &(cur_pol->line()->point(cur_pol->line()->n_vertices() - 1));

            // emit changed objects
            emit updatedObject(insert_id, UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
            emit updatedObject(cur_pol->id(), UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
          }

          // update
          emit updateView();
        }
Jan Möbius's avatar
 
Jan Möbius committed
1174 1175 1176 1177 1178
      }
    }
  }

  // Move splitted ? -> move reference point
Jan Möbius's avatar
Jan Möbius committed
1179 1180 1181 1182 1183
  if (_event->type() == QEvent::MouseMove)
    if (move_point_ref_ != 0) {

      unsigned int node_idx, target_idx;
      ACG::Vec3d hit_point;
Jan Möbius's avatar
 
Jan Möbius committed
1184
      // pick
Jan Möbius's avatar
Jan Möbius committed
1185 1186 1187
      if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point)) {

        (*move_point_ref_) = (PolyLine::Point) hit_point;
Jan Möbius's avatar
 
Jan Möbius committed
1188

Jan Möbius's avatar
Jan Möbius committed
1189 1190 1191
        // update
        //	emit updatedObject(cur_insert_id_, UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
        emit updateView();
Jan Möbius's avatar
 
Jan Möbius committed
1192 1193 1194 1195
      }
    }

  // Release splitted? -> release reference point
Jan Möbius's avatar
Jan Möbius committed
1196 1197 1198
  if (_event->type() == QEvent::MouseButtonRelease) {

    if (cur_move_id_ != -1)
Jan Möbius's avatar
 
Jan Möbius committed
1199
      emit updatedObject(cur_move_id_, UPDATE_TOPOLOGY | UPDATE_GEOMETRY);
Jan Möbius's avatar
Jan Möbius committed
1200

Jan Möbius's avatar
 
Jan Möbius committed
1201 1202
    move_point_ref_ = 0;
    cur_move_id_ = -1;
Jan Möbius's avatar
Jan Möbius committed
1203

Jan Möbius's avatar
 
Jan Möbius committed
1204
  }
Jan Möbius's avatar
Jan Möbius committed
1205

Jan Möbius's avatar
 
Jan Möbius committed
1206 1207 1208 1209 1210 1211 1212 1213 1214
}

//-----------------------------------------------------------------------------

void
PolyLinePlugin::
me_merge( QMouseEvent* _event )
{
  // Mouse PRESS ?
Jan Möbius's avatar
Jan Möbius committed
1215
  if (_event->type() == QEvent::MouseButtonPress) {
Jan Möbius's avatar
 
Jan Möbius committed
1216 1217
    // release old references
    move_point_ref_ = 0;
Jan Möbius's avatar
Jan Möbius committed
1218
    cur_merge_id_ = -1;
Jan Möbius's avatar
 
Jan Möbius committed
1219

Jan Möbius's avatar
Jan Möbius committed
1220 1221
    unsigned int node_idx, target_idx;
    ACG::Vec3d hit_point;
Jan Möbius's avatar
 
Jan Möbius committed
1222
    // pick
1223
    if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point)) {
Jan Möbius's avatar
 
Jan Möbius committed
1224
      BaseObjectData* obj = 0;
Jan Möbius's avatar
Jan Möbius committed
1225 1226 1227
      if (PluginFunctions::getPickedObject(node_idx, obj)) {
        // is picked object polyline?
        PolyLineObject* cur_pol = PluginFunctions::polyLineObject(obj);
1228
        if (cur_pol) {
1229 1230 1231 1232 1233

          // Check if we got a line segment or a vertex
          if ( target_idx >= cur_pol->line()->n_vertices() )
            return;

Jan Möbius's avatar
Jan Möbius committed
1234 1235 1236
          if (target_idx == cur_pol->line()->n_vertices() - 1 || target_idx == 0) {
            if (target_idx == 0) {
              cur_pol->line()->invert();
Jan Möbius's avatar
Jan Möbius committed
1237
              //target_idx = cur_pol->line()->n_vertices() - 1;
Jan Möbius's avatar
Jan Möbius committed
1238 1239 1240 1241 1242 1243 1244 1245 1246
            }

            // save references
            cur_merge_id_ = cur_pol->id();

            // save reference for moving
            //	    cur_pol->line()->add_point( cur_pol->line()->point( cur_pol->line()->n_vertices()-1));
            move_point_ref_ = &(cur_pol->line()->point(cur_pol->line()->n_vertices() - 1));
          }
1247 1248
        }

Jan Möbius's avatar
 
Jan Möbius committed
1249 1250 1251 1252 1253
      }
    }
  }

  // Move ? -> move reference point
Jan Möbius's avatar
Jan Möbius committed
1254 1255 1256 1257
  if (_event->type() == QEvent::MouseMove && cur_merge_id_ != -1)
    if (move_point_ref_ != 0) {
      unsigned int node_idx, target_idx;
      ACG::Vec3d hit_point;
Jan Möbius's avatar
 
Jan Möbius committed
1258
      // pick
Jan Möbius's avatar
Jan Möbius committed
1259 1260 1261
      if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx,
          &hit_point)) {
        (*move_point_ref_) = (PolyLine::Point) hit_point;
Jan Möbius's avatar
 
Jan Möbius committed
1262

Jan Möbius's avatar
Jan Möbius committed
1263 1264 1265
        // update
        //	emit updatedObject(cur_merge_id_);
        emit updateView();
Jan Möbius's avatar
 
Jan Möbius committed
1266 1267 1268 1269
      }
    }

  // Mouse RELEASE ?
Jan Möbius's avatar
Jan Möbius committed
1270
  if (_event->type() == QEvent::MouseButtonRelease && cur_merge_id_ != -1) {
Jan Möbius's avatar
 
Jan Möbius committed
1271 1272 1273
    PolyLine::Point p_save;

    // reset move references
Jan Möbius's avatar
Jan Möbius committed
1274
    if (move_point_ref_ != 0) {
Jan Möbius's avatar
 
Jan Möbius committed
1275 1276 1277 1278
      // remove intermediate point
      // restore orig polyline
      BaseObjectData *obj = 0;
      PluginFunctions::getObject(cur_merge_id_, obj);
Jan Möbius's avatar
Jan Möbius committed
1279
      PolyLineObject* opol = PluginFunctions::polyLineObject(obj);
Jan Möbius's avatar
 
Jan Möbius committed
1280 1281 1282

      // store position if merging fails
      p_save = opol->line()->back();
Jan Möbius's avatar
Jan Möbius committed
1283
      opol->line()->resize(opol->line()->n_vertices() - 1);
Jan Möbius's avatar
 
Jan Möbius committed
1284 1285 1286 1287 1288

      // release reference
      move_point_ref_ = 0;
    }

Jan Möbius's avatar
Jan Möbius committed
1289 1290 1291
    unsigned int node_idx, target_idx;
    ACG::Vec3d hit_point;

Jan Möbius's avatar
 
Jan Möbius committed
1292
    // pick
1293
    if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point)) {
Jan Möbius's avatar
Jan Möbius committed
1294

Jan Möbius's avatar
Jan Möbius committed
1295 1296
      bool merged = false;

Jan Möbius's avatar
 
Jan Möbius committed
1297
      BaseObjectData* obj = 0;
Jan Möbius's avatar
Jan Möbius committed
1298

Jan Möbius's avatar
Jan Möbius committed
1299 1300 1301 1302 1303 1304
      if (PluginFunctions::getPickedObject(node_idx, obj)) {

        // is picked object polyline? -> get second polyline
        PolyLineObject* second_pol = PluginFunctions::polyLineObject(obj);

        if (second_pol) {
1305 1306 1307 1308 1309

          // Check if we got a line segment or a vertex
          if ( target_idx >= second_pol->line()->n_vertices() )
            return;

Jan Möbius's avatar
Jan Möbius committed
1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361
          // restore first polyline
          BaseObjectData *obj2 = 0;
          PluginFunctions::getObject(cur_merge_id_, obj2);
          PolyLineObject* first_pol = PluginFunctions::polyLineObject(obj2);

          // get idxs
          unsigned int first_idx = first_pol->line()->n_vertices() - 1;
          unsigned int second_idx = target_idx;

          // both polylines open?
          if (first_pol->line()->is_closed() || second_pol->line()->is_closed())
            return;

          bool inv_first(false), inv_second(false);

          // wrong ordering first Polyline?
          if (first_idx == 0) {
            inv_first = true;
            first_idx = first_pol->line()->n_vertices() - 1;
          }

          // wrong ordering second Polyline?
          if (second_idx == second_pol->line()->n_vertices() - 1) {
            inv_second = true;
            second_idx = 0;
          }

          // two endpoints available?
          if (first_idx == first_pol->line()->n_vertices() - 1 && second_idx == 0) {
            // same polyline?
            if (first_pol->id() == second_pol->id()) {
              // simply close line
              first_pol->line()->set_closed(true);
            } else {
              // invert if necessary
              if (inv_first)
                first_pol->line()->invert();
              if (inv_second)
                second_pol->line()->invert();

              // append second polyline to first one
              first_pol->line()->append(*second_pol->line());

              // set flag
              merged = true;

              // delete appended
              emit deleteObject(second_pol->id());
            }

          }
        }
Jan Möbius's avatar
 
Jan Möbius committed
1362 1363
      }

Jan Möbius's avatar
Jan Möbius committed
1364 1365 1366 1367 1368 1369
      if (!merged) {
        // remove intermediate point
        // restore orig polyline
        BaseObjectData *obj = 0;
        PluginFunctions::getObject(cur_merge_id_, obj);
        PolyLineObject* opol = PluginFunctions::polyLineObject(obj);
Jan Möbius's avatar
 
Jan Möbius committed
1370

Jan Möbius's avatar
Jan Möbius committed
1371
        opol->line()->add_point(p_save);
Jan Möbius's avatar
 
Jan Möbius committed
1372 1373 1374 1375 1376 1377 1378 1379
      }
    }

    // update
    emit updatedObject(cur_merge_id_, UPDATE_GEOMETRY | UPDATE_TOPOLOGY);

    // release old references
    move_point_ref_ = 0;
Jan Möbius's avatar
Jan Möbius committed
1380
    cur_merge_id_ = -1;
Jan Möbius's avatar
 
Jan Möbius committed
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393
  }

}


//-----------------------------------------------------------------------------


void
PolyLinePlugin::
me_smart_move( QMouseEvent* _event )
{
  // MousePress ? -> select vertex and start timer
1394 1395 1396 1397 1398
  if (_event->type() == QEvent::MouseButtonPress) {

    unsigned int node_idx, target_idx;
    ACG::Vec3d hit_point;

Jan Möbius's avatar
 
Jan Möbius committed
1399
    // pick
1400 1401
    if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx, target_idx, &hit_point)) {

Jan Möbius's avatar
 
Jan Möbius committed
1402
      BaseObjectData* obj = 0;
1403 1404 1405 1406 1407 1408
      if (PluginFunctions::getPickedObject(node_idx, obj)) {

        // is picked object polyline?
        PolyLineObject* cur_pol = PluginFunctions::polyLineObject(obj);
        if (cur_pol) {

1409 1410
		  cur_polyline_obj_ = cur_pol;

1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
          // Check if we got a line segment or a vertex
          if ( target_idx >= cur_pol->line()->n_vertices() )
            return;

          // save references
          cur_smart_move_obj_ = cur_pol;
          if (cur_pol->line()->vertex_selections_available()) {
            if (!(_event->modifiers() & (Qt::ShiftModifier)))
              cur_pol->line()->vertex_selection(target_idx) = true;
            else {
              cur_pol->line()->vertex_selection(target_idx) = false;
              emit updateView();
            }
          }

        }

        // start timer
        if (!(_event->modifiers() & (Qt::ShiftModifier)))
          smart_move_timer_->start(20);
Jan Möbius's avatar
 
Jan Möbius committed
1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447
      }
    }
  }


  // MouseRelease ? -> stop timer
  if( _event->type() == QEvent::MouseButtonRelease)
  {
    smart_move_timer_->stop();
    cur_smart_move_obj_ = NULL;
  }


  // call move event
  me_move( _event);
}

1448 1449
//-----------------------------------------------------------------------------

Jan Möbius's avatar
 
Jan Möbius committed
1450 1451 1452 1453 1454 1455 1456 1457
void
PolyLinePlugin::
slotEditModeChanged()
{
  PluginFunctions::pickMode("PolyLine");
  PluginFunctions::actionMode(Viewer::PickingMode);
}

1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478
//-----------------------------------------------------------------------------

void
PolyLinePlugin::
updateHandles(PolyLineObject* _lineObject)
{
  PolyLineCircleData* circleData = dynamic_cast<PolyLineCircleData*>(_lineObject->objectData(CIRCLE_DATA) );
  GlutObjectNode* H0, *H1, *C;
  _lineObject->getAdditionalNode(C,  name(), "circle");
  _lineObject->getAdditionalNode(H0, name(), "handle0");
  _lineObject->getAdditionalNode(H1, name(), "handle1");
  if(C)
    C->set_position(createCircle_getHit(circleData, circleData->circleCenter_));
  if(H0)
    H0->set_position(createCircle_getHit(circleData, circleData->circleCenter_ + circleData->circleMainAxis_ * circleData->circleMainRadius_));
  if(H1)
    H1->set_position(createCircle_getHit(circleData, circleData->circleCenter_ + circleData->circleSideAxis_ * circleData->circleSideRadius_));
}

//-----------------------------------------------------------------------------

Jan Möbius's avatar
 
Jan Möbius committed
1479 1480 1481 1482 1483
void 
PolyLinePlugin::
slotPickToolbarAction(QAction* _action) {
  if ( _action == insertAction_ ) {
    tool_->rb_insert->setChecked(true);
1484 1485 1486
  } else if ( _action == insertCircleAction_ ) {
	    tool_->rb_InsertCircle->setChecked(true);
  }  else if ( _action == deleteAction_ ) {
Jan Möbius's avatar
 
Jan Möbius committed
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
    tool_->rb_delete->setChecked(true);
  } else if ( _action == moveAction_ ) {
    tool_->rb_move->setChecked(true);
  } else if ( _action == smartMoveAction_ ) {
    tool_->rb_smart_move->setChecked(true);
  } else if ( _action == mergeAction_ ) {
    tool_->rb_merge->setChecked(true);
  } else if ( _action == splitAction_ ) {
    tool_->rb_split->setChecked(true);
  }
}

void 
PolyLinePlugin::
slotSetPolyLineMode(QAction* _action) {
  if (_action == polyLineAction_ ){
    PluginFunctions::actionMode(Viewer::PickingMode);
    PluginFunctions::pickMode("PolyLine");
    
    polyLineAction_->setChecked( true );
  }
}

//-----------------------------------------------------------------------------


void 
PolyLinePlugin::
slotEnablePickMode(QString _name)
{
  std::cerr << "slotEnablePickMode\n";

  PluginFunctions::pickMode("PolyLine");
  PluginFunctions::actionMode(Viewer::PickingMode);

  if(tool_ )
  {
    if(_name == "INSERT")
      tool_->rb_insert->setChecked(true);
    else if(_name == "DELETE")
      tool_->rb_delete->setChecked(true);
    else if(_name == "MOVE")
      tool_->rb_move->setChecked(true);
    else if(_name == "SPLIT")
      tool_->rb_split->setChecked(true);
    else  if(_name == "MERGE")
      tool_->rb_merge->setChecked(true);
    else if( _name == "SMART_MOVE")
      tool_->rb_smart_move->setChecked(true);
  }
}

//-----------------------------------------------------------------------------

1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552
bool
PolyLinePlugin::
pick_triangle_mesh( QPoint mPos,
						TriMeshObject*& _mesh_object_, TriMesh::FaceHandle& _fh, TriMesh::VertexHandle& _vh, ACG::Vec3d& _hitPoint)
{
  // invalidate return values
  _fh = TriMesh::FaceHandle  (-1);
  _vh = TriMesh::VertexHandle(-1);

  unsigned int target_idx = 0, node_idx = 0;
  ACG::Vec3d hit_point;

Jan Möbius's avatar
Jan Möbius committed
1553

1554 1555 1556 1557

  if( PluginFunctions::scenegraphPick( ACG::SceneGraph::PICK_FACE, mPos, node_idx, target_idx, &hit_point ) )
  {
    // first check if a sphere was clicked
Jan Möbius's avatar
Jan Möbius committed
1558
    BaseObjectData* object(0);
1559 1560 1561 1562
    if( PluginFunctions::