Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
VolumeMeshSelectionPlugin.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: 11942 $ *
45  * $Author: kremer $ *
46  * $Date: 2011-07-06 15:10:17 +0200 (Wed, 06 Jul 2011) $ *
47  * *
48  \*===========================================================================*/
49 
50 #include "VolumeMeshSelectionPlugin.hh"
51 
52 // Primitive type icons
53 #define VERTEX_TYPE "selection_vertex.png"
54 #define EDGE_TYPE "selection_edge.png"
55 #define FACE_TYPE "selection_face.png"
56 #define CELL_TYPE "datacontrol-boundingBox.png"
57 // Custom selection mode
58 #define COLUMN_SELECTION "column-selection.png"
59 #define SHEET_SELECTION "sheet-selection.png"
60 // =======================================
61 // Define operations
62 // =======================================
63 // Vertices:
64 #define V_SELECT_ALL "Select All Vertices"
65 #define V_DESELECT_ALL "Deselect All Vertices"
66 #define V_INVERT "Invert Vertex Selection"
67 #define V_DELETE "Delete Selected Vertices"
68 // Edges:
69 #define E_SELECT_ALL "Select All Edges"
70 #define E_DESELECT_ALL "Deselect All Edges"
71 #define E_INVERT "Invert Edge Selection"
72 #define E_DELETE "Delete Selected Edges"
73 // Faces:
74 #define F_SELECT_ALL "Select All Faces"
75 #define F_DESELECT_ALL "Deselect All Faces"
76 #define F_INVERT "Invert Face Selection"
77 #define F_DELETE "Delete Selected Faces"
78 // Cells:
79 #define C_SELECT_ALL "Select All Cells"
80 #define C_DESELECT_ALL "Deselect All Cells"
81 #define C_INVERT "Invert Cell Selection"
82 #define C_DELETE "Delete Selected Cells"
83 
86  vertexType_(0), edgeType_(0), allSupportedTypes_(0), lastPickedCell_(HexahedralMesh::InvalidCellHandle),
87  lastPickedOrientation_(0) {
88 }
89 
90 //==============================================================================================
91 
93 }
94 
95 //==============================================================================================
96 
97 void VolumeMeshSelectionPlugin::initializePlugin() {
98 
99  // Tell core about all scriptable slots
101 }
102 
103 //==============================================================================================
104 
105 void VolumeMeshSelectionPlugin::pluginsInitialized() {
106  // Create new selection environment for volumemeshs
107  // and register volumemesh data type for the environment.
108 
109  QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
110 
111  emit
112  addSelectionEnvironment("VolumeMesh Selections", "Select volume mesh primitives.",
113  iconPath + "datacontrol-boundingBox.png", environmentHandle_);
114 
115  // Register mesh object types
116  emit
118  emit
120 
121  emit addPrimitiveType(environmentHandle_, "Select Volume Mesh Vertices", iconPath + VERTEX_TYPE, vertexType_);
122  emit addPrimitiveType(environmentHandle_, "Select Volume Mesh Edges", iconPath + EDGE_TYPE, edgeType_);
123  emit addPrimitiveType(environmentHandle_, "Select Volume Mesh Faces", iconPath + FACE_TYPE, faceType_);
124  emit addPrimitiveType(environmentHandle_, "Select Volume Mesh Cells", iconPath + CELL_TYPE, cellType_);
125 
126  emit addCustomSelectionMode(environmentHandle_, "Column Selection", "Select entire column of cells",
127  iconPath + COLUMN_SELECTION, cellType_, columnSelectionHandle_);
128 
129  emit
130  addCustomSelectionMode(environmentHandle_, "Sheet Selection", "Select entire sheet of cells",
131  iconPath + SHEET_SELECTION, cellType_, sheetSelectionHandle_);
132 
135 
136  // Determine, which selection modes are requested
137  emit showToggleSelectionMode(environmentHandle_, true, allSupportedTypes_);
138 
139  emit showVolumeLassoSelectionMode(environmentHandle_, true, allSupportedTypes_);
140  emit showFloodFillSelectionMode(environmentHandle_, true, floodFillSupportedTypes_);
141 
142  // Define vertex operations
143  QStringList vertexOperations;
144  vertexOperations.append(V_SELECT_ALL);
145  vertexOperations.append(V_DESELECT_ALL);
146  vertexOperations.append(V_INVERT);
147  vertexOperations.append(V_DELETE);
148 
149  QStringList edgeOperations;
150  edgeOperations.append(E_SELECT_ALL);
151  edgeOperations.append(E_DESELECT_ALL);
152  edgeOperations.append(E_INVERT);
153  edgeOperations.append(E_DELETE);
154 
155  QStringList faceOperations;
156  faceOperations.append(F_SELECT_ALL);
157  faceOperations.append(F_DESELECT_ALL);
158  faceOperations.append(F_INVERT);
159  faceOperations.append(F_DELETE);
160 
161  QStringList cellOperations;
162  cellOperations.append(C_SELECT_ALL);
163  cellOperations.append(C_DESELECT_ALL);
164  cellOperations.append(C_INVERT);
165  cellOperations.append(C_DELETE);
166 
167  emit
168  addSelectionOperations(environmentHandle_, vertexOperations, "Vertex Operations", vertexType_);
169  emit
170  addSelectionOperations(environmentHandle_, edgeOperations, "Edge Operations", edgeType_);
171  emit
172  addSelectionOperations(environmentHandle_, faceOperations, "Face Operations", faceType_);
173  emit
174  addSelectionOperations(environmentHandle_, cellOperations, "Cell Operations", cellType_);
175 
176  // Register key shortcuts:
177 
178  // Select (a)ll
179  emit
180  registerKeyShortcut(Qt::Key_A, Qt::ControlModifier);
181  // (C)lear selection
182  emit
183  registerKeyShortcut(Qt::Key_C, Qt::NoModifier);
184  // (I)nvert selection
185  emit
186  registerKeyShortcut(Qt::Key_I, Qt::NoModifier);
187  // Delete selected entities
188  emit registerKeyShortcut(Qt::Key_Delete, Qt::NoModifier);
189 }
190 
191 //==============================================================================================
192 
194 
195  /*
196  * TODO: Complete this function for all supported types
197  */
198 }
199 
200 //==============================================================================================
201 
203  SelectionInterface::PrimitiveType t = 0u;
204  emit getActivePrimitiveType(t);
205  return (t & vertexType_) > 0;
206 }
207 
209  SelectionInterface::PrimitiveType t = 0u;
210  emit getActivePrimitiveType(t);
211  return (t & edgeType_) > 0;
212 }
213 
215  SelectionInterface::PrimitiveType t = 0u;
216  emit getActivePrimitiveType(t);
217  return (t & faceType_) > 0;
218 }
219 
221  SelectionInterface::PrimitiveType t = 0u;
222  emit getActivePrimitiveType(t);
223  return (t & cellType_) > 0;
224 }
225 
226 //==============================================================================================
227 
229 
230  SelectionInterface::PrimitiveType type = 0u;
231  emit getActivePrimitiveType(type);
232 
233  if((type & allSupportedTypes_) == 0)
234  return;
235 
236  // Test if operation should be applied to target objects only
237  bool targetsOnly = false;
238  emit targetObjectsOnly(targetsOnly);
241 
242  if (_operation == V_SELECT_ALL) {
244  o_it != PluginFunctions::objectsEnd(); ++o_it) {
245  if (o_it->visible())
246  selectAllVertices(o_it->id());
247  }
248  } else if (_operation == V_DESELECT_ALL) {
250  o_it != PluginFunctions::objectsEnd(); ++o_it) {
251  if (o_it->visible())
252  deselectAllVertices(o_it->id());
253  }
254  } else if (_operation == V_INVERT) {
256  o_it != PluginFunctions::objectsEnd(); ++o_it) {
257  if (o_it->visible())
258  invertVertexSelection(o_it->id());
259  }
260  } else if (_operation == V_DELETE) {
262  o_it != PluginFunctions::objectsEnd(); ++o_it) {
263  if (o_it->visible())
264  deleteSelectedVertices(o_it->id());
265  }
266  } else if (_operation == E_SELECT_ALL) {
268  o_it != PluginFunctions::objectsEnd(); ++o_it) {
269  if (o_it->visible())
270  selectAllEdges(o_it->id());
271  }
272  } else if (_operation == E_DESELECT_ALL) {
274  o_it != PluginFunctions::objectsEnd(); ++o_it) {
275  if (o_it->visible())
276  deselectAllEdges(o_it->id());
277  }
278  } else if (_operation == E_INVERT) {
280  o_it != PluginFunctions::objectsEnd(); ++o_it) {
281  if (o_it->visible())
282  invertEdgeSelection(o_it->id());
283  }
284  } else if (_operation == E_DELETE) {
286  o_it != PluginFunctions::objectsEnd(); ++o_it) {
287  if (o_it->visible())
288  deleteSelectedEdges(o_it->id());
289  }
290  } else if (_operation == F_SELECT_ALL) {
292  o_it != PluginFunctions::objectsEnd(); ++o_it) {
293  if (o_it->visible())
294  selectAllFaces(o_it->id());
295  }
296  } else if (_operation == F_DESELECT_ALL) {
298  o_it != PluginFunctions::objectsEnd(); ++o_it) {
299  if (o_it->visible())
300  deselectAllFaces(o_it->id());
301  }
302  } else if (_operation == F_INVERT) {
304  o_it != PluginFunctions::objectsEnd(); ++o_it) {
305  if (o_it->visible())
306  invertFaceSelection(o_it->id());
307  }
308  } else if (_operation == F_DELETE) {
310  o_it != PluginFunctions::objectsEnd(); ++o_it) {
311  if (o_it->visible())
312  deleteSelectedFaces(o_it->id());
313  }
314  } else if (_operation == C_SELECT_ALL) {
316  o_it != PluginFunctions::objectsEnd(); ++o_it) {
317  if (o_it->visible())
318  selectAllCells(o_it->id());
319  }
320  } else if (_operation == C_DESELECT_ALL) {
322  o_it != PluginFunctions::objectsEnd(); ++o_it) {
323  if (o_it->visible())
324  deselectAllCells(o_it->id());
325  }
326  } else if (_operation == C_INVERT) {
328  o_it != PluginFunctions::objectsEnd(); ++o_it) {
329  if (o_it->visible())
330  invertCellSelection(o_it->id());
331  }
332  } else if (_operation == C_DELETE) {
334  o_it != PluginFunctions::objectsEnd(); ++o_it) {
335  if (o_it->visible())
336  deleteSelectedCells(o_it->id());
337  }
338  }
339 }
340 
341 //==============================================================================================
342 
344  SelectionInterface::PrimitiveType _currentType, bool _deselect) {
345 
346  // Return if none of the currently active types is handled by this plugin
347  if((_currentType & allSupportedTypes_) == 0)
348  return;
349 
350  // Return if mouse event is not a left-button click
351  if(_event->button() != Qt::LeftButton)
352  return;
353 
354  unsigned int node_idx, target_idx;
355  ACG::Vec3d hit_point;
356 
357  BaseObjectData* object = 0;
358 
359  if(_currentType & vertexType_) {
360  // Perform picking
361  bool successfullyPicked = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_VERTEX, _event->pos(),
362  node_idx, target_idx, &hit_point)
363  && PluginFunctions::getPickedObject(node_idx, object);
364 
365  if(successfullyPicked) {
366 
369  if(!polyMesh && !hexMesh) {
370  emit log(LOGERR, tr("Neither polyhedral nor hexahedral mesh!"));
371  return;
372  }
373 
377 
378  if(status[OpenVolumeMesh::VertexHandle(target_idx)].selected() || _deselect)
379  status[OpenVolumeMesh::VertexHandle(target_idx)].set_selected(false);
380  else
381  status[OpenVolumeMesh::VertexHandle(target_idx)].set_selected(true);
382 
383  emit updatedObject(object->id(), UPDATE_SELECTION);
384  }
385  }
386 
387  if(_currentType & edgeType_) {
388  // Perform picking
389  bool successfullyPicked = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_EDGE, _event->pos(), node_idx,
390  target_idx, &hit_point)
391  && PluginFunctions::getPickedObject(node_idx, object);
392 
393  if(successfullyPicked) {
394 
397  if(!polyMesh && !hexMesh) {
398  emit log(LOGERR, tr("Neither polyhedral nor hexahedral mesh!"));
399  return;
400  }
401 
405 
406  if(status[OpenVolumeMesh::EdgeHandle(target_idx)].selected() || _deselect)
407  status[OpenVolumeMesh::EdgeHandle(target_idx)].set_selected(false);
408  else
409  status[OpenVolumeMesh::EdgeHandle(target_idx)].set_selected(true);
410 
411  emit updatedObject(object->id(), UPDATE_SELECTION);
412  }
413  }
414 
415  if(_currentType & faceType_) {
416  // Perform picking
417  bool successfullyPicked = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx,
418  target_idx, &hit_point)
419  && PluginFunctions::getPickedObject(node_idx, object);
420 
421  if(successfullyPicked) {
422 
425  if(!polyMesh && !hexMesh) {
426  emit log(LOGERR, tr("Neither polyhedral nor hexahedral mesh!"));
427  return;
428  }
429 
433 
434  if(status[OpenVolumeMesh::FaceHandle(target_idx)].selected() || _deselect)
435  status[OpenVolumeMesh::FaceHandle(target_idx)].set_selected(false);
436  else
437  status[OpenVolumeMesh::FaceHandle(target_idx)].set_selected(true);
438 
439  emit updatedObject(object->id(), UPDATE_SELECTION);
440  }
441  }
442 
443  if(_currentType & cellType_) {
444 
445  // Perform picking
446  bool successfullyPicked = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_CELL, _event->pos(), node_idx,
447  target_idx, &hit_point)
448  && PluginFunctions::getPickedObject(node_idx, object);
449 
450  if(successfullyPicked) {
451 
454  if(!polyMesh && !hexMesh) {
455  emit log(LOGERR, tr("Neither polyhedral nor hexahedral mesh!"));
456  return;
457  }
458 
462 
463  if(status[OpenVolumeMesh::CellHandle(target_idx)].selected() || _deselect) {
464  status[OpenVolumeMesh::CellHandle(target_idx)].set_selected(false);
465  } else {
466  status[OpenVolumeMesh::CellHandle(target_idx)].set_selected(true);
467  }
468 
469  emit updatedObject(object->id(), UPDATE_SELECTION);
470  }
471  }
472 }
473 
474 //==============================================================================================
475 
477  PrimitiveType _currentType, bool _deselect)
478 {
479  if ((_currentType & allSupportedTypes_) == 0) return;
480 
481  if (_event->type() == QEvent::MouseButtonPress)
482  {
483  volumeLassoPoints_.append(_event->pos());
484  return;
485  }
486  else if (_event->type() == QEvent::MouseButtonDblClick)
487  {
489  bool updateGL = state.updateGL();
490  state.set_updateGL (false);
491 
492  QPolygon p(volumeLassoPoints_);
493  QRegion region = QRegion(p);
494 
495  SelectVolumeAction action(region, this, _currentType, _deselect, state);
497 
498  state.set_updateGL(updateGL);
499 
500  // Clear lasso points
501  volumeLassoPoints_.clear();
502  }
503 }
504 
506  double _maxAngle, PrimitiveType _currentType, bool _deselect)
507 {
508  // Return if none of the currently active types is handled by this plugin
509  if ((_currentType & floodFillSupportedTypes_) == 0)
510  return;
511 
512  unsigned int node_idx, target_idx;
513  ACG::Vec3d hit_point;
514 
515  // pick Anything to find all possible objects
517  _event->pos(), node_idx, target_idx, &hit_point))
518  {
519  BaseObjectData* object = 0;
520 
521  if (PluginFunctions::getPickedObject(node_idx, object))
522  {
523  if (object->dataType() == DATA_POLYHEDRAL_MESH)
524  {
526  _event->pos(), node_idx, target_idx, &hit_point))
527  {
528  if (PluginFunctions::getPickedObject(node_idx, object))
529  {
530  if (object->dataType(DATA_POLYHEDRAL_MESH))
531  {
533  target_idx, _maxAngle, _currentType, _deselect);
534 
535  emit updatedObject(object->id(), UPDATE_SELECTION);
536  }
537  }
538  }
539  }
540  else if(object->dataType() == DATA_HEXAHEDRAL_MESH)
541  {
543  _event->pos(), node_idx, target_idx, &hit_point))
544  {
545  if(PluginFunctions::getPickedObject(node_idx, object) )
546  {
547  if(object->dataType(DATA_HEXAHEDRAL_MESH))
548  {
550  target_idx, _maxAngle, _currentType, _deselect);
551 
552  emit updatedObject(object->id(), UPDATE_SELECTION);
553  }
554  }
555  }
556  }
557  else
558  {
559  emit log(LOGERR, tr("floodFillSelection: Unsupported dataType"));
560  }
561  }
562  }
563 }
564 
567 {
568  BaseObjectData* object = 0;
569  if (PluginFunctions::getPickedObject(_node->id(), object))
570  {
571  bool selected = false;
572  if (object->dataType(DATA_POLYHEDRAL_MESH))
573  {
575  selected = plugin_->volumeSelection(m, state_, &region_, type_, deselection_);
576 
577  } else if(object->dataType(DATA_HEXAHEDRAL_MESH)) {
578 
580  selected = plugin_->volumeSelection(m, state_, &region_, type_, deselection_);
581  }
582 
583  if (selected){
584  emit plugin_->updatedObject(object->id(), UPDATE_SELECTION);
585  }
586  }
587  return true;
588 }
589 
590 //==============================================================================================
591 
592 void VolumeMeshSelectionPlugin::slotCustomSelection(QMouseEvent *_event, PrimitiveType _currentType,
593  QString _customIdentifier, bool _deselect) {
594 
595  if(_customIdentifier != columnSelectionHandle_ && _customIdentifier != sheetSelectionHandle_)
596  return;
597 
598  // Return if mouse event is not a left-button click
599  if(_event->button() != Qt::LeftButton || _event->type() != QEvent::MouseButtonPress)
600  return;
601 
602  if(_customIdentifier == columnSelectionHandle_) {
603 
604  ACG::Vec3d hit_point;
605 
606  if(_currentType & cellType_) {
607 
608  BaseObjectData* object = 0;
609 
610  // Perform picking
611  unsigned int node_idx, target_idx;
612  bool successfullyPicked = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(),
613  node_idx, target_idx, &hit_point)
614  && PluginFunctions::getPickedObject(node_idx, object);
615 
616  if(successfullyPicked) {
617 
619  if(!hexMeshObject) {
620  emit log(LOGERR, "Could not get hexahedral mesh object!");
621  return;
622  }
623  OpenVolumeMesh::StatusAttrib& status = hexMeshObject->status();
624 
625  HexahedralMesh* hexMesh = hexMeshObject->mesh();
626 
627  // Get first inside halfface
630  (hexMesh->is_boundary(hexMesh->halfface_handle(fh, 0)) ? hexMesh->halfface_handle(fh, 1)
631  : hexMesh->halfface_handle(fh, 0));
632 
633  while(!hexMesh->is_boundary(cif)) {
634  // Get associated cell
635  OpenVolumeMesh::CellHandle ch = hexMesh->incident_cell(cif);
636 
637  if(status[ch].selected() || _deselect)
638  status[ch].set_selected(false);
639  else
640  status[ch].set_selected(true);
641 
642  cif = hexMesh->opposite_halfface_handle_in_cell(cif, ch);
643  cif = hexMesh->opposite_halfface_handle(cif);
644  }
645 
646  emit updatedObject(object->id(), UPDATE_SELECTION);
647  }
648  }
649  }
650 
651  if(_customIdentifier == sheetSelectionHandle_) {
652 
653  if(_currentType & cellType_) {
654 
655  BaseObjectData* object = 0;
656  ACG::Vec3d hit_point;
657 
658  // Perform picking
659  unsigned int node_idx, target_idx;
660  bool successfullyPicked = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(),
661  node_idx, target_idx, &hit_point)
662  && PluginFunctions::getPickedObject(node_idx, object);
663 
664  if(successfullyPicked) {
665 
667  if(!hexMeshObject) {
668  emit log(LOGERR, "Could not get hexahedral mesh object!");
669  return;
670  }
671  OpenVolumeMesh::StatusAttrib& status = hexMeshObject->status();
672 
673  HexahedralMesh* hexMesh = hexMeshObject->mesh();
674 
675  // Get first inside halfface
678  (hexMesh->is_boundary(hexMesh->halfface_handle(fh, 0)) ? hexMesh->halfface_handle(fh, 1)
679  : hexMesh->halfface_handle(fh, 0));
680 
681  // Get picked cell
682  OpenVolumeMesh::CellHandle ch = hexMesh->incident_cell(cif);
683 
684  if(lastPickedCell_ == HexahedralMesh::InvalidCellHandle) {
685 
686  lastPickedCell_ = ch;
687  lastPickedOrientation_ = hexMesh->orientation(cif, ch);
688  status[lastPickedCell_].set_selected(!status[lastPickedCell_].selected());
689  emit updatedObject(object->id(), UPDATE_SELECTION);
690  } else {
691 
692  // Select whole sheet
693  // Get orientation of common face
694  HFPair pair = getCommonFace(lastPickedCell_, ch, hexMesh);
695 
696  unsigned char secondDir = hexMesh->orientation(pair.first, lastPickedCell_);
697  unsigned char orthDir = hexMesh->orthogonal_orientation(lastPickedOrientation_, secondDir);
698 
699  orientationMap_.clear();
700  status[lastPickedCell_].set_selected(!status[lastPickedCell_].selected());
701 
702  // Start with last picked cell
703  std::set<OpenVolumeMesh::CellHandle> unprocessed;
704  unprocessed.insert(lastPickedCell_);
705  std::set<OpenVolumeMesh::CellHandle> processed;
706 
707  orientationMap_.insert(
708  std::pair<OpenVolumeMesh::CellHandle, unsigned char>(lastPickedCell_,
709  orthDir));
710 
711  // Flood-fill cell sheet
712  while(!unprocessed.empty() ) {
713 
714  OpenVolumeMesh::CellHandle cur_c = *unprocessed.begin();
715  unprocessed.erase(cur_c);
716  status[cur_c].set_selected(!status[cur_c].selected());
717  processed.insert(cur_c);
718 
719  std::map<OpenVolumeMesh::CellHandle, unsigned char>::iterator f = orientationMap_.find(cur_c);
720  if(f == orientationMap_.end()) {
721  emit log(LOGERR, "Could not get orientation of current cell in sheet!");
722  return;
723  }
724  unsigned char od = f->second;
725 
726  for(OpenVolumeMesh::CellSheetCellIter csc_it = hexMesh->csc_iter(cur_c, od); csc_it.valid(); ++csc_it) {
727  if(processed.count(*csc_it) > 0)
728  continue;
729 
730  unsigned char new_o = getOrthogonalOrientationOfNeighborCell(cur_c, *csc_it, od, hexMesh);
731  orientationMap_.insert(std::pair<OpenVolumeMesh::CellHandle, unsigned char>(*csc_it, new_o));
732  unprocessed.insert(*csc_it);
733  }
734  }
735 
736  lastPickedCell_ = HexahedralMesh::InvalidCellHandle;
737  emit updatedObject(object->id(), UPDATE_SELECTION);
738  }
739  }
740  }
741  }
742 }
743 
744 //==============================================================================================
745 
747  const OpenVolumeMesh::CellHandle& _ch2,
748  unsigned char _firstOrthDirection,
749  const HexahedralMesh* _mesh) const {
750 
751  // Return orientation of halfface in _ch2 that corresponds to
752  // _firstOrthDirection in the first cell
753 
754  OpenVolumeMesh::HalfFaceHandle firstOrthHF = _mesh->get_oriented_halfface(_firstOrthDirection, _ch1);
755  HFPair commonHF = getCommonFace(_ch1, _ch2, _mesh);
756 
757  // Get edge that's shared on the orth side
758  std::vector<OpenVolumeMesh::HalfEdgeHandle> hes1 = _mesh->halfface(firstOrthHF).halfedges();
759  std::vector<OpenVolumeMesh::HalfEdgeHandle> hes2 = _mesh->halfface(commonHF.first).halfedges();
760  OpenVolumeMesh::HalfEdgeHandle sharedHE = HexahedralMesh::InvalidHalfEdgeHandle;
761  for(std::vector<OpenVolumeMesh::HalfEdgeHandle>::const_iterator he_it1 = hes1.begin(); he_it1 != hes1.end(); ++he_it1) {
762  for(std::vector<OpenVolumeMesh::HalfEdgeHandle>::const_iterator he_it2 = hes2.begin(); he_it2 != hes2.end(); ++he_it2) {
763  if(_mesh->edge_handle(*he_it1) == _mesh->edge_handle(*he_it2)) {
764  sharedHE = _mesh->opposite_halfedge_handle(*he_it2);
765  break;
766  }
767  if(sharedHE != HexahedralMesh::InvalidHalfEdgeHandle)
768  break;
769  }
770  }
771 
772  return _mesh->orientation(_mesh->adjacent_halfface_in_cell(commonHF.second, sharedHE), _ch2);
773 }
774 
775 //==============================================================================================
776 
778  const OpenVolumeMesh::CellHandle& _ch2,
779  const HexahedralMesh* _mesh) const {
780 
781  std::vector<OpenVolumeMesh::HalfFaceHandle> hfs1 = _mesh->cell(_ch1).halffaces();
782  std::vector<OpenVolumeMesh::HalfFaceHandle> hfs2 = _mesh->cell(_ch2).halffaces();
783 
784  for(std::vector<OpenVolumeMesh::HalfFaceHandle>::const_iterator hf_it1 = hfs1.begin(); hf_it1 != hfs1.end(); ++hf_it1) {
785 
786  for(std::vector<OpenVolumeMesh::HalfFaceHandle>::const_iterator hf_it2 = hfs2.begin(); hf_it2 != hfs2.end(); ++hf_it2) {
787 
788  if(_mesh->face_handle(*hf_it1) == _mesh->face_handle(*hf_it2)) {
789  return HFPair(*hf_it1, *hf_it2);
790  }
791  }
792  }
793 
794  return HFPair(HexahedralMesh::InvalidHalfFaceHandle, HexahedralMesh::InvalidHalfFaceHandle);
795 }
796 
797 //==============================================================================================
798 
799 void VolumeMeshSelectionPlugin::loadSelection(int _objId, const QString& _filename) {
800 
801 // // Load ini file
802 // INIFile file;
803 //
804 // if(!file.connect(_filename, false)) {
805 // emit log(LOGERR, QString("Could not read file '%1'!").arg(_filename));
806 // return;
807 // }
808 //
809 // // Load selection from file
810 // loadIniFile(file, _objId);
811 }
812 
813 //==============================================================================================
814 
815 void VolumeMeshSelectionPlugin::loadIniFile(INIFile& _ini, int _id) {
816  // From INI Interface
817  // Load plugin specific settings
818 
819  BaseObjectData* bod = NULL;
820  PluginFunctions::getObject(_id, bod);
821  if(!bod) {
822  emit log(LOGERR, "Could not get base object data!");
823  return;
824  }
825 
826  QString section = QString("PolyhedralMeshSelection") + "//" + bod->name();
827  if(!_ini.section_exists(section)) {
828  return;
829  }
830 
831  std::vector<int> ids;
832  // Load vertex selection:
833  _ini.get_entry(ids, section, "VertexSelection");
834  selectVertices(_id, ids);
835  ids.clear();
836  // Load edge selection:
837  _ini.get_entry(ids, section, "EdgeSelection");
838  selectEdges(_id, ids);
839  ids.clear();
840  // Load half-edge selection:
841  _ini.get_entry(ids, section, "HalfEdgeSelection");
842  selectHalfEdges(_id, ids);
843  ids.clear();
844  // Load face selection:
845  _ini.get_entry(ids, section, "FaceSelection");
846  selectFaces(_id, ids);
847  ids.clear();
848  // Load half-face selection:
849  _ini.get_entry(ids, section, "HalfFaceSelection");
850  selectHalfFaces(_id, ids);
851  ids.clear();
852  // Load cell selection:
853  _ini.get_entry(ids, section, "CellSelection");
854  selectCells(_id, ids);
855  ids.clear();
856 }
857 
858 //==============================================================================================
859 
860 void VolumeMeshSelectionPlugin::saveIniFile(INIFile& _ini, int _id) {
861  // From INI Interface
862  // Save plugin specific settings
863 
864  BaseObjectData* bod = NULL;
865  PluginFunctions::getObject(_id, bod);
866  if(!bod) {
867  emit log(LOGERR, "Could not get base object data!");
868  return;
869  }
870 
871  QString section = QString("PolyhedralMeshSelection") + "//" + bod->name();
872 
873  _ini.add_entry(section, "VertexSelection", getVertexSelection(_id));
874  _ini.add_entry(section, "EdgeSelection", getEdgeSelection(_id));
875  _ini.add_entry(section, "HalfEdgeSelection", getHalfEdgeSelection(_id));
876  _ini.add_entry(section, "FaceSelection", getFaceSelection(_id));
877  _ini.add_entry(section, "HalfFaceSelection", getHalfFaceSelection(_id));
878  _ini.add_entry(section, "CellSelection", getCellSelection(_id));
879 }
880 
881 //==============================================================================================
882 
884 
885  // Iterate over all polyhedral mesh objects in the scene and save
886  // the selections for all supported entity types
888  o_it != PluginFunctions::objectsEnd(); ++o_it) {
889 
890  // Read section for each object
891  // Append object name to section identifier
892  QString section = QString("PolyhedralMeshSelection") + "//" + o_it->name();
893  if(!_file.section_exists(section)) {
894  continue;
895  }
896 
897  std::vector<int> ids;
898  // Load vertex selection:
899  _file.get_entry(ids, section, "VertexSelection");
900  selectVertices(o_it->id(), ids);
901  ids.clear();
902  // Load edge selection:
903  _file.get_entry(ids, section, "EdgeSelection");
904  selectEdges(o_it->id(), ids);
905  ids.clear();
906  // Load half-edge selection:
907  _file.get_entry(ids, section, "HalfEdgeSelection");
908  selectHalfEdges(o_it->id(), ids);
909  ids.clear();
910  // Load face selection:
911  _file.get_entry(ids, section, "FaceSelection");
912  selectFaces(o_it->id(), ids);
913  ids.clear();
914  // Load half-face selection:
915  _file.get_entry(ids, section, "HalfFaceSelection");
916  selectHalfFaces(o_it->id(), ids);
917  ids.clear();
918  // Load cell selection:
919  _file.get_entry(ids, section, "CellSelection");
920  selectCells(o_it->id(), ids);
921  ids.clear();
922  }
923 }
924 
925 //==============================================================================================
926 
928 
929  // Iterate over all volumemesh objects in the scene and save
930  // the selections for all vertices
933  o_it != PluginFunctions::objectsEnd(); ++o_it) {
934 
935  // Create section for each object
936  // Append object name to section identifier
937  QString section = QString("PolyhedralMeshSelection") + "//" + o_it->name();
938 
939  // Store vertex selection:
940  _file.add_entry(section, "VertexSelection", getVertexSelection(o_it->id()));
941  _file.add_entry(section, "EdgeSelection", getEdgeSelection(o_it->id()));
942  _file.add_entry(section, "HalfEdgeSelection", getHalfEdgeSelection(o_it->id()));
943  _file.add_entry(section, "FaceSelection", getFaceSelection(o_it->id()));
944  _file.add_entry(section, "HalfFaceSelection", getHalfFaceSelection(o_it->id()));
945  _file.add_entry(section, "CellSelection", getCellSelection(o_it->id()));
946  }
947 }
948 
949 //==============================================================================================
950 
951 void VolumeMeshSelectionPlugin::slotKeyShortcutEvent(int _key, Qt::KeyboardModifiers _modifiers) {
952 
953  SelectionInterface::PrimitiveType type = 0u;
954  emit
955  getActivePrimitiveType(type);
956 
957  if((type & allSupportedTypes_) == 0) {
958  // No supported type is active
959  return;
960  }
961 
962  bool targetsOnly = false;
963  emit
964  targetObjectsOnly(targetsOnly);
967 
968  if(_key == Qt::Key_A && _modifiers == Qt::ControlModifier) {
969  // Select all entities
971  o_it != PluginFunctions::objectsEnd(); ++o_it) {
972  if (o_it->visible()) {
973  if(type & vertexType_)
974  selectAllVertices(o_it->id());
975  if(type & edgeType_)
976  selectAllEdges(o_it->id());
977  if(type & faceType_)
978  selectAllFaces(o_it->id());
979  if(type & cellType_)
980  selectAllCells(o_it->id());
981  }
982  emit updatedObject(o_it->id(), UPDATE_SELECTION);
983  }
984  } else if(_key == Qt::Key_C && _modifiers == Qt::NoModifier) {
985  // Deselect all entities
987  o_it != PluginFunctions::objectsEnd(); ++o_it) {
988  if (o_it->visible()) {
989  if(type & vertexType_)
990  deselectAllVertices(o_it->id());
991  if(type & edgeType_)
992  deselectAllEdges(o_it->id());
993  if(type & faceType_)
994  deselectAllFaces(o_it->id());
995  if(type & cellType_)
996  deselectAllCells(o_it->id());
997  }
998  emit updatedObject(o_it->id(), UPDATE_SELECTION);
999  }
1000  } else if(_key == Qt::Key_I && _modifiers == Qt::NoModifier) {
1001  // Invert entity selection
1003  o_it != PluginFunctions::objectsEnd(); ++o_it) {
1004  if (o_it->visible()) {
1005  if(type & vertexType_)
1006  invertVertexSelection(o_it->id());
1007  if(type & edgeType_)
1008  invertEdgeSelection(o_it->id());
1009  if(type & faceType_)
1010  invertFaceSelection(o_it->id());
1011  if(type & cellType_)
1012  invertCellSelection(o_it->id());
1013  }
1014  emit updatedObject(o_it->id(), UPDATE_SELECTION);
1015  }
1016 
1017  } else if(_key == Qt::Key_Delete && _modifiers == Qt::NoModifier) {
1018  // Delete selected entities and its children
1020  o_it != PluginFunctions::objectsEnd(); ++o_it) {
1021  if(o_it->visible()) {
1022  if(type & vertexType_)
1023  deleteSelectedVertices(o_it->id());
1024  if(type & edgeType_)
1025  deleteSelectedEdges(o_it->id());
1026  if(type & faceType_)
1027  deleteSelectedFaces(o_it->id());
1028  if(type & cellType_)
1029  deleteSelectedCells(o_it->id());
1030  }
1031  emit updatedObject(o_it->id(), UPDATE_ALL);
1032  }
1033  }
1034 }
1035 
1036 //==============================================================================================
1037 
1038 #if QT_VERSION < 0x050000
1039  Q_EXPORT_PLUGIN2(volumemeshselectionplugin, VolumeMeshSelectionPlugin);
1040 #endif
1041 
1042 
QString columnSelectionHandle_
Handle to selection environment.
void slotCustomSelection(QMouseEvent *_event, SelectionInterface::PrimitiveType _currentType, QString _customIdentifier, bool _deselect)
Called whenever the user performs a custom selection.
PrimitiveType allSupportedTypes_
Handle to selection environment.
IdList getCellSelection(int _objectId)
Get current cell selection.
~VolumeMeshSelectionPlugin()
Default destructor.
QString sheetSelectionHandle_
Handle to selection environment.
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
bool cellTypeActive()
Is cell type active? (for use in plugins that need mesh selection)
MeshT * mesh()
return a pointer to the mesh
const QStringList ALL_OBJECTS
Iterable object range.
unsigned int id() const
Definition: BaseNode.hh:399
PrimitiveType edgeType_
Handle to selection environment.
PrimitiveType cellType_
Handle to selection environment.
void slotToggleSelection(QMouseEvent *_event, SelectionInterface::PrimitiveType _currentType, bool _deselect)
Called whenever the user performs a toggle selection.
QString name() const
return the name of the object. The name defaults to NONAME if unset.
Definition: BaseObject.cc:741
VolumeMeshSelectionPlugin()
Default constructor.
picks faces (should be implemented for all nodes)
Definition: BaseNode.hh:104
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
OpenVolumeMesh::CellHandle lastPickedCell_
Handle to selection environment.
#define DATA_POLYHEDRAL_MESH
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
void deleteSelectedVertices(int _objectId, bool _preserveManifoldness=true)
Delete selected vertices from mesh.
bool getObject(int _identifier, BSplineCurveObject *&_object)
void deselectAllFaces(int _objectId)
Deselect all faces of a volume mesh.
std::pair< OpenVolumeMesh::HalfFaceHandle, OpenVolumeMesh::HalfFaceHandle > HFPair
Handle to selection environment.
void invertCellSelection(int _objectId)
Invert cell selection.
bool volumeSelection(MeshT *_mesh, int _objectId, ACG::GLState &_state, QRegion *_region, PrimitiveType _primitiveTypes, bool _deselection)
Surface volume selection tool.
bool faceTypeActive()
Is face type active? (for use in plugins that need mesh selection)
void slotLoadSelection(const INIFile &_file)
Load selection for specific objects in the scene.
const QStringList TARGET_OBJECTS("target")
Iterable object range.
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
picks verices (may not be implemented for all nodes)
Definition: BaseNode.hh:108
void slotKeyShortcutEvent(int _key, Qt::KeyboardModifiers _modifiers)
One of the previously registered keys has been pressed.
bool get_entry(QString &_val, const QString &_section, const QString &_key) const
Access to a string entry.
Definition: INIFile.cc:439
const UpdateType UPDATE_SELECTION(UpdateTypeSet(1)<< 4)
Selection updated.
Traverse the scenegraph and call the selection function for all mesh nodes.
void add_entry(const QString &_section, const QString &_key, const QString &_value)
Addition / modification of a string entry.
Definition: INIFile.cc:263
std::map< OpenVolumeMesh::CellHandle, unsigned char > orientationMap_
Handle to selection environment.
PolyhedralMeshObject * polyhedralMeshObject(BaseObjectData *_object)
Cast an BaseObject to an PolyhedralMeshObject if possible.
PrimitiveType faceType_
Handle to selection environment.
picks edges (may not be implemented for all nodes)
Definition: BaseNode.hh:106
bool edgeTypeActive()
Is vertex type active? (for use in plugins that need mesh selection)
void selectCells(int _objectId, const IdList &_ids, bool _deselect=false)
Select specific cells of a volume mesh.
void selectHalfEdges(int _objectId, const IdList &_ids, bool _deselect=false)
Select specific half-edges of a volume mesh.
Class for the handling of simple configuration files.
Definition: INIFile.hh:105
void invertFaceSelection(int _objectId)
Invert face selection.
void selectAllVertices(int _objectId)
Select all vertices of a volume mesh.
HexahedralMeshObject * hexahedralMeshObject(BaseObjectData *_object)
Cast an BaseObject to an HexahedralMeshObject if possible.
bool operator()(BaseNode *_node)
Traverse the scenegraph and call the selection function for all mesh nodes.
void selectHalfFaces(int _objectId, const IdList &_ids, bool _deselect=false)
Select specific half-faces of a volume mesh.
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
void invertEdgeSelection(int _objectId)
Invert edge selection.
PrimitiveType vertexType_
Primitive type handles:
void deleteSelectedEdges(int _objectId, bool _preserveManifoldness=true)
Delete selected edges from mesh.
const StatusAttrib & status() const
return a pointer to the mesh
ACG::SceneGraph::BaseNode * getRootNode()
Get the root node for data objects.
void selectAllFaces(int _objectId)
Select all faces of a volume mesh.
void selectFaces(int _objectId, const IdList &_ids, bool _deselect=false)
Select specific faces of a volume mesh.
IdList getVertexSelection(int _objectId)
Get current vertex selection.
bool vertexTypeActive()
Is vertex type active? (for use in plugins that need mesh selection)
void set_updateGL(bool _b)
should GL matrices be updated after each matrix operation
Definition: GLState.hh:242
void selectEdges(int _objectId, const IdList &_ids, bool _deselect=false)
Select specific edges of a volume mesh.
void deselectAllVertices(int _objectId)
Deselect all vertices of a volume mesh.
void selectVertices(int _objectId, const IdList &_ids, bool _deselect=false)
Select specific vertices of a volume mesh.
IdList getHalfFaceSelection(int _objectId)
Get current half-face selection.
void deleteSelectedCells(int _objectId, bool _preserveManifoldness=true)
Delete selected cells from mesh.
QVector< QPoint > volumeLassoPoints_
Keep volume lasso points.
picks faces (may not be implemented for all nodes)
Definition: BaseNode.hh:102
void slotVolumeLassoSelection(QMouseEvent *_event, SelectionInterface::PrimitiveType _currentType, bool _deselect)
Called whenever the user performs a volume lasso selection.
void slotSelectionOperation(QString _operation)
A specific operation is requested.
IdList getHalfEdgeSelection(int _objectId)
Get current half-edge selection.
void selectAllEdges(int _objectId)
Select all edges of a volume mesh.
void floodFillSelection(MeshT *_mesh, uint _fh, double _maxAngle, PrimitiveType _primitiveTypes, bool _deselection)
Select all entities that are connected (and do not exceed the maximum dihedral angle) ...
void selectAllCells(int _objectId)
Select all cells of a volume mesh.
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, unsigned int &_nodeIdx, unsigned int &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
unsigned char lastPickedOrientation_
Handle to selection environment.
void updateSlotDescriptions()
Set slot descriptions for scripting functions.
#define DATA_HEXAHEDRAL_MESH
QStringList IteratorRestriction
Iterable object range.
IdList getEdgeSelection(int _objectId)
Get current edge selection.
void deleteSelectedFaces(int _objectId, bool _preserveManifoldness=true)
Delete selected faces from mesh.
void invertVertexSelection(int _objectId)
Invert vertex selection.
bool section_exists(const QString &_section) const
Check if given section exists in the current INI file.
Definition: INIFile.cc:233
HFPair getCommonFace(const OpenVolumeMesh::CellHandle &_ch1, const OpenVolumeMesh::CellHandle &_ch2, const HexahedralMesh *_mesh) const
Handle to selection environment.
Predefined datatypes.
Definition: DataTypes.hh:96
QString environmentHandle_
Handle to selection environment.
PrimitiveType floodFillSupportedTypes_
Handle to selection environment.
ACG::GLState & glState()
Get the glState of the Viewer.
void traverse(BaseNode *_node, Action &_action)
Definition: SceneGraph.hh:143
bool getPickedObject(const unsigned int _node_idx, BaseObjectData *&_object)
Get the picked mesh.
void deselectAllCells(int _objectId)
Deselect all cells of a volume mesh.
IdList getFaceSelection(int _objectId)
Get current face selection.
HexahedralMesh * hexahedralMesh(BaseObjectData *_object)
Get an HexahedralMesh from an object.
void deselectAllEdges(int _objectId)
Deselect all edges of a volume mesh.
int id() const
Definition: BaseObject.cc:201
void slotSaveSelection(INIFile &_file)
Save selection for all objects in the scene.
bool updateGL() const
should GL matrices be updated after each matrix operation
Definition: GLState.hh:240
PolyhedralMesh * polyhedralMesh(BaseObjectData *_object)
Get an PolyhedralMesh from an object.
unsigned char getOrthogonalOrientationOfNeighborCell(const OpenVolumeMesh::CellHandle &_ch1, const OpenVolumeMesh::CellHandle &_ch2, unsigned char _firstOrthDirection, const HexahedralMesh *_mesh) const
Handle to selection environment.
void slotFloodFillSelection(QMouseEvent *_event, double _maxAngle, SelectionInterface::PrimitiveType _currentType, bool _deselect)
Called whenever the user performs a flood fill selection.