mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-24 11:45:53 +01:00
Added support for arbitrary CRSs in GeoJSON files
This commit is contained in:
parent
b7b03c1d5a
commit
8780a40b9f
@ -1,5 +1,6 @@
|
|||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
#include "map/crs.h"
|
||||||
#include "geojsonparser.h"
|
#include "geojsonparser.h"
|
||||||
|
|
||||||
#define MARKER_SIZE_MEDIUM 12
|
#define MARKER_SIZE_MEDIUM 12
|
||||||
@ -125,6 +126,35 @@ static bool isJSONObject(QFile *file)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Coordinates coordinates(const QJsonArray &data, const Projection &proj)
|
||||||
|
{
|
||||||
|
if (data.count() >= 2 && data.at(0).isDouble() && data.at(1).isDouble())
|
||||||
|
return proj.xy2ll(PointD(data.at(0).toDouble(), data.at(1).toDouble()));
|
||||||
|
else
|
||||||
|
return Coordinates();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GeoJSONParser::crs(const QJsonObject &object, Projection &proj)
|
||||||
|
{
|
||||||
|
if (!object.contains("crs"))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
QJsonObject crsObj(object["crs"].toObject());
|
||||||
|
if (crsObj["type"].toString() != "name" || !crsObj.contains("properties")) {
|
||||||
|
_errorString = "Invalid crs object";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QString str(crsObj["properties"].toObject()["name"].toString());
|
||||||
|
proj = CRS::projection(str);
|
||||||
|
|
||||||
|
if (proj.isValid())
|
||||||
|
return true;
|
||||||
|
else {
|
||||||
|
_errorString = QString("%1: unknown CRS").arg(str);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GeoJSONParser::Type GeoJSONParser::type(const QJsonObject &json)
|
GeoJSONParser::Type GeoJSONParser::type(const QJsonObject &json)
|
||||||
{
|
{
|
||||||
QString str(json["type"].toString());
|
QString str(json["type"].toString());
|
||||||
@ -151,206 +181,337 @@ GeoJSONParser::Type GeoJSONParser::type(const QJsonObject &json)
|
|||||||
return Unknown;
|
return Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeoJSONParser::point(const QJsonArray &coordinates, Waypoint &waypoint,
|
bool GeoJSONParser::point(const QJsonObject &object, const Projection &parent,
|
||||||
const QJsonValue &properties)
|
const QJsonValue &properties, Waypoint &waypoint)
|
||||||
{
|
{
|
||||||
if (coordinates.count() < 2 || !coordinates.at(0).isDouble()
|
if (!object.contains("coordinates")) {
|
||||||
|| !coordinates.at(1).isDouble()) {
|
_errorString = "Missing Point coordinates array";
|
||||||
_errorString = "Invalid Point Coordinates";
|
return false;
|
||||||
|
}
|
||||||
|
if (object["coordinates"].isNull())
|
||||||
|
return true;
|
||||||
|
QJsonArray coordinates(object["coordinates"].toArray());
|
||||||
|
if (coordinates.isEmpty())
|
||||||
|
return true;
|
||||||
|
Projection proj;
|
||||||
|
if (!crs(object, proj))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Coordinates c(::coordinates(coordinates, proj.isNull() ? parent : proj));
|
||||||
|
if (!c.isValid()) {
|
||||||
|
_errorString = "Invalid Point coordinates";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setWaypointProperties(waypoint, properties);
|
waypoint.setCoordinates(c);
|
||||||
|
|
||||||
waypoint.setCoordinates(Coordinates(coordinates.at(0).toDouble(),
|
|
||||||
coordinates.at(1).toDouble()));
|
|
||||||
if (coordinates.count() == 3 && coordinates.at(2).isDouble())
|
if (coordinates.count() == 3 && coordinates.at(2).isDouble())
|
||||||
waypoint.setElevation(coordinates.at(2).toDouble());
|
waypoint.setElevation(coordinates.at(2).toDouble());
|
||||||
|
|
||||||
|
setWaypointProperties(waypoint, properties);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeoJSONParser::multiPoint(const QJsonArray &coordinates,
|
bool GeoJSONParser::multiPoint(const QJsonObject &object,
|
||||||
QVector<Waypoint> &waypoints, const QJsonValue &properties)
|
const Projection &parent, const QJsonValue &properties,
|
||||||
|
QVector<Waypoint> &waypoints)
|
||||||
{
|
{
|
||||||
|
if (!object.contains("coordinates")) {
|
||||||
|
_errorString = "Missing MultiPoint coordinates array";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (object["coordinates"].isNull())
|
||||||
|
return true;
|
||||||
|
QJsonArray coordinates(object["coordinates"].toArray());
|
||||||
|
if (coordinates.isEmpty())
|
||||||
|
return true;
|
||||||
|
Projection proj;
|
||||||
|
if (!crs(object, proj))
|
||||||
|
return false;
|
||||||
|
|
||||||
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 MultiPoint coordinates";
|
_errorString = "Invalid MultiPoint data";
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
waypoints.resize(waypoints.size() + 1);
|
waypoints.resize(waypoints.size() + 1);
|
||||||
if (!point(coordinates.at(i).toArray(), waypoints.last(), properties))
|
|
||||||
|
QJsonArray data(coordinates.at(i).toArray());
|
||||||
|
Coordinates c(::coordinates(data, proj.isNull() ? parent : proj));
|
||||||
|
if (!c.isValid()) {
|
||||||
|
_errorString = "Invalid MultiPoint coordinates";
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
waypoints.last().setCoordinates(c);
|
||||||
|
if (data.count() == 3 && data.at(2).isDouble())
|
||||||
|
waypoints.last().setElevation(data.at(2).toDouble());
|
||||||
|
|
||||||
|
setWaypointProperties(waypoints.last(), properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeoJSONParser::lineString(const QJsonArray &coordinates,
|
bool GeoJSONParser::lineString(const QJsonObject &object,
|
||||||
SegmentData &segment)
|
const Projection &parent, const QJsonValue &properties, TrackData &track)
|
||||||
{
|
{
|
||||||
|
if (!object.contains("coordinates")) {
|
||||||
|
_errorString = "Missing LineString coordinates array";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (object["coordinates"].isNull())
|
||||||
|
return true;
|
||||||
|
QJsonArray coordinates(object["coordinates"].toArray());
|
||||||
|
if (coordinates.isEmpty())
|
||||||
|
return true;
|
||||||
|
Projection proj;
|
||||||
|
if (!crs(object, proj))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
track.append(SegmentData());
|
||||||
|
|
||||||
for (int i = 0; i < coordinates.size(); i++) {
|
for (int i = 0; i < coordinates.size(); i++) {
|
||||||
QJsonArray point(coordinates.at(i).toArray());
|
if (!coordinates.at(i).isArray()) {
|
||||||
if (point.count() < 2 || !point.at(0).isDouble()
|
_errorString = "Invalid LineString data";
|
||||||
|| !point.at(1).isDouble()) {
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray data(coordinates.at(i).toArray());
|
||||||
|
Coordinates c(::coordinates(data, proj.isNull() ? parent : proj));
|
||||||
|
if (!c.isValid()) {
|
||||||
_errorString = "Invalid LineString coordinates";
|
_errorString = "Invalid LineString coordinates";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Trackpoint t(Coordinates(point.at(0).toDouble(),
|
Trackpoint t(c);
|
||||||
point.at(1).toDouble()));
|
if (data.count() == 3 && data.at(2).isDouble())
|
||||||
if (point.count() == 3 && point.at(2).isDouble())
|
t.setElevation(data.at(2).toDouble());
|
||||||
t.setElevation(point.at(2).toDouble());
|
track.last().append(t);
|
||||||
segment.append(t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GeoJSONParser::lineString(const QJsonArray &coordinates, TrackData &track,
|
|
||||||
const QJsonValue &properties)
|
|
||||||
{
|
|
||||||
setTrackProperties(track, properties);
|
setTrackProperties(track, properties);
|
||||||
|
|
||||||
track.append(SegmentData());
|
|
||||||
|
|
||||||
lineString(coordinates, track.last());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeoJSONParser::multiLineString(const QJsonArray &coordinates,
|
bool GeoJSONParser::multiLineString(const QJsonObject &object,
|
||||||
TrackData &track, const QJsonValue &properties)
|
const Projection &parent, const QJsonValue &properties, TrackData &track)
|
||||||
{
|
{
|
||||||
setTrackProperties(track, properties);
|
if (!object.contains("coordinates")) {
|
||||||
|
_errorString = "Missing MultiLineString coordinates array";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (object["coordinates"].isNull())
|
||||||
|
return true;
|
||||||
|
QJsonArray coordinates(object["coordinates"].toArray());
|
||||||
|
if (coordinates.isEmpty())
|
||||||
|
return true;
|
||||||
|
Projection proj;
|
||||||
|
if (!crs(object, proj))
|
||||||
|
return false;
|
||||||
|
|
||||||
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 MultiLineString coordinates";
|
_errorString = "Invalid MultiLineString data";
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
track.append(SegmentData());
|
track.append(SegmentData());
|
||||||
if (!lineString(coordinates.at(i).toArray(), track.last()))
|
|
||||||
return false;
|
QJsonArray ls(coordinates.at(i).toArray());
|
||||||
|
for (int j = 0; j < ls.size(); j++) {
|
||||||
|
if (!ls.at(j).isArray()) {
|
||||||
|
_errorString = "Invalid MultiLineString LineString data";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray data(ls.at(j).toArray());
|
||||||
|
Coordinates c(::coordinates(data, proj.isNull() ? parent : proj));
|
||||||
|
if (!c.isValid()) {
|
||||||
|
_errorString = "Invalid MultiLineString coordinates";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Trackpoint t(c);
|
||||||
|
if (data.count() == 3 && data.at(2).isDouble())
|
||||||
|
t.setElevation(data.at(2).toDouble());
|
||||||
|
track.last().append(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTrackProperties(track, properties);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeoJSONParser::polygon(const QJsonArray &coordinates, ::Polygon &pg)
|
bool GeoJSONParser::polygon(const QJsonObject &object, const Projection &parent,
|
||||||
|
const QJsonValue &properties, Area &area)
|
||||||
{
|
{
|
||||||
|
if (!object.contains("coordinates")) {
|
||||||
|
_errorString = "Missing Polygon coordinates array";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (object["coordinates"].isNull())
|
||||||
|
return true;
|
||||||
|
QJsonArray coordinates(object["coordinates"].toArray());
|
||||||
|
if (coordinates.isEmpty())
|
||||||
|
return true;
|
||||||
|
Projection proj;
|
||||||
|
if (!crs(object, proj))
|
||||||
|
return false;
|
||||||
|
::Polygon pg;
|
||||||
|
|
||||||
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 Polygon linear ring";
|
_errorString = "Invalid Polygon linear ring";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QJsonArray lr(coordinates.at(i).toArray());
|
QJsonArray lr(coordinates.at(i).toArray());
|
||||||
QVector<Coordinates> data;
|
QVector<Coordinates> data;
|
||||||
|
|
||||||
for (int j = 0; j < lr.size(); j++) {
|
for (int j = 0; j < lr.size(); j++) {
|
||||||
|
if (!lr.at(j).isArray()) {
|
||||||
|
_errorString = "Invalid Polygon linear ring data";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QJsonArray point(lr.at(j).toArray());
|
QJsonArray point(lr.at(j).toArray());
|
||||||
if (point.count() < 2 || !point.at(0).isDouble()
|
Coordinates c(::coordinates(point, proj.isNull() ? parent : proj));
|
||||||
|| !point.at(1).isDouble()) {
|
if (!c.isValid()) {
|
||||||
_errorString = "Invalid Polygon linear ring coordinates";
|
_errorString = "Invalid Polygon linear ring coordinates";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
data.append(Coordinates(point.at(0).toDouble(),
|
data.append(c);
|
||||||
point.at(1).toDouble()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pg.append(data);
|
pg.append(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
area.append(pg);
|
||||||
|
setAreaProperties(area, properties);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeoJSONParser::polygon(const QJsonArray &coordinates, Area &area,
|
bool GeoJSONParser::multiPolygon(const QJsonObject &object,
|
||||||
const QJsonValue &properties)
|
const Projection &parent, const QJsonValue &properties, Area &area)
|
||||||
{
|
{
|
||||||
setAreaProperties(area, properties);
|
if (!object.contains("coordinates")) {
|
||||||
|
_errorString = "Missing MultiPolygon coordinates array";
|
||||||
::Polygon p;
|
return false;
|
||||||
if (!polygon(coordinates, p))
|
}
|
||||||
|
if (object["coordinates"].isNull())
|
||||||
|
return true;
|
||||||
|
QJsonArray coordinates(object["coordinates"].toArray());
|
||||||
|
if (coordinates.isEmpty())
|
||||||
|
return true;
|
||||||
|
Projection proj;
|
||||||
|
if (!crs(object, proj))
|
||||||
return false;
|
return false;
|
||||||
area.append(p);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GeoJSONParser::multiPolygon(const QJsonArray &coordinates,
|
|
||||||
Area &area, const QJsonValue &properties)
|
|
||||||
{
|
|
||||||
setAreaProperties(area, properties);
|
|
||||||
|
|
||||||
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 coordinates";
|
_errorString = "Invalid MultiPolygon data";
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
::Polygon p;
|
::Polygon pg;
|
||||||
if (!polygon(coordinates.at(i).toArray(), p))
|
|
||||||
return false;
|
QJsonArray polygon(coordinates.at(i).toArray());
|
||||||
area.append(p);
|
for (int j = 0; j < polygon.size(); j++) {
|
||||||
|
if (!polygon.at(j).isArray()) {
|
||||||
|
_errorString = "Invalid MultiPolygon linear ring";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray lr(polygon.at(j).toArray());
|
||||||
|
QVector<Coordinates> data;
|
||||||
|
|
||||||
|
for (int k = 0; k < lr.size(); k++) {
|
||||||
|
if (!lr.at(k).isArray()) {
|
||||||
|
_errorString = "Invalid MultiPolygon linear ring data";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray point(lr.at(k).toArray());
|
||||||
|
Coordinates c(::coordinates(point, proj.isNull() ? parent : proj));
|
||||||
|
if (!c.isValid()) {
|
||||||
|
_errorString = "Invalid MultiPolygon linear ring coordinates";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data.append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
pg.append(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
area.append(pg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setAreaProperties(area, properties);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeoJSONParser::geometryCollection(const QJsonObject &json,
|
bool GeoJSONParser::geometryCollection(const QJsonObject &object,
|
||||||
QList<TrackData> &tracks, QList<Area> &areas,
|
const Projection &parent, const QJsonValue &properties,
|
||||||
QVector<Waypoint> &waypoints, const QJsonValue &properties)
|
QList<TrackData> &tracks, QList<Area> &areas, QVector<Waypoint> &waypoints)
|
||||||
{
|
{
|
||||||
if (!json.contains("geometries") || !json["geometries"].isArray()) {
|
if (!object.contains("geometries") || !object["geometries"].isArray()) {
|
||||||
_errorString = "Invalid/missing GeometryCollection geometries array";
|
_errorString = "Invalid/missing GeometryCollection geometries array";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonArray geometries(json["geometries"].toArray());
|
QJsonArray geometries(object["geometries"].toArray());
|
||||||
|
Projection proj;
|
||||||
|
if (!crs(object, proj))
|
||||||
|
return false;
|
||||||
|
|
||||||
for (int i = 0; i < geometries.size(); i++) {
|
for (int i = 0; i < geometries.size(); i++) {
|
||||||
QJsonObject geometry(geometries.at(i).toObject());
|
QJsonObject geometry(geometries.at(i).toObject());
|
||||||
|
|
||||||
switch (type(geometry)) {
|
switch (type(geometry)) {
|
||||||
case Point:
|
case Point:
|
||||||
waypoints.resize(waypoints.size() + 1);
|
waypoints.resize(waypoints.size() + 1);
|
||||||
if (!point(geometry["coordinates"].toArray(), waypoints.last(),
|
if (!point(geometry, proj.isNull() ? parent : proj, properties,
|
||||||
properties))
|
waypoints.last()))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case MultiPoint:
|
case MultiPoint:
|
||||||
if (!multiPoint(geometry["coordinates"].toArray(), waypoints,
|
if (!multiPoint(geometry, proj.isNull() ? parent : proj,
|
||||||
properties))
|
properties, waypoints))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case LineString:
|
case LineString:
|
||||||
tracks.append(TrackData());
|
tracks.append(TrackData());
|
||||||
if (!lineString(geometry["coordinates"].toArray(),
|
if (!lineString(geometry, proj.isNull() ? parent : proj,
|
||||||
tracks.last(), properties))
|
properties, tracks.last()))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case MultiLineString:
|
case MultiLineString:
|
||||||
tracks.append(TrackData());
|
tracks.append(TrackData());
|
||||||
if (!multiLineString(geometry["coordinates"].toArray(),
|
if (!multiLineString(geometry, proj.isNull() ? parent : proj,
|
||||||
tracks.last(), properties))
|
properties, tracks.last()))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case Polygon:
|
case Polygon:
|
||||||
areas.append(Area());
|
areas.append(Area());
|
||||||
if (!polygon(geometry["coordinates"].toArray(), areas.last(),
|
if (!polygon(geometry, proj.isNull() ? parent : proj, properties,
|
||||||
properties))
|
areas.last()))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case MultiPolygon:
|
case MultiPolygon:
|
||||||
areas.append(Area());
|
areas.append(Area());
|
||||||
if (!multiPolygon(geometry["coordinates"].toArray(),
|
if (!multiPolygon(geometry, proj.isNull() ? parent : proj,
|
||||||
areas.last(), properties))
|
properties, areas.last()))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case GeometryCollection:
|
case GeometryCollection:
|
||||||
if (!geometryCollection(geometry, tracks, areas, waypoints,
|
if (!geometryCollection(geometry, proj.isNull() ? parent : proj,
|
||||||
properties))
|
properties, tracks, areas, waypoints))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -363,38 +524,47 @@ bool GeoJSONParser::geometryCollection(const QJsonObject &json,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeoJSONParser::feature(const QJsonObject &json, QList<TrackData> &tracks,
|
bool GeoJSONParser::feature(const QJsonObject &object, const Projection &parent,
|
||||||
QList<Area> &areas, QVector<Waypoint> &waypoints)
|
QList<TrackData> &tracks, QList<Area> &areas, QVector<Waypoint> &waypoints)
|
||||||
{
|
{
|
||||||
QJsonValue properties(json["properties"]);
|
if (!object.contains("geometry") || !object["geometry"].isObject()) {
|
||||||
QJsonObject geometry(json["geometry"].toObject());
|
_errorString = "Invalid/missing Feature geometry object";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonValue properties(object["properties"]);
|
||||||
|
QJsonObject geometry(object["geometry"].toObject());
|
||||||
|
Projection proj;
|
||||||
|
if (!crs(object, proj))
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (type(geometry)) {
|
switch (type(geometry)) {
|
||||||
case Point:
|
case Point:
|
||||||
waypoints.resize(waypoints.size() + 1);
|
waypoints.resize(waypoints.size() + 1);
|
||||||
return point(geometry["coordinates"].toArray(), waypoints.last(),
|
return point(geometry, proj.isNull() ? parent : proj, properties,
|
||||||
properties);
|
waypoints.last());
|
||||||
case MultiPoint:
|
case MultiPoint:
|
||||||
return multiPoint(geometry["coordinates"].toArray(), waypoints,
|
return multiPoint(geometry, proj.isNull() ? parent : proj,
|
||||||
properties);
|
properties, waypoints);
|
||||||
case LineString:
|
case LineString:
|
||||||
tracks.append(TrackData());
|
tracks.append(TrackData());
|
||||||
return lineString(geometry["coordinates"].toArray(), tracks.last(),
|
return lineString(geometry, proj.isNull() ? parent : proj,
|
||||||
properties);
|
properties, tracks.last());
|
||||||
case MultiLineString:
|
case MultiLineString:
|
||||||
tracks.append(TrackData());
|
tracks.append(TrackData());
|
||||||
return multiLineString(geometry["coordinates"].toArray(),
|
return multiLineString(geometry, proj.isNull() ? parent : proj,
|
||||||
tracks.last(), properties);
|
properties, tracks.last());
|
||||||
case GeometryCollection:
|
case GeometryCollection:
|
||||||
return geometryCollection(geometry, tracks, areas, waypoints);
|
return geometryCollection(geometry, proj.isNull() ? parent : proj,
|
||||||
|
properties, tracks, areas, waypoints);
|
||||||
case Polygon:
|
case Polygon:
|
||||||
areas.append(Area());
|
areas.append(Area());
|
||||||
return polygon(geometry["coordinates"].toArray(), areas.last(),
|
return polygon(geometry, proj.isNull() ? parent : proj, properties,
|
||||||
properties);
|
areas.last());
|
||||||
case MultiPolygon:
|
case MultiPolygon:
|
||||||
areas.append(Area());
|
areas.append(Area());
|
||||||
return multiPolygon(geometry["coordinates"].toArray(), areas.last(),
|
return multiPolygon(geometry, proj.isNull() ? parent : proj,
|
||||||
properties);
|
properties, areas.last());
|
||||||
default:
|
default:
|
||||||
_errorString = geometry["type"].toString()
|
_errorString = geometry["type"].toString()
|
||||||
+ ": invalid/missing Feature geometry";
|
+ ": invalid/missing Feature geometry";
|
||||||
@ -402,18 +572,23 @@ bool GeoJSONParser::feature(const QJsonObject &json, QList<TrackData> &tracks,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeoJSONParser::featureCollection(const QJsonObject &json,
|
bool GeoJSONParser::featureCollection(const QJsonObject &object,
|
||||||
QList<TrackData> &tracks, QList<Area> &areas,
|
const Projection &parent, QList<TrackData> &tracks, QList<Area> &areas,
|
||||||
QVector<Waypoint> &waypoints)
|
QVector<Waypoint> &waypoints)
|
||||||
{
|
{
|
||||||
if (!json.contains("features") || !json["features"].isArray()) {
|
if (!object.contains("features") || !object["features"].isArray()) {
|
||||||
_errorString = "Invalid/missing FeatureCollection features array";
|
_errorString = "Invalid/missing FeatureCollection features array";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonArray features(json["features"].toArray());
|
QJsonArray features(object["features"].toArray());
|
||||||
|
Projection proj;
|
||||||
|
if (!crs(object, proj))
|
||||||
|
return false;
|
||||||
|
|
||||||
for (int i = 0; i < features.size(); i++)
|
for (int i = 0; i < features.size(); i++)
|
||||||
if (!feature(features.at(i).toObject(), tracks, areas, waypoints))
|
if (!feature(features.at(i).toObject(), proj.isNull() ? parent : proj,
|
||||||
|
tracks, areas, waypoints))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -426,7 +601,7 @@ bool GeoJSONParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
Q_UNUSED(routes);
|
Q_UNUSED(routes);
|
||||||
|
|
||||||
if (!isJSONObject(file)) {
|
if (!isJSONObject(file)) {
|
||||||
_errorString = "Not a GeoJSON file";
|
_errorString = "Not a JSON file";
|
||||||
return false;
|
return false;
|
||||||
} else
|
} else
|
||||||
file->reset();
|
file->reset();
|
||||||
@ -440,37 +615,39 @@ bool GeoJSONParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject json(doc.object());
|
QJsonObject object(doc.object());
|
||||||
|
Projection proj(GCS::WGS84());
|
||||||
|
|
||||||
switch (type(json)) {
|
switch (type(object)) {
|
||||||
case Point:
|
case Point:
|
||||||
waypoints.resize(waypoints.size() + 1);
|
waypoints.resize(waypoints.size() + 1);
|
||||||
return point(json["coordinates"].toArray(), waypoints.last());
|
return point(object, proj, QJsonValue(), waypoints.last());
|
||||||
case MultiPoint:
|
case MultiPoint:
|
||||||
return multiPoint(json["coordinates"].toArray(), waypoints);
|
return multiPoint(object, proj, QJsonValue(), waypoints);
|
||||||
case LineString:
|
case LineString:
|
||||||
tracks.append(TrackData());
|
tracks.append(TrackData());
|
||||||
return lineString(json["coordinates"].toArray(), tracks.last());
|
return lineString(object, proj, QJsonValue(), tracks.last());
|
||||||
case MultiLineString:
|
case MultiLineString:
|
||||||
tracks.append(TrackData());
|
tracks.append(TrackData());
|
||||||
return multiLineString(json["coordinates"].toArray(), tracks.last());
|
return multiLineString(object, proj, QJsonValue(), tracks.last());
|
||||||
case GeometryCollection:
|
case GeometryCollection:
|
||||||
return geometryCollection(json, tracks, areas, waypoints);
|
return geometryCollection(object, proj, QJsonValue(), tracks, areas,
|
||||||
|
waypoints);
|
||||||
case Feature:
|
case Feature:
|
||||||
return feature(json, tracks, areas, waypoints);
|
return feature(object, proj, tracks, areas, waypoints);
|
||||||
case FeatureCollection:
|
case FeatureCollection:
|
||||||
return featureCollection(json, tracks, areas, waypoints);
|
return featureCollection(object, proj, tracks, areas, waypoints);
|
||||||
case Polygon:
|
case Polygon:
|
||||||
areas.append(Area());
|
areas.append(Area());
|
||||||
return polygon(json["coordinates"].toArray(), areas.last());
|
return polygon(object, proj, QJsonValue(), areas.last());
|
||||||
case MultiPolygon:
|
case MultiPolygon:
|
||||||
areas.append(Area());
|
areas.append(Area());
|
||||||
return multiPolygon(json["coordinates"].toArray(), areas.last());
|
return multiPolygon(object, proj, QJsonValue(), areas.last());
|
||||||
case Unknown:
|
case Unknown:
|
||||||
if (json["type"].toString().isNull())
|
if (object["type"].toString().isNull())
|
||||||
_errorString = "Not a GeoJSON file";
|
_errorString = "Not a GeoJSON file";
|
||||||
else
|
else
|
||||||
_errorString = json["type"].toString()
|
_errorString = object["type"].toString()
|
||||||
+ ": unknown GeoJSON object";
|
+ ": unknown GeoJSON object";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
class QJsonObject;
|
class QJsonObject;
|
||||||
class QJsonArray;
|
class QJsonArray;
|
||||||
|
class Projection;
|
||||||
|
|
||||||
class GeoJSONParser : public Parser
|
class GeoJSONParser : public Parser
|
||||||
{
|
{
|
||||||
@ -30,27 +31,27 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Type type(const QJsonObject &json);
|
Type type(const QJsonObject &json);
|
||||||
bool point(const QJsonArray &coordinates, Waypoint &waypoint,
|
bool crs(const QJsonObject &object, Projection &proj);
|
||||||
const QJsonValue &properties = QJsonValue());
|
bool point(const QJsonObject &object, const Projection &parent,
|
||||||
bool multiPoint(const QJsonArray &coordinates,
|
const QJsonValue &properties, Waypoint &waypoint);
|
||||||
QVector<Waypoint> &waypoints, const QJsonValue &properties = QJsonValue());
|
bool multiPoint(const QJsonObject &object, const Projection &parent,
|
||||||
bool lineString(const QJsonArray &coordinates, SegmentData &segment);
|
const QJsonValue &properties, QVector<Waypoint> &waypoints);
|
||||||
bool lineString(const QJsonArray &coordinates, TrackData &track,
|
bool lineString(const QJsonObject &coordinates, const Projection &parent,
|
||||||
const QJsonValue &properties = QJsonValue());
|
const QJsonValue &properties, TrackData &track);
|
||||||
bool multiLineString(const QJsonArray &coordinates,
|
bool multiLineString(const QJsonObject &object, const Projection &proj,
|
||||||
TrackData &track, const QJsonValue &properties = QJsonValue());
|
const QJsonValue &properties, TrackData &track);
|
||||||
bool polygon(const QJsonArray &coordinates, ::Polygon &pg);
|
bool polygon(const QJsonObject &object, const Projection &parent,
|
||||||
bool polygon(const QJsonArray &coordinates, Area &area,
|
const QJsonValue &properties, Area &area);
|
||||||
const QJsonValue &properties = QJsonValue());
|
bool multiPolygon(const QJsonObject &object, const Projection &proj,
|
||||||
bool multiPolygon(const QJsonArray &coordinates, Area &area,
|
const QJsonValue &properties, Area &area);
|
||||||
const QJsonValue &properties = QJsonValue());
|
bool geometryCollection(const QJsonObject &json, const Projection &parent,
|
||||||
bool geometryCollection(const QJsonObject &json, QList<TrackData> &tracks,
|
const QJsonValue &properties, QList<TrackData> &tracks,
|
||||||
QList<Area> &areas, QVector<Waypoint> &waypoints,
|
|
||||||
const QJsonValue &properties = QJsonValue());
|
|
||||||
bool feature(const QJsonObject &json, QList<TrackData> &tracks,
|
|
||||||
QList<Area> &areas, QVector<Waypoint> &waypoints);
|
|
||||||
bool featureCollection(const QJsonObject &json, QList<TrackData> &tracks,
|
|
||||||
QList<Area> &areas, QVector<Waypoint> &waypoints);
|
QList<Area> &areas, QVector<Waypoint> &waypoints);
|
||||||
|
bool feature(const QJsonObject &json, const Projection &parent,
|
||||||
|
QList<TrackData> &tracks, QList<Area> &areas,
|
||||||
|
QVector<Waypoint> &waypoints);
|
||||||
|
bool featureCollection(const QJsonObject &object, const Projection &parent,
|
||||||
|
QList<TrackData> &tracks, QList<Area> &areas, QVector<Waypoint> &waypoints);
|
||||||
|
|
||||||
QString _errorString;
|
QString _errorString;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user