1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-06-27 03:29:16 +02:00

Added support for polygon objects

This commit is contained in:
2019-01-31 01:46:53 +01:00
parent 91e633e9fa
commit 50306ecb84
53 changed files with 949 additions and 213 deletions

39
src/data/area.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef AREA_H
#define AREA_H
#include <QString>
#include <QList>
#include "polygon.h"
class Area : public QList<Polygon>
{
public:
const QString& name() const {return _name;}
const QString& description() const {return _desc;}
void setName(const QString &name) {_name = name;}
void setDescription(const QString &desc) {_desc = desc;}
bool isValid() const
{
if (isEmpty())
return false;
for (int i = 0; i < size(); i++)
if (!at(i).isValid())
return false;
return true;
}
RectC boundingRect() const
{
RectC ret;
for (int i = 0; i < size(); i++)
ret |= at(i).boundingRect();
return ret;
}
private:
QString _name;
QString _desc;
};
#endif // AREA_H

View File

@ -1,10 +1,12 @@
#include "csvparser.h"
bool CSVParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints)
{
Q_UNUSED(tracks);
Q_UNUSED(routes);
Q_UNUSED(polygons);
bool res;
_errorLine = 1;

View File

@ -9,7 +9,7 @@ public:
CSVParser() : _errorLine(0) {}
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QVector<Waypoint> &waypoints);
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _errorString;}
int errorLine() const {return _errorLine;}

View File

