2012-06-23 12:30:38 +02:00
|
|
|
/* This file is part of Clementine.
|
|
|
|
Copyright 2012, David Sansome <me@davidsansome.com>
|
2014-12-17 19:02:21 +01:00
|
|
|
Copyright 2012, 2014, John Maguire <john.maguire@gmail.com>
|
|
|
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
2012-06-23 12:30:38 +02:00
|
|
|
|
|
|
|
Clementine is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Clementine is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2012-06-20 12:18:51 +02:00
|
|
|
#include "geolocator.h"
|
|
|
|
|
2015-04-11 22:52:31 +02:00
|
|
|
#include <QJsonDocument>
|
|
|
|
#include <QJsonObject>
|
2020-09-18 16:15:19 +02:00
|
|
|
#include <QJsonParseError>
|
|
|
|
#include <QStringList>
|
|
|
|
#include <cmath>
|
|
|
|
#include <limits>
|
2012-06-20 12:18:51 +02:00
|
|
|
|
|
|
|
#include "core/closure.h"
|
2012-06-20 14:12:37 +02:00
|
|
|
#include "core/logging.h"
|
2012-06-20 12:18:51 +02:00
|
|
|
|
2016-01-08 13:09:13 +01:00
|
|
|
const char* Geolocator::kUrl = "https://data.clementine-player.org/geolocate";
|
2012-06-20 12:18:51 +02:00
|
|
|
|
|
|
|
using std::numeric_limits;
|
|
|
|
|
|
|
|
Geolocator::LatLng::LatLng()
|
2014-02-07 16:34:20 +01:00
|
|
|
: lat_e6_(numeric_limits<int>::min()),
|
|
|
|
lng_e6_(numeric_limits<int>::min()) {}
|
2012-06-20 12:18:51 +02:00
|
|
|
|
|
|
|
Geolocator::LatLng::LatLng(int lat_e6, int lng_e6)
|
2014-02-07 16:34:20 +01:00
|
|
|
: lat_e6_(lat_e6), lng_e6_(lng_e6) {}
|
2012-06-20 12:18:51 +02:00
|
|
|
|
2012-06-20 14:12:37 +02:00
|
|
|
Geolocator::LatLng::LatLng(const QString& latlng)
|
2014-02-07 16:34:20 +01:00
|
|
|
: lat_e6_(numeric_limits<int>::min()), lng_e6_(numeric_limits<int>::min()) {
|
2012-06-20 14:12:37 +02:00
|
|
|
QStringList split = latlng.split(",");
|
|
|
|
if (split.length() != 2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const double lat = split[0].toDouble();
|
|
|
|
const double lng = split[1].toDouble();
|
|
|
|
lat_e6_ = static_cast<int>(lat * 1e6);
|
|
|
|
lng_e6_ = static_cast<int>(lng * 1e6);
|
|
|
|
}
|
|
|
|
|
|
|
|
Geolocator::LatLng::LatLng(const QString& lat, const QString& lng) {
|
|
|
|
lat_e6_ = static_cast<int>(lat.toDouble() * 1e6);
|
|
|
|
lng_e6_ = static_cast<int>(lng.toDouble() * 1e6);
|
|
|
|
}
|
|
|
|
|
|
|
|
int Geolocator::LatLng::Distance(const Geolocator::LatLng& other) const {
|
|
|
|
static const int kEarthRadiusMetres = 6372800;
|
|
|
|
|
|
|
|
double lat_a = lat_e6() / 1000000.0 * (M_PI / 180.0);
|
|
|
|
double lng_a = lng_e6() / 1000000.0 * (M_PI / 180.0);
|
|
|
|
|
|
|
|
double lat_b = other.lat_e6() / 1000000.0 * (M_PI / 180.0);
|
|
|
|
double lng_b = other.lng_e6() / 1000000.0 * (M_PI / 180.0);
|
|
|
|
|
|
|
|
double delta_longitude = lng_b - lng_a;
|
|
|
|
|
|
|
|
double sines = sin(lat_a) * sin(lat_b);
|
|
|
|
double cosines = cos(lat_a) * cos(lat_b) * cos(delta_longitude);
|
|
|
|
double central_angle = acos(sines + cosines);
|
|
|
|
double distance_metres = kEarthRadiusMetres * central_angle;
|
|
|
|
return static_cast<int>(distance_metres);
|
|
|
|
}
|
|
|
|
|
2012-06-20 12:18:51 +02:00
|
|
|
bool Geolocator::LatLng::IsValid() const {
|
|
|
|
return lat_e6_ != numeric_limits<int>::min() &&
|
|
|
|
lng_e6_ != numeric_limits<int>::min();
|
|
|
|
}
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
Geolocator::Geolocator(QObject* parent) : QObject(parent) {}
|
2012-06-20 12:18:51 +02:00
|
|
|
|
|
|
|
void Geolocator::Geolocate() {
|
|
|
|
QNetworkRequest req = QNetworkRequest(QUrl(kUrl));
|
|
|
|
QNetworkReply* reply = network_.get(req);
|
2014-02-07 16:34:20 +01:00
|
|
|
NewClosure(reply, SIGNAL(finished()), this,
|
|
|
|
SLOT(RequestFinished(QNetworkReply*)), reply);
|
2012-06-20 12:18:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Geolocator::RequestFinished(QNetworkReply* reply) {
|
|
|
|
reply->deleteLater();
|
|
|
|
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) != 200) {
|
|
|
|
emit Finished(LatLng());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-04-11 22:52:31 +02:00
|
|
|
QJsonParseError error;
|
2020-09-18 16:15:19 +02:00
|
|
|
QJsonDocument json_document =
|
|
|
|
QJsonDocument::fromJson(reply->readAll(), &error);
|
2015-04-11 22:52:31 +02:00
|
|
|
if (error.error != QJsonParseError::NoError) {
|
2012-06-20 12:18:51 +02:00
|
|
|
emit Finished(LatLng());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-04-11 22:52:31 +02:00
|
|
|
QJsonObject json_object = json_document.object();
|
|
|
|
QString latlng = json_object["latlng"].toString();
|
2012-06-20 12:18:51 +02:00
|
|
|
|
2012-06-20 14:12:37 +02:00
|
|
|
LatLng ll(latlng);
|
|
|
|
emit Finished(ll);
|
|
|
|
}
|
2012-06-20 12:18:51 +02:00
|
|
|
|
2012-06-20 14:12:37 +02:00
|
|
|
QDebug operator<<(QDebug dbg, const Geolocator::LatLng& ll) {
|
|
|
|
dbg.nospace() << "(" << ll.lat_e6() << "," << ll.lng_e6() << ")";
|
|
|
|
return dbg.space();
|
2012-06-20 12:18:51 +02:00
|
|
|
}
|