2015-10-05 01:43:48 +02:00
|
|
|
#include <QFile>
|
2018-01-30 00:30:26 +01:00
|
|
|
#include <QDir>
|
2018-04-13 21:14:12 +02:00
|
|
|
#include "common/rectc.h"
|
2016-10-23 11:09:20 +02:00
|
|
|
#include "data.h"
|
2015-10-05 01:43:48 +02:00
|
|
|
#include "poi.h"
|
|
|
|
|
|
|
|
|
2016-10-09 23:46:30 +02:00
|
|
|
POI::POI(QObject *parent) : QObject(parent)
|
|
|
|
{
|
|
|
|
_errorLine = 0;
|
2016-12-06 01:48:26 +01:00
|
|
|
_radius = 1000;
|
2016-10-09 23:46:30 +02:00
|
|
|
}
|
|
|
|
|
2018-01-30 00:30:26 +01:00
|
|
|
bool POI::loadFile(const QString &path, bool dir)
|
2016-02-11 20:58:52 +01:00
|
|
|
{
|
2016-10-23 11:09:20 +02:00
|
|
|
Data data;
|
2016-03-05 18:01:13 +01:00
|
|
|
FileIndex index;
|
|
|
|
|
|
|
|
index.enabled = true;
|
|
|
|
index.start = _data.size();
|
2015-10-05 01:43:48 +02:00
|
|
|
|
2018-01-30 00:30:26 +01:00
|
|
|
if (!data.loadFile(path)) {
|
|
|
|
if (dir) {
|
|
|
|
if (data.errorLine())
|
|
|
|
_errorString += QString("%1:%2: %3\n").arg(path)
|
|
|
|
.arg(data.errorLine()).arg(data.errorString());
|
|
|
|
else
|
|
|
|
_errorString += path + ": " + data.errorString() + "\n";
|
|
|
|
} else {
|
|
|
|
_errorString = data.errorString();
|
|
|
|
_errorLine = data.errorLine();
|
|
|
|
}
|
2015-10-05 01:43:48 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-10-23 11:09:20 +02:00
|
|
|
for (int i = 0; i < data.waypoints().size(); i++)
|
|
|
|
_data.append(data.waypoints().at(i));
|
2016-03-05 18:01:13 +01:00
|
|
|
index.end = _data.size() - 1;
|
2015-10-05 01:43:48 +02:00
|
|
|
|
2016-03-05 18:01:13 +01:00
|
|
|
for (int i = index.start; i <= index.end; i++) {
|
2016-10-24 00:21:40 +02:00
|
|
|
const Coordinates &p = _data.at(i).coordinates();
|
2015-10-05 01:43:48 +02:00
|
|
|
qreal c[2];
|
2016-10-24 00:21:40 +02:00
|
|
|
c[0] = p.lon();
|
|
|
|
c[1] = p.lat();
|
2015-11-26 19:13:59 +01:00
|
|
|
_tree.Insert(c, c, i);
|
2015-10-05 01:43:48 +02:00
|
|
|
}
|
|
|
|
|
2018-01-30 00:30:26 +01:00
|
|
|
_files.append(path);
|
2016-03-05 18:01:13 +01:00
|
|
|
_indexes.append(index);
|
|
|
|
|
2016-10-23 11:09:20 +02:00
|
|
|
emit pointsChanged();
|
|
|
|
|
2015-10-05 01:43:48 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-01-30 00:30:26 +01:00
|
|
|
bool POI::loadFile(const QString &path)
|
|
|
|
{
|
|
|
|
_errorString.clear();
|
|
|
|
_errorLine = 0;
|
|
|
|
|
|
|
|
return loadFile(path, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool POI::loadDir(const QString &path)
|
|
|
|
{
|
|
|
|
QDir md(path);
|
|
|
|
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
|
|
|
QFileInfoList fl = md.entryInfoList();
|
|
|
|
bool ret = true;
|
|
|
|
|
|
|
|
_errorString.clear();
|
|
|
|
_errorLine = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < fl.size(); i++) {
|
|
|
|
const QFileInfo &fi = fl.at(i);
|
|
|
|
|
|
|
|
if (fi.isDir()) {
|
|
|
|
if (!loadDir(fi.absoluteFilePath()))
|
|
|
|
ret = false;
|
|
|
|
} else {
|
|
|
|
if (!loadFile(fi.absoluteFilePath(), true))
|
|
|
|
ret = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-11-26 19:13:59 +01:00
|
|
|
static bool cb(size_t data, void* context)
|
2015-10-05 01:43:48 +02:00
|
|
|
{
|
2015-11-26 19:13:59 +01:00
|
|
|
QSet<int> *set = (QSet<int>*) context;
|
|
|
|
set->insert((int)data);
|
2015-10-05 01:43:48 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-09-12 19:55:32 +02:00
|
|
|
static Coordinates intermediate(const Coordinates &c1, const Coordinates &c2,
|
|
|
|
double f)
|
|
|
|
{
|
|
|
|
double lat1 = deg2rad(c1.lat());
|
|
|
|
double lon1 = deg2rad(c1.lon());
|
|
|
|
double lat2 = deg2rad(c2.lat());
|
|
|
|
double lon2 = deg2rad(c2.lon());
|
|
|
|
|
|
|
|
double cosLat1 = cos(lat1);
|
|
|
|
double cosLat2 = cos(lat2);
|
|
|
|
double d = 2 * asin(sqrt(pow((sin((lat1 - lat2) / 2)), 2) + cosLat1
|
|
|
|
* cosLat2 * pow(sin((lon1 - lon2) / 2), 2)));
|
|
|
|
double sinD = sin(d);
|
|
|
|
double A = sin((1.0-f)*d) / sinD;
|
|
|
|
double B = sin(f*d) / sinD;
|
|
|
|
double x = A * cosLat1 * cos(lon1) + B * cosLat2 * cos(lon2);
|
|
|
|
double y = A * cosLat1 * sin(lon1) + B * cosLat2 * sin(lon2);
|
|
|
|
double z = A * sin(lat1) + B * sin(lat2);
|
|
|
|
|
|
|
|
return Coordinates(rad2deg(atan2(y, x)), rad2deg(atan2(z, sqrt(x*x + y*y))));
|
|
|
|
}
|
|
|
|
|
2017-11-26 18:54:03 +01:00
|
|
|
QList<Waypoint> POI::points(const Path &path) const
|
2016-07-28 00:23:22 +02:00
|
|
|
{
|
2017-11-26 18:54:03 +01:00
|
|
|
QList<Waypoint> ret;
|
2016-07-28 00:23:22 +02:00
|
|
|
QSet<int> set;
|
|
|
|
qreal min[2], max[2];
|
2017-11-26 18:54:03 +01:00
|
|
|
QSet<int>::const_iterator it;
|
2016-07-28 00:23:22 +02:00
|
|
|
|
2016-12-06 01:48:26 +01:00
|
|
|
|
2018-09-12 19:55:32 +02:00
|
|
|
for (int i = 1; i < path.count(); i++) {
|
|
|
|
double ds = path.at(i).distance() - path.at(i-1).distance();
|
|
|
|
unsigned n = (unsigned)ceil(ds / _radius);
|
|
|
|
for (unsigned j = 0; j < n; j++) {
|
|
|
|
RectC br(n > 1 ? intermediate(path.at(i-1).coordinates(),
|
|
|
|
path.at(i).coordinates(), (double)j/(double)n)
|
|
|
|
: path.at(i-1).coordinates(), _radius);
|
|
|
|
|
|
|
|
min[0] = br.topLeft().lon();
|
|
|
|
min[1] = br.bottomRight().lat();
|
|
|
|
max[0] = br.bottomRight().lon();
|
|
|
|
max[1] = br.topLeft().lat();
|
|
|
|
|
|
|
|
_tree.Search(min, max, cb, &set);
|
|
|
|
}
|
2016-07-28 00:23:22 +02:00
|
|
|
}
|
|
|
|
|
2018-09-12 19:55:32 +02:00
|
|
|
RectC br(path.last().coordinates(), _radius);
|
|
|
|
min[0] = br.topLeft().lon();
|
|
|
|
min[1] = br.bottomRight().lat();
|
|
|
|
max[0] = br.bottomRight().lon();
|
|
|
|
max[1] = br.topLeft().lat();
|
|
|
|
|
|
|
|
_tree.Search(min, max, cb, &set);
|
|
|
|
|
|
|
|
|
2017-11-26 18:54:03 +01:00
|
|
|
for (it = set.constBegin(); it != set.constEnd(); ++it)
|
|
|
|
ret.append(_data.at(*it));
|
2015-10-05 01:43:48 +02:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-11-26 18:54:03 +01:00
|
|
|
QList<Waypoint> POI::points(const Waypoint &point) const
|
2016-10-08 14:53:10 +02:00
|
|
|
{
|
2017-11-26 18:54:03 +01:00
|
|
|
QList<Waypoint> ret;
|
2016-10-08 14:53:10 +02:00
|
|
|
QSet<int> set;
|
|
|
|
qreal min[2], max[2];
|
2017-11-26 18:54:03 +01:00
|
|
|
QSet<int>::const_iterator it;
|
2016-10-08 14:53:10 +02:00
|
|
|
|
2018-04-13 21:14:12 +02:00
|
|
|
RectC br(point.coordinates(), _radius);
|
|
|
|
min[0] = br.topLeft().lon();
|
|
|
|
min[1] = br.bottomRight().lat();
|
|
|
|
max[0] = br.bottomRight().lon();
|
|
|
|
max[1] = br.topLeft().lat();
|
2016-12-06 01:48:26 +01:00
|
|
|
|
2017-11-26 18:54:03 +01:00
|
|
|
_tree.Search(min, max, cb, &set);
|
2016-10-08 14:53:10 +02:00
|
|
|
|
2017-11-26 18:54:03 +01:00
|
|
|
for (it = set.constBegin(); it != set.constEnd(); ++it)
|
|
|
|
ret.append(_data.at(*it));
|
2016-10-08 14:53:10 +02:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-03-05 18:01:13 +01:00
|
|
|
void POI::enableFile(const QString &fileName, bool enable)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
i = _files.indexOf(fileName);
|
|
|
|
Q_ASSERT(i >= 0);
|
|
|
|
_indexes[i].enabled = enable;
|
|
|
|
|
|
|
|
_tree.RemoveAll();
|
|
|
|
for (int i = 0; i < _indexes.count(); i++) {
|
|
|
|
FileIndex idx = _indexes.at(i);
|
|
|
|
if (!idx.enabled)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (int j = idx.start; j <= idx.end; j++) {
|
2016-10-24 00:21:40 +02:00
|
|
|
const Coordinates &p = _data.at(j).coordinates();
|
2016-03-05 18:01:13 +01:00
|
|
|
qreal c[2];
|
2016-10-24 00:21:40 +02:00
|
|
|
c[0] = p.lon();
|
|
|
|
c[1] = p.lat();
|
2016-03-05 18:01:13 +01:00
|
|
|
_tree.Insert(c, c, j);
|
|
|
|
}
|
|
|
|
}
|
2016-10-09 23:46:30 +02:00
|
|
|
|
2016-10-11 00:19:42 +02:00
|
|
|
emit pointsChanged();
|
2016-03-05 18:01:13 +01:00
|
|
|
}
|
|
|
|
|
2015-10-05 01:43:48 +02:00
|
|
|
void POI::clear()
|
|
|
|
{
|
|
|
|
_tree.RemoveAll();
|
|
|
|
_data.clear();
|
2016-03-05 18:01:13 +01:00
|
|
|
_files.clear();
|
|
|
|
_indexes.clear();
|
2016-10-09 23:46:30 +02:00
|
|
|
|
2016-10-11 00:19:42 +02:00
|
|
|
emit pointsChanged();
|
2016-10-09 23:46:30 +02:00
|
|
|
}
|
|
|
|
|
2016-12-06 01:48:26 +01:00
|
|
|
void POI::setRadius(unsigned radius)
|
2016-10-09 23:46:30 +02:00
|
|
|
{
|
|
|
|
_radius = radius;
|
|
|
|
|
2016-10-11 00:19:42 +02:00
|
|
|
emit pointsChanged();
|
2015-10-05 01:43:48 +02:00
|
|
|
}
|