@ -63,20 +63,13 @@ static QHash<QString, Parser*> parsers()
QHash<QString, Parser*> Data::_parsers = parsers();
bool Data::_useDEM = false;
Data::~Data()
void Data::processData(const QList<TrackData> &trackData,
const QList<RouteData> &routeData)
{
for (int i = 0; i < _tracks.count(); i++)
delete _tracks.at(i);
for (int i = 0; i < _routes.count(); i++)
delete _routes.at(i);
}
void Data::processData()
{
for (int i = 0; i < _trackData.count(); i++)
_tracks.append(new Track(_trackData.at(i)));
for (int i = 0; i < _routeData.count(); i++)
_routes.append(new Route(_routeData.at(i)));
for (int i = 0; i < trackData.count(); i++)
_tracks.append(Track(trackData.at(i)));
for (int i = 0; i < routeData.count(); i++)
_routes.append(Route(routeData.at(i)));
for (int i = 0; i < _waypoints.size(); i++) {
if (!_waypoints.at(i).hasElevation() || _useDEM) {
qreal elevation = DEM::elevation(_waypoints.at(i).coordinates());
@ -90,6 +83,8 @@ Data::Data(const QString &fileName, bool poi)
{
QFile file(fileName);
QFileInfo fi(fileName);
QList<TrackData> trackData;
QList<RouteData> routeData;
_valid = false;
_errorLine = 0;
@ -101,9 +96,10 @@ Data::Data(const QString &fileName, bool poi)
QHash<QString, Parser*>::iterator it;
if ((it = _parsers.find(fi.suffix().toLower())) != _parsers.end()) {
if (it.value()->parse(&file, _trackData, _routeData, _waypoints)) {
if (it.value()->parse(&file, trackData, routeData, _polygons,
_waypoints)) {
if (!poi)
processData();
processData(trackData, routeData);
_valid = true;
return;
} else {
@ -112,9 +108,10 @@ Data::Data(const QString &fileName, bool poi)
}
} else {
for (it = _parsers.begin(); it != _parsers.end(); it++) {
if (it.value()->parse(&file, _trackData, _routeData, _waypoints)) {
if (it.value()->parse(&file, trackData, routeData, _polygons,
_waypoints)) {
if (!poi)
processData();
processData(trackData, routeData);
_valid = true;
return;
}

View File

@ -15,15 +15,15 @@ class Data
{
public:
Data(const QString &fileName, bool poi = false);
~Data();
bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;}
int errorLine() const {return _errorLine;}
const QList<Track*> &tracks() const {return _tracks;}
const QList<Route*> &routes() const {return _routes;}
const QList<Track> &tracks() const {return _tracks;}
const QList<Route> &routes() const {return _routes;}
const QVector<Waypoint> &waypoints() const {return _waypoints;}
const QList<Area> &areas() const {return _polygons;}
static QString formats();
static QStringList filter();
@ -31,19 +31,18 @@ public:
static void useDEM(bool use);
private:
void processData();
void processData(const QList<TrackData> &trackData,
const QList<RouteData> &routeData);
bool _valid;
QString _errorString;
int _errorLine;
QList<Track*> _tracks;
QList<Route*> _routes;
QList<Track> _tracks;
QList<Route> _routes;
QList<Area> _polygons;
QVector<Waypoint> _waypoints;
QList<TrackData> _trackData;
QList<RouteData> _routeData;
static QHash<QString, Parser*> _parsers;
static bool _useDEM;
};

View File

@ -372,10 +372,12 @@ bool FITParser::parseHeader(CTX &ctx)
}
bool FITParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes,
QList<Area> &polygons, QVector<Waypoint> &waypoints)
{
Q_UNUSED(routes);
Q_UNUSED(waypoints);
Q_UNUSED(polygons);
CTX ctx(file);

View File

@ -9,7 +9,7 @@ class FITParser : public Parser
{
public:
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QVector<Waypoint> &waypoints);
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _errorString;}
int errorLine() const {return 0;}

View File

@ -3,20 +3,7 @@
#include "geojsonparser.h"
enum Type {
Unknown,
Point,
LineString,
MultiPoint,
Polygon,
MultiLineString,
MultiPolygon,
GeometryCollection,
Feature,
FeatureCollection
};
static Type type(const QJsonObject &json)
GeoJSONParser::Type GeoJSONParser::type(const QJsonObject &json)
{
QString str(json["type"].toString());
@ -57,6 +44,8 @@ bool GeoJSONParser::point(const QJsonArray &coordinates, Waypoint &waypoint,
waypoint.setElevation(coordinates.at(2).toDouble());
if (properties.contains("title") && properties["title"].isString())
waypoint.setName(properties["title"].toString());
if (properties.contains("name") && properties["name"].isString())
waypoint.setName(properties["name"].toString());
if (properties.contains("description")
&& properties["description"].isString())
waypoint.setDescription(properties["description"].toString());
@ -69,7 +58,7 @@ bool GeoJSONParser::multiPoint(const QJsonArray &coordinates,
{
for (int i = 0; i < coordinates.size(); i++) {
if (!coordinates.at(i).isArray()) {
_errorString = "Invalid MultiPoint Coordinates";
_errorString = "Invalid MultiPoint coordinates";
return false;
} else {
waypoints.resize(waypoints.size() + 1);
@ -86,6 +75,8 @@ bool GeoJSONParser::lineString(const QJsonArray &coordinates, TrackData &track,
{
if (properties.contains("title") && properties["title"].isString())
track.setName(properties["title"].toString());
if (properties.contains("name") && properties["name"].isString())
track.setName(properties["name"].toString());
if (properties.contains("description")
&& properties["description"].isString())
track.setDescription(properties["description"].toString());
@ -94,7 +85,7 @@ bool GeoJSONParser::lineString(const QJsonArray &coordinates, TrackData &track,
QJsonArray point(coordinates.at(i).toArray());
if (point.count() < 2 || !point.at(0).isDouble()
|| !point.at(1).isDouble()) {
_errorString = "Invalid LineString Coordinates";
_errorString = "Invalid LineString coordinates";
return false;
}
@ -113,7 +104,7 @@ bool GeoJSONParser::multiLineString(const QJsonArray &coordinates,
{
for (int i = 0; i < coordinates.size(); i++) {
if (!coordinates.at(i).isArray()) {
_errorString = "Invalid MultiLineString Coordinates";
_errorString = "Invalid MultiLineString coordinates";
return false;
} else {
tracks.append(TrackData());
@ -126,9 +117,76 @@ bool GeoJSONParser::multiLineString(const QJsonArray &coordinates,
return true;
}
bool GeoJSONParser::geometryCollection(const QJsonObject &json,
QList<TrackData> &tracks, QVector<Waypoint> &waypoints,
bool GeoJSONParser::polygon(const QJsonArray &coordinates, ::Polygon &pg)
{
for (int i = 0; i < coordinates.size(); i++) {
if (!coordinates.at(i).isArray()) {
_errorString = "Invalid Polygon linear ring";
return false;
}
const QJsonArray lr(coordinates.at(i).toArray());
pg.append(QVector<Coordinates>());
QVector<Coordinates> &data = pg.last();
for (int j = 0; j < lr.size(); j++) {
QJsonArray point(lr.at(j).toArray());
if (point.count() < 2 || !point.at(0).isDouble()
|| !point.at(1).isDouble()) {
_errorString = "Invalid Polygon linear ring coordinates";
return false;
}
data.append(Coordinates(point.at(0).toDouble(),
point.at(1).toDouble()));
}
}
return true;
}
bool GeoJSONParser::polygon(const QJsonArray &coordinates, Area &area,
const QJsonObject &properties)
{
if (properties.contains("title") && properties["title"].isString())
area.setName(properties["title"].toString());
if (properties.contains("name") && properties["name"].isString())
area.setName(properties["name"].toString());
if (properties.contains("description")
&& properties["description"].isString())
area.setDescription(properties["description"].toString());
area.append(::Polygon());
return polygon(coordinates, area.last());
}
bool GeoJSONParser::multiPolygon(const QJsonArray &coordinates,
Area &area, const QJsonObject &properties)
{
if (properties.contains("title") && properties["title"].isString())
area.setName(properties["title"].toString());
if (properties.contains("name") && properties["name"].isString())
area.setName(properties["name"].toString());
if (properties.contains("description")
&& properties["description"].isString())
area.setDescription(properties["description"].toString());
for (int i = 0; i < coordinates.size(); i++) {
if (!coordinates.at(i).isArray()) {
_errorString = "Invalid MultiPolygon coordinates";
return false;
} else {
area.append(::Polygon());
if (!polygon(coordinates.at(i).toArray(), area.last()))
return false;
}
}
return true;
}
bool GeoJSONParser::geometryCollection(const QJsonObject &json,
QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints, const QJsonObject &properties)
{
if (!json.contains("geometries") || !json["geometries"].isArray()) {
_errorString = "Invalid/missing GeometryCollection geometries array";
@ -162,10 +220,19 @@ bool GeoJSONParser::geometryCollection(const QJsonObject &json,
return false;
break;
case Polygon:
areas.append(Area());
if (!polygon(geometry["coordinates"].toArray(), areas.last(),
properties))
return false;
break;
case MultiPolygon:
areas.append(Area());
if (!multiPolygon(geometry["coordinates"].toArray(),
areas.last(), properties))
return false;
break;
case GeometryCollection:
if (!geometryCollection(geometry, tracks, waypoints,
if (!geometryCollection(geometry, tracks, areas, waypoints,
properties))
return false;
break;
@ -180,7 +247,7 @@ bool GeoJSONParser::geometryCollection(const QJsonObject &json,
}
bool GeoJSONParser::feature(const QJsonObject &json, QList<TrackData> &tracks,
QVector<Waypoint> &waypoints)
QList<Area> &areas, QVector<Waypoint> &waypoints)
{
QJsonObject properties(json["properties"].toObject());
QJsonObject geometry(json["geometry"].toObject());
@ -201,10 +268,15 @@ bool GeoJSONParser::feature(const QJsonObject &json, QList<TrackData> &tracks,
return multiLineString(geometry["coordinates"].toArray(), tracks,
properties);
case GeometryCollection:
return geometryCollection(geometry, tracks, waypoints);
return geometryCollection(geometry, tracks, areas, waypoints);
case Polygon:
areas.append(Area());
return polygon(geometry["coordinates"].toArray(), areas.last(),
properties);
case MultiPolygon:
return true;
areas.append(Area());
return multiPolygon(geometry["coordinates"].toArray(), areas.last(),
properties);
default:
_errorString = geometry["type"].toString()
+ ": invalid/missing Feature geometry";
@ -213,7 +285,8 @@ bool GeoJSONParser::feature(const QJsonObject &json, QList<TrackData> &tracks,
}
bool GeoJSONParser::featureCollection(const QJsonObject &json,
QList<TrackData> &tracks, QVector<Waypoint> &waypoints)
QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints)
{
if (!json.contains("features") || !json["features"].isArray()) {
_errorString = "Invalid/missing FeatureCollection features array";
@ -222,7 +295,7 @@ bool GeoJSONParser::featureCollection(const QJsonObject &json,
QJsonArray features(json["features"].toArray());
for (int i = 0; i < features.size(); i++)
if (!feature(features.at(i).toObject(), tracks, waypoints))
if (!feature(features.at(i).toObject(), tracks, areas, waypoints))
return false;
return true;
@ -230,7 +303,7 @@ bool GeoJSONParser::featureCollection(const QJsonObject &json,
bool GeoJSONParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes, QList<Area> &areas, QVector<Waypoint> &waypoints)
{
Q_UNUSED(routes);
QJsonParseError error;
@ -256,14 +329,17 @@ bool GeoJSONParser::parse(QFile *file, QList<TrackData> &tracks,
case MultiLineString:
return multiLineString(json["coordinates"].toArray(), tracks);
case GeometryCollection:
return geometryCollection(json, tracks, waypoints);
return geometryCollection(json, tracks, areas, waypoints);
case Feature:
return feature(json, tracks, waypoints);
return feature(json, tracks, areas, waypoints);
case FeatureCollection:
return featureCollection(json, tracks, waypoints);
return featureCollection(json, tracks, areas, waypoints);
case Polygon:
areas.append(Area());
return polygon(json["coordinates"].toArray(), areas.last());
case MultiPolygon:
return true;
areas.append(Area());
return multiPolygon(json["coordinates"].toArray(), areas.last());
case Unknown:
if (json["type"].toString().isNull())
_errorString = "Not a GeoJSON file";

View File

@ -11,11 +11,25 @@ class GeoJSONParser : public Parser
{
public:
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QVector<Waypoint> &waypoints);
QList<Area> &areas, QVector<Waypoint> &waypoints);
QString errorString() const {return _errorString;}
int errorLine() const {return 0;}
private:
enum Type {
Unknown,
Point,
LineString,
MultiPoint,
Polygon,
MultiLineString,
MultiPolygon,
GeometryCollection,
Feature,
FeatureCollection
};
Type type(const QJsonObject &json);
bool point(const QJsonArray &coordinates, Waypoint &waypoint,
const QJsonObject &properties = QJsonObject());
bool multiPoint(const QJsonArray &coordinates,
@ -24,12 +38,18 @@ private:
const QJsonObject &properties = QJsonObject());
bool multiLineString(const QJsonArray &coordinates,
QList<TrackData> &tracks, const QJsonObject &properties = QJsonObject());
bool polygon(const QJsonArray &coordinates, ::Polygon &pg);
bool polygon(const QJsonArray &coordinates, Area &area,
const QJsonObject &properties = QJsonObject());
bool multiPolygon(const QJsonArray &coordinates, Area &area,
const QJsonObject &properties = QJsonObject());
bool geometryCollection(const QJsonObject &json, QList<TrackData> &tracks,
QVector<Waypoint> &waypoints, const QJsonObject &properties = QJsonObject());
QList<Area> &areas, QVector<Waypoint> &waypoints,
const QJsonObject &properties = QJsonObject());
bool feature(const QJsonObject &json, QList<TrackData> &tracks,
QVector<Waypoint> &waypoints);
QList<Area> &areas, QVector<Waypoint> &waypoints);
bool featureCollection(const QJsonObject &json, QList<TrackData> &tracks,
QVector<Waypoint> &waypoints);
QList<Area> &areas, QVector<Waypoint> &waypoints);
QString _errorString;
};

View File

@ -216,8 +216,11 @@ void GPXParser::gpx(QList<TrackData> &tracks, QList<RouteData> &routes,
}
bool GPXParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints)
{
Q_UNUSED(polygons);
_reader.clear();
_reader.setDevice(file);
_reader.setNamespaceProcessing(false);

View File

@ -8,8 +8,8 @@
class GPXParser : public Parser
{
public:
bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints);
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _reader.errorString();}
int errorLine() const {return _reader.lineNumber();}

View File

@ -39,6 +39,14 @@ inline QDebug operator<<(QDebug dbg, const GraphPoint &point)
}
#endif // QT_NO_DEBUG
typedef QVector<GraphPoint> Graph;
class Graph : public QVector<GraphPoint>
{
public:
Graph() {}
Graph(int size) : QVector<GraphPoint>(size) {}
Graph(const Graph &other) : QVector<GraphPoint>(other) {}
bool isValid() const {return size() >= 2;}
};
#endif // GRAPH_H

View File

@ -192,9 +192,11 @@ bool IGCParser::readCRecord(RouteData &route, const char *line, int len)
}
bool IGCParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints)
{
Q_UNUSED(waypoints);
Q_UNUSED(polygons);
qint64 len;
char line[76 + 2 + 1 + 1];
bool route = false, track = false;

View File

@ -11,8 +11,8 @@ class IGCParser : public Parser
public:
IGCParser() : _errorLine(0) {}
bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints);
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _errorString;}
int errorLine() const {return _errorLine;}

View File

@ -186,6 +186,63 @@ bool KMLParser::lineCoordinates(TrackData &track)
return true;
}
bool KMLParser::polygonCoordinates(QVector<Coordinates> &points)
{
QString data = _reader.readElementText();
const QChar *sp, *ep, *cp, *vp;
int c = 0;
qreal val[3];
bool res;
sp = data.constData();
ep = sp + data.size();
for (cp = sp; cp < ep; cp++)
if (!cp->isSpace())
break;
for (vp = cp; cp <= ep; cp++) {
if (*cp == ',') {
if (c > 1)
return false;
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
val[c] = QString(vp, cp - vp).toDouble(&res);
#else // QT_VERSION < 5
val[c] = QStringRef(&data, vp - sp, cp - vp).toDouble(&res);
#endif // QT_VERSION < 5
if (!res)
return false;
c++;
vp = cp + 1;
} else if (cp->isSpace() || cp->isNull()) {
if (c < 1 || c > 2)
return false;
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
val[c] = QString(vp, cp - vp).toDouble(&res);
#else // QT_VERSION < 5
val[c] = QStringRef(&data, vp - sp, cp - vp).toDouble(&res);
#endif // QT_VERSION < 5
if (!res)
return false;
points.append(Coordinates(val[0], val[1]));
if (!points.last().isValid())
return false;
while (cp->isSpace())
cp++;
c = 0;
vp = cp;
}
}
return true;
}
QDateTime KMLParser::timeStamp()
{
QDateTime ts;
@ -211,6 +268,52 @@ void KMLParser::lineString(TrackData &track)
}
}
void KMLParser::linearRing(QVector<Coordinates> &coordinates)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("coordinates")) {
if (!polygonCoordinates(coordinates))
_reader.raiseError("Invalid coordinates");
} else
_reader.skipCurrentElement();
}
}
void KMLParser::boundary(QVector<Coordinates> &coordinates)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("LinearRing"))
linearRing(coordinates);
else
_reader.skipCurrentElement();
}
}
void KMLParser::polygon(Area &area)
{
area.append(Polygon());
Polygon &polygon = area.last();
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("outerBoundaryIs")) {
if (!area.isEmpty()) {
_reader.raiseError("Multiple polygon outerBoundaryIss");
return;
}
polygon.append(QVector<Coordinates>());
boundary(polygon.last());
} else if (_reader.name() == QLatin1String("innerBoundaryIs")) {
if (area.isEmpty()) {
_reader.raiseError("Missing polygon outerBoundaryIs");
return;
}
polygon.append(QVector<Coordinates>());
boundary(polygon.last());
} else
_reader.skipCurrentElement();
}
}
void KMLParser::point(Waypoint &waypoint)
{
while (_reader.readNextStartElement()) {
@ -380,7 +483,7 @@ void KMLParser::multiTrack(TrackData &t)
}
}
void KMLParser::multiGeometry(QList<TrackData> &tracks,
void KMLParser::multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints, const QString &name, const QString &desc,
const QDateTime timestamp)
{
@ -398,12 +501,19 @@ void KMLParser::multiGeometry(QList<TrackData> &tracks,
t.setName(name);
t.setDescription(desc);
lineString(t);
} else if (_reader.name() == QLatin1String("Polygon")) {
areas.append(Area());
Area &a = areas.last();
a.setName(name);
a.setDescription(desc);
polygon(a);
} else
_reader.skipCurrentElement();
}
}
void KMLParser::placemark(QList<TrackData> &tracks, QVector<Waypoint> &waypoints)
void KMLParser::placemark(QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints)
{
QString name, desc;
QDateTime timestamp;
@ -416,7 +526,7 @@ void KMLParser::placemark(QList<TrackData> &tracks, QVector<Waypoint> &waypoints
else if (_reader.name() == QLatin1String("TimeStamp"))
timestamp = timeStamp();
else if (_reader.name() == QLatin1String("MultiGeometry"))
multiGeometry(tracks, waypoints, name, desc, timestamp);
multiGeometry(tracks, areas, waypoints, name, desc, timestamp);
else if (_reader.name() == QLatin1String("Point")) {
waypoints.append(Waypoint());
Waypoint &w = waypoints.last();
@ -443,51 +553,60 @@ void KMLParser::placemark(QList<TrackData> &tracks, QVector<Waypoint> &waypoints
t.setName(name);
t.setDescription(desc);
multiTrack(t);
} else if (_reader.name() == QLatin1String("Polygon")) {
areas.append(Area());
Area &a = areas.last();
a.setName(name);
a.setDescription(desc);
polygon(a);
} else
_reader.skipCurrentElement();
}
}
void KMLParser::folder(QList<TrackData> &tracks, QVector<Waypoint> &waypoints)
void KMLParser::folder(QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("Placemark"))
placemark(tracks, waypoints);
placemark(tracks, areas, waypoints);
else if (_reader.name() == QLatin1String("Folder"))
folder(tracks, waypoints);
folder(tracks, areas, waypoints);
else
_reader.skipCurrentElement();
}
}
void KMLParser::document(QList<TrackData> &tracks, QVector<Waypoint> &waypoints)
void KMLParser::document(QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("Placemark"))
placemark(tracks, waypoints);
placemark(tracks, areas, waypoints);
else if (_reader.name() == QLatin1String("Folder"))
folder(tracks, waypoints);
folder(tracks, areas, waypoints);
else
_reader.skipCurrentElement();
}
}
void KMLParser::kml(QList<TrackData> &tracks, QVector<Waypoint> &waypoints)
void KMLParser::kml(QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("Document"))
document(tracks, waypoints);
document(tracks, areas, waypoints);
else if (_reader.name() == QLatin1String("Placemark"))
placemark(tracks, waypoints);
placemark(tracks, areas, waypoints);
else if (_reader.name() == QLatin1String("Folder"))
folder(tracks, waypoints);
folder(tracks, areas, waypoints);
else
_reader.skipCurrentElement();
}
}
bool KMLParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes, QList<Area> &areas, QVector<Waypoint> &waypoints)
{
Q_UNUSED(routes);
@ -496,7 +615,7 @@ bool KMLParser::parse(QFile *file, QList<TrackData> &tracks,
if (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("kml"))
kml(tracks, waypoints);
kml(tracks, areas, waypoints);
else
_reader.raiseError("Not a KML file");
}

View File

@ -8,24 +8,33 @@
class KMLParser : public Parser
{
public:
bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints);
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Area> &areas, QVector<Waypoint> &waypoints);
QString errorString() const {return _reader.errorString();}
int errorLine() const {return _reader.lineNumber();}
private:
void kml(QList<TrackData> &tracks, QVector<Waypoint> &waypoints);
void document(QList<TrackData> &tracks, QVector<Waypoint> &waypoints);
void folder(QList<TrackData> &tracks, QVector<Waypoint> &waypoints);
void placemark(QList<TrackData> &tracks, QVector<Waypoint> &waypoints);
void multiGeometry(QList<TrackData> &tracks, QVector<Waypoint> &waypoints,
const QString &name, const QString &desc, const QDateTime timestamp);
void kml(QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints);
void document(QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints);
void folder(QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints);
void placemark(QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints);
void multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints, const QString &name, const QString &desc,
const QDateTime timestamp);
void track(TrackData &track);
void multiTrack(TrackData &t);
void lineString(TrackData &track);
void linearRing(QVector<Coordinates> &coordinates);
void boundary(QVector<Coordinates> &coordinates);
void polygon(Area &area);
void point(Waypoint &waypoint);
bool pointCoordinates(Waypoint &waypoint);
bool lineCoordinates(TrackData &track);
bool polygonCoordinates(QVector<Coordinates> &points);
bool coord(Trackpoint &trackpoint);
void extendedData(TrackData &track, int start);
void schemaData(TrackData &track, int start);

View File

@ -58,10 +58,12 @@ void LOCParser::loc(QVector<Waypoint> &waypoints)
}
bool LOCParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints)
{
Q_UNUSED(tracks);
Q_UNUSED(routes);
Q_UNUSED(polygons);
_reader.clear();
_reader.setDevice(file);

View File

@ -7,8 +7,8 @@
class LOCParser : public Parser
{
public:
bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints);
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _reader.errorString();}
int errorLine() const {return _reader.lineNumber();}

