Qt Virtual Chart Table (QVCT)
CInstrumentGASpeed.cpp
Go to the documentation of this file.
1 // INDENTING (emacs/vi): -*- mode:c++; tab-width:2; c-basic-offset:2; intent-tabs-mode:nil; -*- ex: set tabstop=2 expandtab:
2 
3 /*
4  * Qt Virtual Chart Table (QVCT)
5  * Copyright (C) 2012 Cedric Dufour <http://cedric.dufour.name>
6  * Author: Cedric Dufour <http://cedric.dufour.name>
7  *
8  * The Qt Virtual Chart Table (QVCT) is free software:
9  * you can redistribute it and/or modify it under the terms of the GNU General
10  * Public License as published by the Free Software Foundation, Version 3.
11  *
12  * The Qt Virtual Chart Table (QVCT) is distributed in the hope
13  * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
14  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15  *
16  * See the GNU General Public License for more details.
17  */
18 
19 // C/C++
20 #include <cmath>
21 
22 // QT
23 #include <QBrush>
24 #include <QFont>
25 #include <QPainter>
26 #include <QPointF>
27 #include <QPen>
28 #include <QPixmap>
29 #include <QSizeF>
30 #include <QWidget>
31 
32 // QVCT
33 #include "QVCTRuntime.hpp"
35 
36 
37 //------------------------------------------------------------------------------
38 // CONSTRUCTORS / DESTRUCTOR
39 //------------------------------------------------------------------------------
40 
42  : CInstrument( _poVesselCockpit )
43  , bForceRedraw( true )
44  , eUnit( CUnitSpeed::M_S )
45  , fdSpeed( CDataCourse::UNDEFINED_SPEED )
46 {
47 }
48 
49 
50 //------------------------------------------------------------------------------
51 // METHODS: CInstrument (implement/override)
52 //------------------------------------------------------------------------------
53 
55 {
56  // Retrieve parameters and values
57  CVesselPoint* __poVesselPoint = CInstrument::useVesselPoint();
59  double __fdSpeed = __poVesselPoint ? __poVesselPoint->GroundCourse.getSpeed() : 0.0;
60 
61  // Redraw pixmap only if required
62  if( bForceRedraw
63  || qPixmapBuffer.size() != QWidget::size()
64  || eUnit != __eUnit
65  || fdSpeed != __fdSpeed )
66  {
67  // Draw resources
68  if( bForceRedraw
69  || qPixmapBufferBackground.size() != QWidget::size()
70  || eUnit != __eUnit )
71  {
72  drawStatic( __eUnit );
73  }
74  drawDynamic( __eUnit, __poVesselPoint );
75 
76  // Update cache parameters and values
77  bForceRedraw = false;
78  eUnit = __eUnit;
79  fdSpeed = __fdSpeed;
80  }
81 
82  // Draw pixmap
83  QPainter __qPainter;
84  __qPainter.begin( this );
85  __qPainter.setRenderHints( QPainter::SmoothPixmapTransform | QPainter::Antialiasing | QPainter::TextAntialiasing );
86  __qPainter.drawPixmap( 0, 0, qPixmapBuffer );
87  __qPainter.end();
88 }
89 
90 
91 //------------------------------------------------------------------------------
92 // METHODS
93 //------------------------------------------------------------------------------
94 
95 //
96 // OTHER
97 //
98 
100 {
101  // Widget geometry
102  QPointF __qPointFCenter = QPointF( QRectF( QWidget::rect() ).center() );
103  double __fdSizeFactor = ( QWidget::width() < QWidget::height() ? (double)QWidget::width() : (double)QWidget::height() ) / 1200.0;
104  QTransform __qTransform;
105  __qTransform.translate( __qPointFCenter.x(), __qPointFCenter.y() );
106  __qTransform.scale( __fdSizeFactor, __fdSizeFactor );
107 
108  // Painter and resources
109  if( qPixmapBufferBackground.size() != QWidget::size() ) qPixmapBufferBackground = QPixmap( QWidget::size() );
110  qPixmapBufferBackground.fill( Qt::transparent );
111  QPainter __qPainter( &qPixmapBufferBackground );
112  QPen __qPen;
113  QFont __qFont;
114  __qPainter.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing );
115 
116  // Draw
117  __qPainter.setWorldTransform( __qTransform );
118  int __iTicksLarge = 0, __iTicksSmall = 0, __iDigitsMax = 0;
119  switch( _eUnit )
120  {
121  case CUnitSpeed::M_S: __iTicksLarge = 7; __iTicksSmall = 35; __iDigitsMax = 150; break;
122  case CUnitSpeed::KM_H: __iTicksLarge = 6; __iTicksSmall = 30; __iDigitsMax = 600; break;
123  case CUnitSpeed::MI_H: __iTicksLarge = 7; __iTicksSmall = 35; __iDigitsMax = 350; break;
124  case CUnitSpeed::KT: __iTicksLarge = 6; __iTicksSmall = 30; __iDigitsMax = 300; break;
125  default: return;
126  }
127 
128  // ... delimiting corona
129  __qPen.setColor( Qt::white );
130  __qPen.setWidth( 10.0 );
131  __qPainter.setPen( __qPen );
132  __qPainter.setBrush( QBrush( QColor( 32, 32, 32, 255 ) ) );
133  __qPainter.drawEllipse( QPointF( 0.0, 0.0 ), 495.0, 495.0 );
134 
135  // ... small ticks
136  for( int __i=0; __i<=__iTicksSmall; __i++ )
137  {
138  double __fdAngle = (double)__i * QVCT::PI * 34.0 / 18.0 / __iTicksSmall;
139  QPointF __qPointFAngle( sin( __fdAngle ), -cos( __fdAngle ) );
140  __qPainter.drawLine( 450.0*__qPointFAngle, 480.0*__qPointFAngle );
141  }
142 
143  // ... large ticks and digits
144  __qFont.setPixelSize( 90.0 );
145  __qFont.setBold( true );
146  __qPainter.setFont( __qFont );
147  {
148  QRectF __qRectFText( QPointF( -135.0, -45.0 ), QSizeF( 270.0, 90.0 ) );
149  for( int __i=0; __i<=__iTicksLarge; __i++ )
150  {
151  double __fdAngle = (double)__i * QVCT::PI * 34.0 / 18.0 / __iTicksLarge;
152  QPointF __qPointFAngle( sin( __fdAngle ), -cos( __fdAngle ) );
153  __qPainter.drawLine( 420.0*__qPointFAngle, 480.0*__qPointFAngle );
154  if( !__i ) continue;
155  QPointF __qPointFAngleText( __qPointFAngle.x(), __qPointFAngle.y()*1.15 );
156  __qPainter.drawText( __qRectFText.translated( 300.0*__qPointFAngleText ), Qt::AlignCenter, QString::number( __i*__iDigitsMax/__iTicksLarge ) );
157  }
158  }
159 
160  // ... name and units
161  __qPen.setColor( Qt::lightGray );
162  __qPen.setWidth( 5.0 );
163  __qPainter.setPen( __qPen );
164  __qPainter.setBrush( QBrush( QColor( 32, 32, 32, 255 ) ) );
165  __qFont.setPixelSize( 50.0 );
166  __qFont.setBold( false );
167  __qPainter.setFont( __qFont );
168  {
169  QRectF __qRectFText( QPointF( -200.0, -30.0 ), QSizeF( 400.0, 60.0 ) );
170  __qPainter.drawText( __qRectFText.translated( QPointF( 0, -150.0 ) ), Qt::AlignCenter, CUnitSpeed::toSymbol( _eUnit ) );
171  __qPainter.drawText( __qRectFText.translated( QPointF( 0, +150.0 ) ), Qt::AlignCenter, "GS" );
172  }
173 
174  // ... data
175  {
176  QRectF __qRectFFrame( QPointF( -150.0, -60.0 ), QSizeF( 300.0, 120.0 ) );
177  QRectF __qRectFText( QPointF( -125.0, -30.0 ), QSizeF( 250.0, 60.0 ) );
178  __qPainter.drawRoundedRect( __qRectFFrame.translated( QPointF( +425.0, +515.0 ) ), 10.0, 10.0 );
179  __qPainter.drawText( __qRectFText.translated( QPointF( +440.0, +540.0 ) ), Qt::AlignRight, CUnitSpeed::toSymbol( _eUnit ) );
180  }
181 }
182 
184 {
185  double __fdSpeed = _poVesselPoint ? _poVesselPoint->GroundCourse.getSpeed() : 0.0;
186  double __fdSpeedConverted = __fdSpeed != CDataCourse::UNDEFINED_SPEED ? CUnitSpeed::toValue( __fdSpeed, _eUnit ) : 0.0;
187 
188  // Widget geometry
189  QPointF __qPointFCenter = QPointF( QRectF( QWidget::rect() ).center() );
190  double __fdSizeFactor = ( QWidget::width() < QWidget::height() ? (double)QWidget::width() : (double)QWidget::height() ) / 1200.0;
191  QTransform __qTransform;
192  __qTransform.translate( __qPointFCenter.x(), __qPointFCenter.y() );
193  __qTransform.scale( __fdSizeFactor, __fdSizeFactor );
194 
195  // Painter and resources
197  QPainter __qPainter( &qPixmapBuffer );
198  QPen __qPen;
199  QFont __qFont;
200  __qPainter.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing );
201 
202  // Draw
203  __qPainter.setWorldTransform( __qTransform );
204  double __fdValueMax = 0;
205  switch( _eUnit )
206  {
207  case CUnitSpeed::M_S: __fdValueMax = 150.0; break;
208  case CUnitSpeed::KM_H: __fdValueMax = 600.0; break;
209  case CUnitSpeed::MI_H: __fdValueMax = 350.0; break;
210  case CUnitSpeed::KT: __fdValueMax = 300.0; break;
211  default: return;
212  }
213 
214  // ... speed
215  __qPen.setColor( Qt::black );
216  __qPen.setWidth( 0 );
217  __qPainter.setPen( __qPen );
218  __qPainter.setBrush( QBrush( Qt::white ) );
219  double __fdSpeedLimited = __fdSpeedConverted;
220  if( __fdSpeedLimited > __fdValueMax ) __fdSpeedLimited = __fdValueMax;
221  __qPainter.rotate( __fdSpeedLimited/__fdValueMax * 340.0 );
222  {
223  static const QPointF __pqPointFPolygon[5] =
224  {
225  QPointF( -15.0, -10.0 ),
226  QPointF( -15.0, -370.0 ),
227  QPointF( 0.0, -400.0 ),
228  QPointF( +15.0, -370.0 ),
229  QPointF( +15.0, -10.0 ),
230  };
231  __qPainter.drawConvexPolygon( __pqPointFPolygon, 5 );
232  }
233 
234  // ... center mask
235  __qPainter.setWorldTransform( __qTransform );
236  __qPainter.drawEllipse( QPointF( 0.0, 0.0 ), 40.0, 40.0 );
237  __qPainter.setBrush( QBrush( Qt::black ) );
238  __qPainter.drawEllipse( QPointF( 0.0, 0.0 ), 30.0, 30.0 );
239 
240  // ... data
241  __qPen.setColor( Qt::white );
242  __qPen.setWidth( 0 );
243  __qPainter.setPen( __qPen );
244  __qFont.setPixelSize( 50.0 );
245  __qFont.setBold( false );
246  __qFont.setItalic( !_poVesselPoint || __fdSpeed == CDataCourse::UNDEFINED_SPEED || !_poVesselPoint->GroundCourseValidity.isValidSpeed() );
247  __qPainter.setFont( __qFont );
248  {
249  QRectF __qRectFText( QPointF( -125.0, -30.0 ), QSizeF( 250.0, 60.0 ) );
250  QString __qsGS( "n/a" );
251  if( _poVesselPoint && __fdSpeed != CDataCourse::UNDEFINED_SPEED )
252  {
253  int __iPrecision;
254  switch( _eUnit )
255  {
256  case CUnitSpeed::M_S: __iPrecision = 1; break;
257  default: __iPrecision = 0;
258  }
259  __qsGS = QString::number( __fdSpeedConverted, 'f', __iPrecision );
260  }
261  __qPainter.drawText( __qRectFText.translated( QPointF( +425.0, +490.0 ) ), Qt::AlignCenter, __qsGS );
262  }
263 
264  // ... OFF flag
265  if( !_poVesselPoint )
266  {
267  __qPen.setColor( Qt::black );
268  __qPainter.setPen( __qPen );
269  __qPainter.setBrush( QBrush( Qt::red ) );
270  __qFont.setBold( true );
271  __qFont.setItalic( false );
272  __qPainter.setFont( __qFont );
273  QRectF __qRectFText( QPointF( -75.0, -30.0 ), QSizeF( 150.0, 60.0 ) );
274  __qPainter.drawRect( __qRectFText.translated( QPointF( +150.0, -50.0 ) ) );
275  __qPainter.drawText( __qRectFText.translated( QPointF( +150.0, -50.0 ) ), Qt::AlignCenter, "OFF" );
276  }
277 }
CDataCourse GroundCourse
Ground course.
CDataCourseValidity GroundCourseValidity
Ground course validity.
bool isValidSpeed() const
Returns the horizontal speed's (global) validity status.
(Geographical) Course data [bearing, horizontal/vertical speeds]
Definition: CDataCourse.hpp:34
static constexpr double UNDEFINED_SPEED
Specific value for an undefined speed.
Definition: CDataCourse.hpp:44
double getSpeed() const
Returns this course's horizontal speed, in meters per second.
QPixmap qPixmapBufferBackground
Pixmap buffer used to render and cache the instrument's (static) background.
double fdSpeed
Speed at which the last rendering was achieved.
virtual void draw()
Draws the instrument (resets if the vessel is undefined)
void drawStatic(CUnitSpeed::EUnit _eUnit)
QPixmap qPixmapBuffer
Pixmap buffer used to render and cache the instrument.
CUnitSpeed::EUnit eUnit
Unit for which the last rendering was achieved.
bool bForceRedraw
Forces the redraw of the instrument (not matter its cache content)
void drawDynamic(CUnitSpeed::EUnit _eUnit, const CVesselPoint *_poVesselPoint)
CInstrumentGASpeed(CVesselCockpit *_poVesselCockpit)
Generic instrument.
Definition: CInstrument.hpp:39
CVesselPoint * useVesselPoint()
Returns parent cockpit's associated vessel (0 if the vessel is undefined)
Definition: CInstrument.cpp:54
CUnitSpeed::EUnit getUnitSpeed()
[Unit] Returns the speed format/unit
Definition: CSettings.hpp:353
Speed unit (m/s,km/h,mi/h,kt) rendering/parsing class.
Definition: CUnitSpeed.hpp:45
static double toValue(double _fdValue, EUnit _eUnit)
Returns the converted value, using the specified format/unit.
Definition: CUnitSpeed.cpp:66
static QString toSymbol(EUnit _eUnit)
Returns the human-readable symbol corresponding to the given format/unit ID.
Definition: CUnitSpeed.cpp:41
EUnit
Format/unit ID.
Definition: CUnitSpeed.hpp:53
@ KM_H
kilometers per hour [km/h]
Definition: CUnitSpeed.hpp:55
@ MI_H
statute miles per hour [mi/h]
Definition: CUnitSpeed.hpp:56
@ KT
nautical miles per hour (knots) [kt]
Definition: CUnitSpeed.hpp:57
@ M_S
meters per second [m/s]
Definition: CUnitSpeed.hpp:54
[UI] Generic vessel's cockpit view (window)
[UI] Vessel overlay point (item) / vessel
static CSettings * useSettings()
static constexpr double PI
Definition: QVCT.hpp:45