1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-24 03:35:53 +01:00
GPXSee/src/data/poi.cpp

213 lines
4.2 KiB
C++

#include <QFile>
#include <QDir>
#include "common/rectc.h"
#include "common/greatcircle.h"
#include "common/wgs84.h"
#include "data.h"
#include "path.h"
#include "poi.h"
static bool cb(size_t data, void* context)
{
QSet<int> *set = (QSet<int>*) context;
set->insert((int)data);
return true;
}
POI::File::File(int start, int end, const QVector<Waypoint> &data)
: _enabled(true)
{
qreal c[2];
for (int i = start; i <= end; i++) {
const Coordinates &p = data.at(i).coordinates();
c[0] = p.lon();
c[1] = p.lat();
_tree.Insert(c, c, i);
}
}
void POI::File::search(const RectC &rect, QSet<int> &set) const
{
qreal min[2], max[2];
if (_enabled) {
if (rect.left() > rect.right()) {
min[0] = rect.topLeft().lon();
min[1] = rect.bottomRight().lat();
max[0] = 180.0;
max[1] = rect.topLeft().lat();
_tree.Search(min, max, cb, &set);
min[0] = -180.0;
min[1] = rect.bottomRight().lat();
max[0] = rect.bottomRight().lon();
max[1] = rect.topLeft().lat();
_tree.Search(min, max, cb, &set);
} else {
min[0] = rect.topLeft().lon();
min[1] = rect.bottomRight().lat();
max[0] = rect.bottomRight().lon();
max[1] = rect.topLeft().lat();
_tree.Search(min, max, cb, &set);
}
}
}
POI::POI(QObject *parent) : QObject(parent)
{
_errorLine = 0;
_radius = 1000;
}
POI::~POI()
{
qDeleteAll(_files);
}
bool POI::loadFile(const QString &path)
{
Data data(path);
if (!data.isValid()) {
_errorString = data.errorString();
_errorLine = data.errorLine();
return false;
}
int start = _data.size();
_data.append(data.waypoints());
_files.insert(path, new File(start, _data.size() - 1, _data));
emit pointsChanged();
return true;
}
TreeNode<QString> POI::loadDir(const QString &path)
{
QDir md(path);
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
md.setSorting(QDir::DirsFirst);
QFileInfoList fl = md.entryInfoList();
TreeNode<QString> tree(md.dirName());
for (int i = 0; i < fl.size(); i++) {
const QFileInfo &fi = fl.at(i);
if (fi.isDir()) {
TreeNode<QString> child(loadDir(fi.absoluteFilePath()));
if (!child.isEmpty())
tree.addChild(child);
} else {
if (loadFile(fi.absoluteFilePath()))
tree.addItem(fi.absoluteFilePath());
else
qWarning("%s: %s", qPrintable(fi.absoluteFilePath()),
qPrintable(_errorString));
}
}
return tree;
}
void POI::search(const RectC &rect, QSet<int> &set) const
{
for (ConstIterator it = _files.constBegin(); it != _files.constEnd(); ++it)
(*it)->search(rect, set);
}
QList<Waypoint> POI::points(const Path &path) const
{
QList<Waypoint> ret;
QSet<int> set;
QSet<int>::const_iterator it;
for (int i = 0; i < path.count(); i++) {
const PathSegment &segment = path.at(i);
for (int j = 1; j < segment.size(); j++) {
double ds = segment.at(j).distance() - segment.at(j-1).distance();
unsigned n = (unsigned)ceil(ds / _radius);
if (n > 1) {
GreatCircle gc(segment.at(j-1).coordinates(),
segment.at(j).coordinates());
for (unsigned k = 0; k < n; k++) {
RectC br(gc.pointAt((double)k/n), _radius);
search(br, set);
}
} else {
RectC br(segment.at(j-1).coordinates(), _radius);
search(br, set);
}
}
}
RectC br(path.last().last().coordinates(), _radius);
search(br, set);
for (it = set.constBegin(); it != set.constEnd(); ++it)
ret.append(_data.at(*it));
return ret;
}
QList<Waypoint> POI::points(const Waypoint &point) const
{
QList<Waypoint> ret;
QSet<int> set;
QSet<int>::const_iterator it;
RectC br(point.coordinates(), _radius);
search(br, set);
for (it = set.constBegin(); it != set.constEnd(); ++it)
ret.append(_data.at(*it));
return ret;
}
QList<Waypoint> POI::points(const RectC &rect) const
{
QList<Waypoint> ret;
QSet<int> set;
QSet<int>::const_iterator it;
double offset = rad2deg(_radius / WGS84_RADIUS);
RectC br(rect.adjusted(-offset, offset, offset, -offset));
search(br, set);
for (it = set.constBegin(); it != set.constEnd(); ++it)
ret.append(_data.at(*it));
return ret;
}
bool POI::enableFile(const QString &fileName, bool enable)
{
Iterator it = _files.find(fileName);
if (it == _files.end())
return false;
(*it)->enable(enable);
emit pointsChanged();
return true;
}
void POI::setRadius(unsigned radius)
{
_radius = radius;
emit pointsChanged();
}