/** * Tell the Collector that you are interested in this relation * and want it kept until all members have been assembled and * it is handed back to you. * * The relation is copied and stored in a buffer inside the * collector. */ void add_relation(const osmium::Relation& relation) { const size_t offset = m_relations_buffer.committed(); m_relations_buffer.add_item(relation); RelationMeta relation_meta(offset); int n = 0; for (auto& member : m_relations_buffer.get<osmium::Relation>(offset).members()) { if (static_cast<TCollector*>(this)->keep_member(relation_meta, member)) { member_meta(member.type()).emplace_back(member.ref(), m_relations.size(), n); relation_meta.increment_need_members(); } else { member.ref(0); // set member id to zero to indicate we are not interested } ++n; } assert(offset == m_relations_buffer.committed()); if (relation_meta.has_all_members()) { m_relations_buffer.rollback(); } else { m_relations_buffer.commit(); m_relations.push_back(std::move(relation_meta)); // std::cerr << "added relation id=" << relation.id() << "\n"; } }
bool middle_pgsql_t::ways_get(osmid_t id, osmium::memory::Buffer &buffer) const { char const *paramValues[1]; PGconn *sql_conn = way_table->sql_conn; // Make sure we're out of copy mode */ pgsql_endCopy(way_table); char tmp[16]; snprintf(tmp, sizeof(tmp), "%" PRIdOSMID, id); paramValues[0] = tmp; PGresult *res = pgsql_execPrepared(sql_conn, "get_way", 1, paramValues, PGRES_TUPLES_OK); if (PQntuples(res) != 1) { PQclear(res); return false; } { osmium::builder::WayBuilder builder(buffer); builder.set_id(id); pgsql_parse_nodes(PQgetvalue(res, 0, 0), buffer, builder); pgsql_parse_tags(PQgetvalue(res, 0, 1), buffer, builder); } PQclear(res); buffer.commit(); return true; }
bool middle_pgsql_t::relations_get(osmid_t id, osmium::memory::Buffer &buffer) const { char tmp[16]; char const *paramValues[1]; PGconn *sql_conn = rel_table->sql_conn; taglist_t member_temp; // Make sure we're out of copy mode */ pgsql_endCopy(rel_table); snprintf(tmp, sizeof(tmp), "%" PRIdOSMID, id); paramValues[0] = tmp; PGresult *res = pgsql_execPrepared(sql_conn, "get_rel", 1, paramValues, PGRES_TUPLES_OK); // Fields are: members, tags, member_count */ if (PQntuples(res) != 1) { PQclear(res); return false; } { osmium::builder::RelationBuilder builder(buffer); builder.set_id(id); pgsql_parse_members(PQgetvalue(res, 0, 0), buffer, builder); pgsql_parse_tags(PQgetvalue(res, 0, 1), buffer, builder); } PQclear(res); buffer.commit(); return true; }
size_t middle_pgsql_t::ways_get_list(const idlist_t &ids, osmium::memory::Buffer &buffer) const { if (ids.empty()) return 0; char tmp[16]; std::unique_ptr<char[]> tmp2(new (std::nothrow) char[ids.size() * 16]); char const *paramValues[1]; if (tmp2 == nullptr) return 0; //failed to allocate memory, return */ // create a list of ids in tmp2 to query the database */ sprintf(tmp2.get(), "{"); for (auto id : ids) { snprintf(tmp, sizeof(tmp), "%" PRIdOSMID ",", id); strncat(tmp2.get(), tmp, sizeof(char)*(ids.size()*16 - 2)); } tmp2[strlen(tmp2.get()) - 1] = '}'; // replace last , with } to complete list of ids*/ pgsql_endCopy(way_table); PGconn *sql_conn = way_table->sql_conn; paramValues[0] = tmp2.get(); PGresult *res = pgsql_execPrepared(sql_conn, "get_way_list", 1, paramValues, PGRES_TUPLES_OK); int countPG = PQntuples(res); idlist_t wayidspg; for (int i = 0; i < countPG; i++) { wayidspg.push_back(strtoosmid(PQgetvalue(res, i, 0), nullptr, 10)); } // Match the list of ways coming from postgres in a different order // back to the list of ways given by the caller */ int outres = 0; for (auto id : ids) { for (int j = 0; j < countPG; j++) { if (id == wayidspg[j]) { { osmium::builder::WayBuilder builder(buffer); builder.set_id(id); pgsql_parse_nodes(PQgetvalue(res, j, 1), buffer, builder); pgsql_parse_tags(PQgetvalue(res, j, 2), buffer, builder); } buffer.commit(); outres++; break; } } } PQclear(res); return outres; }
std::size_t parse_polygon_array(const rapidjson::Value& value, osmium::memory::Buffer& buffer) { { osmium::builder::AreaBuilder builder{buffer}; parse_rings(value, builder); } return buffer.commit(); }
/** * Parses one line in OPL format. The line must not have a newline * character at the end. Buffer.commit() is called automatically if the * write succeeded. * * @param data Line must be in this zero-delimited string. * @param buffer Result will be written to this buffer. * * @returns true if an entity was parsed, false otherwise (for instance * when the line is empty). * @throws osmium::opl_error If the parsing fails. */ inline bool opl_parse(const char* data, osmium::memory::Buffer& buffer) { try { const bool wrote_something = osmium::io::detail::opl_parse_line(0, data, buffer); buffer.commit(); return wrote_something; } catch (const osmium::opl_error&) { buffer.rollback(); throw; } }
/** * Assemble an area from the given way. * The resulting area is put into the out_buffer. * * @returns false if there was some kind of error building the * area, true otherwise. */ bool operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) { if (!config().create_way_polygons) { return true; } if (config().problem_reporter) { config().problem_reporter->set_object(osmium::item_type::way, way.id()); config().problem_reporter->set_nodes(way.nodes().size()); } // Ignore (but count) ways without segments. if (way.nodes().size() < 2) { ++stats().short_ways; return false; } if (!way.ends_have_same_id()) { ++stats().duplicate_nodes; if (config().problem_reporter) { config().problem_reporter->report_duplicate_node(way.nodes().front().ref(), way.nodes().back().ref(), way.nodes().front().location()); } } ++stats().from_ways; stats().invalid_locations = segment_list().extract_segments_from_way(config().problem_reporter, stats().duplicate_nodes, way); if (!config().ignore_invalid_locations && stats().invalid_locations > 0) { return false; } if (config().debug_level > 0) { std::cerr << "\nAssembling way " << way.id() << " containing " << segment_list().size() << " nodes\n"; } // Now create the Area object and add the attributes and tags // from the way. const bool okay = create_area(out_buffer, way); if (okay) { out_buffer.commit(); } else { out_buffer.rollback(); } if (debug()) { std::cerr << "Done: " << stats() << "\n"; } return okay; }
/** * Assemble an area from the given way. * * The resulting area is put into the out_buffer. * * @returns false if there was some kind of error building the * area, true otherwise. */ bool operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) { segment_list().extract_segments_from_way(config().problem_reporter, stats().duplicate_nodes, way); if (!create_rings()) { return false; } { osmium::builder::AreaBuilder builder{out_buffer}; builder.initialize_from_object(way); add_rings_to_area(builder); } out_buffer.commit(); return true; }
/** * Assemble an area from the given relation and its members. * The resulting area is put into the out_buffer. * * @returns false if there was some kind of error building the * area(s), true otherwise. */ bool operator()(const osmium::Relation& relation, const std::vector<const osmium::Way*>& members, osmium::memory::Buffer& out_buffer) { if (!config().create_new_style_polygons) { return true; } assert(relation.cmembers().size() >= members.size()); if (config().problem_reporter) { config().problem_reporter->set_object(osmium::item_type::relation, relation.id()); } if (relation.members().empty()) { ++stats().no_way_in_mp_relation; return false; } ++stats().from_relations; stats().invalid_locations = segment_list().extract_segments_from_ways(config().problem_reporter, stats().duplicate_nodes, stats().duplicate_ways, relation, members); if (!config().ignore_invalid_locations && stats().invalid_locations > 0) { return false; } stats().member_ways = members.size(); if (stats().member_ways == 1) { ++stats().single_way_in_mp_relation; } if (config().debug_level > 0) { std::cerr << "\nAssembling relation " << relation.id() << " containing " << members.size() << " way members with " << segment_list().size() << " nodes\n"; } // Now create the Area object and add the attributes and tags // from the relation. bool okay = create_area(out_buffer, relation, members); if (okay) { out_buffer.commit(); } else { out_buffer.rollback(); } return okay; }
std::size_t parse_multipolygon_array(const rapidjson::Value& value, osmium::memory::Buffer& buffer) { assert(value.IsArray()); const auto array = value.GetArray(); if (array.Empty()) { throw config_error{"Multipolygon must contain at least one polygon array."}; } { osmium::builder::AreaBuilder builder{buffer}; for (const auto& polygon : array) { if (!polygon.IsArray()) { throw config_error{"Polygon must be an array."}; } parse_rings(polygon, builder); } } return buffer.commit(); }