Developer Documentation
PolyLineSelectionPlugin.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#include "PolyLineSelectionPlugin.hh"
51
53
54// Primitive type icons
55#define VERTEX_TYPE "polyline_vertex.png"
56#define EDGE_TYPE "polyline_edge.png"
57// =======================================
58// Define operations
59// =======================================
60// Vertices:
61#define V_SELECT_ALL "Select All Vertices"
62#define V_DESELECT_ALL "Deselect All Vertices"
63#define V_INVERT "Invert Vertex Selection"
64#define V_DELETE "Delete Selected Vertices"
65// Edges:
66#define E_SELECT_ALL "Select All Edges"
67#define E_DESELECT_ALL "Deselect All Edges"
68#define E_INVERT "Invert Edge Selection"
69#define E_DELETE "Delete Selected Edges"
70
73vertexType_(0),
74edgeType_(0),
75allSupportedTypes_(0) {
76}
77
78//==============================================================================================
79
81}
82
83//==============================================================================================
84
85void PolyLineSelectionPlugin::initializePlugin() {
86
87 // Tell core about all scriptable slots
89}
90
91//==============================================================================================
92
93void PolyLineSelectionPlugin::pluginsInitialized() {
94 // Create new selection environment for polylines
95 // and register polyline data type for the environment.
96
97 QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
98
99 emit addSelectionEnvironment("PolyLine Selections", "Select polyline primitives.",
100 iconPath + "polyline_type.png", environmentHandle_);
101
102 // Register mesh object types
103 emit registerType(environmentHandle_, DATA_POLY_LINE);
104
105 emit addPrimitiveType(environmentHandle_, "Select Polyline Vertices", iconPath + VERTEX_TYPE, vertexType_);
106 emit addPrimitiveType(environmentHandle_, "Select Polyline Edges", iconPath + EDGE_TYPE, edgeType_);
107
109
110 // Determine, which selection modes are requested
111 emit showToggleSelectionMode(environmentHandle_, true, allSupportedTypes_);
112 emit showVolumeLassoSelectionMode(environmentHandle_, true, allSupportedTypes_);
113
114 // Define vertex operations
115 QStringList vertexOperations;
116 vertexOperations.append(V_SELECT_ALL);
117 vertexOperations.append(V_DESELECT_ALL);
118 vertexOperations.append(V_INVERT);
119 vertexOperations.append(V_DELETE);
120
121 QStringList edgeOperations;
122 edgeOperations.append(E_SELECT_ALL);
123 edgeOperations.append(E_DESELECT_ALL);
124 edgeOperations.append(E_INVERT);
125 edgeOperations.append(E_DELETE);
126
127 emit addSelectionOperations(environmentHandle_, vertexOperations, "Vertex Operations", vertexType_);
128 emit addSelectionOperations(environmentHandle_, edgeOperations, "Edge Operations", edgeType_);
129
130 // Register key shortcuts:
131
132 // Select (a)ll
133 emit registerKeyShortcut(Qt::Key_A, Qt::ControlModifier);
134 // (C)lear selection
135 emit registerKeyShortcut(Qt::Key_C, Qt::NoModifier);
136 // (I)nvert selection
137 emit registerKeyShortcut(Qt::Key_I, Qt::NoModifier);
138 // Delete selected entities
139 emit registerKeyShortcut(Qt::Key_Delete, Qt::NoModifier);
140}
141
142//==============================================================================================
143
145
146 emit setSlotDescription("selectAllVertices(int)", tr("Select all vertices of a polyline"),
147 QStringList("objectId"), QStringList("Id of object"));
148 emit setSlotDescription("deselectAllVertices(int)", tr("Deselect all vertices of a polyline"),
149 QStringList("objectId"), QStringList("Id of object"));
150 emit setSlotDescription("invertVertexSelection(int)", tr("Invert vertex selection"),
151 QStringList("objectId"), QStringList("Id of object"));
152 emit setSlotDescription("deleteSelectedVertices(int)", tr("Delete selected vertices"),
153 QStringList("objectId"), QStringList("Id of object"));
154 emit setSlotDescription("selectVertices(int,IdList)", tr("Select the specified vertices"),
155 QString("objectId,vertexList").split(","), QString("Id of object,List of vertices").split(","));
156
157 emit setSlotDescription("selectAllEdges(int)", tr("Select all edges of a polyline"),
158 QStringList("objectId"), QStringList("Id of object"));
159 emit setSlotDescription("deselectAllEdges(int)", tr("Deselect all edges of a polyline"),
160 QStringList("objectId"), QStringList("Id of object"));
161 emit setSlotDescription("invertEdgeSelection(int)", tr("Invert edge selection"),
162 QStringList("objectId"), QStringList("Id of object"));
163 emit setSlotDescription("deleteSelectedEdges(int)", tr("Delete selected edges"),
164 QStringList("objectId"), QStringList("Id of object"));
165 emit setSlotDescription("selectEdges(int,IdList)", tr("Select the specified edges"),
166 QString("objectId,edgeList").split(","), QString("Id of object,List of edges").split(","));
167
168 emit setSlotDescription("loadSelection(int,QString)", tr("Load selection from selection file"),
169 QString("objectId,filename").split(","), QString("Id of an object,Selection file").split(","));
170}
171
172//==============================================================================================
173
174void PolyLineSelectionPlugin::slotSelectionOperation(const QString& _operation) {
175
176 SelectionInterface::PrimitiveType type = 0u;
177 emit getActivePrimitiveType(type);
178
179 if((type & allSupportedTypes_) == 0)
180 return;
181
182 // Test if operation should be applied to target objects only
183 bool targetsOnly = false;
184 emit targetObjectsOnly(targetsOnly);
187
188 if(_operation == V_SELECT_ALL) {
189 // Select all vertices
191 o_it != PluginFunctions::objectsEnd(); ++o_it) {
192 if (o_it->visible()) {
193 selectAllVertices(o_it->id());
194 }
195
196 emit updatedObject(o_it->id(), UPDATE_SELECTION);
197 }
198 } else if (_operation == V_DESELECT_ALL) {
199 // Deselect all vertices
201 o_it != PluginFunctions::objectsEnd(); ++o_it) {
202 if (o_it->visible()) {
203 deselectAllVertices(o_it->id());
204 }
205
206 emit updatedObject(o_it->id(), UPDATE_SELECTION);
207 }
208 } else if (_operation == V_INVERT) {
209 // Deselect all vertices
211 o_it != PluginFunctions::objectsEnd(); ++o_it) {
212 if (o_it->visible()) {
213 invertVertexSelection(o_it->id());
214 }
215
216 emit updatedObject(o_it->id(), UPDATE_SELECTION);
217 }
218 } else if (_operation == V_DELETE) {
219 // Deselect all vertices
221 o_it != PluginFunctions::objectsEnd(); ++o_it) {
222 if (o_it->visible()) {
223 deleteSelectedVertices(o_it->id());
224 }
225
226 emit updatedObject(o_it->id(), UPDATE_SELECTION);
227 }
228 } else if(_operation == E_SELECT_ALL) {
229 // Select all vertices
231 o_it != PluginFunctions::objectsEnd(); ++o_it) {
232 if (o_it->visible()) {
233 selectAllEdges(o_it->id());
234 }
235
236 emit updatedObject(o_it->id(), UPDATE_SELECTION);
237 }
238 } else if (_operation == E_DESELECT_ALL) {
239 // Deselect all vertices
241 o_it != PluginFunctions::objectsEnd(); ++o_it) {
242 if (o_it->visible()) {
243 deselectAllEdges(o_it->id());
244 }
245
246 emit updatedObject(o_it->id(), UPDATE_SELECTION);
247 }
248 } else if (_operation == E_INVERT) {
249 // Deselect all vertices
251 o_it != PluginFunctions::objectsEnd(); ++o_it) {
252 if (o_it->visible()) {
253 invertEdgeSelection(o_it->id());
254 }
255
256 emit updatedObject(o_it->id(), UPDATE_SELECTION);
257 }
258 } else if (_operation == E_DELETE) {
259 // Deselect all vertices
261 o_it != PluginFunctions::objectsEnd(); ++o_it) {
262 if (o_it->visible()) {
263 deleteSelectedEdges(o_it->id());
264 }
265
266 emit updatedObject(o_it->id(), UPDATE_SELECTION);
267 }
268 }
269}
270
271//==============================================================================================
272
273void PolyLineSelectionPlugin::slotToggleSelection(QMouseEvent* _event, SelectionInterface::PrimitiveType _currentType, bool _deselect) {
274
275 // Return if none of the currently active types is handled by this plugin
276 if((_currentType & allSupportedTypes_) == 0) return;
277
278 // Return if mouse event is not a left-button click
279 if(_event->button() != Qt::LeftButton) return;
280
281 size_t node_idx, target_idx;
282 ACG::Vec3d hit_point;
283
284 BaseObjectData* object = 0;
285
286 if(_currentType & vertexType_) {
287 // Perform picking
288 bool successfullyPicked = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_VERTEX, _event->pos(), node_idx,
289 target_idx, &hit_point) && PluginFunctions::getPickedObject(node_idx, object);
290
291 if(successfullyPicked) {
292 PolyLine* polyline = PluginFunctions::polyLine(object);
293
294 if(!polyline)
295 return;
296
297 if(polyline->vertex_selected(target_idx) || _deselect)
298 polyline->deselect_vertex(target_idx);
299 else
300 polyline->select_vertex(target_idx);
301
302 emit updatedObject(object->id(), UPDATE_SELECTION);
303 }
304 }
305
306 if(_currentType & edgeType_) {
307 // Perform picking
308 bool successfullyPicked = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_EDGE, _event->pos(), node_idx,
309 target_idx, &hit_point) && PluginFunctions::getPickedObject(node_idx, object);
310
311 if(successfullyPicked) {
312 PolyLine* polyline = PluginFunctions::polyLine(object);
313
314 if(!polyline)
315 return;
316
317 if(polyline->edge_selected(target_idx) || _deselect)
318 polyline->deselect_edge(target_idx);
319 else
320 polyline->select_edge(target_idx);
321
322 emit updatedObject(object->id(), UPDATE_SELECTION);
323 }
324 }
325}
326
327//==============================================================================================
328
329void PolyLineSelectionPlugin::slotVolumeLassoSelection(QMouseEvent* _event, SelectionInterface::PrimitiveType _currentType, bool _deselect) {
330
331 // Return if none of the currently active types is handled by this plugin
332 if((_currentType & allSupportedTypes_) == 0) return;
333
334 ACG::Vec3d hit_point;
335
336 if(_event->type() == QEvent::MouseButtonPress) {
337
339 QPoint p(_event->pos().x(), state.viewport_height() - _event->pos().y());
340
341 volumeLassoPoints_.append(p);
342
343 return;
344
345 } else if(_event->type() == QEvent::MouseButtonDblClick) {
346
348
349 QPolygon polygon(volumeLassoPoints_);
350
351 bool targetsOnly = false;
352 emit targetObjectsOnly(targetsOnly);
355
356 // Select all vertices that lie in this region
358 o_it != PluginFunctions::objectsEnd(); ++o_it) {
359
360 if (o_it->visible()) {
361
363
364 if(plo) {
365
366 PolyLine* polyline = plo->line();
367
368 if(polyline) {
369
370 if(_currentType & vertexType_) {
371
372 for(unsigned int i = 0; i < polyline->n_vertices(); ++i) {
373 ACG::Vec3d pp = state.project(polyline->point(i));
374 QPoint p((int)pp[0], (int)pp[1]);
375
376 if(polygon.containsPoint(p, Qt::OddEvenFill)) {
377 if(_deselect)
378 polyline->deselect_vertex(i);
379 else
380 polyline->select_vertex(i);
381 }
382 }
383 }
384
385 if(_currentType & edgeType_) {
386
387 for(unsigned int i = 0; i < polyline->n_vertices(); ++i) {
388
389 ACG::Vec3d edgeMidPoint = polyline->point(i) + 0.5*polyline->edge_vector(i);
390
391 ACG::Vec3d pp = state.project(edgeMidPoint);
392 QPoint p((int)pp[0], (int)pp[1]);
393
394 if(polygon.containsPoint(p, Qt::OddEvenFill)) {
395 if(_deselect)
396 polyline->deselect_edge(i);
397 else
398 polyline->select_edge(i);
399 }
400 }
401 }
402 }
403 }
404 }
405
406 emit updatedObject(o_it->id(), UPDATE_SELECTION);
407 }
408
409
410 // Clear lasso points
411 volumeLassoPoints_.clear();
412 }
413}
414
415//==============================================================================================
416
417void PolyLineSelectionPlugin::loadSelection(int _objId, const QString& _filename) {
418
419 // Load ini file
420 INIFile file;
421
422 if(!file.connect(_filename, false)) {
423 emit log(LOGERR, QString("Could not read file '%1'!").arg(_filename));
424 return;
425 }
426
427 // Load selection from file
428 loadIniFile(file, _objId);
429}
430
431//==============================================================================================
432
433void PolyLineSelectionPlugin::loadIniFile(INIFile& _ini, int _id) {
434 // From INI Interface
435 // Load plugin specific settings
436}
437
438//==============================================================================================
439
440void PolyLineSelectionPlugin::saveIniFile(INIFile& _ini, int _id) {
441 // From INI Interface
442 // Save plugin specific settings
443}
444
445//==============================================================================================
446
448
449 // Iterate over all polyline objects in the scene and save
450 // the selections for all supported entity types
452 o_it != PluginFunctions::objectsEnd(); ++o_it) {
453
454 // Read section for each object
455 // Append object name to section identifier
456 QString section = QString("PolyLineSelection") + "//" + o_it->name();
457 if(!_file.section_exists(section)) {
458 continue;
459 }
460
461 std::vector<int> ids;
462 // Load vertex selection:
463 _file.get_entry(ids, section, "VertexSelection");
464 selectVertices(o_it->id(), ids);
465 ids.clear();
466 // Load edge selection:
467 _file.get_entry(ids, section, "EdgeSelection");
468 selectEdges(o_it->id(), ids);
469 ids.clear();
470
471 emit updatedObject(o_it->id(), UPDATE_SELECTION);
472 }
473}
474
475//==============================================================================================
476
478
479 // Iterate over all polyline objects in the scene and save
480 // the selections for all vertices
482 o_it != PluginFunctions::objectsEnd(); ++o_it) {
483
484 // Create section for each object
485 // Append object name to section identifier
486 QString section = QString("PolyLineSelection") + "//" + o_it->name();
487
488 // Store vertex selection:
489 _file.add_entry(section, "VertexSelection", getVertexSelection(o_it->id()));
490 _file.add_entry(section, "EdgeSelection", getEdgeSelection(o_it->id()));
491 }
492}
493
494//==============================================================================================
495
496void PolyLineSelectionPlugin::slotKeyShortcutEvent(int _key, Qt::KeyboardModifiers _modifiers) {
497
498 SelectionInterface::PrimitiveType type = 0u;
499 emit getActivePrimitiveType(type);
500
501 if((type & allSupportedTypes_) == 0) {
502 // No supported type is active
503 return;
504 }
505
506 bool targetsOnly = false;
507 emit targetObjectsOnly(targetsOnly);
510
511 if(_key == Qt::Key_A && _modifiers == Qt::ControlModifier) {
512 // Select all vertices
514 o_it != PluginFunctions::objectsEnd(); ++o_it) {
515 if (o_it->visible()) {
516 if(type & vertexType_)
517 selectAllVertices(o_it->id());
518 if(type & edgeType_)
519 selectAllEdges(o_it->id());
520 }
521 emit updatedObject(o_it->id(), UPDATE_SELECTION);
522 }
523 } else if(_key == Qt::Key_C && _modifiers == Qt::NoModifier) {
524 // Deselect all vertices
526 o_it != PluginFunctions::objectsEnd(); ++o_it) {
527 if (o_it->visible()) {
528 if(type & vertexType_)
529 deselectAllVertices(o_it->id());
530 if(type & edgeType_)
531 deselectAllEdges(o_it->id());
532 }
533 emit updatedObject(o_it->id(), UPDATE_SELECTION);
534 }
535 } else if(_key == Qt::Key_I && _modifiers == Qt::NoModifier) {
536 // Invert vertex selection
538 o_it != PluginFunctions::objectsEnd(); ++o_it) {
539 if (o_it->visible()) {
540 if(type & vertexType_)
541 invertVertexSelection(o_it->id());
542 if(type & edgeType_)
543 invertEdgeSelection(o_it->id());
544 }
545 emit updatedObject(o_it->id(), UPDATE_SELECTION);
546 }
547 } else if(_key == Qt::Key_Delete && _modifiers == Qt::NoModifier) {
548 // Delete selected vertices and its children
550 o_it != PluginFunctions::objectsEnd(); ++o_it) {
551 if (o_it->visible()) {
552 if(type & vertexType_)
553 deleteSelectedVertices(o_it->id());
554 if(type & edgeType_)
555 deleteSelectedEdges(o_it->id());
556 }
557 emit updatedObject(o_it->id(), UPDATE_ALL);
558 }
559 }
560}
561
562//==============================================================================================
563
564
565
566
@ LOGERR
#define DATA_POLY_LINE
Definition: PolyLine.hh:64
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:640
int viewport_height() const
get viewport height
Definition: GLState.hh:849
size_t n_vertices() const
Get number of vertices.
Definition: PolyLineT.hh:119
Point edge_vector(unsigned int _i) const
get the i-th oriented edge vector
Definition: PolyLineT.hh:169
Point & point(unsigned int _i)
Get a point of the polyline.
Definition: PolyLineT.hh:145
int id() const
Definition: BaseObject.cc:188
Predefined datatypes.
Definition: DataTypes.hh:83
Class for the handling of simple configuration files.
Definition: INIFile.hh:100
bool connect(const QString &name, const bool create)
Connect INIFile object with given filename.
Definition: INIFile.cc:70
bool get_entry(QString &_val, const QString &_section, const QString &_key) const
Access to a string entry.
Definition: INIFile.cc:433
bool section_exists(const QString &_section) const
Check if given section exists in the current INI file.
Definition: INIFile.cc:227
void add_entry(const QString &_section, const QString &_key, const QString &_value)
Addition / modification of a string entry.
Definition: INIFile.cc:257
PolyLine * line()
return a pointer to the line
void slotKeyShortcutEvent(int _key, Qt::KeyboardModifiers _modifiers)
One of the previously registered keys has been pressed.
IdList getVertexSelection(int _objectId)
Get current vertex selection.
PrimitiveType vertexType_
Primitive type handles:
PrimitiveType allSupportedTypes_
Handle to selection environment.
void invertEdgeSelection(int _objectId)
Invert edge selection.
void selectEdges(int _objectId, const IdList &_ids, bool _deselect=false)
Select specific edges of a skeleton.
void updateSlotDescriptions()
Set slot descriptions for scripting functions.
void slotVolumeLassoSelection(QMouseEvent *_event, SelectionInterface::PrimitiveType _currentType, bool _deselect)
Called whenever the user performs a volume lasso selection.
void slotLoadSelection(const INIFile &_file)
Load selection for specific objects in the scene.
void deselectAllEdges(int _objectId)
Deselect all edges of a skeleton.
PrimitiveType edgeType_
Handle to selection environment.
QString environmentHandle_
Handle to selection environment.
void selectAllVertices(int _objectId)
Select all vertices of a skeleton.
void invertVertexSelection(int _objectId)
Invert vertex selection.
void deleteSelectedEdges(int _objectId)
Delete selected edges.
PolyLineSelectionPlugin()
Default constructor.
void slotSaveSelection(INIFile &_file)
Save selection for all objects in the scene.
void slotToggleSelection(QMouseEvent *_event, SelectionInterface::PrimitiveType _currentType, bool _deselect)
Called whenever the user performs a toggle selection.
void deselectAllVertices(int _objectId)
Deselect all vertices of a skeleton.
void deleteSelectedVertices(int _objectId)
Delete selected vertices.
QVector< QPoint > volumeLassoPoints_
Keep volume lasso points.
IdList getEdgeSelection(int _objectId)
Get current edge selection.
void selectAllEdges(int _objectId)
Select all edges of a skeleton.
void selectVertices(int _objectId, const IdList &_ids, bool _deselect=false)
Select specific vertices of a skeleton.
~PolyLineSelectionPlugin()
Default destructor.
ACG::GLState & glState()
Get the glState of the Viewer.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
const UpdateType UPDATE_SELECTION(UpdateTypeSet(16))
Selection updated.
@ PICK_EDGE
picks edges (may not be implemented for all nodes)
Definition: PickTarget.hh:80
@ PICK_VERTEX
picks verices (may not be implemented for all nodes)
Definition: PickTarget.hh:82
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
PolyLine * polyLine(BaseObjectData *_object)
Get a poly Line from an object.
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
bool getPickedObject(const size_t _node_idx, BaseObjectData *&_object)
Get the picked mesh.
QStringList IteratorRestriction
Iterable object range.
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, size_t &_nodeIdx, size_t &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
const QStringList TARGET_OBJECTS("target")
Iterable object range.
const QStringList ALL_OBJECTS
Iterable object range.
PolyLineObject * polyLineObject(BaseObjectData *_object)
Cast an BaseObject to a PolyLineObject if possible.