RulerPlugin.cc 11.8 KB
Newer Older
Matthias Möller's avatar
Matthias Möller committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*===========================================================================*\
*                                                                            *
*                              OpenFlipper                                   *
*      Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen       *
*                           www.openflipper.org                              *
*                                                                            *
*--------------------------------------------------------------------------- *
*  This file is part of OpenFlipper.                                         *
*                                                                            *
*  OpenFlipper is free software: you can redistribute it and/or modify       *
*  it under the terms of the GNU Lesser General Public License as            *
*  published by the Free Software Foundation, either version 3 of            *
*  the License, or (at your option) any later version with the               *
*  following exceptions:                                                     *
*                                                                            *
*  If other files instantiate templates or use macros                        *
*  or inline functions from this file, or you compile this file and          *
*  link it with other files to produce an executable, this file does         *
*  not by itself cause the resulting executable to be covered by the         *
*  GNU Lesser General Public License. This exception does not however        *
*  invalidate any other reasons why the executable file might be             *
*  covered by the GNU Lesser General Public License.                         *
*                                                                            *
*  OpenFlipper is distributed in the hope that it will be useful,            *
*  but WITHOUT ANY WARRANTY; without even the implied warranty of            *
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
*  GNU Lesser General Public License for more details.                       *
*                                                                            *
*  You should have received a copy of the GNU LesserGeneral Public           *
*  License along with OpenFlipper. If not,                                   *
*  see <http://www.gnu.org/licenses/>.                                       *
*                                                                            *
\*===========================================================================*/

/*===========================================================================*\
*                                                                            *
*   $Revision: 14395 $                                                       *
*   $LastChangedBy: moeller $                                                *
*   $Date: 2012-04-16 14:46:02 +0200 (Mon, 16 Apr 2012) $                     *
*                                                                            *
\*===========================================================================*/


#include "RulerPlugin.hh"

#include <OpenFlipper/BasePlugin/PluginFunctions.hh>

//------------------------------------------------------------------------------
RulerPlugin::RulerPlugin()
:
buttonAction_(0),
pickModeName_("MeasureDistance"),
53
54
55
lineNodeName_("Ruler-Plugin LineNode"),
textNodeName_("Ruler-Plugin TextNode"),
textTransformNodeName_("Ruler-Plugin TransformNode"),
Matthias Möller's avatar
Matthias Möller committed
56
57
58
59
60
hitStage_(firstClick),
hitPoints_( ),
lineNode_(0),
textNode_(0),
textTransformNode_(0),
61
62
lineDrag_(-1),
dblClickCheck_(false)
Matthias Möller's avatar
Matthias Möller committed
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

{

}

//------------------------------------------------------------------------------
RulerPlugin::~RulerPlugin()
{

}
//------------------------------------------------------------------------------
void RulerPlugin::showDistance()
{
  ACG::Vec3d Point1 = hitPoints_[0];
  ACG::Vec3d Point2 = hitPoints_[1];

79
  //creates the line
Matthias Möller's avatar
Matthias Möller committed
80
81
82
83
84
  lineNode_->clear_points();
  lineNode_->set_color(OpenMesh::Vec4f(1.0f,0.0f,0.0f,1.0f));
  lineNode_->set_line_width(3);
  lineNode_->add_line(Point1,Point2);

85
  //set params for the text
Matthias Möller's avatar
Matthias Möller committed
86
87
88
89
  ACG::Vec3d distVec = Point1 - Point2;
  QString distanceStr = QString().number((distVec).length());
  textNode_->setText(distanceStr.toStdString());
  textNode_->multipassNodeSetActive(8, true);
90
  textNode_->setSize(1);
Matthias Möller's avatar
Matthias Möller committed
91

92
  //translate and scale text
Matthias Möller's avatar
Matthias Möller committed
93
  textTransformNode_->loadIdentity();
94
  textTransformNode_->translate(Point1);
Matthias Möller's avatar
Matthias Möller committed
95
  ACG::Vec3d halfDist = distVec/2.f;
96
97
  textTransformNode_->translate(-halfDist);
  textTransformNode_->scale(distVec.length()*0.125);
Matthias Möller's avatar
Matthias Möller committed
98
99
100
101
102
103
104

  emit updateView();
}

//------------------------------------------------------------------------------
void RulerPlugin::initializePlugin()
{
105
  QToolBar *button = new QToolBar("Ruler");
Matthias Möller's avatar
Matthias Möller committed
106
107
108
109
110
111

  buttonAction_ = new QAction(tr("<B>Ruler</B><br> Display the distance between two points."),this);

  button->addAction(buttonAction_);
  buttonAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"ruler.png"));
  buttonAction_->setCheckable(true);
