Changes: added GPS class and made app get from location from GPS
[ptas] / zouba / location.cpp
1 #include "location.h"
2
3 #include "location_p.h"
4
5 #include "ytv.h"
6
7 #include <QString>
8 #include <QObject>
9 #include <QNetworkAccessManager>
10 #include <QUrl>
11 #include <QNetworkRequest>
12 #include <QNetworkReply>
13 #include <QXmlStreamReader>
14 #include <QDebug>
15 #include <QXmlStreamAttributes>
16 #include <QStringRef>
17 #include <QGeoPositionInfo>
18
19 #include <math.h>
20
21 const double Location::KkjZoneInfo[6][2] = {
22   {18.0,  500000.0},
23   {21.0, 1500000.0},
24   {24.0, 2500000.0},
25   {27.0, 3500000.0},
26   {30.0, 4500000.0},
27   {33.0, 5500000.0}
28 };
29
30 QTM_USE_NAMESPACE
31
32 Location::Location( QString x, QString y ) :
33   q( new LocationPrivate( x, y ) ),
34   manager( new QNetworkAccessManager(this) )
35 {
36   connect( manager, SIGNAL( finished(QNetworkReply*) ), this, SLOT( replyFinished(QNetworkReply*) ) );
37 }
38
39 Location::Location( const QGeoPositionInfo &positionInfo ) :
40   q( new LocationPrivate() ),
41   manager(0)
42 {
43   qreal latitude = positionInfo.coordinate().latitude();
44   qreal longitude = positionInfo.coordinate().longitude();
45
46   KKJ outX(0);
47   KKJ outY(0);
48
49   WGS84lola_to_KKJxy( longitude, latitude, &outX, &outY);
50
51   q->setX( outX );
52   q->setY( outY );
53   q->setValid( true );
54 }
55
56 Location::Location( const Location &from ) :
57   QObject(0),
58   q( new LocationPrivate() ),
59   manager(0)
60 {
61   q->setX( from.x() );
62   q->setY( from.y() );
63   q->setValid( from.isValid() );
64   if ( from.manager != 0 ) {
65     manager = new QNetworkAccessManager(this);
66     connect( manager, SIGNAL( finished(QNetworkReply*) ), this, SLOT( replyFinished(QNetworkReply*) ) );
67   }
68 }
69
70 Location::Location() :
71   q( new LocationPrivate() ),
72   manager( new QNetworkAccessManager(this) )
73 {
74   connect( manager, SIGNAL( finished(QNetworkReply*) ), this, SLOT( replyFinished(QNetworkReply*) ) );
75 }
76
77 Location::~Location()
78 {
79   delete q;
80   q=0;
81   delete manager;
82   manager=0;
83 }
84
85 Location &Location::operator=( const Location &from )
86 {
87   q = new LocationPrivate();
88   q->setX( from.x() );
89   q->setY( from.y() );
90   q->setValid( from.isValid() );
91   if ( from.manager != 0 ) {
92     manager = new QNetworkAccessManager(this);
93     connect( manager, SIGNAL( finished(QNetworkReply*) ), this, SLOT( replyFinished(QNetworkReply*) ) );
94   } else {
95     manager = 0;
96   }
97   
98   return *this;
99 }
100
101 void Location::resolveAddress( QString address )
102 {
103   QUrl fullUrl( ytv );
104
105   fullUrl.addEncodedQueryItem( "key", address.toAscii().toPercentEncoding() );
106   fullUrl.addQueryItem( "user", username );
107   fullUrl.addQueryItem( "pass", password );
108
109   manager->get( QNetworkRequest( fullUrl ) );
110 }
111
112 void Location::replyFinished( QNetworkReply * reply )
113 {
114   q->parseReply( reply->readAll() );
115
116   if ( isValid() ) {
117     emit( becomeValid() );
118   }
119 }
120
121 QString Location::x() const
122 {
123   return q->x();
124 }
125
126 QString Location::y() const
127 {
128   return q->y();
129 }
130
131 bool Location::isValid() const
132 {
133   return q->isValid();
134 }
135
136
137 // Degrees to radians
138 double Location::radians(double deg)
139 {
140   return deg * M_PI / 180.0;
141 }
142
143 // Radians to degrees
144 double Location::degrees(double rad)
145 {
146   return rad * 180.0 / M_PI;
147 }
148
149 // Function:  KKJ_Zone_I
150 int Location::KKJ_Zone_I(KKJ easting)
151 {
152   int zoneNumber = floor(easting / 1000000.0);
153   if (zoneNumber < 0 || zoneNumber > 5) {
154     zoneNumber = -1;
155   }
156
157   return zoneNumber;
158 }
159
160 // Function:  KKJ_Zone_Lo
161 int Location::KKJ_Zone_Lo(double kkjlo)
162 {
163   // determine the zonenumber from KKJ easting
164   // takes KKJ zone which has center meridian
165   // longitude nearest (in math value) to
166   // the given KKJ longitude
167   int zoneNumber = 5;
168   while (zoneNumber >= 0) {
169     if (fabs(kkjlo - KkjZoneInfo[zoneNumber][0]) <= 1.5) {
170       break;
171     }
172     zoneNumber--;
173   }
174
175   return zoneNumber;
176 }
177
178
179 // Function:  KKJlalo_to_WGS84lalo
180 void Location::KKJlola_to_WGS84lola(double kkjlo, double kkjla, double *outLongitude, double *outLatitude)
181 {
182   double dLa = radians(0.124867E+01 + -0.269982E+00 * kkjla + 0.191330E+00 * kkjlo + 0.356119E-02 * kkjla * kkjla + -0.122312E-02 * kkjla * kkjlo + -0.335514E-03 * kkjlo * kkjlo) / 3600.0;
183   double dLo = radians(-0.286111E+02 + 0.114183E+01 * kkjla + -0.581428E+00 * kkjlo + -0.152421E-01 * kkjla * kkjla + 0.118177E-01 * kkjla * kkjlo + 0.826646E-03 * kkjlo * kkjlo) / 3600.0;
184
185   *outLatitude = degrees(radians(kkjla) + dLa);
186   *outLongitude = degrees(radians(kkjlo) + dLo);
187 }
188
189
190 // Function:  WGS84lalo_to_KKJlalo
191 void Location::WGS84lola_to_KKJlola(double longitude, double latitude, double *outLongitude, double *outLatitude) 
192 {
193   double dLa = radians(-0.124766E+01 + 0.269941E+00 * latitude + -0.191342E+00 * longitude + -0.356086E-02 * latitude * latitude + 0.122353E-02 * latitude * longitude + 0.335456E-03 * longitude * longitude) / 3600.0;
194   double dLo = radians(0.286008E+02 + -0.114139E+01 * latitude + 0.581329E+00 * longitude + 0.152376E-01 * latitude * latitude + -0.118166E-01 * latitude * longitude + -0.826201E-03 * longitude * longitude) / 3600.0;
195
196   *outLatitude = degrees(radians(latitude) + dLa);
197   *outLongitude = degrees(radians(longitude) + dLo);
198 }
199
200
201 // Function:  KKJlalo_to_KKJxy
202 void Location::KKJlola_to_KKJxy(double lon, double lat, int zoneNumber, KKJ *outX, KKJ *outY) 
203 {
204   // Hayford ellipsoid
205   double a = 6378388.0;
206   double f  = 1.0 / 297.0;
207   double b  = (1.0 - f) * a;
208   double bb = b * b;
209   double c  = (a / b) * a;
210   double ee = (a * a - bb) / bb;
211   double n = (a - b) / (a + b);
212   double nn = n * n;
213
214   double Lo = radians(lon) - radians(KkjZoneInfo[zoneNumber][0]);
215   double cosLa = cos(radians(lat));
216   double NN = ee * cosLa * cosLa;
217   double LaF = atan(tan(radians(lat)) / cos(Lo * sqrt(1.0 + NN)));
218   double cosLaF = cos(LaF);
219   double t = (tan(Lo) * cosLaF) / sqrt(1.0 + ee * cosLaF * cosLaF);
220   double A = a / (1.0 + n);
221   double A1 = A * (1.0 + nn / 4.0 + nn * nn / 64.0);
222   double A2 = A * 1.5 * n * (1.0 - nn / 8.0);
223   double A3 = A * 0.9375 * nn * (1.0 - nn / 4.0);
224   double A4 = A * 35.0 / 48.0 * nn * n;
225
226   *outY = A1 * LaF - A2 * sin(2.0 * LaF) + A3 * sin(4.0 * LaF) - A4 * sin(6.0 * LaF);
227   *outX = c * log(t + sqrt(1.0 + t * t)) + 500000.0 + zoneNumber * 1000000.0;
228 }
229
230 // Function:  KKJxy_to_KKJlalo
231 void Location::KKJxy_to_KKJlola(KKJ x, KKJ y, double *outLongitude, double *outLatitude)
232 {
233   // Scan iteratively the target area, until find matching
234   // KKJ coordinate value.  Area is defined with Hayford Ellipsoid.
235   int zoneNumber = KKJ_Zone_I(x);
236   double minLo = radians(18.5);
237   double maxLo = radians(32.0);
238   double minLa = radians(59.0);
239   double maxLa = radians(70.5);
240
241   int i = 1;
242   KKJ tmpX, tmpY;
243
244   while (i < 35) {
245     double deltaLo = maxLo - minLo;
246     double deltaLa = maxLa - minLa;
247     *outLongitude = degrees(minLo + 0.5 * deltaLo);
248     *outLatitude = degrees(minLa + 0.5 * deltaLa);
249     KKJlola_to_KKJxy(*outLongitude, *outLatitude, zoneNumber, &tmpX, &tmpY);
250     if (tmpY < y) {
251       minLa = minLa + 0.45 * deltaLa;
252     } else {
253       maxLa = minLa + 0.55 * deltaLa;
254     }
255
256     if (tmpX < x) {
257       minLo = minLo + 0.45 * deltaLo;
258     } else {
259       maxLo = minLo + 0.55 * deltaLo;
260     }
261
262     i++;
263   }
264 }
265
266 void Location::WGS84lola_to_KKJxy(double longitude, double latitude, KKJ *outX, KKJ *outY)
267 {
268   double kkjlo, kkjla;
269
270   WGS84lola_to_KKJlola(longitude, latitude, &kkjlo, &kkjla);
271   int zoneNumber = KKJ_Zone_Lo(kkjlo);
272   KKJlola_to_KKJxy(kkjlo, kkjla, zoneNumber, outX, outY);
273 }
274
275 void Location::KKJxy_to_WGS84lola(KKJ x, KKJ y, double *outLongitude, double *outLatitude)
276 {
277   double kkjlo, kkjla;
278
279   KKJxy_to_KKJlola(x, y, &kkjlo, &kkjla);
280   KKJlola_to_WGS84lola(kkjlo, kkjla, outLongitude, outLatitude);
281
282 }
283