Developer Documentation
RulerPlugin.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 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 #include "RulerPlugin.hh"
52 
55 
56 //------------------------------------------------------------------------------
57 RulerPlugin::RulerPlugin()
58 :
59 buttonAction_(0),
60 pickModeName_("MeasureDistance"),
61 lineDrag_(-1),
62 dblClickCheck_(false),
63 optionsWidget_(0),
64 textSizeSettingName_(name()+QString("/TextSize"))
65 {
66 
67 }
68 
69 //------------------------------------------------------------------------------
70 RulerPlugin::~RulerPlugin()
71 {
72  reset();
73 }
74 //------------------------------------------------------------------------------
75 void RulerPlugin::initializePlugin()
76 {
77  QToolBar *button = new QToolBar("Ruler");
78 
79  buttonAction_ = new QAction(tr("<B>Ruler</B><br> Display the distance between two points."),this);
80 
81  button->addAction(buttonAction_);
82  buttonAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"ruler.png"));
83  buttonAction_->setCheckable(true);
84  WhatsThisGenerator whatsThisGen("Ruler");
85  whatsThisGen.setWhatsThis(buttonAction_,tr("Measures the distance between two points.<br><b>LeftClick</b>: define/change the position.<br><b>DoubleClick</b>: reset the ruler.<br>"));
86 
87  buttonAction_->setChecked(false);
88 
89  connect(buttonAction_,SIGNAL(triggered()), this , SLOT(slotChangePickMode()) );
90  emit addToolbar(button);
91 }
92 
93 //------------------------------------------------------------------------------
94 void RulerPlugin::pluginsInitialized()
95 {
96  emit addPickMode(pickModeName_);
97 }
98 
99 //------------------------------------------------------------------------------
100 void RulerPlugin::slotMouseEvent(QMouseEvent* _event)
101 {
102  if ( PluginFunctions::pickMode() != pickModeName_)
103  return;
104 
106 //set one of the points, depending on the hit state (first, second or modifying)
107  if (_event->type() == QEvent::MouseButtonRelease )
108  {
109  unsigned int node_idx, target_idx;
110  OpenMesh::Vec3d hitPoint;
111 
112  // Get picked object's identifier by picking in scenegraph
113  if ( PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING ,_event->pos(), node_idx, target_idx, &hitPoint) && !dblClickCheck_)
114  {
115  if (!currentRuler_)
116  {
117  //create a new Ruler
118  BaseObjectData* object;
119  if ( PluginFunctions::getPickedObject(node_idx, object) )
120  {
121  currentRuler_.reset(new Ruler(object,name(),0));
122  connect(currentRuler_.get(),SIGNAL(updateView()),this,SIGNAL(updateView()));
123  unsigned textSize = OpenFlipperSettings().value(textSizeSettingName_,16).toUInt();
124  currentRuler_->setTextSize(textSize);
125  currentRuler_->setPoints(hitPoint,hitPoint);
126  enableDragMode(1);
127  }
128 
129  }
130  else
131  {
132  //Ruler was created -> change position of a point
133  if (!dragModeActive())
134  {
135  //dragmode is disabled -> update position of nearest point
136  float distToStart = (currentRuler_->points()[0] - hitPoint).length();
137  float distToEnd = (currentRuler_->points()[1] - hitPoint).length();
138  if (distToStart < distToEnd)
139  currentRuler_->setStartPoint(hitPoint);
140  else
141  currentRuler_->setEndPoint(hitPoint);
142  }
143  else
144  {
145  //second: drag mode is enabled so we can easily update the position
146  if (lineDrag_ == 0)
147  currentRuler_->setStartPoint(hitPoint);
148  else
149  currentRuler_->setEndPoint(hitPoint);
150  disableDragMode();
151  }
152  }
153  }
154  else // if nothing was picked
155  {
156  reset();
157  }
158  }
159 
161  else if (_event->type() == QEvent::MouseButtonPress)
162  {//enable drag mode
163 
164  if (currentRuler_)
165  {
166  //decides which point is the nearest one, so
167  //it can be dragged
168  unsigned int node_idx, target_idx;
169  OpenMesh::Vec3d hitPoint;
170 
171  // Get picked object's identifier by picking in scenegraph
172  if ( PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING ,_event->pos(), node_idx, target_idx, &hitPoint) )
173  {
174  float distToStart = (currentRuler_->points()[0] - hitPoint).length();
175  float distToEnd = (currentRuler_->points()[1] - hitPoint).length();
176  enableDragMode( (distToStart < distToEnd)? 0 : 1);
177  }
178  }
179  }
181  else if (_event->type() == QEvent::MouseMove && dragModeActive())
182  {//mouse moved and drag mode is enabled
183 
184  unsigned int node_idx, target_idx;
185  OpenMesh::Vec3d hitPoint;
186  ACG::Vec3d hitPoints[2];
187  std::copy(currentRuler_->points(),currentRuler_->points()+2,hitPoints);
188 
189  // Get picked object's identifier by picking in scenegraph
190  if ( !PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING ,_event->pos(), node_idx, target_idx, &hitPoint) )
191  {
192  //if mouse is not over an object, get the unprojected coordinates and the last z-value
193  QPoint position = _event->pos();
194  ACG::Vec3d viewCoords = ACG::Vec3d(position.x(), PluginFunctions::viewerProperties().glState().context_height() - position.y(), 0.5);
195  hitPoint = PluginFunctions::viewerProperties().glState().unproject(viewCoords);
196  hitPoints[lineDrag_] = ACG::Vec3d(hitPoint.data()[0], hitPoint.data()[1], hitPoints[lineDrag_].data()[2] );
197  }
198  else
199  hitPoints[lineDrag_] = hitPoint;
200 
201  currentRuler_->setPoints(hitPoints[0],hitPoints[1]);
202  }
203 
205  else if (_event->type() == QEvent::MouseButtonDblClick)
206  {//reset
207  reset();
208  dblClickCheck_ = true;
209  }
210  if (dblClickCheck_ && _event->type() == QEvent::MouseButtonRelease)
211  dblClickCheck_ = false;
212 }
213 
214 //------------------------------------------------------------------------------
215 void RulerPlugin::reset()
216 {
217  currentRuler_.reset();
218  lineDrag_ = -1;
219 }
220 //------------------------------------------------------------------------------
221 void RulerPlugin::enableDragMode(const int _point)
222 {
223  lineDrag_ = _point;
224  emit setPickModeMouseTracking(pickModeName_,true);
225 }
226 
227 //------------------------------------------------------------------------------
228 void RulerPlugin::disableDragMode()
229 {
230  lineDrag_ = -1;
231  emit setPickModeMouseTracking(pickModeName_,false);
232 }
233 
234 //------------------------------------------------------------------------------
235 void RulerPlugin::slotChangePickMode()
236 {
237  PluginFunctions::actionMode( Viewer::PickingMode );
238  PluginFunctions::pickMode(pickModeName_);
239 
240 }
241 
242 //------------------------------------------------------------------------------
243 void RulerPlugin::slotPickModeChanged(const std::string& _mode)
244 {
245  buttonAction_->setChecked(_mode == pickModeName_);
246 }
247 
248 //------------------------------------------------------------------------------
249 void RulerPlugin::slotAllCleared()
250 {
251  disableDragMode();
252 }
253 
254 void RulerPlugin::objectDeleted(int _id)
255 {
256  if (!currentRuler_)
257  return;
258 
259  disableDragMode();
260  if (_id == currentRuler_->getBaseObj()->id())
261  {
262  disconnect(currentRuler_.get(),SIGNAL(updateView()),this,SIGNAL(updateView()));
263  currentRuler_.reset();
264  }
265 }
266 //------------------------------------------------------------------------------
268 {
269  if (!optionsWidget_)
270  {
271  optionsWidget_ = new RulerOptions();
272  }
273 
274  unsigned textSize = OpenFlipperSettings().value(textSizeSettingName_,16).toUInt();
275  optionsWidget_->textSizeSpinBox->setValue(textSize);
276  _widget = optionsWidget_;
277  return true;
278 }
279 //------------------------------------------------------------------------------
280 void RulerPlugin::applyOptions()
281 {
282  int textSize = optionsWidget_->textSizeSpinBox->value();
283  if (currentRuler_)
284  currentRuler_->setTextSize(textSize);
285  OpenFlipperSettings().setValue(textSizeSettingName_,textSize);
286 }
287 //------------------------------------------------------------------------------
288 void RulerPlugin::slotViewChanged()
289 {
290 
291  if (!currentRuler_)
292  return;
293 
294  //compute line direction
295  ACG::Vec3d lineVector = currentRuler_->points()[0] - currentRuler_->points()[1];
297 
298  float cosAngleLineRight = lineVector.normalize() | rightVec;
299  float cosAngleUpLine = PluginFunctions::upVector().normalized() | lineVector.normalized() ;
300 
301 
302  rightVec *= -0.5f*currentRuler_->textScale();
303  ACG::Vec3d updownVec = PluginFunctions::upVector()*currentRuler_->textScale();
304 
305  //compute up/down offset
306  if (cosAngleLineRight > 0.f)
307  {
308  updownVec *= (cosAngleUpLine < 0.f) ? -2.f : 0.5f;
309  }
310  else
311  {
312  updownVec *= (cosAngleUpLine < 0.f) ? 0.5f : -2.0f;
313  }
314 
315  // small offset to the right and big offset up/down depending on the line
316  currentRuler_->setTextOffset(rightVec+updownVec);
317 
318 
319 }
320 
321 #if QT_VERSION < 0x050000
322  Q_EXPORT_PLUGIN2( rulerPlugin , RulerPlugin );
323 #endif
324 
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, unsigned int &_nodeIdx, unsigned int &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
ACG::Vec3d upVector(int _viewer)
Get the current up vector.
ACG::GLState & glState()
Get the glState of the Viewer.
int context_height() const
get gl context height
Definition: GLState.hh:833
auto normalized() const -> decltype(*this/std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:439
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
bool getPickedObject(const unsigned int _node_idx, BaseObjectData *&_object)
Get the picked mesh.
a class which provides an link generator for WhatsThisMessages linking to the user doc If you have an...
const std::string pickMode()
Get the current Picking mode.
bool initializeOptionsWidget(QWidget *&_widget)
Initialize the Options Widget.
Definition: RulerPlugin.cc:267
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
void viewingDirection(const ACG::Vec3d &_dir, const ACG::Vec3d &_up, int _viewer)
Set the viewing direction.
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:649
Definition: Ruler.hh:56
Viewer::ActionMode actionMode()
Get the current Action mode.
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:428
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
Scalar * data()
access to Scalar array
Definition: Vector11T.hh:193