View File

@ -478,9 +478,11 @@ bool NMEAParser::readZDA(const char *line, int len)
}
bool NMEAParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints)
{
Q_UNUSED(routes);
Q_UNUSED(polygons);
qint64 len;
char line[80 + 2 + 1 + 1];

View File

@ -10,8 +10,8 @@ class NMEAParser : public Parser
public:
NMEAParser() : _errorLine(0), _GGA(false) {}
bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints);
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _errorString;}
int errorLine() const {return _errorLine;}

View File

@ -27,10 +27,12 @@ static QByteArray &decode(QByteArray &ba)
bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints)
{
Q_UNUSED(waypoints);
Q_UNUSED(routes);
Q_UNUSED(polygons);
bool res;
const GCS *gcs = 0;
@ -113,10 +115,12 @@ bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
}
bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints)
{
Q_UNUSED(waypoints);
Q_UNUSED(tracks);
Q_UNUSED(polygons);
bool res, record = false;
const GCS *gcs = 0;
@ -211,10 +215,12 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
}
bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints)
{
Q_UNUSED(tracks);
Q_UNUSED(routes);
Q_UNUSED(polygons);
bool res;
const GCS *gcs = 0;

View File

@ -9,7 +9,7 @@ public:
PLTParser() : _errorLine(0) {}
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QVector<Waypoint> &waypoints);
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _errorString;}
int errorLine() const {return _errorLine;}
@ -24,7 +24,7 @@ public:
RTEParser() : _errorLine(0) {}
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QVector<Waypoint> &waypoints);
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _errorString;}
int errorLine() const {return _errorLine;}
@ -39,7 +39,7 @@ public:
WPTParser() : _errorLine(0) {}
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QVector<Waypoint> &waypoints);
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _errorString;}
int errorLine() const {return _errorLine;}

