1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-27 21:24:47 +01:00

Compare commits

...

2 Commits

Author SHA1 Message Date
ff50ffa003 Use the CT type for geographic/projected projections distinguishing 2024-03-11 23:12:51 +01:00
026ef5854d Improved error reporting
+ code cleanup
2024-03-11 23:09:38 +01:00
4 changed files with 78 additions and 81 deletions

View File

@ -7,6 +7,9 @@
#define MARKER_SIZE_SMALL 8 #define MARKER_SIZE_SMALL 8
#define MARKER_SIZE_LARGE 16 #define MARKER_SIZE_LARGE 16
#define PROJ(object, parent) \
((object).isNull() ? (parent) : (object))
static int markerSize(const QString &str) static int markerSize(const QString &str)
{ {
if (str == "small") if (str == "small")
@ -110,7 +113,7 @@ static bool isWS(char c)
return (c == 0x20 || c == 0x09 || c == 0x0A || c == 0x0D) ? true : false; return (c == 0x20 || c == 0x09 || c == 0x0A || c == 0x0D) ? true : false;
} }
static bool isJSONObject(QFile *file) static bool possiblyJSONObject(QFile *file)
{ {
char c; char c;
@ -126,12 +129,21 @@ static bool isJSONObject(QFile *file)
return false; return false;
} }
static Coordinates coordinates(const QJsonArray &data, const Projection &proj) bool GeoJSONParser::a2c(const QJsonArray &data, const Projection &proj,
Coordinates &c)
{ {
if (data.count() >= 2 && data.at(0).isDouble() && data.at(1).isDouble()) c = (data.count() >= 2 && data.at(0).isDouble() && data.at(1).isDouble())
return proj.xy2ll(PointD(data.at(0).toDouble(), data.at(1).toDouble())); ? proj.xy2ll(PointD(data.at(0).toDouble(), data.at(1).toDouble()))
else : Coordinates();
return Coordinates();
if (c.isValid())
return true;
else {
QJsonDocument doc(QJsonDocument::fromVariant(data.toVariantList()));
_errorString = QString("%1: invalid coordinates")
.arg(QString::fromUtf8(doc.toJson(QJsonDocument::Compact)));
return false;
}
} }
bool GeoJSONParser::crs(const QJsonObject &object, Projection &proj) bool GeoJSONParser::crs(const QJsonObject &object, Projection &proj)
@ -197,11 +209,9 @@ bool GeoJSONParser::point(const QJsonObject &object, const Projection &parent,
if (!crs(object, proj)) if (!crs(object, proj))
return false; return false;
Coordinates c(::coordinates(coordinates, proj.isNull() ? parent : proj)); Coordinates c;
if (!c.isValid()) { if (!a2c(coordinates, PROJ(proj, parent), c))
_errorString = "Invalid Point coordinates";
return false; return false;
}
Waypoint waypoint(c); Waypoint waypoint(c);
if (coordinates.count() == 3 && coordinates.at(2).isDouble()) if (coordinates.count() == 3 && coordinates.at(2).isDouble())
@ -226,6 +236,7 @@ bool GeoJSONParser::multiPoint(const QJsonObject &object,
Projection proj; Projection proj;
if (!crs(object, proj)) if (!crs(object, proj))
return false; return false;
Coordinates c;
for (int i = 0; i < coordinates.size(); i++) { for (int i = 0; i < coordinates.size(); i++) {
if (!coordinates.at(i).isArray()) { if (!coordinates.at(i).isArray()) {
@ -233,11 +244,8 @@ bool GeoJSONParser::multiPoint(const QJsonObject &object,
return false; return false;
} else { } else {
QJsonArray data(coordinates.at(i).toArray()); QJsonArray data(coordinates.at(i).toArray());
Coordinates c(::coordinates(data, proj.isNull() ? parent : proj)); if (!a2c(data, PROJ(proj, parent), c))
if (!c.isValid()) {
_errorString = "Invalid MultiPoint coordinates";
return false; return false;
}
Waypoint waypoint(c); Waypoint waypoint(c);
if (data.count() == 3 && data.at(2).isDouble()) if (data.count() == 3 && data.at(2).isDouble())
@ -266,7 +274,8 @@ bool GeoJSONParser::lineString(const QJsonObject &object,
Projection proj; Projection proj;
if (!crs(object, proj)) if (!crs(object, proj))
return false; return false;
SegmentData sd; SegmentData segment;
Coordinates c;
for (int i = 0; i < coordinates.size(); i++) { for (int i = 0; i < coordinates.size(); i++) {
if (!coordinates.at(i).isArray()) { if (!coordinates.at(i).isArray()) {
@ -275,19 +284,16 @@ bool GeoJSONParser::lineString(const QJsonObject &object,
} }
QJsonArray data(coordinates.at(i).toArray()); QJsonArray data(coordinates.at(i).toArray());
Coordinates c(::coordinates(data, proj.isNull() ? parent : proj)); if (!a2c(data, PROJ(proj, parent), c))
if (!c.isValid()) {
_errorString = "Invalid LineString coordinates";
return false; return false;
}
Trackpoint t(c); Trackpoint t(c);
if (data.count() == 3 && data.at(2).isDouble()) if (data.count() == 3 && data.at(2).isDouble())
t.setElevation(data.at(2).toDouble()); t.setElevation(data.at(2).toDouble());
sd.append(t); segment.append(t);
} }
TrackData track(sd); TrackData track(segment);
setTrackProperties(track, properties); setTrackProperties(track, properties);
tracks.append(track); tracks.append(track);
@ -311,6 +317,7 @@ bool GeoJSONParser::multiLineString(const QJsonObject &object,
if (!crs(object, proj)) if (!crs(object, proj))
return false; return false;
TrackData track; TrackData track;
Coordinates c;
for (int i = 0; i < coordinates.size(); i++) { for (int i = 0; i < coordinates.size(); i++) {
if (!coordinates.at(i).isArray()) { if (!coordinates.at(i).isArray()) {
@ -327,11 +334,8 @@ bool GeoJSONParser::multiLineString(const QJsonObject &object,
} }
QJsonArray data(ls.at(j).toArray()); QJsonArray data(ls.at(j).toArray());
Coordinates c(::coordinates(data, proj.isNull() ? parent : proj)); if (!a2c(data, PROJ(proj, parent), c))
if (!c.isValid()) {
_errorString = "Invalid MultiLineString coordinates";
return false; return false;
}
Trackpoint t(c); Trackpoint t(c);
if (data.count() == 3 && data.at(2).isDouble()) if (data.count() == 3 && data.at(2).isDouble())
@ -364,7 +368,8 @@ bool GeoJSONParser::polygon(const QJsonObject &object, const Projection &parent,
Projection proj; Projection proj;
if (!crs(object, proj)) if (!crs(object, proj))
return false; return false;
::Polygon pg; ::Polygon poly;
Coordinates c;
for (int i = 0; i < coordinates.size(); i++) { for (int i = 0; i < coordinates.size(); i++) {
if (!coordinates.at(i).isArray()) { if (!coordinates.at(i).isArray()) {
@ -382,18 +387,16 @@ bool GeoJSONParser::polygon(const QJsonObject &object, const Projection &parent,
} }
QJsonArray point(lr.at(j).toArray()); QJsonArray point(lr.at(j).toArray());
Coordinates c(::coordinates(point, proj.isNull() ? parent : proj)); if (!a2c(point, PROJ(proj, parent), c))
if (!c.isValid()) {
_errorString = "Invalid Polygon linear ring coordinates";
return false; return false;
}
data.append(c); data.append(c);
} }
pg.append(data); poly.append(data);
} }
Area area(pg); Area area(poly);
setAreaProperties(area, properties); setAreaProperties(area, properties);
areas.append(area); areas.append(area);
@ -416,14 +419,14 @@ bool GeoJSONParser::multiPolygon(const QJsonObject &object,
if (!crs(object, proj)) if (!crs(object, proj))
return false; return false;
Area area; Area area;
Coordinates c;
for (int i = 0; i < coordinates.size(); i++) { for (int i = 0; i < coordinates.size(); i++) {
if (!coordinates.at(i).isArray()) { if (!coordinates.at(i).isArray()) {
_errorString = "Invalid MultiPolygon data"; _errorString = "Invalid MultiPolygon data";
return false; return false;
} else { } else {
::Polygon pg; ::Polygon poly;
QJsonArray polygon(coordinates.at(i).toArray()); QJsonArray polygon(coordinates.at(i).toArray());
for (int j = 0; j < polygon.size(); j++) { for (int j = 0; j < polygon.size(); j++) {
@ -442,18 +445,16 @@ bool GeoJSONParser::multiPolygon(const QJsonObject &object,
} }
QJsonArray point(lr.at(k).toArray()); QJsonArray point(lr.at(k).toArray());
Coordinates c(::coordinates(point, proj.isNull() ? parent : proj)); if (!a2c(point, PROJ(proj, parent), c))
if (!c.isValid()) {
_errorString = "Invalid MultiPolygon linear ring coordinates";
return false; return false;
}
data.append(c); data.append(c);
} }
pg.append(data); poly.append(data);
} }
area.append(pg); area.append(poly);
} }
} }
@ -482,37 +483,36 @@ bool GeoJSONParser::geometryCollection(const QJsonObject &object,
switch (type(geometry)) { switch (type(geometry)) {
case Point: case Point:
if (!point(geometry, proj.isNull() ? parent : proj, properties, if (!point(geometry, PROJ(proj, parent), properties,
waypoints)) waypoints))
return false; return false;
break; break;
case MultiPoint: case MultiPoint:
if (!multiPoint(geometry, proj.isNull() ? parent : proj, if (!multiPoint(geometry, PROJ(proj, parent), properties,
properties, waypoints)) waypoints))
return false; return false;
break; break;
case LineString: case LineString:
if (!lineString(geometry, proj.isNull() ? parent : proj, if (!lineString(geometry, PROJ(proj, parent), properties,
properties, tracks)) tracks))
return false; return false;
break; break;
case MultiLineString: case MultiLineString:
if (!multiLineString(geometry, proj.isNull() ? parent : proj, if (!multiLineString(geometry, PROJ(proj, parent), properties,
properties, tracks)) tracks))
return false; return false;
break; break;
case Polygon: case Polygon:
if (!polygon(geometry, proj.isNull() ? parent : proj, properties, if (!polygon(geometry, PROJ(proj, parent), properties, areas))
areas))
return false; return false;
break; break;
case MultiPolygon: case MultiPolygon:
if (!multiPolygon(geometry, proj.isNull() ? parent : proj, if (!multiPolygon(geometry, PROJ(proj, parent), properties,
properties, areas)) areas))
return false; return false;
break; break;
case GeometryCollection: case GeometryCollection:
if (!geometryCollection(geometry, proj.isNull() ? parent : proj, if (!geometryCollection(geometry, PROJ(proj, parent),
properties, tracks, areas, waypoints)) properties, tracks, areas, waypoints))
return false; return false;
break; break;
@ -542,26 +542,22 @@ bool GeoJSONParser::feature(const QJsonObject &object, const Projection &parent,
switch (type(geometry)) { switch (type(geometry)) {
case Point: case Point:
return point(geometry, proj.isNull() ? parent : proj, properties, return point(geometry, PROJ(proj, parent), properties, waypoints);
waypoints);
case MultiPoint: case MultiPoint:
return multiPoint(geometry, proj.isNull() ? parent : proj, return multiPoint(geometry, PROJ(proj, parent), properties,
properties, waypoints); waypoints);
case LineString: case LineString:
return lineString(geometry, proj.isNull() ? parent : proj, return lineString(geometry, PROJ(proj, parent), properties, tracks);
properties, tracks);
case MultiLineString: case MultiLineString:
return multiLineString(geometry, proj.isNull() ? parent : proj, return multiLineString(geometry, PROJ(proj, parent), properties,
properties, tracks); tracks);
case GeometryCollection: case GeometryCollection:
return geometryCollection(geometry, proj.isNull() ? parent : proj, return geometryCollection(geometry, PROJ(proj, parent), properties,
properties, tracks, areas, waypoints); tracks, areas, waypoints);
case Polygon: case Polygon:
return polygon(geometry, proj.isNull() ? parent : proj, properties, return polygon(geometry, PROJ(proj, parent), properties, areas);
areas);
case MultiPolygon: case MultiPolygon:
return multiPolygon(geometry, proj.isNull() ? parent : proj, return multiPolygon(geometry, PROJ(proj, parent), properties, areas);
properties, areas);
default: default:
_errorString = geometry["type"].toString() _errorString = geometry["type"].toString()
+ ": invalid/missing Feature geometry"; + ": invalid/missing Feature geometry";
@ -584,8 +580,8 @@ bool GeoJSONParser::featureCollection(const QJsonObject &object,
return false; return false;
for (int i = 0; i < features.size(); i++) for (int i = 0; i < features.size(); i++)
if (!feature(features.at(i).toObject(), proj.isNull() ? parent : proj, if (!feature(features.at(i).toObject(), PROJ(proj, parent), tracks,
tracks, areas, waypoints)) areas, waypoints))
return false; return false;
return true; return true;
@ -597,8 +593,8 @@ bool GeoJSONParser::parse(QFile *file, QList<TrackData> &tracks,
{ {
Q_UNUSED(routes); Q_UNUSED(routes);
if (!isJSONObject(file)) { if (!possiblyJSONObject(file)) {
_errorString = "Not a JSON file"; _errorString = "Not a GeoJSON file";
return false; return false;
} else } else
file->reset(); file->reset();
@ -607,8 +603,8 @@ bool GeoJSONParser::parse(QFile *file, QList<TrackData> &tracks,
QJsonDocument doc(QJsonDocument::fromJson(file->readAll(), &error)); QJsonDocument doc(QJsonDocument::fromJson(file->readAll(), &error));
if (doc.isNull()) { if (doc.isNull()) {
_errorString = "JSON parse error: " + error.errorString() + " [" _errorString = QString("JSON parse error on offset %1: %2")
+ QString::number(error.offset) + "]"; .arg(QString::number(error.offset), error.errorString());
return false; return false;
} }

View File

@ -30,6 +30,7 @@ private:
FeatureCollection FeatureCollection
}; };
bool a2c(const QJsonArray &data, const Projection &proj, Coordinates &c);
Type type(const QJsonObject &json); Type type(const QJsonObject &json);
bool crs(const QJsonObject &object, Projection &proj); bool crs(const QJsonObject &object, Projection &proj);
bool point(const QJsonObject &object, const Projection &parent, bool point(const QJsonObject &object, const Projection &parent,

View File

@ -8,7 +8,6 @@
#include "proj/polarstereographic.h" #include "proj/polarstereographic.h"
#include "proj/obliquestereographic.h" #include "proj/obliquestereographic.h"
#include "proj/polyconic.h" #include "proj/polyconic.h"
#include "proj/latlon.h"
#include "datum.h" #include "datum.h"
#include "gcs.h" #include "gcs.h"
#include "pcs.h" #include "pcs.h"
@ -40,7 +39,7 @@ Projection::Method::Method(int id)
Projection::Projection(const PCS &pcs) Projection::Projection(const PCS &pcs)
: _gcs(pcs.gcs()), _ct(0), _units(pcs.conversion().units()), : _gcs(pcs.gcs()), _ct(0), _units(pcs.conversion().units()),
_cs(pcs.conversion().cs()), _geographic(false) _cs(pcs.conversion().cs())
{ {
const Ellipsoid &ellipsoid = _gcs.datum().ellipsoid(); const Ellipsoid &ellipsoid = _gcs.datum().ellipsoid();
const Projection::Setup &setup = pcs.conversion().setup(); const Projection::Setup &setup = pcs.conversion().setup();
@ -115,7 +114,7 @@ Projection::Projection(const PCS &pcs)
} }
Projection::Projection(const GCS &gcs, const CoordinateSystem &cs) Projection::Projection(const GCS &gcs, const CoordinateSystem &cs)
: _gcs(gcs), _units(LinearUnits(9001)), _cs(cs), _geographic(true) : _gcs(gcs), _units(LinearUnits(9001)), _cs(cs)
{ {
_ct = new LatLon(gcs.angularUnits()); _ct = new LatLon(gcs.angularUnits());
} }
@ -125,7 +124,6 @@ Projection::Projection(const Projection &p)
_gcs = p._gcs; _gcs = p._gcs;
_units = p._units; _units = p._units;
_ct = p._ct ? p._ct->clone() : 0; _ct = p._ct ? p._ct->clone() : 0;
_geographic = p._geographic;
_cs = p._cs; _cs = p._cs;
} }
@ -142,7 +140,6 @@ Projection &Projection::operator=(const Projection &p)
_gcs = p._gcs; _gcs = p._gcs;
_units = p._units; _units = p._units;
_ct = p._ct ? p._ct->clone() : 0; _ct = p._ct ? p._ct->clone() : 0;
_geographic = p._geographic;
_cs = p._cs; _cs = p._cs;
} }
@ -155,7 +152,7 @@ bool Projection::operator==(const Projection &p) const
return false; return false;
return (*_ct == *p._ct && _gcs == p._gcs && _units == p._units return (*_ct == *p._ct && _gcs == p._gcs && _units == p._units
&& _cs == p._cs && _geographic == p._geographic); && _cs == p._cs);
} }
PointD Projection::ll2xy(const Coordinates &c) const PointD Projection::ll2xy(const Coordinates &c) const

View File

@ -7,6 +7,7 @@
#include "linearunits.h" #include "linearunits.h"
#include "coordinatesystem.h" #include "coordinatesystem.h"
#include "gcs.h" #include "gcs.h"
#include "proj/latlon.h"
class PCS; class PCS;
class CT; class CT;
@ -70,7 +71,7 @@ public:
int _id; int _id;
}; };
Projection() : _ct(0), _geographic(false) {} Projection() : _ct(0) {}
Projection(const Projection &p); Projection(const Projection &p);
Projection(const PCS &pcs); Projection(const PCS &pcs);
Projection(const GCS &gcs, const CoordinateSystem &cs Projection(const GCS &gcs, const CoordinateSystem &cs
@ -90,7 +91,10 @@ public:
// and except of WMTS/WMS it is not needed. // and except of WMTS/WMS it is not needed.
return (_gcs.isValid() && _ct != 0 && _units.isValid()); return (_gcs.isValid() && _ct != 0 && _units.isValid());
} }
bool isGeographic() const {return _geographic;} bool isGeographic() const
{
return (dynamic_cast<const LatLon*>(_ct) != 0);
}
PointD ll2xy(const Coordinates &c) const; PointD ll2xy(const Coordinates &c) const;
Coordinates xy2ll(const PointD &p) const; Coordinates xy2ll(const PointD &p) const;
@ -103,7 +107,6 @@ private:
const CT *_ct; const CT *_ct;
LinearUnits _units; LinearUnits _units;
CoordinateSystem _cs; CoordinateSystem _cs;
bool _geographic;
}; };
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG