Qt Virtual Chart Table (QVCT)
CChart.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 <QDomElement> // QtXml module
24 #include <QKeyEvent>
25 #include <QPainter>
26 #include <QPalette>
27 #include <QPixmap>
28 #include <QRectF>
29 #include <QWidget>
30 #include <QXmlStreamWriter>
31 
32 // QVCT
33 #include "QVCT.hpp"
34 #include "QVCTRuntime.hpp"
35 #include "charts/CChart.hpp"
38 
39 
40 //------------------------------------------------------------------------------
41 // CONSTRUCTORS / DESTRUCTOR
42 //------------------------------------------------------------------------------
43 
44 CChart::CChart( const QString& _rqsFileName, QWidget* _pqParent )
45  : QWidget( _pqParent )
46  , poChartGDALRaster( 0 )
47  , poChartGDALElevation( 0 )
48  , bShowElevation( false )
49 {
50  poChartGDALRaster = new CChartGDALRaster( _rqsFileName );
51  if( poChartGDALRaster->getStatus() != QVCT::OK ) return;
52  QPalette __qPalette( QWidget::palette() );
53  __qPalette.setColor( QPalette::Background, Qt::black );
54  QWidget::setPalette( __qPalette );
55  QWidget::setAutoFillBackground(true);
56  QWidget::setCursor( QCursor( QPixmap( ":cursors/crosshair.png" ), 15, 15 ) );
57  qPointFDatPosition = QRectF( poChartGDALRaster->getDatGeometry() ).center();
58  bPositionLock = true;
59  fdZoom = 1.0;
60  bZoomLock = true;
61 }
62 
64 {
67 }
68 
69 void CChart::addElevation( const QString& _rqsFileName )
70 {
71  poChartGDALElevation = new CChartGDALElevation( _rqsFileName );
73  {
74  delete poChartGDALElevation;
76  }
77 }
78 
79 
80 //------------------------------------------------------------------------------
81 // METHODS: QWidget (OVERRIDE)
82 //------------------------------------------------------------------------------
83 
84 void CChart::paintEvent( QPaintEvent* _pqPaintEvent )
85 {
86  //qDebug( "DEBUG[%s]", Q_FUNC_INFO );
87  qRectFDrawArea = QRectF( 0, 0, QWidget::width(), QWidget::height() );
88  draw();
89 }
90 
91 
92 //------------------------------------------------------------------------------
93 // METHODS
94 //------------------------------------------------------------------------------
95 
96 //
97 // SETTERS
98 //
99 
101 {
102  qRectFDrawArea = QRectF( 0, 0, QWidget::width(), QWidget::height() );
103 }
104 
105 void CChart::setGeoPosition( const CDataPosition& _roGeoPosition )
106 {
108 }
109 
110 void CChart::showElevation( bool _bShow )
111 {
112  if( !poChartGDALElevation ) return;
113  if( bShowElevation != _bShow )
114  {
120  }
121  bShowElevation = _bShow;
122 }
123 
124 //
125 // GETTERS
126 //
127 
129 {
130  return poChartGDALRaster->getStatus();
131 }
132 
133 QString CChart::getFileName() const
134 {
135  return poChartGDALRaster->getFileName();
136 }
137 
139 {
141 }
142 
144 {
146 }
147 
149 {
150  return qRectFDrawArea.center();
151 }
152 
153 double CChart::getZoomFit() const
154 {
155  QRect __qRectDatGeometry = poChartGDALRaster->getDatGeometry();
156  double __fdZoomWidth = qRectFDrawArea.width() / (double)__qRectDatGeometry.width();
157  double __fdZoomHeight = qRectFDrawArea.height() / (double)__qRectDatGeometry.height();
158  return( __fdZoomWidth < __fdZoomHeight ? __fdZoomWidth : __fdZoomHeight );
159 }
160 
161 double CChart::getZoomArea( const CDataPosition& _roGeoPosition1, const CDataPosition& _roGeoPosition2 ) const
162 {
163  double __fdLongitude1 = _roGeoPosition1.getLongitude(), __fdLongitude2 = _roGeoPosition2.getLongitude();
164  double __fdLatitude1 = _roGeoPosition1.getLatitude(), __fdLatitude2 = _roGeoPosition2.getLatitude();
165  CDataPosition __oGeoPosition( ( __fdLongitude1 + __fdLongitude2 ) / 2.0, ( __fdLatitude1 + __fdLatitude1 ) / 2.0 );
166  double __fdResolution = poChartGDALRaster->getResolution( poChartGDALRaster->toDatPosition( __oGeoPosition ) );
167  double __fdLatitudeMaxCos;
168  if( __fdLatitude1 * __fdLatitude2 < 0 ) __fdLatitudeMaxCos = 0;
169  else if( fabs( __fdLatitude1 ) < fabs( __fdLatitude2 ) ) __fdLatitudeMaxCos = __fdLatitude1;
170  else __fdLatitudeMaxCos = __fdLatitude2;
171  double __fdZoomWidth = qRectFDrawArea.width() / ( fabs( ( __fdLongitude2 - __fdLongitude1 ) * cos( __fdLatitudeMaxCos * QVCT::DEG2RAD ) ) * 111120.0 / __fdResolution );
172  double __fdZoomHeight = qRectFDrawArea.height() / ( fabs( __fdLatitude2 - __fdLatitude1 ) * 111120.0 / __fdResolution );
173  return( __fdZoomWidth < __fdZoomHeight ? __fdZoomWidth : __fdZoomHeight );
174 }
175 
176 double CChart::getResolution() const
177 {
179 }
180 
181 //
182 // OTHER
183 //
184 
185 CDataPosition CChart::toGeoPosition( const QPointF& _rqPointFDrawPosition ) const
186 {
187  CDataPosition __oGeoPosition = poChartGDALRaster->toGeoPosition( poChartGDALRaster->getDatPosition() + ( _rqPointFDrawPosition - qRectFDrawArea.center() ) / poChartGDALRaster->getZoom() );
188  if( poChartGDALElevation ) __oGeoPosition.setElevation( poChartGDALElevation->getElevation( __oGeoPosition ) );
189  return __oGeoPosition;
190 }
191 
192 QPointF CChart::toDrawPosition( const CDataPosition& _roGeoPosition ) const
193 {
195  return( ( poChartGDALRaster->toDatPosition( _roGeoPosition ) - poChartGDALRaster->getDatPosition() ) * poChartGDALRaster->getZoom() + qRectFDrawArea.center() );
196 }
197 
198 void CChart::move( const QPointF& _rqPointFDrawPositionOffset )
199 {
200  qPointFDatPosition += _rqPointFDrawPositionOffset / poChartGDALRaster->getZoom();
201 }
202 
204 {
205  // Constant drawing resources
206  static const QPointF __qPointFCrosshairA1(5,0), __qPointFCrosshairA2(15,0);
207  static const QPointF __qPointFCrosshairB1(0,5), __qPointFCrosshairB2(0,15);
208  static const QPointF __qPointFCrosshairC1(-5,0), __qPointFCrosshairC2(-15,0);
209  static const QPointF __qPointFCrosshairD1(0,-5), __qPointFCrosshairD2(0,-15);
210 
211  // Draw
212  QPainter __qPainter;
213  __qPainter.begin( this );
214  __qPainter.setRenderHints( QPainter::SmoothPixmapTransform | QPainter::Antialiasing | QPainter::TextAntialiasing );
215  // ... chart / elevation model
216  __qPainter.setOpacity( (double)QVCTRuntime::useSettings()->getChartOpacity()/100.0 );
217  if( bShowElevation )
218  {
220  poChartGDALRaster->move( qPointFDatPosition, fdZoom ); // keep the actual chart position/zoom in sync.
221  poChartGDALElevation->draw( &__qPainter,
222  __qPointFDatPosition,
224  }
225  else
226  {
227  if( poChartGDALElevation ) poChartGDALElevation->move( qPointFDatPosition, fdZoom ); // clear any cached rendering
229  }
230  __qPainter.setOpacity( 1.0 );
231  // ... overlays
232  QVCTRuntime::useLandmarkOverlay()->draw( this, &__qPainter );
233  QVCTRuntime::useRouteOverlay()->draw( this, &__qPainter );
234  QVCTRuntime::useTrackOverlay()->draw( this, &__qPainter );
235  QVCTRuntime::useVesselOverlay()->draw( this, &__qPainter );
236  QVCTRuntime::usePointerOverlay()->draw( this, &__qPainter );
237  // ... center crosshair
238  QPen __qPen;
239  __qPen.setColor( QColor( 0, 0, 0, 128 ) );
240  __qPen.setWidth( 1 );
241  __qPainter.setPen( __qPen );
242  QPointF __qPointF = qRectFDrawArea.center();
243  __qPainter.drawPoint( __qPointF );
244  __qPainter.setPen( __qPen );
245  __qPainter.drawLine( __qPointF + __qPointFCrosshairA1, __qPointF + __qPointFCrosshairA2 );
246  __qPainter.drawLine( __qPointF + __qPointFCrosshairB1, __qPointF + __qPointFCrosshairB2 );
247  __qPainter.drawLine( __qPointF + __qPointFCrosshairC1, __qPointF + __qPointFCrosshairC2 );
248  __qPainter.drawLine( __qPointF + __qPointFCrosshairD1, __qPointF + __qPointFCrosshairD2 );
249  // ... [end]
250  __qPainter.end();
251 }
252 
253 void CChart::print( QPrinter* _pqPrinter )
254 {
255  // Printer
256  QPainter __qPainter;
257  __qPainter.begin( _pqPrinter );
258  __qPainter.setRenderHints( QPainter::SmoothPixmapTransform | QPainter::Antialiasing | QPainter::TextAntialiasing );
259  // ... chart / elevation model
260  if( bShowElevation )
261  {
263  poChartGDALRaster->move( qPointFDatPosition, fdZoom ); // keep the actual chart position/zoom in sync.
264  poChartGDALElevation->draw( &__qPainter,
265  __qPointFDatPosition,
267  }
268  else
269  {
270  if( poChartGDALElevation ) poChartGDALElevation->move( qPointFDatPosition, fdZoom ); // clear any cached rendering
272  }
273  // ... overlays
274  QVCTRuntime::useLandmarkOverlay()->draw( this, &__qPainter );
275  QVCTRuntime::useRouteOverlay()->draw( this, &__qPainter );
276  QVCTRuntime::useTrackOverlay()->draw( this, &__qPainter );
277  QVCTRuntime::useVesselOverlay()->draw( this, &__qPainter );
278  QVCTRuntime::usePointerOverlay()->draw( this, &__qPainter );
279  // ... [end]
280  __qPainter.end();
281 }
282 
283 void CChart::parseQVCT( const QDomElement& _rqDomElement )
284 {
285  // Chart table
286  if( _rqDomElement.hasAttribute( "longitude" ) && _rqDomElement.hasAttribute( "longitude" ) )
287  {
288  bPositionLock = false;
289  CDataPosition __oGeoPosition( _rqDomElement.attribute( "longitude" ).toDouble(),
290  _rqDomElement.attribute( "latitude" ).toDouble() );
292  }
293  if( _rqDomElement.hasAttribute( "zoom" ) )
294  {
295  bZoomLock = false;
296  fdZoom = _rqDomElement.attribute( "zoom" ).toDouble();
297  }
298  if( _rqDomElement.hasAttribute( "dem" ) )
299  {
300  QString __qsFilename = _rqDomElement.attribute( "dem" );
301  addElevation( __qsFilename );
302  if( !hasElevation() )
303  {
304  QVCTRuntime::useMainWindow()->fileError( QVCT::OPEN, __qsFilename );
305  }
306  }
307 }
308 
309 void CChart::dumpQVCT( QXmlStreamWriter & _rqXmlStreamWriter ) const
310 {
311  _rqXmlStreamWriter.writeStartElement( "Chart" );
312  _rqXmlStreamWriter.writeAttribute( "raster", poChartGDALRaster->getFileName() );
313  if( poChartGDALElevation ) _rqXmlStreamWriter.writeAttribute( "dem", poChartGDALElevation->getFileName() );
314  if( !bPositionLock )
315  {
317  _rqXmlStreamWriter.writeAttribute( "longitude", QString::number( __oDataPosition.getLongitude() ) );
318  _rqXmlStreamWriter.writeAttribute( "latitude", QString::number( __oDataPosition.getLatitude() ) );
319  }
320  if( !bZoomLock )
321  _rqXmlStreamWriter.writeAttribute( "zoom", QString::number( fdZoom ) );
322  _rqXmlStreamWriter.writeEndElement(); // Chart
323 }
GDAL-based (elevation) chart.
double getElevation(const QPointF &_rqPointFDatPosition) const
Returns the elevation at the given chart pixel position.
GDAL-based (raster) chart.
QPointF getDatPosition() const
Returns the last drawn chart (GDAL dataset) center pixel position.
Definition: CChartGDAL.hpp:140
QRect getDatGeometry() const
Returns the chart (GDAL dataset) geometry (size)
Definition: CChartGDAL.hpp:136
void draw(QPainter *_pqPainter, const QPointF &_rqPointFDatPosition, double _fdZoom)
Draws chart, centered on given chart (GDAL dataset) point [px] and zoomed according to given factor.
Definition: CChartGDAL.cpp:392
CDataPosition toGeoPosition(const QPointF &_rqPointFDatPosition) const
Converts the given chart pixel position to geographical position.
Definition: CChartGDAL.cpp:356
void move(const QPointF &_rqPointFDatPosition, double _fdZoom)
Moves the chart, centered on given chart (GDAL dataset) point [px] and zoomed according to given fact...
Definition: CChartGDAL.cpp:683
QVCT::EStatus getStatus() const
Returns the chart internal status (after constructing object)
Definition: CChartGDAL.hpp:132
double getResolution(const QPointF &_rqPointFDatPosition) const
Returns the resolution at given chart (GDAL dataset) point [px], in meters per pixel [m/px].
Definition: CChartGDAL.cpp:383
QPointF toDatPosition(const CDataPosition &_roGeoPosition) const
Converts the given (geographical) position [long,lat,elev] to chart (GDAL dataset) point [px].
Definition: CChartGDAL.cpp:368
QString getFileName() const
Returns the chart (GDAL dataset) file name.
Definition: CChartGDAL.hpp:134
double getZoom() const
Returns the last drawn chart (GDAL dataset) zoom factor.
Definition: CChartGDAL.hpp:142
bool hasElevation() const
Returns whether this chart has been associated elevation model data.
Definition: CChart.hpp:149
QString getFileName() const
Returns the underlying chart (GDAL dataset) file name.
Definition: CChart.cpp:133
void dumpQVCT(QXmlStreamWriter &_rqXmlStreamWriter) const
Stores this object's content to the given QVCT destination (file)
Definition: CChart.cpp:309
void parseQVCT(const QDomElement &_rqDomElement)
Retrieves this object's content from the given QVCT source (file)
Definition: CChart.cpp:283
double getZoomFit() const
Returns the zoom factor allowing to view the entire chart.
Definition: CChart.cpp:153
void print(QPrinter *_pqPrinter)
Prints the chart.
Definition: CChart.cpp:253
void draw()
Draws the chart (on screen)
Definition: CChart.cpp:203
CChartGDALElevation * poChartGDALElevation
GDAL data elevation model (dataset)
Definition: CChart.hpp:56
double fdZoom
Current zoom factor.
Definition: CChart.hpp:68
virtual ~CChart()
Definition: CChart.cpp:63
double getResolution() const
Returns the resolution of the chart at its current position, in meters per pixel [m/px].
Definition: CChart.cpp:176
void move(const QPointF &_rqPointFDrawPositionOffset)
Move the current (center) chart position by specified offset (in the draw area)
Definition: CChart.cpp:198
QPointF qPointFDatPosition
Current (center) position in the GDAL dataset.
Definition: CChart.hpp:62
bool bZoomLock
Zoom lock status.
Definition: CChart.hpp:71
void setGeoPosition(const CDataPosition &_roGeoPosition)
Sets the current (center) position (geographical coordinates) of the chart.
Definition: CChart.cpp:105
virtual void paintEvent(QPaintEvent *_pqPaintEvent)
Definition: CChart.cpp:84
QVCT::EStatus getStatus() const
Returns the internal status of the object.
Definition: CChart.cpp:128
CDataPosition getGeoPosition() const
Returns the current (center) position (geographical coordinates) of the chart.
Definition: CChart.cpp:143
CChart(const QString &_rqsFileName, QWidget *_pqParent=0)
Definition: CChart.cpp:44
bool bPositionLock
Position lock status.
Definition: CChart.hpp:65
void resetDrawArea()
Resets the viewport draw area (to the widget's area)
Definition: CChart.cpp:100
QPointF toDrawPosition(const CDataPosition &_roGeoPosition) const
Converts the given (geographical) position [long,lat,elev] to chart draw point [px].
Definition: CChart.cpp:192
CDataPosition toGeoPosition(const QPointF &_rqPointFDrawPosition) const
Converts the given chart draw position to geographical position.
Definition: CChart.cpp:185
CChartGDALRaster * poChartGDALRaster
GDAL chart (dataset)
Definition: CChart.hpp:53
void showElevation(bool _bShow)
Sets the elevation model show status.
Definition: CChart.cpp:110
QRectF qRectFDrawArea
Viewport draw area.
Definition: CChart.hpp:59
bool bShowElevation
Elevation model show status.
Definition: CChart.hpp:74
double getZoomArea(const CDataPosition &_roGeoPosition1, const CDataPosition &_roGeoPosition2) const
Returns the zoom factor allowing to view the given geographical area (defined by its opposite corners...
Definition: CChart.cpp:161
QPointF getDrawPositionCenter() const
Returns the viewport draw area's center position.
Definition: CChart.cpp:148
void addElevation(const QString &_rqsFileName)
Add elevation model data to chart.
Definition: CChart.cpp:69
CDataPosition getGeoPositionCenter() const
Returns the center position (geographical coordinates) of the chart.
Definition: CChart.cpp:138
(Geographical) Position data [long,lat,elev]
double getLongitude() const
Returns this position's longitude, in degrees.
double getLatitude() const
Returns this position's latitude, in degrees.
void setElevation(double _fdElevation)
Sets the elevation, in meters.
void fileError(QVCT::EFileOperation _eFileOperation, const QString &_rqsFilename)
Displays a generic error message for an invalid file name and operation (open/save)
void draw(const CChart *_poChart, QPainter *_pqPainter)
Draws this overlay.
Definition: COverlay.cpp:86
void forceRedraw()
Forces this overlay's rendering (not matter its cache content)
Definition: COverlay.hpp:115
static CPointerOverlay * usePointerOverlay()
static CVesselOverlay * useVesselOverlay()
static CRouteOverlay * useRouteOverlay()
static CMainWindow * useMainWindow()
static CSettings * useSettings()
static CLandmarkOverlay * useLandmarkOverlay()
static CTrackOverlay * useTrackOverlay()
EStatus
Definition: QVCT.hpp:41
@ OK
Definition: QVCT.hpp:41
@ OPEN
Definition: QVCT.hpp:42
static constexpr double DEG2RAD
Definition: QVCT.hpp:46