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