Qt Virtual Chart Table (QVCT)
CChartGDALElevation.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 // GDAL
23 #include <gdal.h>
24 #include <gdal_alg.h>
25 
26 // QVCT
27 #include "data/CDataPosition.hpp"
29 
30 
31 //------------------------------------------------------------------------------
32 // CONSTRUCTORS / DESTRUCTOR
33 //------------------------------------------------------------------------------
34 
35 CChartGDALElevation::CChartGDALElevation( const QString& _rqsFileName )
36  : CChartGDAL()
37 {
38  open( _rqsFileName );
39 
40  // Check data type
41  if( eStatus == QVCT::OK )
42  {
43  switch( eColorEncoding )
44  {
45  case GRAY_U16:
46  case GRAY_S16:
47  case GRAY_U32:
48  case GRAY_S32:
49  case GRAY_F32:
50  case GRAY_F64:
51  break;
52  default:
53  qCritical( "ERROR[%s]: Unsupported data type (%s)", Q_FUNC_INFO, qPrintable( _rqsFileName ) );
55  return;
56  }
57  }
58 
59  // Update palette for elevation rendering
60  qColorTable[0] = qRgba( 0, 0, 0, 0 ); // no value
61  for( int i=1; i<=127; i++ ) qColorTable[i] = qRgba( 0, 48+0.375*i, 96+0.75*i, 255 ); // -9'921.875m to -78.125m; blue (water)
62  for( int i=128; i<=152; i++ ) qColorTable[i] = qRgba( 4*i-480, 128, 0, 255 ); // 0.0m to 1'875.0m; green (greenery)
63  for( int i=153; i<=183; i++ ) qColorTable[i] = qRgba( 4*i-480, 4*i-480, 8*i-1216, 255 ); // 1'953.125m to 4'296.875m; fade to white (snow)
64  for( int i=184; i<=255; i++ ) qColorTable[i] = qRgba( 439-i, 255, 255, 255 ); // 4'375.0m to 9'921.875m; fade to cyan (ice)
65 }
66 
68 {}
69 
70 
71 //------------------------------------------------------------------------------
72 // METHODS: CChartGDAL (implements/override)
73 //------------------------------------------------------------------------------
74 
75 CDataPosition CChartGDALElevation::toGeoPosition( const QPointF& _rqPointFDatPosition ) const
76 {
77  CDataPosition __oGeoPosition;
78  if( eStatus != QVCT::OK ) return __oGeoPosition;
79  double __fdX = (double)_rqPointFDatPosition.x(), __fdY = (double)_rqPointFDatPosition.y(), __fdZ = 0;
80  int __iSuccess = TRUE;
81  GDALGenImgProjTransform( pGDALProjectionTransformer, false, 1, &__fdX, &__fdY, &__fdZ, &__iSuccess );
82  if( __iSuccess != TRUE ) return __oGeoPosition;
83  __oGeoPosition.setPosition( __fdX, __fdY, getElevation( _rqPointFDatPosition ) );
84  return __oGeoPosition;
85 }
86 
87 void CChartGDALElevation::rasterBuffer( QImage* _pqImage, const QVector<quint16>& _rqVector ) const
88 {
89  uchar* __pqImageBit = _pqImage->bits();
90  const quint16* __pqVectorBit = _rqVector.data();
91  for( int x=_pqImage->width()-1; x>=0; x-- )
92  for( int y=_pqImage->height()-1; y>=0; y-- )
93  *__pqImageBit++ = rasterValue( *__pqVectorBit++ );
94 }
95 
96 void CChartGDALElevation::rasterBuffer( QImage* _pqImage, const QVector<qint16>& _rqVector ) const
97 {
98  uchar* __pqImageBit = _pqImage->bits();
99  const qint16* __pqVectorBit = _rqVector.data();
100  for( int x=_pqImage->width()-1; x>=0; x-- )
101  for( int y=_pqImage->height()-1; y>=0; y-- )
102  *__pqImageBit++ = rasterValue( *__pqVectorBit++ );
103 }
104 
105 void CChartGDALElevation::rasterBuffer( QImage* _pqImage, const QVector<quint32>& _rqVector ) const
106 {
107  uchar* __pqImageBit = _pqImage->bits();
108  const quint32* __pqVectorBit = _rqVector.data();
109  for( int x=_pqImage->width()-1; x>=0; x-- )
110  for( int y=_pqImage->height()-1; y>=0; y-- )
111  *__pqImageBit++ = rasterValue( *__pqVectorBit++ );
112 }
113 
114 void CChartGDALElevation::rasterBuffer( QImage* _pqImage, const QVector<qint32>& _rqVector ) const
115 {
116  uchar* __pqImageBit = _pqImage->bits();
117  const qint32* __pqVectorBit = _rqVector.data();
118  for( int x=_pqImage->width()-1; x>=0; x-- )
119  for( int y=_pqImage->height()-1; y>=0; y-- )
120  *__pqImageBit++ = rasterValue( *__pqVectorBit++ );
121 }
122 
123 void CChartGDALElevation::rasterBuffer( QImage* _pqImage, const QVector<float>& _rqVector ) const
124 {
125  uchar* __pqImageBit = _pqImage->bits();
126  const float* __pqVectorBit = _rqVector.data();
127  for( int x=_pqImage->width()-1; x>=0; x-- )
128  for( int y=_pqImage->height()-1; y>=0; y-- )
129  *__pqImageBit++ = rasterValue( *__pqVectorBit++ );
130 }
131 
132 void CChartGDALElevation::rasterBuffer( QImage* _pqImage, const QVector<double>& _rqVector ) const
133 {
134  uchar* __pqImageBit = _pqImage->bits();
135  const double* __pqVectorBit = _rqVector.data();
136  for( int x=_pqImage->width()-1; x>=0; x-- )
137  for( int y=_pqImage->height()-1; y>=0; y-- )
138  *__pqImageBit++ = rasterValue( *__pqVectorBit++ );
139 }
140 
141 
142 //------------------------------------------------------------------------------
143 // METHODS
144 //------------------------------------------------------------------------------
145 
146 //
147 // OTHER
148 //
149 
150 double CChartGDALElevation::getElevation( const QPointF& _rqPointFDatPosition ) const
151 {
152  double __fdElevation = CDataPosition::UNDEFINED_ELEVATION;
153  if( !qRectGeometry.contains( (int)( _rqPointFDatPosition.x()+0.5 ), (int)( _rqPointFDatPosition.y()+0.5 ) ) ) return __fdElevation;
154  double __fdXint, __fdXdec, __fdYint, __fdYdec;
155  __fdXdec = modf( _rqPointFDatPosition.x(), &__fdXint );
156  __fdYdec = modf( _rqPointFDatPosition.y(), &__fdYint );
157  switch( eColorEncoding )
158  {
159 
160  case GRAY_U16:
161  {
162  QVector<quint16> __qVector( 4 );
163  GDALRasterBand* __poGDALRasterBand = poGDALDataset->GetRasterBand( 1 );
164  CPLErr tCPLErr = __poGDALRasterBand->RasterIO( GF_Read,
165  (int)__fdXint, (int)__fdYint,
166  2, 2,
167  __qVector.data(),
168  2, 2,
169  GDT_UInt16,
170  sizeof(quint16), 2*sizeof(quint16) );
171  if( tCPLErr != CE_None )
172  {
173  qCritical( "ERROR[%s]: Failed to rasterize elevation data", Q_FUNC_INFO );
174  return __fdElevation;
175  }
176  __fdElevation = interpolateValue( __qVector[0], __qVector[1], __qVector[2], __qVector[3], __fdXdec, __fdYdec );
177  }
178  break;
179 
180  case GRAY_S16:
181  {
182  QVector<qint16> __qVector( 4 );
183  GDALRasterBand* __poGDALRasterBand = poGDALDataset->GetRasterBand( 1 );
184  CPLErr tCPLErr = __poGDALRasterBand->RasterIO( GF_Read,
185  (int)__fdXint, (int)__fdYint,
186  2, 2,
187  __qVector.data(),
188  2, 2,
189  GDT_Int16,
190  sizeof(qint16), 2*sizeof(qint16) );
191  if( tCPLErr != CE_None )
192  {
193  qCritical( "ERROR[%s]: Failed to rasterize elevation data", Q_FUNC_INFO );
194  return __fdElevation;
195  }
196  __fdElevation = interpolateValue( __qVector[0], __qVector[1], __qVector[2], __qVector[3], __fdXdec, __fdYdec );
197  }
198  break;
199 
200  case GRAY_U32:
201  {
202  QVector<quint32> __qVector( 4 );
203  GDALRasterBand* __poGDALRasterBand = poGDALDataset->GetRasterBand( 1 );
204  CPLErr tCPLErr = __poGDALRasterBand->RasterIO( GF_Read,
205  (int)__fdXint, (int)__fdYint,
206  2, 2,
207  __qVector.data(),
208  2, 2,
209  GDT_UInt32,
210  sizeof(quint32), 2*sizeof(quint32) );
211  if( tCPLErr != CE_None )
212  {
213  qCritical( "ERROR[%s]: Failed to rasterize elevation data", Q_FUNC_INFO );
214  return __fdElevation;
215  }
216  __fdElevation = interpolateValue( __qVector[0], __qVector[1], __qVector[2], __qVector[3], __fdXdec, __fdYdec );
217  }
218  break;
219 
220  case GRAY_S32:
221  {
222  QVector<qint32> __qVector( 4 );
223  GDALRasterBand* __poGDALRasterBand = poGDALDataset->GetRasterBand( 1 );
224  CPLErr tCPLErr = __poGDALRasterBand->RasterIO( GF_Read,
225  (int)__fdXint, (int)__fdYint,
226  2, 2,
227  __qVector.data(),
228  2, 2,
229  GDT_Int32,
230  sizeof(qint32), 2*sizeof(qint32) );
231  if( tCPLErr != CE_None )
232  {
233  qCritical( "ERROR[%s]: Failed to rasterize elevation data", Q_FUNC_INFO );
234  return __fdElevation;
235  }
236  __fdElevation = interpolateValue( __qVector[0], __qVector[1], __qVector[2], __qVector[3], __fdXdec, __fdYdec );
237  }
238  break;
239 
240  case GRAY_F32:
241  {
242  QVector<float> __qVector( 4 );
243  GDALRasterBand* __poGDALRasterBand = poGDALDataset->GetRasterBand( 1 );
244  CPLErr tCPLErr = __poGDALRasterBand->RasterIO( GF_Read,
245  (int)__fdXint, (int)__fdYint,
246  2, 2,
247  __qVector.data(),
248  2, 2,
249  GDT_Float32,
250  sizeof(float), 2*sizeof(float) );
251  if( tCPLErr != CE_None )
252  {
253  qCritical( "ERROR[%s]: Failed to rasterize elevation data", Q_FUNC_INFO );
254  return __fdElevation;
255  }
256  __fdElevation = interpolateValue( __qVector[0], __qVector[1], __qVector[2], __qVector[3], __fdXdec, __fdYdec );
257  }
258  break;
259 
260  case GRAY_F64:
261  {
262  QVector<double> __qVector( 4 );
263  GDALRasterBand* __poGDALRasterBand = poGDALDataset->GetRasterBand( 1 );
264  CPLErr tCPLErr = __poGDALRasterBand->RasterIO( GF_Read,
265  (int)__fdXint, (int)__fdYint,
266  2, 2,
267  __qVector.data(),
268  2, 2,
269  GDT_Float64,
270  sizeof(double), 2*sizeof(double) );
271  if( tCPLErr != CE_None )
272  {
273  qCritical( "ERROR[%s]: Failed to rasterize elevation data", Q_FUNC_INFO );
274  return __fdElevation;
275  }
276  __fdElevation = interpolateValue( __qVector[0], __qVector[1], __qVector[2], __qVector[3], __fdXdec, __fdYdec );
277  }
278  break;
279 
280  default:;
281 
282  }
283 
284  return __fdElevation;
285 }
286 
287 double CChartGDALElevation::getElevation( const CDataPosition& _roGeoPosition ) const
288 {
289  return getElevation( toDatPosition( _roGeoPosition ) );
290 }
291 
292 uchar CChartGDALElevation::rasterValue( double _fdValue ) const
293 {
294  _fdValue = ( _fdValue / 78.125 ) + 128.0;
295  if( _fdValue > 255.0 ) _fdValue = 255.0;
296  else if( _fdValue < 0.0 ) _fdValue = 0.0;
297  return (uchar)(_fdValue+0.5);
298 }
299 
300 double CChartGDALElevation::interpolateValue( double _fdP11, double _fdP21, double _fdP12, double _fdP22, double _fdX, double _fdY ) const
301 {
302  return _fdP11 * ( 1.0 - _fdX ) * ( 1.0 - _fdY )
303  + _fdP21 * _fdX * ( 1.0 - _fdY )
304  + _fdP12 * ( 1.0 - _fdX ) * _fdY
305  + _fdP22 * _fdX * _fdY;
306 }
CChartGDALElevation(const QString &_rqsFileName)
virtual void rasterBuffer(QImage *_pqImage, const QVector< quint16 > &_rqVector) const
Rasterizes UInt16 buffer.
uchar rasterValue(double _fdValue) const
CDataPosition toGeoPosition(const QPointF &_rqPointFDatPosition) const
double interpolateValue(double _fdP11, double _fdP21, double _fdP12, double _fdP22, double _fdX, double _fdY) const
double getElevation(const QPointF &_rqPointFDatPosition) const
Returns the elevation at the given chart pixel position.
Generic GDAL-based dataset.
Definition: CChartGDAL.hpp:53
void open(const QString &_rqsFileName)
Opens the underlying GDAL dataset.
Definition: CChartGDAL.cpp:61
void * pGDALProjectionTransformer
Underlying GDAL dataset projection transformer (to internal WGS84)
Definition: CChartGDAL.hpp:98
QRect qRectGeometry
Chart (GDAL dataset) geometry (size)
Definition: CChartGDAL.hpp:79
EColorEncoding eColorEncoding
Chart (GDAL dataset) color encoding.
Definition: CChartGDAL.hpp:81
QPointF toDatPosition(const CDataPosition &_roGeoPosition) const
Converts the given (geographical) position [long,lat,elev] to chart (GDAL dataset) point [px].
Definition: CChartGDAL.cpp:368
QVCT::EStatus eStatus
Chart internal status.
Definition: CChartGDAL.hpp:75
GDALDataset * poGDALDataset
Underlying GDAL dataset.
Definition: CChartGDAL.hpp:96
QVector< QRgb > qColorTable
Color table (for GRAY/PALETTE_* color encodings)
Definition: CChartGDAL.hpp:109
(Geographical) Position data [long,lat,elev]
void setPosition(double _fdLongitude, double _fdLatitude, double _fdElevation=UNDEFINED_ELEVATION)
Sets new coordinates.
static constexpr double UNDEFINED_ELEVATION
Specific value for an undefined elevation.
@ ERROR
Definition: QVCT.hpp:41
@ OK
Definition: QVCT.hpp:41