Qt Virtual Chart Table (QVCT)
CDataPosition.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 <QDataStream>
24 
25 // GPS
26 #include <gps.h>
27 
28 // QVCT
29 #include "data/CDataPosition.hpp"
30 
31 
32 //------------------------------------------------------------------------------
33 // CONSTANTS / STATIC
34 //------------------------------------------------------------------------------
35 
39 
40 double CDataPosition::distanceGC( const CDataPosition& _roGP1, const CDataPosition& _roGP2 )
41 {
42  // NOTE: DEG_2_RAD and RAD_2_DEG come from "gps.h"
43  double __fdLon1 = _roGP1.fdLongitude * DEG_2_RAD, __fdLat1 = _roGP1.fdLatitude * DEG_2_RAD;
44  double __fdLon2 = _roGP2.fdLongitude * DEG_2_RAD, __fdLat2 = _roGP2.fdLatitude * DEG_2_RAD;
45  double __fdLonD = __fdLon2 - __fdLon1, __fdLatD = __fdLat2 - __fdLat1;
46 
47  // Formula shamelessly copied from http://www.movable-type.co.uk/scripts/latlong.html
48  double __fdLonS = sin( __fdLonD/2.0 ), __fdLatS = sin( __fdLatD/2.0 );
49  double __fdA = __fdLatS*__fdLatS + cos( __fdLat1 )*cos( __fdLat2 )*__fdLonS*__fdLonS;
50  double __fdDistance = ( WGS84A + WGS84B ) * atan2( sqrt( __fdA ), sqrt( 1.0-__fdA ) );
51  return __fdDistance;
52 }
53 
54 double CDataPosition::bearingGC( const CDataPosition& _roGP1, const CDataPosition& _roGP2 )
55 {
56  // NOTE: DEG_2_RAD and RAD_2_DEG come from "gps.h"
57  double __fdLon1 = _roGP1.fdLongitude * DEG_2_RAD, __fdLat1 = _roGP1.fdLatitude * DEG_2_RAD;
58  double __fdLon2 = _roGP2.fdLongitude * DEG_2_RAD, __fdLat2 = _roGP2.fdLatitude * DEG_2_RAD;
59  double __fdLonD = __fdLon2 - __fdLon1;
60 
61  // Formula shamelessly copied from http://www.movable-type.co.uk/scripts/latlong.html
62  double __fdBearing = atan2( sin( __fdLonD )*cos( __fdLat2 ),
63  cos( __fdLat1 )*sin( __fdLat2 ) - sin( __fdLat1 )*cos( __fdLat2 )*cos( __fdLonD ) );
64  __fdBearing *= RAD_2_DEG;
65  if( __fdBearing < 0 ) __fdBearing += 360;
66  return __fdBearing;
67 }
68 
69 double CDataPosition::distanceRL( const CDataPosition& _roGP1, const CDataPosition& _roGP2 )
70 {
71  // NOTE: GPS_PI, DEG_2_RAD, RAD_2_DEG and WGS84A come from "gps.h"
72  double __fdLon1 = _roGP1.fdLongitude * DEG_2_RAD, __fdLat1 = _roGP1.fdLatitude * DEG_2_RAD;
73  double __fdLon2 = _roGP2.fdLongitude * DEG_2_RAD, __fdLat2 = _roGP2.fdLatitude * DEG_2_RAD;
74  double __fdLonD = __fdLon2 - __fdLon1, __fdLatD = __fdLat2 - __fdLat1;
75 
76  // Formula shamelessly copied from http://www.movable-type.co.uk/scripts/latlong.html
77  double __fdPhiD = log( tan( __fdLat2/2.0 + GPS_PI/4.0 ) / tan( __fdLat1/2.0 + GPS_PI/4.0 ) );
78  double __fdQ = __fdPhiD != 0 ? __fdLatD/__fdPhiD : cos( __fdLat1 );
79  if( fabs( __fdLonD ) > GPS_PI ) __fdLonD = __fdLonD > 0 ? __fdLonD - GPS_PI*2.0 : GPS_PI*2.0 + __fdLonD;
80  double __fdDistance = ( WGS84A + WGS84B ) / 2.0 * sqrt( __fdLatD*__fdLatD + __fdLonD*__fdLonD * __fdQ*__fdQ );
81  return __fdDistance;
82 }
83 
84 double CDataPosition::bearingRL( const CDataPosition& _roGP1, const CDataPosition& _roGP2 )
85 {
86  // NOTE: GPS_PI, DEG_2_RAD and RAD_2_DEG come from "gps.h"
87  double __fdLon1 = _roGP1.fdLongitude * DEG_2_RAD, __fdLat1 = _roGP1.fdLatitude * DEG_2_RAD;
88  double __fdLon2 = _roGP2.fdLongitude * DEG_2_RAD, __fdLat2 = _roGP2.fdLatitude * DEG_2_RAD;
89  double __fdLonD = __fdLon2 - __fdLon1;
90 
91  // Formula shamelessly copied from http://www.movable-type.co.uk/scripts/latlong.html
92  double __fdPhiD = log( tan( __fdLat2/2.0 + GPS_PI/4.0 ) / tan( __fdLat1/2.0 + GPS_PI/4.0 ) );
93  if( fabs( __fdLonD ) > GPS_PI ) __fdLonD = __fdLonD > 0 ? __fdLonD - GPS_PI*2.0 : GPS_PI*2.0 + __fdLonD;
94  double __fdBearing = atan2( __fdLonD, __fdPhiD );
95  __fdBearing *= RAD_2_DEG;
96  if( __fdBearing < 0 ) __fdBearing += 360;
97  return __fdBearing;
98 }
99 
100 double CDataPosition::length( const CDataPosition& _roGP1, const CDataPosition& _roGP2 )
101 {
102  double __fdDistance = CDataPosition::distanceRL( _roGP1, _roGP2 );
104  {
105  double __fdClimb = _roGP2.fdElevation - _roGP1.fdElevation;
106  __fdDistance = sqrt( __fdDistance*__fdDistance + __fdClimb*__fdClimb );
107  }
108  return __fdDistance;
109 }
110 
111 
112 //------------------------------------------------------------------------------
113 // CONSTRUCTORS / DESTRUCTOR
114 //------------------------------------------------------------------------------
115 
117  : fdLongitude( CDataPosition::UNDEFINED_LONGITUDE )
118  , fdLatitude( CDataPosition::UNDEFINED_LATITUDE )
119  , fdElevation( CDataPosition::UNDEFINED_ELEVATION )
120 {}
121 
122 CDataPosition::CDataPosition( double _fdLongitude, double _fdLatitude, double _fdElevation )
123 {
124  setPosition( _fdLongitude, _fdLatitude, _fdElevation );
125 }
126 
128 {
129  setPosition( _roDataPosition );
130 }
131 
132 
133 //------------------------------------------------------------------------------
134 // METHODS
135 //------------------------------------------------------------------------------
136 
137 //
138 // SETTERS
139 //
140 
141 void CDataPosition::setPosition( double _fdLongitude, double _fdLatitude, double _fdElevation )
142 {
143  if( _fdLongitude != UNDEFINED_LONGITUDE && _fdLatitude != UNDEFINED_LATITUDE )
144  {
145  // Normalize latitude => [-90;90]
146  while( _fdLatitude >= 270 ) _fdLatitude -= 360;
147  while( _fdLatitude <= -270 ) _fdLatitude += 360;
148  if( _fdLatitude > 90 ) { _fdLatitude = 180 - _fdLatitude; _fdLongitude += 180; }
149  if( _fdLatitude < -90 ) { _fdLatitude = -180 - _fdLatitude; _fdLongitude += 180; }
150 
151  // Normalize longitude => [-180;180]
152  while( _fdLongitude > 180 ) _fdLongitude -= 360;
153  while( _fdLongitude < -180 ) _fdLongitude += 360;
154  }
155  else
156  {
157  _fdLongitude = UNDEFINED_LONGITUDE;
158  _fdLatitude = UNDEFINED_LATITUDE;
159  }
160 
161  // Save position
162  fdLongitude = _fdLongitude;
163  fdLatitude = _fdLatitude;
164  fdElevation = _fdElevation;
165 }
166 
167 void CDataPosition::setPosition( const CDataPosition& _roDataPosition )
168 {
169  fdLongitude = _roDataPosition.fdLongitude;
170  fdLatitude = _roDataPosition.fdLatitude;
171  fdElevation = _roDataPosition.fdElevation;
172 }
173 
175 {
179 }
180 
181 //
182 // OTHER
183 //
184 
185 void CDataPosition::serialize( QDataStream& _rqDataStream ) const
186 {
187  _rqDataStream << fdLongitude << fdLatitude << fdElevation;
188 }
189 
190 void CDataPosition::unserialize( QDataStream& _rqDataStream )
191 {
192  _rqDataStream >> fdLongitude >> fdLatitude >> fdElevation;
193 }
194 
195 //
196 // OPERATORS
197 //
198 bool CDataPosition::operator==( const CDataPosition& _roPosition ) const
199 {
200  return( fdLongitude == _roPosition.fdLongitude
201  && fdLatitude == _roPosition.fdLatitude
202  && fdElevation == _roPosition.fdElevation );
203 }
204 
205 bool CDataPosition::operator!=( const CDataPosition& _roPosition ) const
206 {
207  return( fdLongitude != _roPosition.fdLongitude
208  || fdLatitude != _roPosition.fdLatitude
209  || fdElevation != _roPosition.fdElevation );
210 }
211 
212 //
213 // COMPARATORS
214 //
215 
216 bool CDataPosition::compareLongitudeAscending( const CDataPosition& _roPosition1, const CDataPosition& _roPosition2 )
217 {
218  return( _roPosition1.fdLongitude < _roPosition2.fdLongitude );
219 }
220 
221 bool CDataPosition::compareLongitudeDescending( const CDataPosition& _roPosition1, const CDataPosition& _roPosition2 )
222 {
223  return( _roPosition1.fdLongitude > _roPosition2.fdLongitude );
224 }
225 
226 bool CDataPosition::compareLatitudeAscending( const CDataPosition& _roPosition1, const CDataPosition& _roPosition2 )
227 {
228  return( _roPosition1.fdLatitude < _roPosition2.fdLatitude );
229 }
230 
231 bool CDataPosition::compareLatitudeDescending( const CDataPosition& _roPosition1, const CDataPosition& _roPosition2 )
232 {
233  return( _roPosition1.fdLatitude > _roPosition2.fdLatitude );
234 }
235 
236 bool CDataPosition::compareElevationAscending( const CDataPosition& _roPosition1, const CDataPosition& _roPosition2 )
237 {
238  return( _roPosition1.fdElevation < _roPosition2.fdElevation );
239 }
240 
241 bool CDataPosition::compareElevationDescending( const CDataPosition& _roPosition1, const CDataPosition& _roPosition2 )
242 {
243  return( _roPosition1.fdElevation > _roPosition2.fdElevation );
244 }
(Geographical) Position data [long,lat,elev]
double fdElevation
Elevation, in meters.
static bool compareElevationAscending(const CDataPosition &_roPosition1, const CDataPosition &_roPosition2)
Elevation (ascending sort) comparison operator.
static double bearingGC(const CDataPosition &_roPosition1, const CDataPosition &_roPosition2)
Returns the great-circle (initial) bearing between two points, in degrees.
static constexpr double UNDEFINED_LATITUDE
Specific value for an undefined latitude.
static bool compareElevationDescending(const CDataPosition &_roPosition1, const CDataPosition &_roPosition2)
Elevation (descending sort) comparison operator.
void resetPosition()
Resets all coordinates (to an undefined position)
double fdLatitude
Latitude, in degrees.
static bool compareLatitudeDescending(const CDataPosition &_roPosition1, const CDataPosition &_roPosition2)
Latitude (descending sort) comparison operator.
static double bearingRL(const CDataPosition &_roPosition1, const CDataPosition &_roPosition2)
Returns the rhumb-line (constant) bearing between two points, in degrees.
static double distanceRL(const CDataPosition &_roPosition1, const CDataPosition &_roPosition2)
Returns the rhumb-line distance between two points, in meters.
static const CDataPosition UNDEFINED
Specific value for an undefined position.
static constexpr double UNDEFINED_LONGITUDE
Specific value for an undefined longitude.
void serialize(QDataStream &_rqDataStream) const
Serializes (store) this object's data to binary format.
static bool compareLongitudeDescending(const CDataPosition &_roPosition1, const CDataPosition &_roPosition2)
Longitude (descending sort) comparison operator.
void setPosition(double _fdLongitude, double _fdLatitude, double _fdElevation=UNDEFINED_ELEVATION)
Sets new coordinates.
static constexpr double UNDEFINED_ELEVATION
Specific value for an undefined elevation.
double fdLongitude
Longitude, in degrees.
static double length(const CDataPosition &_roPosition1, const CDataPosition &_roPosition2)
Returns the length (rhumb-line distance and elevation delta) between two points, in meters.
bool operator!=(const CDataPosition &_roPosition) const
Inequality operator.
void unserialize(QDataStream &_rqDataStream)
Unserializes (restore) this object's data from binary format.
bool operator==(const CDataPosition &_roPosition) const
Equality operator.
static bool compareLatitudeAscending(const CDataPosition &_roPosition1, const CDataPosition &_roPosition2)
Latitude (ascending sort) comparison operator.
static double distanceGC(const CDataPosition &_roPosition1, const CDataPosition &_roPosition2)
Returns the WGS84-corrected great-circle distance between two points, in meters.
static bool compareLongitudeAscending(const CDataPosition &_roPosition1, const CDataPosition &_roPosition2)
Longitude (ascending sort) comparison operator.