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