Matthias Möller's avatar
Matthias Möller committed
112
113
  WhatsThisGenerator whatsThisGen("Ruler");
  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>"));
Matthias Möller's avatar
Matthias Möller committed
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

  buttonAction_->setChecked(false);

  connect(buttonAction_,SIGNAL(triggered()), this , SLOT(slotChangePickMode()) );
  emit addToolbar(button);
}

//------------------------------------------------------------------------------
void RulerPlugin::pluginsInitialized()
{
  emit addPickMode(pickModeName_);
}

//------------------------------------------------------------------------------
void RulerPlugin::slotMouseEvent(QMouseEvent* _event)
{
130
131
  if ( PluginFunctions::pickMode() != pickModeName_)
    return;
Matthias Möller's avatar
doc    
Matthias Möller committed
132

133
  //set one of the points, depending on the hit state (first, second or modifying)
Matthias Möller's avatar
Matthias Möller committed
134

135
136
137
138
  if (_event->type() == QEvent::MouseButtonRelease )
  {
    unsigned int node_idx, target_idx;
    OpenMesh::Vec3d hitPoint;
Matthias Möller's avatar
Matthias Möller committed
139

140
141
142
143
144
145
146
147
    // Get picked object's identifier by picking in scenegraph
    if ( PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING ,_event->pos(), node_idx, target_idx, &hitPoint) && !dblClickCheck_)
    {
      if (hitStage_ == firstClick)
      {
        //get or create the line
        BaseObjectData* object;
        if ( PluginFunctions::getPickedObject(node_idx, object) )
Matthias Möller's avatar
Matthias Möller committed
148
149
        {

150
151
152
153
154
155
156
          //create line, point, text and transformation nodes
          if (!object->getAdditionalNode(lineNode_,name(),lineNodeName_.c_str()))
          {
            lineNode_ = new ACG::SceneGraph::LineNode(ACG::SceneGraph::LineNode::LineSegmentsMode,
                object->manipulatorNode(),lineNodeName_);
            object->addAdditionalNode(lineNode_,name(),lineNodeName_.c_str());
          }
Matthias Möller's avatar
Matthias Möller committed
157

158
          if (!object->getAdditionalNode(textTransformNode_,name(),textTransformNodeName_.c_str()))
Matthias Möller's avatar
Matthias Möller committed
159
          {
160
161
            textTransformNode_ = new ACG::SceneGraph::TransformNode(lineNode_,textTransformNodeName_.c_str());
            object->addAdditionalNode(textTransformNode_,name(),textTransformNodeName_.c_str());
Matthias Möller's avatar
Matthias Möller committed
162
          }
163
164

          if (!object->getAdditionalNode(textNode_,name(),textNodeName_.c_str()))
Matthias Möller's avatar
Matthias Möller committed
165
          {
166
167
168
            textNode_ = new ACG::SceneGraph::TextNode(textTransformNode_,textNodeName_,ACG::SceneGraph::TextNode::SCREEN_ALIGNED,true);
            object->addAdditionalNode(textNode_,name(),textNodeName_.c_str());

Matthias Möller's avatar
Matthias Möller committed
169
          }
170
171
172
173
174
175
176
177

        }//end creating nodes

        hitPoints_[1] = hitPoints_[0] = hitPoint;
        hitStage_ = secondClick;

        enableDragMode(1);
        showDistance();
Matthias Möller's avatar
Matthias Möller committed
178
      }
179
      else if (hitStage_ == secondClick)
Matthias Möller's avatar
Matthias Möller committed
180
      {
181
182
183
        disableDragMode();
        //second position was clicked, so distance can be computed and displayed
        hitPoints_[1] = hitPoint;
Matthias Möller's avatar
doc    
Matthias Möller committed
184

185
186
        // show picked object
        showDistance();
Matthias Möller's avatar
Matthias Möller committed
187

188
189
190
        //after this stage, the points can be modified by a simple click
        hitStage_ = modifyPoint;
      }
Matthias Möller's avatar
Matthias Möller committed
191
      else if (hitStage_ == modifyPoint)
192
193
194
195
196
      {
        //two modes:
        //first: no point was dragged, so we can compute and change the position
        //of the nearest one
        if (lineDrag_ < 0)
Matthias Möller's avatar
Matthias Möller committed
197
198
199
200
        {
          float firstDist = (hitPoints_[0] - hitPoint).length();
          float secondDist = (hitPoints_[1] - hitPoint).length();
          if (firstDist < secondDist)
201
            hitPoints_[0] = hitPoint;
Matthias Möller's avatar
Matthias Möller committed
202
          else
203
            hitPoints_[1] = hitPoint;
Matthias Möller's avatar
Matthias Möller committed
204
        }
205
206
207
208
209
210
211
        else
          //second: drag mode is enabled so we can easily update the position
        {
          hitPoints_[lineDrag_] = hitPoint;
          disableDragMode();
        }
        showDistance();
Matthias Möller's avatar
Matthias Möller committed
212
213
      }
    }
214
215
216
217
218
219
220
    else // if nothing was picked
    {
      reset();
    }
  }
  else if (_event->type() == QEvent::MouseButtonPress)
  {//enable drag mode
Matthias Möller's avatar
doc    
Matthias Möller committed
221

222
223
224
225
    if (hitStage_ == modifyPoint)
    {
      //decides which point is the nearest one, so
      //it can be dragged
Matthias Möller's avatar
Matthias Möller committed
226
227
228
229
      unsigned int node_idx, target_idx;
      OpenMesh::Vec3d hitPoint;

      // Get picked object's identifier by picking in scenegraph
230
      if ( PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING ,_event->pos(), node_idx, target_idx, &hitPoint) )
Matthias Möller's avatar
Matthias Möller committed
231
      {
232
233
234
235
        float firstDist = (hitPoints_[0] - hitPoint).length();
        float secondDist = (hitPoints_[1] - hitPoint).length();
        enableDragMode( (firstDist < secondDist)? 0 : 1);
        showDistance();
Matthias Möller's avatar
Matthias Möller committed
236
237
      }
    }
