Developer Documentation
TypePolyhedralMesh.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 #include "TypePolyhedralMesh.hh"
47 
48 #include <QMenu>
49 #include <QInputDialog>
50 #include <QFormLayout>
51 #include <QLabel>
52 
53 TypePolyhedralMeshPlugin::TypePolyhedralMeshPlugin() :
54 render_switch_(NULL),
55 translucency_factor_action_(NULL),
56 optionsWidget_(NULL),
57 scalingFactorSpinBox_(NULL),
58 translucencyFactorSpinBox_(NULL),
59 renderBoundaryCheckBox_(NULL),
60 scalingFactorSettingName_(name() + QString("/CellScalingFactor")),
61 translucencyFactorSettingName_(name() + QString("/TranslucencyFactor")),
62 renderBoundarySettingName_(name() + QString("/RenderBoundaryOnly"))
63 {
64 }
65 
66 bool TypePolyhedralMeshPlugin::registerType() {
67 
68  addDataType("PolyhedralMesh", tr("Polyhedral Volume Mesh"));
69  setTypeIcon("PolyhedralMesh", "PolyVolMeshType.png");
70  return true;
71 }
72 
73 //----------------------------------------------------------------------------
74 
75 void TypePolyhedralMeshPlugin::pluginsInitialized() {
76 
77  if(OpenFlipper::Options::nogui()) return;
78 
79  emit registerKey(Qt::Key_F8, Qt::ShiftModifier, "Set scaling of cell shrinkage");
80 
81  QMenu* menu = new QMenu("Polyhedral Mesh Options");
82 
83  // scaling action in context menu
84  QAction* act_scale_cells = new QAction(tr("Scale cells (Shift-F8)"), this);
85  act_scale_cells->setStatusTip(tr("Scale cells (Shift-F8)"));
86  connect(act_scale_cells, SIGNAL( triggered() ), this, SLOT( slot_change_shrinkage() ));
87  menu->addAction(act_scale_cells);
88 
89  // Change rendering
90  render_switch_ = new QAction(tr("Render Boundary Only"), this);
91  render_switch_->setStatusTip(tr("Render Boundary Only"));
92  render_switch_->setCheckable(true);
93  render_switch_->setChecked(OpenFlipperSettings().value(renderBoundarySettingName_, false).toBool());
94  connect(render_switch_, SIGNAL( triggered() ), this, SLOT( switchRendering() ));
95  menu->addAction(render_switch_);
96 
97  translucency_factor_action_ = new QAction(tr("Set Translucency Factor"), this);
98  translucency_factor_action_->setStatusTip(tr("Set Translucency Factor"));
99  translucency_factor_action_->setCheckable(false);
100  connect(translucency_factor_action_, SIGNAL( triggered() ), this, SLOT( setTranslucencyFactor() ));
101  menu->addAction(translucency_factor_action_);
102 
103  emit addContextMenuItem(menu->menuAction(), DATA_POLYHEDRAL_MESH, CONTEXTOBJECTMENU);
104 }
105 
106 //----------------------------------------------------------------------------
107 
108 int TypePolyhedralMeshPlugin::addEmpty() {
109 
110 
111  // new object data struct
113 
114  if ( OpenFlipperSettings().value("Core/File/AllTarget",false).toBool() )
115  object->target(true);
116  else {
117 
118  // Only the first object in the scene will be target
119  if ( PluginFunctions::objectCount() == 1 )
120  object->target(true);
121 
122  // If no target is available, we set the new object as target
123  if (PluginFunctions::targetCount() == 0 )
124  object->target(true);
125  }
126 
127  QString name = QString(tr("New PolyHedral Mesh %1.ovm").arg( object->id() ));
128 
129  // call the local function to update names
130  QFileInfo f(name);
131  object->setName(f.fileName());
132 
133  // enable backface culling
134  object->materialNode()->applyProperties(ACG::SceneGraph::MaterialNode::All);
135 
136  // set the default colors
137  const QColor color = OpenFlipper::Options::defaultColor();
138  const ACG::Vec4f default_color(color.redF(), color.greenF(), color.blueF(), color.alphaF());
139  object->materialNode()->set_color(default_color);
140 
141  // Set rendering props
142  if(OpenFlipper::Options::gui())
143  {
144  object->meshNode()->set_scaling(OpenFlipperSettings().value(scalingFactorSettingName_, 0.8).toDouble());
145  object->meshNode()->set_translucency_factor(OpenFlipperSettings().value(translucencyFactorSettingName_, 0.1f).toFloat());
146  object->update();
147 
148  object->show();
149  }
150 
151 
152  // emit log(LOGINFO, object->getObjectinfo());
153 
154  emit emptyObjectAdded(object->id());
155 
156  return object->id();
157 }
158 
159 //----------------------------------------------------------------------------
160 
161 
162 void TypePolyhedralMeshPlugin::slotKeyEvent(QKeyEvent* _event) {
163 
164  switch (_event->key()) {
165  case Qt::Key_F8:
166  if (_event->modifiers() & Qt::ShiftModifier)
167  slot_change_shrinkage();
168  break;
169  default:
170  break;
171  }
172 }
173 
174 //----------------------------------------------------------------------------
175 
176 void TypePolyhedralMeshPlugin::slotObjectUpdated(int _identifier, const UpdateType& _type) {
177 
178  if( !_type.contains(UPDATE_ALL) && !_type.contains(UPDATE_GEOMETRY))
179  return;
180 
181  PlaneObject* pobj;
182  if (PluginFunctions::getObject(_identifier, pobj))
183  slot_update_planes_in_scenegraph_node();
184 }
185 
186 //----------------------------------------------------------------------------
187 
188 void TypePolyhedralMeshPlugin::objectDeleted(int _identifier) {
189 
190  PlaneObject* pobj;
191  if (PluginFunctions::getObject(_identifier, pobj)) {
192  slot_update_planes_in_scenegraph_node(_identifier);
193  }
194 }
195 
196 //----------------------------------------------------------------------------
197 
198 void TypePolyhedralMeshPlugin::switchRendering() {
199 
200  QVariant contextObject = render_switch_->data();
201  int objectId = contextObject.toInt();
202 
203  if(objectId == -1)
204  return;
205 
206  BaseObjectData* bod = 0;
207  if(!PluginFunctions::getObject(objectId, bod))
208  return;
209 
211 
212  if(polyMeshObject) {
213  polyMeshObject->meshNode()->set_boundary_only(render_switch_->isChecked());
214  polyMeshObject->meshNode()->set_geometry_changed(true);
215  }
216 }
217 
218 //----------------------------------------------------------------------------
219 
220 void TypePolyhedralMeshPlugin::setTranslucencyFactor() {
221 
222  QVariant contextObject = translucency_factor_action_->data();
223  int objectId = contextObject.toInt();
224 
225  if(objectId == -1)
226  return;
227 
228  BaseObjectData* bod = 0;
229  if(!PluginFunctions::getObject(objectId, bod))
230  return;
231 
233 
234  if(polyMeshObject) {
235 
236  bool ok;
237  float val = polyMeshObject->meshNode()->translucency_factor();
238  double factor = QInputDialog::getDouble(0, tr("Set translucency factor"), tr("Factor [0, 1]:"), val,
239  0.0, 1.0, 2, &ok);
240 
241  if (ok)
242  polyMeshObject->meshNode()->set_translucency_factor(static_cast<float>(factor));
243  }
244 }
245 
246 //----------------------------------------------------------------------------
247 
248 void TypePolyhedralMeshPlugin::slot_update_planes_in_scenegraph_node(int _deletedObject) {
249 
250  std::vector<Plane> planes;
251 
252  // collect planes
254  != PluginFunctions::objectsEnd(); ++o_it) {
255 
256  if(o_it->id() == _deletedObject) continue;
257 
262  x /= x.sqrnorm();
263  y /= y.sqrnorm();
264 
265  planes.push_back(Plane(p, n, x, y));
266  }
267 
268  // iterate over all target polyvolmeshes
270  != PluginFunctions::objectsEnd(); ++o_it) {
271 
272  PluginFunctions::polyhedralMeshObject(*o_it)->meshNode()->clear_cut_planes();
273  for (unsigned int i = 0; i < planes.size(); ++i) {
274  PluginFunctions::polyhedralMeshObject(*o_it)->meshNode()->add_cut_plane(planes[i]);
275  }
276  PluginFunctions::polyhedralMeshObject(*o_it)->meshNode()->set_geometry_changed(true);
277  }
278 
279  emit updateView();
280 }
281 
282 //----------------------------------------------------------------------------
283 
284 
285 void TypePolyhedralMeshPlugin::slot_change_shrinkage() {
286 
288  != PluginFunctions::objectsEnd(); ++o_it) {
289  // Popup dialog
290  bool ok;
291  double val = PluginFunctions::polyhedralMeshObject(*o_it)->meshNode()->scaling();
292  double scale = QInputDialog::getDouble(0, tr("Set singularity scaling for cell shrinkage"), tr("Size * :"), val,
293  0.0, 1.0, 2, &ok);
294 
295  if (ok) {
296  PluginFunctions::polyhedralMeshObject(*o_it)->meshNode()->set_scaling(scale);
297  emit updatedObject((*o_it)->id(), UPDATE_GEOMETRY);
298  }
299  }
300 }
301 
302 //------------------------------------------------------------------------------
303 
305 {
306  if (!optionsWidget_) {
307 
308  optionsWidget_ = new QWidget;
309  QFormLayout* layout = new QFormLayout;
310 
311  scalingFactorSpinBox_ = new QDoubleSpinBox;
312  scalingFactorSpinBox_->setRange(0.0, 1.0);
313  scalingFactorSpinBox_->setDecimals(2);
314  scalingFactorSpinBox_->setSingleStep(0.01);
315 
316  translucencyFactorSpinBox_ = new QDoubleSpinBox;
317  translucencyFactorSpinBox_->setRange(0.0, 1.0);
318  translucencyFactorSpinBox_->setDecimals(2);
319  translucencyFactorSpinBox_->setSingleStep(0.01);
320 
321  renderBoundaryCheckBox_ = new QCheckBox(tr("Render boundary only"), optionsWidget_);
322 
323  layout->addRow(new QLabel(tr("Default cell scaling factor")), scalingFactorSpinBox_);
324  layout->addRow(new QLabel(tr("Default translucency factor")), translucencyFactorSpinBox_);
325  layout->addRow(renderBoundaryCheckBox_);
326 
327  optionsWidget_->setLayout(layout);
328  }
329 
330  double scalingFactor = OpenFlipperSettings().value(scalingFactorSettingName_, 0.8).toDouble();
331  double translucencyFactor = OpenFlipperSettings().value(translucencyFactorSettingName_, 0.1).toDouble();
332  bool renderBoundary = OpenFlipperSettings().value(renderBoundarySettingName_, false).toBool();
333 
334  scalingFactorSpinBox_->setValue(scalingFactor);
335  translucencyFactorSpinBox_->setValue(translucencyFactor);
336  renderBoundaryCheckBox_->setChecked(renderBoundary);
337 
338  _widget = optionsWidget_;
339 
340  return true;
341 }
342 
343 //------------------------------------------------------------------------------
344 
345 void TypePolyhedralMeshPlugin::applyOptions()
346 {
347  OpenFlipperSettings().setValue(scalingFactorSettingName_, scalingFactorSpinBox_->value());
348  OpenFlipperSettings().setValue(translucencyFactorSettingName_, translucencyFactorSpinBox_->value());
349  OpenFlipperSettings().setValue(renderBoundarySettingName_, renderBoundaryCheckBox_->isChecked());
350 }
351 
352 
353 
#define DATA_POLYHEDRAL_MESH
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
PolyhedralMeshObject * polyhedralMeshObject(BaseObjectData *_object)
Cast an BaseObject to an PolyhedralMeshObject if possible.
virtual void updateView()
Update current view in Main Application.
ACG::Vec3d yDirection()
local y direction (multiplied with height)
Definition: PlaneNode.cc:279
int objectCount()
Get the number of available objects.
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
VolumeMeshObject< PolyhedralMesh > PolyhedralMeshObject
Typedef for a mesh object containing a polyhedral mesh.
ACG::Vec3d xDirection()
local x direction (multiplied with width)
Definition: PlaneNode.cc:272
const QStringList ALL_OBJECTS
Iterable object range.
PlaneNode * planeNode(BaseObjectData *_object)
Get a PlaneNode from an object.
int id() const
Definition: BaseObject.cc:190
DLLEXPORT DataType addDataType(QString _name, QString _readableName)
Adds a datatype and returns the id for the new type.
Definition: Types.cc:117
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
DLLEXPORT void setTypeIcon(DataType _id, QString _icon)
Set an Icon for a given DataType.
Definition: Types.cc:223
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
ACG::Vec3d position()
get center position of the plane
Definition: PlaneNode.cc:258
PolyMeshObject * polyMeshObject(BaseObjectData *_object)
Cast an BaseObject to a PolyMeshObject if possible.
int targetCount()
Get the number of target objects.
Update type class.
Definition: UpdateType.hh:60
const QStringList TARGET_OBJECTS("target")
Iterable object range.
QString name()
Return a name for the plugin.
virtual void registerKey(int _key, Qt::KeyboardModifiers _modifiers, QString _description, bool _multiUse=false)
Register a key-combination for your plugin.
Definition: KeyInterface.hh:71
bool contains(const UpdateType &_type) const
Check if this update contains the given UpdateType.
Definition: UpdateType.cc:104
ACG::SceneGraph::VolumeMeshNodeT< MeshT > * meshNode()
Get the Scenegraph Mesh Node.
decltype(std::declval< S >() *std::declval< S >()) sqrnorm() const
compute squared euclidean norm
Definition: Vector11T.hh:402
#define DATA_PLANE
Definition: Plane.hh:58
bool initializeOptionsWidget(QWidget *&_widget)
Initialize the Options Widget.
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
ACG::Vec3d normal()
get current normal
Definition: PlaneNode.cc:265
The Menu will be shown when an object was picked.
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121