CGR Localization
 All Classes Namespaces Files Functions Variables Macros Pages
vector_display.cpp
1 //========================================================================
2 // This software is free: you can redistribute it and/or modify
3 // it under the terms of the GNU Lesser General Public License Version 3,
4 // as published by the Free Software Foundation.
5 //
6 // This software is distributed in the hope that it will be useful,
7 // but WITHOUT ANY WARRANTY; without even the implied warranty of
8 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 // GNU Lesser General Public License for more details.
10 //
11 // You should have received a copy of the GNU Lesser General Public License
12 // Version 3 in the file COPYING that came with this distribution.
13 // If not, see <http://www.gnu.org/licenses/>.
14 //========================================================================
20 //========================================================================
21 
22 #include "vector_display.h"
23 
24 VectorDisplay::Color::Color(uint32_t col)
25 {
26  r=float((col & 0xFF0000ull)>>16)/255.0;
27  g=float((col & 0xFF00ull)>>8)/255.0;
28  b=float(col & 0xFFull)/255.0;
29 }
30 
31 VectorDisplay::Color::Color(float _r, float _g, float _b)
32 {
33  r=_r;
34  g=_g;
35  b=_b;
36 }
37 
38 VectorDisplay::VectorDisplay(QWidget* parent) : QGLWidget(QGLFormat ( QGL::SampleBuffers ),parent)
39 {
40  lines.clear();
41  points.clear();
42  robotAngle = 0.0;
43  robotLoc.set(0.0,0.0);
44  displayWindow = 100.0;
45 
46  lineThickness = 2.0;
47  pointsSize = 1.5;
48 
49  viewScale = 1.0;
50  viewXOffset = viewYOffset = 0.0;
51 
52  ptrCallback = NULL;
53  followRobot = false;
54  showRobot = true;
55 
56  connect(this, SIGNAL(redraw()), this, SLOT(redrawHandler()));
57 
58 }
59 
60 void VectorDisplay::redrawHandler()
61 {
62  graphicsMutex.lock();
63  this->update();
64  graphicsMutex.unlock();
65 }
66 
67 void VectorDisplay::mousePressEvent(QMouseEvent* event)
68 {
69  leftButton = event->buttons().testFlag(Qt::LeftButton);
70  midButton = event->buttons().testFlag(Qt::MidButton);
71  rightButton = event->buttons().testFlag(Qt::RightButton);
72  bool shiftKey = event->modifiers().testFlag(Qt::ShiftModifier);
73  bool ctrlKey = event->modifiers().testFlag(Qt::ControlModifier);
74  bool altKey = event->modifiers().testFlag(Qt::AltModifier);
75 
76  if(leftButton || midButton){
77  // Start Pan
78  mouseStartX = event->x();
79  mouseStartY = event->y();
80  redraw();
81  }
82  if( (ctrlKey || shiftKey || altKey) && leftButton ){
83  double scale = 2.0*viewScale*min(width(),height())/displayWindow;
84  double x = (double(event->x()) - 0.5*double(width()) - viewXOffset)/scale;
85  double y = (0.5*double(height()) - double(event->y()) - viewYOffset)/scale;
86 
87  setLocation.set(x,y);
88  mouseStartX = event->x();
89  mouseStartY = event->y();
90  }
91 
92 }
93 
94 void VectorDisplay::mouseReleaseEvent(QMouseEvent* event)
95 {
96  bool shiftKey = event->modifiers().testFlag(Qt::ShiftModifier);
97  bool ctrlKey = event->modifiers().testFlag(Qt::ControlModifier);
98  bool altKey = event->modifiers().testFlag(Qt::AltModifier);
99 
100  double scale = 2.0*viewScale*min(width(),height())/displayWindow;
101  double x = (double(event->x()) - 0.5*double(width()) - viewXOffset)/scale;
102  double y = (0.5*double(height()) - double(event->y()) - viewYOffset)/scale;
103  vector2d setLocation2(x,y);
104 
105  if( shiftKey && leftButton ){
106  double setOrientation = atan2(-(event->y()-mouseStartY),event->x()-mouseStartX);
107  if(ptrCallback)
108  ptrCallback(setLocation,setLocation2,setOrientation, 3);
109  }else if( ctrlKey && leftButton ){
110  double setOrientation = atan2(-(event->y()-mouseStartY),event->x()-mouseStartX);
111  if(ptrCallback)
112  ptrCallback(setLocation,setLocation2,setOrientation, 2);
113  }else if( altKey && leftButton ){
114  double setOrientation = atan2(-(event->y()-mouseStartY),event->x()-mouseStartX);
115  if(ptrCallback)
116  ptrCallback(setLocation,setLocation2,setOrientation, 1);
117  }
118 }
119 
120 void VectorDisplay::mouseMoveEvent(QMouseEvent* event)
121 {
122  static const bool debug = false;
123  bool leftButton = event->buttons().testFlag(Qt::LeftButton);
124  bool midButton = event->buttons().testFlag(Qt::MidButton);
125  bool rightButton = event->buttons().testFlag(Qt::RightButton);
126  bool shiftKey = event->modifiers().testFlag(Qt::ShiftModifier);
127  bool ctrlKey = event->modifiers().testFlag(Qt::ControlModifier);
128  bool altKey = event->modifiers().testFlag(Qt::AltModifier);
129 
130  if(debug) printf("MouseMove Event, Left:%d Mid:%d Right:%d\n", leftButton?1:0, midButton?1:0, rightButton?1:0);
131  if(shiftKey || ctrlKey || altKey){
132  //No need to do anything - location or target will be set
133  return;
134  }
135  if(leftButton){
136  //Pan
137  viewXOffset += double(event->x() - mouseStartX);
138  viewYOffset -= double(event->y() - mouseStartY);
139  mouseStartX = event->x();
140  mouseStartY = event->y();
141  redraw();
142  }else if(midButton){
143  //Zoom
144  double zoomRatio = -double(event->y() - mouseStartY)/500.0;
145  double oldScale = viewScale;
146  viewScale = viewScale*(1.0+zoomRatio);
147  viewXOffset *= viewScale/oldScale;
148  viewYOffset *= viewScale/oldScale;
149  mouseStartX = event->x();
150  mouseStartY = event->y();
151  redraw();
152  }
153 }
154 
155 void VectorDisplay::wheelEvent(QWheelEvent* event)
156 {
157  static const bool debug = false;
158  double zoomRatio = double(event->delta())/1000.0;
159  double oldScale = viewScale;
160  viewScale = viewScale*(1.0+zoomRatio);
161  viewXOffset *= viewScale/oldScale;
162  viewYOffset *= viewScale/oldScale;
163  if(debug) printf("Zoom: %5.3f\n",viewScale);
164  redraw();
165 }
166 
167 void VectorDisplay::keyPressEvent(QKeyEvent* event)
168 {
169  static const bool debug = false;
170  // bool shiftKey = event->modifiers().testFlag(Qt::ShiftModifier);
171  bool ctrlKey = event->modifiers().testFlag(Qt::ControlModifier);
172  if(debug) printf("KeyPress: 0x%08X\n",event->key());
173  if(event->key() == Qt::Key_Space)
174  resetView();
175  if(event->key() == Qt::Key_Escape)
176  close();
177  if(event->key() == Qt::Key_F){
178  followRobot = !followRobot;
179  if(followRobot)
180  viewXOffset = viewYOffset = 0.0;
181  redraw();
182  }
183  if(event->key() == Qt::Key_R){
184  showRobot = !showRobot;
185  redraw();
186  }
187  if(event->key() == Qt::Key_BracketLeft){
188  if(ctrlKey)
189  pointsSize = max(0.1,pointsSize-0.1);
190  else
191  lineThickness = max(0.1,lineThickness-0.1);
192  redraw();
193  }
194  if(event->key() == Qt::Key_BracketRight){
195  if(ctrlKey)
196  pointsSize += 0.1;
197  else
198  lineThickness += 0.1;
199  redraw();
200  }
201 }
202 
203 void VectorDisplay::resetView()
204 {
205  viewScale = 1.0;
206  viewXOffset = viewYOffset = 0.0;
207  redraw();
208 }
209 
210 void VectorDisplay::initializeGL()
211 {
212  glEnable(GL_MULTISAMPLE);
213 }
214 
215 void VectorDisplay::setupViewport(int width, int height)
216 {
217  glViewport(0, 0, width, height);
218  glMatrixMode(GL_PROJECTION);
219  glLoadIdentity();
220  glOrtho(-0.5*viewScale*width+viewXOffset, 0.5*viewScale*width+viewXOffset, -0.5*viewScale*height+viewYOffset, 0.5*viewScale*height+viewYOffset, minZValue, maxZValue);
221  glMatrixMode(GL_MODELVIEW);
222 }
223 
224 void VectorDisplay::resizeGL(int width, int height)
225 {
226  setupViewport(width, height);
227 }
228 
229 void VectorDisplay::drawCircles(float lineThickness)
230 {
231  static const float circleSize = 0.3;
232 
233  bool coloredCircles = (circleColors.size()==circles.size());
234  if(coloredCircles){
235  for(unsigned int i=0; i<circles.size(); i++){
236  glColor4f(circleColors[i].red(), circleColors[i].green(), circleColors[i].blue(), 1.0);
237  drawArc(circles[i].x, circles[i].y, circleSize,circleSize+lineThickness,0,M_2PI);
238  }
239  }else{
240  glColor4f(0.35,0.35,0.35,1.0);
241  for(unsigned int i=0; i<circles.size(); i++){
242  drawArc(circles[i].x, circles[i].y, circleSize,circleSize+lineThickness,0,M_2PI);
243  }
244  }
245 }
246 
247 template <class num> void VectorDisplay::drawLine(GVector::vector2d< num >& p0, GVector::vector2d< num >& p1, num lineWidth)
248 {
249  Line2d<num> l(p0,p1);
250  drawLine<num>(l,lineWidth);
251 }
252 
253 template <class num> void VectorDisplay::drawLine(Line2d< num >& line, num lineWidth)
254 {
255  GVector::vector2d<num> v0=line.P0(), v1=line.P1();
256  GVector::vector2d<num> d = line.Dir();
257  GVector::vector2d<num> n = line.Perp()*lineWidth;
258  d *= lineWidth;
259  v0 = v0-d;
260  v1 = v1+d;
261  GVector::vector2d<num> p0=v0-n, p1=v1-n, p2=v1+n, p3=v0+n;
262 
263  //glColor4f(0.35,0.35,0.35,1.0);
264  glBegin(GL_QUADS);
265  glVertex3f(V2COMP(p0),0.0);
266  glVertex3f(V2COMP(p1),0.0);
267  glVertex3f(V2COMP(p2),0.0);
268  glVertex3f(V2COMP(p3),0.0);
269  glEnd();
270 }
271 
272 template <class num> void VectorDisplay::drawPoint(GVector::vector2d<num> loc, float pointSize)
273 {
274  drawQuad(loc.x-pointSize, loc.y-pointSize, loc.x+pointSize, loc.y+pointSize, 0.2);
275 }
276 
277 
278 void VectorDisplay::drawLines(float lineThickness)
279 {
280  bool coloredLines = (lineColors.size()==lines.size());
281  if(coloredLines){
282  for(unsigned int i=0; i<lines.size(); i++){
283  glColor4f(lineColors[i].red(), lineColors[i].green(), lineColors[i].blue(), 1.0);
284  drawLine(lines[i],lineThickness);
285  }
286  }else{
287  glColor4f(0.35,0.35,0.35,1.0);
288  for(unsigned int i=0; i<lines.size(); i++){
289  drawLine(lines[i],lineThickness);
290  }
291  }
292 }
293 
294 void VectorDisplay::drawPoints(float pointsSize)
295 {
296  bool coloredPoints = (pointColors.size()==points.size());
297  if(coloredPoints){
298  for(unsigned int i=0; i<points.size(); i++){
299  glColor4f(pointColors[i].red(), pointColors[i].green(), pointColors[i].blue(), 1.0);
300  drawPoint(points[i],pointsSize);
301  }
302  }else{
303  glColor4f(0.94,0.46,0.12,1.0);
304 
305  for(unsigned int i=0; i<points.size(); i++){
306  drawPoint(points[i],pointsSize);
307  }
308  }
309 }
310 
311 void VectorDisplay::paintEvent(QPaintEvent* event)
312 {
313 
314  graphicsMutex.lock();
315  makeCurrent();
316  glClearColor(BACKGROUND_COLOR);
317  glShadeModel(GL_SMOOTH);
318  glDisable(GL_LIGHTING);
319  glDisable(GL_CULL_FACE);
320  glEnable(GL_DEPTH_TEST);
321  glEnable(GL_MULTISAMPLE);
322 
323  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
324  glMatrixMode(GL_MODELVIEW);
325  glPushMatrix();
326  glLoadIdentity();
327 
328  double scale = 2.0*viewScale*min(width(),height())/displayWindow;
329  glTranslatef(viewXOffset, viewYOffset, 0.0);
330  glScalef(scale,scale,scale);
331 
332  if(followRobot)
333  glTranslatef(-(robotLoc.x),-(robotLoc.y),0.0);
334 
335  drawLines(lineThickness/scale);
336  drawCircles(lineThickness/scale);
337  drawPoints(pointsSize/scale);
338 
339  //drawArc(0,0,1.0, 1.5,0.0,M_2PI);
340  if(showRobot){
341  const double robotSize = 0.25;
342  vector2d h;
343  h.heading(robotAngle);
344  vector2d p = robotLoc + 2.0*robotSize*h;
345  glColor4f(1.0, 0.416, 0.0, 1.0);
346  drawArc(robotLoc,robotSize, robotSize+1.5*lineThickness/scale,0.0,M_2PI,0.0,RAD(4.0));
347  drawLine(robotLoc,p, 0.75*lineThickness/scale);
348  }
349 
350  //vectorTextTest();
351  glPopMatrix();
352  swapBuffers();
353  graphicsMutex.unlock();
354 }
355 
356 void VectorDisplay::updateLines(vector<line2f> _lines, vector<Color> _lineColors)
357 {
358  graphicsMutex.lock();
359  lines = _lines;
360  if(lines.size()==_lineColors.size())
361  lineColors = _lineColors;
362  else
363  lineColors.clear();
364  graphicsMutex.unlock();
365  redraw();
366 }
367 
368 void VectorDisplay::updatePoints(vector< vector2f > _points, vector< Color > _pointColors)
369 {
370  graphicsMutex.lock();
371  points = _points;
372  if(points.size()==_pointColors.size())
373  pointColors = _pointColors;
374  else
375  pointColors.clear();
376  graphicsMutex.unlock();
377  redraw();
378 }
379 
380 void VectorDisplay::updateCircles(vector< vector2f > _circles, vector< Color > _circleColors)
381 {
382  graphicsMutex.lock();
383  circles = _circles;
384  if(circles.size()==_circleColors.size())
385  circleColors = _circleColors;
386  else
387  circleColors.clear();
388  graphicsMutex.unlock();
389  redraw();
390 }
391 
392 void VectorDisplay::updateDisplay(vector2d _robotLoc, double _robotAngle, double _displayWindow,
393  vector<line2f> _lines, vector<vector2f> _points, vector<vector2f> _circles,
394  vector<Color> _lineColors, vector<Color> _pointColors, vector<Color> _circleColors)
395 {
396  updateLines(_lines,_lineColors);
397  updatePoints(_points,_pointColors);
398  updateCircles(_circles,_circleColors);
399  graphicsMutex.lock();
400  robotAngle = _robotAngle;
401  robotLoc = _robotLoc;
402  displayWindow = _displayWindow;
403  graphicsMutex.unlock();
404  redraw();
405 }
406 
407 void VectorDisplay::resizeEvent(QResizeEvent* event)
408 {
409  QGLWidget::resizeEvent(event);
410  redraw();
411 }
412 
413 template <class num> void VectorDisplay::drawQuad(GVector::vector2d< num > loc1, GVector::vector2d< num > loc2, num z)
414 {
415  glBegin(GL_QUADS);
416  glVertex3d(loc1.x,loc1.y,z);
417  glVertex3d(loc2.x,loc1.y,z);
418  glVertex3d(loc2.x,loc2.y,z);
419  glVertex3d(loc1.x,loc2.y,z);
420  glEnd();
421 }
422 
423 template <class num> void VectorDisplay::drawArc(GVector::vector2d< num > loc, num r1, num r2, num theta1, num theta2, num z, num dTheta)
424 {
425  static const double tesselation = 0.1;
426  if(dTheta<0){
427  dTheta = tesselation/r2;
428  }
429  glBegin(GL_QUAD_STRIP);
430  for(double theta=theta1; theta<theta2; theta+=dTheta){
431  double c1 = cos(theta), s1 = sin(theta);
432  glVertex3d(r2*c1+loc.x,r2*s1+loc.y,z);
433  glVertex3d(r1*c1+loc.x,r1*s1+loc.y,z);
434  }
435  double c1 = cos(theta2), s1 = sin(theta2);
436  glVertex3d(r2*c1+loc.x,r2*s1+loc.y,z);
437  glVertex3d(r1*c1+loc.x,r1*s1+loc.y,z);
438  glEnd();
439 }
void set(num nx, num ny)
set the components of the vector
Definition: gvector.h:768
A GUI for Vector Localization; C++ Interface: VectorDisplay.
void redraw()
Accept Signals to update display.
Definition: line.h:33
void paintEvent(QPaintEvent *event)
Thread-safe way of scheduling display updates.
void heading(num angle)
make a unit vector at given angle
Definition: gvector.h:802