27 #define _USE_MATH_DEFINES
34 const double UrlFactory::EarthRadiusKm = 6378.137;
42 Proxy.setType(QNetworkProxy::DefaultProxy);
47 UserAgent =
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36";
50 CorrectGoogleVersions=
true;
51 isCorrectedGoogleVersions =
false;
52 UseGeocoderCache=
true;
53 UsePlacemarkCache=
true;
58 QString UrlFactory::TileXYToQuadKey(
const int &tileX,
const int &tileY,
const int &levelOfDetail)
const
61 for(
int i = levelOfDetail;
i > 0;
i--)
64 int mask = 1 << (
i - 1);
65 if((tileX & mask) != 0)
69 if((tileY & mask) != 0)
74 quadKey.append(digit);
78 int UrlFactory::GetServerNum(
const Point &pos,
const int &max)
const
80 return (pos.X() + 2 * pos.Y()) % max;
84 isCorrectedGoogleVersions=value;
89 return isCorrectedGoogleVersions;
92 void UrlFactory::TryCorrectGoogleVersions()
94 static bool versionRetrieved =
false;
95 if (versionRetrieved){
99 QMutexLocker locker(&mutex);
102 QNetworkReply *reply =
nullptr;
103 QNetworkRequest qheader;
104 QNetworkAccessManager network;
107 tT.setSingleShot(
true);
108 connect(&network, SIGNAL(finished(QNetworkReply*)),
110 connect(&tT, SIGNAL(timeout()), &q, SLOT(quit()));
111 network.setProxy(
Proxy);
112 #ifdef DEBUG_URLFACTORY
113 qDebug()<<
"Correct GoogleVersion";
114 #endif //DEBUG_URLFACTORY
118 qheader.setRawHeader(
"User-Agent",
UserAgent);
119 reply = network.get(qheader);
126 if( (reply->error()!=QNetworkReply::NoError))
128 #ifdef DEBUG_URLFACTORY
129 qDebug()<<
"Try corrected version error:"<<reply->errorString();
130 #endif //DEBUG_URLFACTORY
133 QString html = QString(reply->readAll());
134 QRegExp reg(
gMapRegex,Qt::CaseInsensitive);
135 qDebug() <<
"index="<<reg.indexIn(html);
136 if(reg.indexIn(html)!=-1)
138 QStringList gc = reg.capturedTexts();
141 #ifdef DEBUG_URLFACTORY
143 #endif //DEBUG_URLFACTORY
146 reg=QRegExp(
gLabRegex,Qt::CaseInsensitive);
147 if(reg.indexIn(html)!=-1)
149 QStringList gc=reg.capturedTexts();
152 #ifdef DEBUG_URLFACTORY
154 #endif //DEBUG_URLFACTORY
156 reg=QRegExp(
gSatRegex,Qt::CaseInsensitive);
157 if(reg.indexIn(html)!=-1)
159 QStringList gc=reg.capturedTexts();
163 #ifdef DEBUG_URLFACTORY
165 #endif //DEBUG_URLFACTORY
167 reg=QRegExp(
gTerRegex,Qt::CaseInsensitive);
168 if(reg.indexIn(html)!=-1)
170 QStringList gc=reg.capturedTexts();
173 #ifdef DEBUG_URLFACTORY
175 #endif //DEBUG_URLFACTORY
177 reply->deleteLater();
178 versionRetrieved =
true;
193 #ifdef DEBUG_URLFACTORY
195 #endif //DEBUG_URLFACTORY
198 case MapType::GoogleMap:
200 QString server =
"mt";
201 QString request =
"vt";
204 GetSecGoogleWords(pos, sec1, sec2);
205 TryCorrectGoogleVersions();
207 return QString(
"http://%1%2.google.com/%3/lyrs=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(
VersionGoogleMap).arg(language).arg(pos.
X()).arg(sec1).arg(pos.
Y()).arg(zoom).arg(sec2);
210 case MapType::GoogleSatellite:
212 QString server =
"khm";
213 QString request =
"kh";
216 GetSecGoogleWords(pos, sec1, sec2);
217 TryCorrectGoogleVersions();
218 return QString(
"http://%1%2.google.com/%3/v=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(
VersionGoogleSatellite).arg(language).arg(pos.
X()).arg(sec1).arg(pos.
Y()).arg(zoom).arg(sec2);
221 case MapType::GoogleLabels:
223 QString server =
"mt";
224 QString request =
"vt";
227 GetSecGoogleWords(pos, sec1, sec2);
228 TryCorrectGoogleVersions();
230 return QString(
"http://%1%2.google.com/%3/lyrs=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(
VersionGoogleLabels).arg(language).arg(pos.
X()).arg(sec1).arg(pos.
Y()).arg(zoom).arg(sec2);
233 case MapType::GoogleTerrain:
235 QString server =
"mt";
236 QString request =
"vt";
239 GetSecGoogleWords(pos, sec1, sec2);
240 TryCorrectGoogleVersions();
241 return QString(
"http://%1%2.google.com/%3/v=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(
VersionGoogleTerrain).arg(language).arg(pos.
X()).arg(sec1).arg(pos.
Y()).arg(zoom).arg(sec2);
244 case MapType::GoogleMapChina:
246 QString server =
"mt";
247 QString request =
"vt";
250 GetSecGoogleWords(pos, sec1, sec2);
251 TryCorrectGoogleVersions();
254 return QString(
"http://%1%2.google.cn/%3/lyrs=%4&hl=%5&gl=cn&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(
VersionGoogleMapChina).arg(
"zh-CN").arg(pos.
X()).arg(sec1).arg(pos.
Y()).arg(zoom).arg(sec2);
257 case MapType::GoogleSatelliteChina:
259 QString server =
"mt";
260 QString request =
"vt";
263 GetSecGoogleWords(pos, sec1, sec2);
267 return QString(
"http://%1%2.google.cn/%3/lyrs=%4&gl=cn&x=%5%6&y=%7&z=%8&s=%9").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(
VersionGoogleSatelliteChina).arg(pos.
X()).arg(sec1).arg(pos.
Y()).arg(zoom).arg(sec2);
270 case MapType::GoogleLabelsChina:
272 QString server =
"mt";
273 QString request =
"vt";
276 GetSecGoogleWords(pos, sec1, sec2);
277 TryCorrectGoogleVersions();
280 return QString(
"http://%1%2.google.cn/%3/imgtp=png32&lyrs=%4&hl=%5&gl=cn&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(
VersionGoogleLabelsChina).arg(
"zh-CN").arg(pos.
X()).arg(sec1).arg(pos.
Y()).arg(zoom).arg(sec2);
283 case MapType::GoogleTerrainChina:
285 QString server =
"mt";
286 QString request =
"vt";
289 GetSecGoogleWords(pos, sec1, sec2);
290 TryCorrectGoogleVersions();
293 return QString(
"http://%1%2.google.com/%3/lyrs=%4&hl=%5&gl=cn&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(
VersionGoogleTerrainChina).arg(
"zh-CN").arg(pos.
X()).arg(sec1).arg(pos.
Y()).arg(zoom).arg(sec2);
296 case MapType::GoogleMapKorea:
298 QString server =
"mt";
299 QString request =
"mt";
302 GetSecGoogleWords(pos, sec1, sec2);
306 QString ret = QString(
"http://%1%2.gmaptiles.co.kr/%3/v=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(
VersionGoogleMapKorea).arg(language).arg(pos.
X()).arg(sec1).arg(pos.
Y()).arg(zoom).arg(sec2);
310 case MapType::GoogleSatelliteKorea:
312 QString server =
"khm";
313 QString request =
"kh";
316 GetSecGoogleWords(pos, sec1, sec2);
320 return QString(
"http://%1%2.google.co.kr/%3/v=%4&x=%5%6&y=%7&z=%8&s=%9").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(
VersionGoogleSatelliteKorea).arg(pos.
X()).arg(sec1).arg(pos.
Y()).arg(zoom).arg(sec2);
323 case MapType::GoogleLabelsKorea:
325 QString server =
"mt";
326 QString request =
"mt";
329 GetSecGoogleWords(pos, sec1, sec2);
333 return QString(
"http://%1%2.gmaptiles.co.kr/%3/v=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(
VersionGoogleLabelsKorea).arg(language).arg(pos.
X()).arg(sec1).arg(pos.
Y()).arg(zoom).arg(sec2);
336 case MapType::YahooMap:
338 return QString(
"http://maps%1.yimg.com/hx/tl?v=%2&.intl=%3&x=%4&y=%5&z=%6&r=1").arg(((GetServerNum(pos, 2)) + 1)).arg(
VersionYahooMap).arg(language).arg(pos.
X()).arg((((1 << zoom) >> 1) - 1 - pos.
Y())).arg((zoom + 1));
341 case MapType::YahooSatellite:
343 return QString(
"http://maps%1.yimg.com/ae/ximg?v=%2&t=a&s=256&.intl=%3&x=%4&y=%5&z=%6&r=1").arg(
"3").arg(
VersionYahooSatellite).arg(language).arg(pos.
X()).arg(((1 << zoom) >> 1) - 1 - pos.
Y()).arg(zoom + 1);
346 case MapType::YahooLabels:
348 return QString(
"http://maps%1.yimg.com/hx/tl?v=%2&t=h&.intl=%3&x=%4&y=%5&z=%6&r=1").arg(
"1").arg(
VersionYahooLabels).arg(language).arg(pos.
X()).arg(((1 << zoom) >> 1) - 1 - pos.
Y()).arg(zoom + 1);
351 case MapType::OpenStreetMap:
353 char letter=
"abc"[GetServerNum(pos, 3)];
354 return QString(
"http://%1.tile.openstreetmap.org/%2/%3/%4.png").arg(letter).arg(zoom).arg(pos.
X()).arg(pos.
Y());
357 case MapType::OpenStreetOsm:
359 char letter =
"abc"[GetServerNum(pos, 3)];
360 return QString(
"http://%1.tah.openstreetmap.org/Tiles/tile/%2/%3/%4.png").arg(letter).arg(zoom).arg(pos.
X()).arg(pos.
Y());
363 case MapType::OpenStreetMapSurfer:
367 return QString(
"http://tiles1.mapsurfer.net/tms_r.ashx?x=%1&y=%2&z=%3").arg(pos.
X()).arg(pos.
Y()).arg(zoom);
370 case MapType::OpenStreetMapSurferTerrain:
374 return QString(
"http://tiles2.mapsurfer.net/tms_t.ashx?x=%1&y=%2&z=%3").arg(pos.
X()).arg(pos.
Y()).arg(zoom);
377 case MapType::BingMap:
379 QString key = TileXYToQuadKey(pos.
X(), pos.
Y(), zoom);
383 case MapType::BingSatellite:
385 QString key = TileXYToQuadKey(pos.
X(), pos.
Y(), zoom);
389 case MapType::BingHybrid:
391 QString key = TileXYToQuadKey(pos.
X(), pos.
Y(), zoom);
395 case MapType::ArcGIS_Map:
399 return QString(
"http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer/tile/%1/%2/%3").arg(zoom).arg(pos.
Y()).arg(pos.
X());
402 case MapType::ArcGIS_Satellite:
406 return QString(
"http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer/tile/%1/%2/%3").arg(zoom).arg(pos.
Y()).arg(pos.
X());
409 case MapType::ArcGIS_ShadedRelief:
413 return QString(
"http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_ShadedRelief_World_2D/MapServer/tile/%1/%2/%3").arg(zoom).arg(pos.
Y()).arg(pos.
X());
416 case MapType::ArcGIS_Terrain:
420 return QString(
"http://server.arcgisonline.com/ArcGIS/rest/services/NGS_Topo_US_2D/MapServer/tile/%1/%2/%3").arg(zoom).arg(pos.
Y()).arg(pos.
X());
423 case MapType::ArcGIS_MapsLT_OrtoFoto:
432 return QString(
"http://dc1.maps.lt/cache/mapslt_ortofoto/map/_alllayers/L%1/R%2/C%3.jpg").arg(zoom,2,10,(QChar)
'0').arg(pos.
Y(),8,16,(QChar)
'0').arg(pos.
X(),8,16,(QChar)
'0');
435 case MapType::ArcGIS_MapsLT_Map:
444 return QString(
"http://dc1.maps.lt/cache/mapslt/map/_alllayers/L%1/R%2/C%3.png").arg(zoom,2,10,(QChar)
'0').arg(pos.
Y(),8,16,(QChar)
'0').arg(pos.
X(),8,16,(QChar)
'0');
447 case MapType::ArcGIS_MapsLT_Map_Labels:
453 return QString(
"http://dc1.maps.lt/cache/mapslt_ortofoto_overlay/map/_alllayers/L%1/R%2/C%3.png").arg(zoom,2,10,(QChar)
'0').arg(pos.
Y(),8,16,(QChar)
'0').arg(pos.
X(),8,16,(QChar)
'0');
456 case MapType::PergoTurkeyMap:
468 QString
x=QString(
"%1").arg(QString::number(pos.
X()),9,(QChar)
'0');
469 x.insert(3,
"/").insert(7,
"/");
470 QString
y=QString(
"%1").arg(QString::number(pos.
Y()),9,(QChar)
'0');
471 y.insert(3,
"/").insert(7,
"/");
473 return QString(
"http://map%1.pergo.com.tr/tile/%2/%3/%4.png").arg(GetServerNum(pos, 4)).arg(zoom,2,10,(QChar)
'0').arg(x).arg(y);
476 case MapType::SigPacSpainMap:
478 return QString(
"http://sigpac.mapa.es/kmlserver/raster/%1@3785/%2.%3.%4.img").arg(
levelsForSigPacSpainMap[zoom]).arg(zoom).arg(pos.
X()).arg((2 << (zoom - 1)) - pos.
Y() - 1);
482 case MapType::YandexMapRu:
484 QString server =
"vec";
488 return QString(
"http://%1").arg(server)+QString(
"0%2.maps.yandex.ru/tiles?l=map&v=%3&x=%4&y=%5&z=%6").arg(GetServerNum(pos, 4)+1).arg(
VersionYandexMap).arg(pos.
X()).arg(pos.
Y()).arg(zoom);
497 void UrlFactory::GetSecGoogleWords(
const Point &pos, QString &sec1, QString &sec2)
501 int seclen = ((pos.
X() * 3) + pos.
Y()) % 8;
503 if(pos.
Y() >= 10000 && pos.
Y() < 100000)
511 QString key = keywords.replace(
' ',
'+');
512 if(language.contains(
"AUTO"))
513 return QString(
"http://maps.googleapis.com/maps/api/geocode/xml?address=%0&sensor=false").arg(key);
515 return QString(
"http://maps.googleapis.com/maps/api/geocode/xml?address=%0&sensor=false&language=%1").arg(key).arg(language);
520 if(language.contains(
"AUTO"))
521 return QString(
"http://maps.googleapis.com/maps/api/geocode/xml?latlng=%0,%1&sensor=false").arg(QString::number(pt.
Lat(),
'f', 7)).arg(QString::number(pt.
Lng(),
'f', 7));
523 return QString(
"http://maps.googleapis.com/maps/api/geocode/xml?latlng=%0,%1&sensor=false&language=%2").arg(QString::number(pt.
Lat(),
'f', 7)).arg(QString::number(pt.
Lng(),
'f', 7)).arg(language);
534 #ifdef DEBUG_URLFACTORY
535 qDebug()<<
"Entered GetLatLngFromGeocoderUrl:";
536 #endif //DEBUG_URLFACTORY
537 status = GeoCoderStatusCode::UNKNOWN_ERROR;
538 QString urlEnd = url.mid(url.indexOf(
"xml?address=")+12,url.indexOf(
"&sensor")-url.indexOf(
"xml?address=")-12);
539 urlEnd.replace( QRegExp(
546 "\\%,\\.,\\+,\\~,\\_"
550 if(geo.isNull()|geo.isEmpty())
552 #ifdef DEBUG_URLFACTORY
553 qDebug()<<
"GetLatLngFromGeocoderUrl:Not in cache going internet";
554 #endif //DEBUG_URLFACTORY
555 QNetworkReply::NetworkError
error;
556 geo = FetchWebRequest(url,error);
557 #ifdef DEBUG_URLFACTORY
558 qDebug()<<
"GetLatLngFromGeocoderUrl:URL="<<url;
559 qDebug()<<
"Finished?"<<
error;
560 #endif //DEBUG_URLFACTORY
561 if(error !=QNetworkReply::NoError)
563 #ifdef DEBUG_URLFACTORY
564 qDebug()<<
"GetLatLngFromGeocoderUrl::Network error";
565 #endif //DEBUG_URLFACTORY
569 #ifdef DEBUG_URLFACTORY
570 qDebug()<<
"GetLatLngFromGeocoderUrl:Reply ok";
571 #endif //DEBUG_URLFACTORY
572 results = GetGeoCodingFromXML(geo,status);
574 if(useCache && status == GeoCoderStatusCode::OK)
581 results = GetGeoCodingFromXML(geo,status);
593 #ifdef DEBUG_URLFACTORY
594 qDebug()<<
"Entered GetLatLngFromGeocoderUrl:";
595 #endif //DEBUG_URLFACTORY
596 status = GeoCoderStatusCode::UNKNOWN_ERROR;
597 QString urlEnd = url.mid(url.indexOf(
"xml?latlng=")+11,url.indexOf(
"&sensor")-url.indexOf(
"xml?latlng=")-11);
598 urlEnd.replace( QRegExp(
605 "\\%,\\.,\\+,\\~,\\_"
609 if(geo.isNull()|geo.isEmpty())
611 #ifdef DEBUG_URLFACTORY
612 qDebug()<<
"GetLatLngFromGeocoderUrl:Not in cache going internet";
613 #endif //DEBUG_URLFACTORY
614 QNetworkReply::NetworkError
error;
615 geo = FetchWebRequest(url,error);
616 #ifdef DEBUG_URLFACTORY
617 qDebug()<<
"GetLatLngFromGeocoderUrl:URL="<<url;
618 qDebug()<<
"Finished?"<<
error;
619 #endif //DEBUG_URLFACTORY
620 if(error !=QNetworkReply::NoError)
622 #ifdef DEBUG_URLFACTORY
623 qDebug()<<
"GetLatLngFromGeocoderUrl::Network error";
624 #endif //DEBUG_URLFACTORY
628 #ifdef DEBUG_URLFACTORY
629 qDebug()<<
"GetLatLngFromGeocoderUrl:Reply ok";
630 #endif //DEBUG_URLFACTORY
631 results = GetGeoCodingFromXML(geo,status);
633 if(useCache && status == GeoCoderStatusCode::OK)
640 results = GetGeoCodingFromXML(geo,status);
646 double dLat1InRad = p1.
Lat() * (M_PI / 180);
647 double dLong1InRad = p1.
Lng() * (M_PI / 180);
648 double dLat2InRad = p2.
Lat() * (M_PI / 180);
649 double dLong2InRad = p2.
Lng() * (M_PI / 180);
650 double dLongitude = dLong2InRad - dLong1InRad;
651 double dLatitude = dLat2InRad - dLat1InRad;
652 double a = pow(sin(dLatitude / 2), 2) + cos(dLat1InRad) * cos(dLat2InRad) * pow(sin(dLongitude / 2), 2);
653 double c = 2 * atan2(sqrt(a), sqrt(1 - a));
654 double dDistance = EarthRadiusKm * c;
663 QDomElement docElem = doc.documentElement();
664 status=GeoCoderStatusCode::TypeByStr(docElem.elementsByTagName(
"status").at(0).toElement().text());
665 if(status != GeoCoderStatusCode::OK)
667 QDomNodeList resultsList=docElem.elementsByTagName(
"result");
668 for(
int ii=0;ii<resultsList.count();++ii)
670 QDomNode result=resultsList.at(ii);
671 QString address=result.namedItem(
"formatted_address").toElement().text();
672 QDomNode location =result.namedItem(
"geometry").namedItem(
"location");
673 double lat = location.namedItem(
"lat").toElement().text().toDouble();
674 double lng = location.namedItem(
"lng").toElement().text().toDouble();
675 geoCodingStruct temp;
677 temp.address=address;
683 QByteArray UrlFactory::FetchWebRequest(QString url,QNetworkReply::NetworkError &result)
685 QNetworkReply *networkReply;
686 QNetworkRequest requestHeader;
687 QNetworkAccessManager network;
688 QEventLoop eventLoop;
691 timeoutTimer.setSingleShot(
true);
692 connect(&network, SIGNAL(finished(QNetworkReply*)),
693 &eventLoop, SLOT(quit()));
694 connect(&timeoutTimer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
695 network.setProxy(
Proxy);
696 requestHeader.setUrl(QUrl(url));
697 requestHeader.setRawHeader(
"User-Agent",
UserAgent);
698 networkReply=network.get(requestHeader);
701 if(!timeoutTimer.isActive())
703 result = QNetworkReply::TimeoutError;
707 result = networkReply->error();
708 ret = networkReply->readAll();
714 QNetworkReply::NetworkError netResult;
715 status = GeoCoderStatusCode::UNKNOWN_ERROR;
716 QString url = QString(
"http://maps.googleapis.com/maps/api/elevation/xml?locations=%0,%1&sensor=false").arg(QString::number(coordinate.
Lat(),
'f', 7)).arg(QString::number(coordinate.
Lng(),
'f', 7));
717 QByteArray answer = FetchWebRequest(url,netResult);
718 if(netResult != QNetworkReply::NoError)
721 doc.setContent(answer);
722 qDebug()<<url<<answer;
723 QDomElement docElem = doc.documentElement();
724 status=GeoCoderStatusCode::TypeByStr(docElem.elementsByTagName(
"status").at(0).toElement().text());
725 if(status != GeoCoderStatusCode::OK)
727 QDomNodeList resultsList=docElem.elementsByTagName(
"result");
728 if(resultsList.count() > 0)
729 return resultsList.at(0).namedItem(
"elevation").toElement().text().toDouble();
end function found on Matlab s file exchange The two functions return identical results
else error('Your technical computing program does not support file choosers.Please input the file name in the argument. ') end elseif nargin >0 logfile