Relations work now
This commit is contained in:
parent
1765590f3e
commit
85ee8ea9f2
3 changed files with 330 additions and 51 deletions
|
@ -10,5 +10,6 @@ add_executable(
|
|||
${NAME}
|
||||
${NAME}.cpp
|
||||
RTree.h
|
||||
xml_centers_output.hpp
|
||||
)
|
||||
target_link_libraries(${NAME} ${OSMIUM_IO_LIBRARIES})
|
||||
|
|
|
@ -32,46 +32,33 @@
|
|||
#include <osmium/visitor.hpp>
|
||||
|
||||
#include "RTree.h"
|
||||
#include "xml_centers_output.hpp"
|
||||
|
||||
using index_type = osmium::index::map::FlexMem<osmium::unsigned_object_id_type,
|
||||
osmium::Location>;
|
||||
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
|
||||
|
||||
class AmenityRelationsManager : public osmium::relations::RelationsManager<AmenityRelationsManager, false, true, false> {
|
||||
public:
|
||||
|
||||
bool new_relation(osmium::Relation const & rel) noexcept {
|
||||
const char *rel_type = rel.tags().get_value_by_key("type");
|
||||
return rel_type && !std::strcmp(rel_type, "multipolygon");
|
||||
}
|
||||
|
||||
void complete_relation(osmium::Relation const & rel) {
|
||||
this->buffer().add_item(rel);
|
||||
this->buffer().commit();
|
||||
}
|
||||
};
|
||||
|
||||
bool AppendToVector(uint16_t cat_id, void *vec) {
|
||||
static_cast<std::vector<uint16_t>*>(vec)->push_back(cat_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
class AmenityHandler : public osmium::handler::Handler {
|
||||
|
||||
constexpr static double kSearchRadius = 0.001; // ~1 km TODO! revert to 0.01
|
||||
constexpr static double kSearchRadius = 0.0001; // ~1 km TODO! revert to 0.01
|
||||
|
||||
typedef RTree<uint16_t, int32_t, 2, double> DatasetTree;
|
||||
typedef std::vector<std::vector<std::string>> TQuery;
|
||||
typedef std::vector<TQuery> TCategory;
|
||||
|
||||
DatasetTree m_tree;
|
||||
osmium::io::Writer &m_writer;
|
||||
osmium::io::xmlcenters::XMLCentersOutput m_centers;
|
||||
std::map<uint16_t, std::vector<TQuery>> m_categories;
|
||||
std::map<uint16_t, std::string> m_category_names;
|
||||
|
||||
void print_object(const osmium::OSMObject &obj,
|
||||
const osmium::Location ¢er) {
|
||||
// TODO
|
||||
std::cout << obj.type() << ' ' << obj.id() << std::endl;
|
||||
std::cout << m_centers.apply(obj, center);
|
||||
}
|
||||
|
||||
// Calculate the center point of a NodeRefList.
|
||||
|
@ -134,11 +121,13 @@ class AmenityHandler : public osmium::handler::Handler {
|
|||
|
||||
TQuery ParseQuery(std::string const & query) {
|
||||
TQuery q;
|
||||
std::vector<std::string> parts, keys;
|
||||
std::vector<std::string> parts;
|
||||
SplitTrim(query, '|', 100, parts);
|
||||
for (std::string const & part : parts) {
|
||||
std::vector<std::string> keys;
|
||||
SplitTrim(part, '=', 100, keys);
|
||||
// TODO
|
||||
if (keys.size() > 0)
|
||||
q.push_back(keys);
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
@ -169,8 +158,7 @@ class AmenityHandler : public osmium::handler::Handler {
|
|||
}
|
||||
|
||||
public:
|
||||
AmenityHandler(const char *categories, osmium::io::Writer &writer)
|
||||
: m_writer(writer) {
|
||||
AmenityHandler(const char *categories) {
|
||||
LoadCategories(categories);
|
||||
}
|
||||
|
||||
|
@ -201,24 +189,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void relation(osmium::Relation const & rel) {
|
||||
int64_t x = 0, y = 0, cnt = 0;
|
||||
for (const auto& member : rel.members()) {
|
||||
if (member.full_member() && member.type() == osmium::item_type::way) {
|
||||
const osmium::Way *way = reinterpret_cast<const osmium::Way*>(&member.get_object());
|
||||
for (const auto& node_ref : way->nodes()) {
|
||||
if (false && node_ref.location()) {
|
||||
x += node_ref.x();
|
||||
y += node_ref.y();
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!cnt)
|
||||
return;
|
||||
|
||||
const osmium::Location center(x / cnt, y / cnt);
|
||||
void multi(osmium::Relation const & rel, osmium::Location const & center) {
|
||||
if (IsEligible(center, rel.tags())) {
|
||||
print_object(rel, center);
|
||||
}
|
||||
|
@ -226,37 +197,67 @@ public:
|
|||
|
||||
}; // class AmenityHandler
|
||||
|
||||
class AmenityRelationsManager : public osmium::relations::RelationsManager<AmenityRelationsManager, false, true, false> {
|
||||
|
||||
AmenityHandler *m_handler;
|
||||
|
||||
public:
|
||||
|
||||
AmenityRelationsManager(AmenityHandler & handler) :
|
||||
RelationsManager(),
|
||||
m_handler(&handler) {
|
||||
}
|
||||
|
||||
bool new_relation(osmium::Relation const & rel) noexcept {
|
||||
const char *rel_type = rel.tags().get_value_by_key("type");
|
||||
return rel_type && !std::strcmp(rel_type, "multipolygon");
|
||||
}
|
||||
|
||||
void complete_relation(osmium::Relation const & rel) {
|
||||
int64_t x = 0, y = 0, cnt = 0;
|
||||
for (auto const & member : rel.members()) {
|
||||
if (member.ref() != 0) {
|
||||
const osmium::Way* way = this->get_member_way(member.ref());
|
||||
for (const auto& node_ref : way->nodes()) {
|
||||
if (node_ref.location()) {
|
||||
x += node_ref.x();
|
||||
y += node_ref.y();
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cnt > 0)
|
||||
m_handler->multi(rel, osmium::Location{x / cnt, y / cnt});
|
||||
}
|
||||
}; // class AmenityRelationsManager
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 3) {
|
||||
std::cerr << "Usage: " << argv[0]
|
||||
<< " <dataset.lst> <osmfile> [<output.xml>]\n";
|
||||
<< " <dataset.lst> <osmfile>\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
const osmium::io::File input_file{argv[2]};
|
||||
const osmium::io::File output_file{argc > 3 ? argv[3] : "", "osm"};
|
||||
const osmium::io::File output_file{"", "osm"};
|
||||
|
||||
std::cerr << "Pass 1/2: Reading relations...\n";
|
||||
AmenityRelationsManager manager;
|
||||
AmenityHandler data_handler(argv[1]);
|
||||
AmenityRelationsManager manager(data_handler);
|
||||
osmium::relations::read_relations(input_file, manager);
|
||||
|
||||
osmium::io::Header header;
|
||||
header.set("generator", argv[0]);
|
||||
osmium::io::Writer writer{output_file, header, osmium::io::overwrite::allow};
|
||||
AmenityHandler data_handler(argv[1], writer);
|
||||
|
||||
std::cerr << "Pass 2/2: Filtering points...\n";
|
||||
index_type index;
|
||||
location_handler_type location_handler{index};
|
||||
location_handler.ignore_errors();
|
||||
osmium::io::Reader reader{input_file};
|
||||
|
||||
osmium::apply(reader, location_handler, data_handler,
|
||||
manager.handler(
|
||||
[&data_handler](const osmium::memory::Buffer &area_buffer) {
|
||||
osmium::apply(area_buffer, data_handler);
|
||||
}));
|
||||
osmium::apply(reader, location_handler, data_handler, manager.handler());
|
||||
|
||||
std::cout.flush();
|
||||
reader.close();
|
||||
writer.close();
|
||||
}
|
||||
|
|
277
filter/xml_centers_output.hpp
Normal file
277
filter/xml_centers_output.hpp
Normal file
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/io/detail/string_util.hpp>
|
||||
#include <osmium/osm/box.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/object.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/timestamp.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace io {
|
||||
|
||||
namespace xmlcenters {
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline void append_lat_lon_attributes(std::string& out, const char* lat, const char* lon, const osmium::Location& location) {
|
||||
out += ' ';
|
||||
out += lat;
|
||||
out += "=\"";
|
||||
osmium::detail::append_location_coordinate_to_string(std::back_inserter(out), location.y());
|
||||
out += "\" ";
|
||||
out += lon;
|
||||
out += "=\"";
|
||||
osmium::detail::append_location_coordinate_to_string(std::back_inserter(out), location.x());
|
||||
out += "\"";
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class XMLCentersOutput {
|
||||
|
||||
std::shared_ptr<std::string> m_out;
|
||||
|
||||
inline void append_xml_encoded_string(std::string & out, const char *data) {
|
||||
osmium::io::detail::append_xml_encoded_string(out, data);
|
||||
}
|
||||
|
||||
void output_int(int64_t value) {
|
||||
if (value < 0) {
|
||||
*m_out += '-';
|
||||
value = -value;
|
||||
}
|
||||
|
||||
char temp[20];
|
||||
char *t = temp;
|
||||
do {
|
||||
*t++ = char(value % 10) + '0';
|
||||
value /= 10;
|
||||
} while (value > 0);
|
||||
|
||||
const auto old_size = m_out->size();
|
||||
m_out->resize(old_size + (t - temp));
|
||||
char* data = &(*m_out)[old_size];
|
||||
do {
|
||||
*data++ += *--t;
|
||||
} while (t != temp);
|
||||
}
|
||||
|
||||
void write_spaces(int num) {
|
||||
for (; num != 0; --num) {
|
||||
*m_out += ' ';
|
||||
}
|
||||
}
|
||||
|
||||
void write_prefix() {
|
||||
write_spaces(2);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write_attribute(const char* name, T value) {
|
||||
*m_out += ' ';
|
||||
*m_out += name;
|
||||
*m_out += "=\"";
|
||||
output_int(value);
|
||||
*m_out += '"';
|
||||
}
|
||||
|
||||
void write_meta(const osmium::OSMObject& object) {
|
||||
write_attribute("id", object.id());
|
||||
|
||||
if (object.version()) {
|
||||
write_attribute("version", object.version());
|
||||
}
|
||||
|
||||
if (object.timestamp()) {
|
||||
*m_out += " timestamp=\"";
|
||||
*m_out += object.timestamp().to_iso();
|
||||
*m_out += "\"";
|
||||
}
|
||||
|
||||
if (!object.user_is_anonymous()) {
|
||||
write_attribute("uid", object.uid());
|
||||
*m_out += " user=\"";
|
||||
append_xml_encoded_string(*m_out, object.user());
|
||||
*m_out += "\"";
|
||||
}
|
||||
|
||||
if (object.changeset()) {
|
||||
write_attribute("changeset", object.changeset());
|
||||
}
|
||||
}
|
||||
|
||||
void write_tags(const osmium::TagList& tags) {
|
||||
for (const auto& tag : tags) {
|
||||
write_spaces(2);
|
||||
*m_out += " <tag k=\"";
|
||||
append_xml_encoded_string(*m_out, tag.key());
|
||||
*m_out += "\" v=\"";
|
||||
append_xml_encoded_string(*m_out, tag.value());
|
||||
*m_out += "\"/>\n";
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
XMLCentersOutput() : m_out(std::make_shared<std::string>()) {
|
||||
}
|
||||
|
||||
std::string apply(osmium::OSMObject const & item, osmium::Location const & center) {
|
||||
switch(item.type()) {
|
||||
case osmium::item_type::node:
|
||||
node(static_cast<const osmium::Node&>(item));
|
||||
break;
|
||||
case osmium::item_type::way:
|
||||
way(static_cast<const osmium::Way&>(item), center);
|
||||
break;
|
||||
case osmium::item_type::relation:
|
||||
relation(static_cast<const osmium::Relation&>(item), center);
|
||||
break;
|
||||
default:
|
||||
throw osmium::unknown_type{};
|
||||
}
|
||||
|
||||
std::string out;
|
||||
using std::swap;
|
||||
swap(out, *m_out);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void node(const osmium::Node& node) {
|
||||
write_prefix();
|
||||
*m_out += "<node";
|
||||
|
||||
write_meta(node);
|
||||
|
||||
if (node.location()) {
|
||||
detail::append_lat_lon_attributes(*m_out, "lat", "lon", node.location());
|
||||
}
|
||||
|
||||
if (node.tags().empty()) {
|
||||
*m_out += "/>\n";
|
||||
return;
|
||||
}
|
||||
|
||||
*m_out += ">\n";
|
||||
|
||||
write_tags(node.tags());
|
||||
|
||||
write_prefix();
|
||||
*m_out += "</node>\n";
|
||||
}
|
||||
|
||||
void way(const osmium::Way& way, osmium::Location const & center) {
|
||||
write_prefix();
|
||||
*m_out += "<way";
|
||||
write_meta(way);
|
||||
|
||||
if (way.tags().empty() && way.nodes().empty()) {
|
||||
*m_out += "/>\n";
|
||||
return;
|
||||
}
|
||||
|
||||
*m_out += ">\n";
|
||||
|
||||
write_prefix();
|
||||
*m_out += " <center";
|
||||
detail::append_lat_lon_attributes(*m_out, "lat", "lon", center);
|
||||
*m_out += "/>\n";
|
||||
|
||||
for (const auto& node_ref : way.nodes()) {
|
||||
write_prefix();
|
||||
*m_out += " <nd";
|
||||
write_attribute("ref", node_ref.ref());
|
||||
*m_out += "/>\n";
|
||||
}
|
||||
|
||||
write_tags(way.tags());
|
||||
|
||||
write_prefix();
|
||||
*m_out += "</way>\n";
|
||||
}
|
||||
|
||||
void relation(const osmium::Relation& relation, osmium::Location const & center) {
|
||||
write_prefix();
|
||||
*m_out += "<relation";
|
||||
write_meta(relation);
|
||||
|
||||
if (relation.tags().empty() && relation.members().empty()) {
|
||||
*m_out += "/>\n";
|
||||
return;
|
||||
}
|
||||
|
||||
*m_out += ">\n";
|
||||
|
||||
write_prefix();
|
||||
*m_out += " <center";
|
||||
detail::append_lat_lon_attributes(*m_out, "lat", "lon", center);
|
||||
*m_out += "/>\n";
|
||||
|
||||
for (const auto& member : relation.members()) {
|
||||
write_prefix();
|
||||
*m_out += " <member type=\"";
|
||||
*m_out += item_type_to_name(member.type());
|
||||
*m_out += '"';
|
||||
write_attribute("ref", member.ref());
|
||||
*m_out += " role=\"";
|
||||
append_xml_encoded_string(*m_out, member.role());
|
||||
*m_out += "\"/>\n";
|
||||
}
|
||||
|
||||
write_tags(relation.tags());
|
||||
|
||||
write_prefix();
|
||||
*m_out += "</relation>\n";
|
||||
}
|
||||
|
||||
}; // class XMLCentersOutputBlock
|
||||
|
||||
} // namespace xmlcenters
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace osmium
|
Loading…
Add table
Reference in a new issue