View File

@ -8,6 +8,7 @@
#include "trackdata.h"
#include "routedata.h"
#include "waypoint.h"
#include "area.h"
class Parser
@ -16,7 +17,8 @@ public:
virtual ~Parser() {}
virtual bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints) = 0;
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints) = 0;
virtual QString errorString() const = 0;
virtual int errorLine() const = 0;
};

View File

@ -4,6 +4,9 @@
#include "common/greatcircle.h"
#include "data.h"
#include "dem.h"
#include "path.h"
#include "area.h"
#include "common/wgs84.h"
#include "poi.h"
@ -177,6 +180,31 @@ QList<Waypoint> POI::points(const Waypoint &point) const
return ret;
}
QList<Waypoint> POI::points(const Area &area) const
{
QList<Waypoint> ret;
qreal min[2], max[2];
QSet<int> set;
QSet<int>::const_iterator it;
RectC br(area.boundingRect());
double offset = rad2deg(_radius / WGS84_RADIUS);
min[0] = br.topLeft().lon() - offset;
min[1] = br.bottomRight().lat() - offset;
max[0] = br.bottomRight().lon() + offset;
max[1] = br.topLeft().lat() + offset;
_tree.Search(min, max, cb, &set);
for (it = set.constBegin(); it != set.constEnd(); ++it)
ret.append(_data.at(*it));
appendElevation(ret);
return ret;
}
void POI::enableFile(const QString &fileName, bool enable)
{
int i;

View File

@ -7,8 +7,10 @@
#include <QStringList>
#include "common/rtree.h"
#include "waypoint.h"
#include "path.h"
class Path;
class Area;
class RectC;
class POI : public QObject
{
@ -28,6 +30,7 @@ public:
QList<Waypoint> points(const Path &path) const;
QList<Waypoint> points(const Waypoint &point) const;
QList<Waypoint> points(const Area &area) const;
const QStringList &files() const {return _files;}
void enableFile(const QString &fileName, bool enable);

15
src/data/polygon.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "polygon.h"
RectC Polygon::boundingRect() const
{
if (isEmpty())
return RectC();
if (first().size() < 3)
return RectC();
RectC rect;
for (int i = 0; i < first().size(); i++)
rect = rect.united(first().at(i));
return rect;
}

17
src/data/polygon.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef POLYGON_H
#define POLYGON_H
#include <QList>
#include <QVector>
#include "common/coordinates.h"
#include "common/rectc.h"
class Polygon : public QList<QVector<Coordinates> >
{
public:
bool isValid() const {return !isEmpty() && first().size() >= 3;}
RectC boundingRect() const;
};
#endif // POLYGON_H

View File

@ -22,12 +22,12 @@ public:
const QString &name() const {return _data.name();}
const QString &description() const {return _data.description();}
bool isNull() const {return (_data.count() < 2);}
bool isValid() const {return _data.size() >= 2;}
static void useDEM(bool use) {_useDEM = use;}
private:
const RouteData &_data;
RouteData _data;
QVector<qreal> _distance;
static bool _useDEM;

View File

@ -99,10 +99,12 @@ void SLFParser::activity(TrackData &track)
}
bool SLFParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints)
{
Q_UNUSED(waypoints);
Q_UNUSED(routes);
Q_UNUSED(polygons);
_reader.clear();
_reader.setDevice(file);

View File

@ -8,8 +8,8 @@ class QDateTime;
class SLFParser : public Parser
{
bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints);
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _reader.errorString();}
int errorLine() const {return _reader.lineNumber();}

View File

@ -233,9 +233,11 @@ void TCXParser::tcx(QList<TrackData> &tracks, QVector<Waypoint> &waypoints)
}
bool TCXParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints)
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints)
{
Q_UNUSED(routes);
Q_UNUSED(polygons);
_reader.clear();
_reader.setDevice(file);

View File

@ -8,8 +8,8 @@
class TCXParser : public Parser
{
public:
bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QVector<Waypoint> &waypoints);
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _reader.errorString();}
int errorLine() const {return _reader.lineNumber();}

View File

@ -33,7 +33,7 @@ public:
const QString &name() const {return _data.name();}
const QString &description() const {return _data.description();}
bool isNull() const {return (_data.size() < 2);}
bool isValid() const {return _data.size() >= 2;}
static void setElevationFilter(int window) {_elevationWindow = window;}
static void setSpeedFilter(int window) {_speedWindow = window;}
@ -50,7 +50,7 @@ public:
private:
bool discardStopPoint(int i) const;
const TrackData &_data;
TrackData _data;
QVector<qreal> _distance;
QVector<qreal> _time;