예제 #1
0
            /**
             * 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";
                }
            }
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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();
}
예제 #6
0
 /**
  * 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;
     }
 }
예제 #7
0
            /**
             * 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;
            }
예제 #8
0
            /**
             * 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;
            }
예제 #9
0
            /**
             * 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;
            }
예제 #10
0
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();
}