From 1ec78dca0bceac99d7a27a981b2fedfea0383b51 Mon Sep 17 00:00:00 2001 From: Patrick Brosi Date: Tue, 24 Sep 2024 16:28:01 +0200 Subject: [PATCH] also handle geojson output for collections correctly --- CMakeLists.txt | 2 +- src/qlever-petrimaps/server/Requestor.cpp | 51 ++++++++++++----------- src/qlever-petrimaps/server/Requestor.h | 14 +++---- src/qlever-petrimaps/server/Server.cpp | 36 +++++++++++----- src/util | 2 +- web/script.js | 2 +- 6 files changed, 63 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf17cbe..1066610 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required (VERSION 3.5) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) project (qlever-petrimaps) diff --git a/src/qlever-petrimaps/server/Requestor.cpp b/src/qlever-petrimaps/server/Requestor.cpp index bde1654..5cb0e38 100644 --- a/src/qlever-petrimaps/server/Requestor.cpp +++ b/src/qlever-petrimaps/server/Requestor.cpp @@ -449,7 +449,8 @@ const ResObj Requestor::getNearest(util::geo::DPoint rp, double rad, double res, util::geo::FPoint p; if (i >= _objects.size()) { size_t cid = i - _objects.size(); - p = clusterGeom(cid, res); + auto dp = clusterGeom(cid, res); + p = {dp.getX(), dp.getY()}; } else { p = _cache->getPoints()[_objects[i].first]; } @@ -580,7 +581,7 @@ const ResObj Requestor::getNearest(util::geo::DPoint rp, double rad, double res, points.size() == 1 ? points[0] : util::geo::centroid(points), requestRow(row), points, - geomLineGeoms(nearestL, rad / 10), geomPolyGeoms(nearestL, rad / 10)}; + geomLineGeoms(nearest, rad / 10), geomPolyGeoms(nearest, rad / 10)}; } if (dBestL < rad && dBestL <= dBest) { @@ -592,26 +593,26 @@ const ResObj Requestor::getNearest(util::geo::DPoint rp, double rad, double res, if (isArea && util::geo::contains(rp, util::geo::DPolygon(dline))) { return {true, nearestL, - {frp}, requestRow(_objects[nearestL].second), - geomPointGeoms(nearest, res), - geomLineGeoms(nearestL, rad / 10), geomPolyGeoms(nearestL, rad / 10)}; + {frp.getX(), frp.getY()}, requestRow(_objects[nearestL].second), + geomPointGeoms(nearestL, res), + geomLineGeoms(nearestL, rad / 10), geomPolyGeoms(nearestL, rad / 10)}; } else { if (isArea) { auto p = util::geo::PolyLine(dline).projectOn(rp).p; - auto fp = util::geo::FPoint(p.getX(), p.getY()); + auto fp = util::geo::DPoint(p.getX(), p.getY()); return {true, nearestL, - {fp}, requestRow(_objects[nearestL].second), - geomPointGeoms(nearest, res), - geomLineGeoms(nearestL, rad / 10), geomPolyGeoms(nearestL, rad / 10)}; + fp, requestRow(_objects[nearestL].second), + geomPointGeoms(nearestL, res), + geomLineGeoms(nearestL, rad / 10), geomPolyGeoms(nearestL, rad / 10)}; } else { auto p = util::geo::PolyLine(dline).projectOn(rp).p; - auto fp = util::geo::FPoint(p.getX(), p.getY()); + auto fp = util::geo::DPoint(p.getX(), p.getY()); return {true, nearestL, - {fp}, + fp, requestRow(_objects[nearestL].second), - geomPointGeoms(nearest, res), + geomPointGeoms(nearestL, res), geomLineGeoms(nearestL, rad / 10), geomPolyGeoms(nearestL, rad / 10)}; } @@ -634,12 +635,12 @@ const ResObj Requestor::getGeom(size_t id, double rad) const { bool isArea = Requestor::isArea(lineId); if (isArea) { - return {true, id, {0, 0}, {}, {}, {}, geomPolyGeoms(id, rad / 10)}; + return {true, id, {0, 0}, {}, geomPointGeoms(id, rad / 10), geomLineGeoms(id, rad / 10), geomPolyGeoms(id, rad / 10)}; } else { - return {true, id, {0, 0}, {}, {}, geomLineGeoms(id, rad / 10), {}}; + return {true, id, {0, 0}, {}, geomPointGeoms(id, rad / 10), geomLineGeoms(id, rad / 10), geomPolyGeoms(id, rad / 10)}; } } else { - return {true, id, geomPointGeoms(id).front(), {}, {}, {}, {}}; + return {true, id, {0, 0}, {}, geomPointGeoms(id, rad / 10), geomLineGeoms(id, rad / 10), geomPolyGeoms(id, rad / 10)}; } } @@ -710,14 +711,14 @@ if (oid > 0) { } // _____________________________________________________________________________ -util::geo::MultiPoint Requestor::geomPointGeoms(size_t oid) const { +util::geo::MultiPoint Requestor::geomPointGeoms(size_t oid) const { return geomPointGeoms(oid, -1); } // _____________________________________________________________________________ -util::geo::MultiPoint Requestor::geomPointGeoms(size_t oid, +util::geo::MultiPoint Requestor::geomPointGeoms(size_t oid, double res) const { - std::vector points; + std::vector points; if (!(res < 0) && oid >= _objects.size()) { return {clusterGeom(oid - _objects.size(), res)}; @@ -731,14 +732,16 @@ util::geo::MultiPoint Requestor::geomPointGeoms(size_t oid, for (size_t i = oid; i < _objects.size() && _objects[i].second == _objects[oid].second; i++) { if (_objects[i].first >= I_OFFSET) continue; - points.push_back(_cache->getPoints()[_objects[i].first]); + auto p = _cache->getPoints()[_objects[i].first]; + points.push_back({p.getX(), p.getY()}); } if (oid > 0) { for (size_t i = oid - 1; i < _objects.size() && _objects[i].second == _objects[oid].second; i--) { if (_objects[i].first >= I_OFFSET) continue; - points.push_back(_cache->getPoints()[_objects[i].first]); + auto p = _cache->getPoints()[_objects[i].first]; + points.push_back({p.getX(), p.getY()}); } } @@ -771,11 +774,11 @@ util::geo::MultiPolygon Requestor::geomPolyGeoms(size_t oid, } // _____________________________________________________________________________ -util::geo::FPoint Requestor::clusterGeom(size_t cid, double res) const { +util::geo::DPoint Requestor::clusterGeom(size_t cid, double res) const { size_t oid = _clusterObjects[cid].first; const auto& pp = _cache->getPoints()[_objects[oid].first]; - if (res < 0) return {pp}; + if (res < 0) return {pp.getX(), pp.getY()}; size_t num = _clusterObjects[cid].second.first; size_t tot = _clusterObjects[cid].second.second; @@ -800,13 +803,13 @@ util::geo::FPoint Requestor::clusterGeom(size_t cid, double res) const { double y = pp.getY() + (rad + row * 13.0) * res * cos(relpos * (2.0 * 3.14159265359 / tot)); - return util::geo::FPoint{x, y}; + return util::geo::DPoint{x, y}; } else { float rad = 2 * tot; float x = pp.getX() + rad * res * sin(num * (2 * 3.14159265359 / tot)); float y = pp.getY() + rad * res * cos(num * (2 * 3.14159265359 / tot)); - return util::geo::FPoint{x, y}; + return util::geo::DPoint{x, y}; } } diff --git a/src/qlever-petrimaps/server/Requestor.h b/src/qlever-petrimaps/server/Requestor.h index 7059f98..cb84737 100644 --- a/src/qlever-petrimaps/server/Requestor.h +++ b/src/qlever-petrimaps/server/Requestor.h @@ -23,13 +23,13 @@ namespace petrimaps { struct ResObj { bool has; size_t id; - util::geo::FPoint pos; + util::geo::DPoint pos; std::vector> cols; // the geometry - std::vector point; - std::vector line; - std::vector poly; + util::geo::MultiPoint point; + util::geo::MultiLine line; + util::geo::MultiPolygon poly; }; struct ReaderCbPair { @@ -96,14 +96,14 @@ class Requestor { util::geo::MultiPolygon geomPolyGeoms(size_t oid, double eps) const; util::geo::MultiLine geomLineGeoms(size_t oid, double eps) const; - util::geo::MultiPoint geomPointGeoms(size_t oid, double res) const; - util::geo::MultiPoint geomPointGeoms(size_t oid) const; + util::geo::MultiPoint geomPointGeoms(size_t oid, double res) const; + util::geo::MultiPoint geomPointGeoms(size_t oid) const; util::geo::DLine extractLineGeom(size_t lineId) const; bool isArea(size_t lineId) const; size_t getNumObjects() const { return _numObjects; } - util::geo::FPoint clusterGeom(size_t cid, double res) const; + util::geo::DPoint clusterGeom(size_t cid, double res) const; std::chrono::time_point createdAt() const { return _createdAt; diff --git a/src/qlever-petrimaps/server/Server.cpp b/src/qlever-petrimaps/server/Server.cpp index 8f379ac..e05234a 100755 --- a/src/qlever-petrimaps/server/Server.cpp +++ b/src/qlever-petrimaps/server/Server.cpp @@ -569,7 +569,17 @@ util::http::Answer Server::handleGeoJSONReq(const Params& pars) const { std::stringstream json; - if (res.poly.size()) { + if ((res.poly.size() != 0) + (res.point.size() != 0) + + (res.line.size() != 0) > + 1) { + util::geo::Collection col; + col.push_back(res.poly); + col.push_back(res.line); + col.push_back(res.point); + + GeoJsonOutput out(json); + out.printLatLng(col, dict); + } else if (res.poly.size()) { GeoJsonOutput out(json); out.printLatLng(res.poly, dict); } else if (res.line.size()) { @@ -577,7 +587,7 @@ util::http::Answer Server::handleGeoJSONReq(const Params& pars) const { out.printLatLng(res.line, dict); } else { GeoJsonOutput out(json); - out.printLatLng(res.pos, dict); + out.printLatLng(res.point, dict); } auto answ = util::http::Answer("200 OK", json.str()); @@ -678,16 +688,24 @@ util::http::Answer Server::handlePosReq(const Params& pars) const { first = false; } - auto ll = - webMercToLatLng(res.pos.getX(), res.pos.getY()); + auto ll = webMercToLatLng(res.pos.getX(), res.pos.getY()); json << "]"; json << std::setprecision(10) << ",\"ll\":{\"lat\" : " << ll.getY() << ",\"lng\":" << ll.getX() << "}"; - if (res.poly.size() + res.point.size() + res.line.size() > 1) { - // TODO: handle multigeometry case - } else if (res.poly.size()) { + if ((res.poly.size() != 0) + (res.point.size() != 0) + + (res.line.size() != 0) > + 1) { + util::geo::Collection col; + col.push_back(res.poly); + col.push_back(res.line); + col.push_back(res.point); + + json << ",\"geom\":"; + GeoJsonOutput out(json); + out.printLatLng(col, {}); + } else if (res.poly.size()) { json << ",\"geom\":"; GeoJsonOutput out(json); out.printLatLng(res.poly, {}); @@ -852,9 +870,7 @@ std::string Server::parseUrl(std::string u, std::string pl, } // _____________________________________________________________________________ -void Server::pngWriteRowCb(png_structp, png_uint_32 row, int) { - _curRow = row; -} +void Server::pngWriteRowCb(png_structp, png_uint_32 row, int) { _curRow = row; } // _____________________________________________________________________________ inline void pngWriteCb(png_structp png_ptr, png_bytep data, png_size_t length) { diff --git a/src/util b/src/util index 608bcfd..8eb25a8 160000 --- a/src/util +++ b/src/util @@ -1 +1 @@ -Subproject commit 608bcfd4a0aa3e7ea1aa8ab2a34ce557bbbaf74c +Subproject commit 8eb25a88d6a0235e1401e028414bf487725d96d9 diff --git a/web/script.js b/web/script.js index 381bcab..a43c42d 100755 --- a/web/script.js +++ b/web/script.js @@ -142,7 +142,7 @@ function loadMap(id, bounds, numObjects) { map.fitBounds(boundsLatLng); sessionId = id; - document.getElementById("stats").innerHTML = "Showing " + numObjects + " objects"; + document.getElementById("stats").innerHTML = "Showing " + numObjects + (numObjects > 1 ? " objects" : " object") + ""; const heatmapLayer = L.nonTiledLayer.wms('heatmap', { minZoom: 0,