238
239
240
241
242
243
  }
  else if (_event->type() == QEvent::MouseMove && lineDrag_ >= 0)
  {//mouse moved and drag mode is enabled

    unsigned int node_idx, target_idx;
    OpenMesh::Vec3d hitPoint;
Matthias Möller's avatar
Matthias Möller committed
244

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
    // Get picked object's identifier by picking in scenegraph
    if ( !PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING ,_event->pos(), node_idx, target_idx, &hitPoint) )
    {
      //if mouse is not over an object, get the unprojected coordinates and the last z-value
      QPoint position = _event->pos();
      ACG::Vec3d viewCoords = ACG::Vec3d(position.x(), PluginFunctions::viewerProperties().glState().context_height() - position.y(), 0.5);
      hitPoint = PluginFunctions::viewerProperties().glState().unproject(viewCoords);
      hitPoints_[lineDrag_] = ACG::Vec3d(hitPoint.data()[0], hitPoint.data()[1], hitPoints_[lineDrag_].data()[2] );
    }
    else
      hitPoints_[lineDrag_] = hitPoint;
    showDistance();
  }
  else if (_event->type() == QEvent::MouseButtonDblClick)
  {//reset
    reset();
    dblClickCheck_ = true;
Matthias Möller's avatar
Matthias Möller committed
262
  }
263
264
  if (dblClickCheck_ && _event->type() == QEvent::MouseButtonRelease)
    dblClickCheck_ = false;
Matthias Möller's avatar
Matthias Möller committed
265
266
267
268
269
270
}

//------------------------------------------------------------------------------
void RulerPlugin::reset()
{
  hitStage_ = firstClick;
271
  lineDrag_ = -1;
Matthias Möller's avatar
Matthias Möller committed
272
273
274
275
  if (lineNode_)
    lineNode_->clear_points();
  if (textNode_)
    textNode_->setText("");
Matthias Möller's avatar
Matthias Möller committed
276
}
277
278
279
280
281
282
283
284
285
286
287
288
289
//------------------------------------------------------------------------------
void RulerPlugin::enableDragMode(const int _point)
{
  lineDrag_ = _point;
  emit setPickModeMouseTracking(pickModeName_,true);
}

//------------------------------------------------------------------------------
void RulerPlugin::disableDragMode()
{
  lineDrag_ = -1;
  emit setPickModeMouseTracking(pickModeName_,false);
}
Matthias Möller's avatar
Matthias Möller committed
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

//------------------------------------------------------------------------------
void RulerPlugin::slotChangePickMode()
{
  PluginFunctions::actionMode( Viewer::PickingMode );
  PluginFunctions::pickMode(pickModeName_);

}

//------------------------------------------------------------------------------
void RulerPlugin::slotPickModeChanged(const std::string& _mode)
{
  buttonAction_->setChecked(_mode == pickModeName_);
}

305
306
307
308
309
310
311
312
313
314
315
//------------------------------------------------------------------------------
void RulerPlugin::slotAllCleared()
{
  hitStage_ = firstClick;
  lineDrag_ = -1;

  lineNode_ = 0;
  textNode_ = 0;
  textTransformNode_ = 0;
}

Matthias Möller's avatar
Matthias Möller committed
316
Q_EXPORT_PLUGIN2( rulerPlugin , RulerPlugin );