Пример #1
0
/* This is the workhorse of pgsql_add_relation, split out because it is used as the callback for iterate relations */
int output_pgsql_t::pgsql_process_relation(osmid_t id, const memberlist_t &members,
        const taglist_t &tags, int exists, bool pending)
{
    /* If the flag says this object may exist already, delete it first */
    if(exists)
        pgsql_delete_relation_from_output(id);

    taglist_t outtags;

    if (m_tagtransform->filter_rel_tags(tags, *m_export_list.get(), outtags))
        return 1;

    idlist_t xid2;
    multitaglist_t xtags2;
    multinodelist_t xnodes;

    for (memberlist_t::const_iterator it = members.begin(); it != members.end(); ++it)
    {
        /* Need to handle more than just ways... */
        if (it->type == OSMTYPE_WAY)
            xid2.push_back(it->id);
    }

    idlist_t xid;
    m_mid->ways_get_list(xid2, xid, xtags2, xnodes);
    int polygon = 0, roads = 0;
    multitaglist_t xtags(xid.size(), taglist_t());
    rolelist_t xrole(xid.size(), 0);

    for (size_t i = 0; i < xid.size(); i++) {
        for (size_t j = i; j < members.size(); j++) {
            if (members[j].id == xid[i]) {
                //filter the tags on this member because we got it from the middle
                //and since the middle is no longer tied to the output it no longer
                //shares any kind of tag transform and therefore all original tags
                //will come back and need to be filtered by individual outputs before
                //using these ways
                m_tagtransform->filter_way_tags(xtags2[i], &polygon, &roads,
                                                *m_export_list.get(), xtags[i]);
                //TODO: if the filter says that this member is now not interesting we
                //should decrement the count and remove his nodes and tags etc. for
                //now we'll just keep him with no tags so he will get filtered later
                xrole[i] = &members[j].role;
                break;
            }
        }
    }

    /* At some point we might want to consider storing the retrieved data in the members, rather than as separate arrays */
    pgsql_out_relation(id, outtags, xnodes, xtags, xid, xrole, pending);

    return 0;
}
Пример #2
0
void middle_pgsql_t::relations_set(osmid_t id, const memberlist_t &members, const taglist_t &tags)
{
    taglist_t member_list;
    char buf[64];

    idlist_t all_parts, node_parts, way_parts, rel_parts;
    all_parts.reserve(members.size());
    node_parts.reserve(members.size());
    way_parts.reserve(members.size());
    rel_parts.reserve(members.size());

    for (memberlist_t::const_iterator it = members.begin(); it != members.end(); ++it) {
        char type = 0;
        switch (it->type)
        {
            case OSMTYPE_NODE:     node_parts.push_back(it->id); type = 'n'; break;
            case OSMTYPE_WAY:      way_parts.push_back(it->id); type = 'w'; break;
            case OSMTYPE_RELATION: rel_parts.push_back(it->id); type = 'r'; break;
            default:
                fprintf(stderr, "Internal error: Unknown member type %d\n", it->type);
                util::exit_nicely();
        }
        sprintf( buf, "%c%" PRIdOSMID, type, it->id );
        member_list.push_back(tag_t(buf, it->role));
    }

    all_parts.insert(all_parts.end(), node_parts.begin(), node_parts.end());
    all_parts.insert(all_parts.end(), way_parts.begin(), way_parts.end());
    all_parts.insert(all_parts.end(), rel_parts.begin(), rel_parts.end());

    copy_buffer.reserve(all_parts.size() * 10 + member_list.size() * 24
                        + tags.size() * 24 + 64);

    // Params: id, way_off, rel_off, parts, members, tags */
    const char *paramValues[6] = { copy_buffer.c_str(), };
    bool copy = rel_table->copyMode;
    char delim = copy ? '\t' : '\0';

    copy_buffer = std::to_string(id);
    copy_buffer+= delim;

    paramValues[1] = paramValues[0] + copy_buffer.size();
    copy_buffer += std::to_string(node_parts.size());
    copy_buffer+= delim;

    paramValues[2] = paramValues[0] + copy_buffer.size();
    copy_buffer += std::to_string(node_parts.size() + way_parts.size());
    copy_buffer+= delim;

    paramValues[3] = paramValues[0] + copy_buffer.size();
    buffer_store_nodes(all_parts);
    copy_buffer+= delim;

    if (member_list.size() == 0) {
        paramValues[4] = nullptr;
        copy_buffer += "\\N";
    } else {
        paramValues[4] = paramValues[0] + copy_buffer.size();
        buffer_store_tags(member_list, copy);
    }
    copy_buffer+= delim;

    if (tags.size() == 0) {
        paramValues[5] = nullptr;
        copy_buffer += "\\N";
    } else {
        paramValues[5] = paramValues[0] + copy_buffer.size();
        buffer_store_tags(tags, copy);
    }

    if (copy) {
        copy_buffer+= '\n';
        pgsql_CopyData(__FUNCTION__, rel_table->sql_conn, copy_buffer);
    } else {
        buffer_correct_params(paramValues, 6);
        pgsql_execPrepared(rel_table->sql_conn, "insert_rel", 6,
                           (const char * const *)paramValues, PGRES_COMMAND_OK);
    }
}
Пример #3
0
int output_gazetteer_t::process_relation(osmid_t id, const memberlist_t &members,
                                         const taglist_t &tags)
{
    const std::string *type = tags.get("type");
    if (!type) {
        delete_unused_full('R', id);
        return 0;
    }

    int cmp_waterway = type->compare("waterway");

    if (*type == "associatedStreet"
            || !(*type == "boundary" || *type == "multipolygon" || !cmp_waterway)) {
        delete_unused_full('R', id);
        return 0;
    }

    places.process_tags(tags);

    if (m_options.append)
        delete_unused_classes('R', id);

    /* Are we interested in this item? */
    if (!places.has_data())
        return 0;

    /* get the boundary path (ways) */
    idlist_t xid2;
    for (memberlist_t::const_iterator it = members.begin(); it != members.end(); ++it) {
        /* only interested in ways */
        if (it->type == OSMTYPE_WAY)
            xid2.push_back(it->id);
    }

    if (xid2.empty()) {
        if (m_options.append)
            delete_unused_full('R', id);

        return 0;
    }

    multitaglist_t xtags;
    multinodelist_t xnodes;
    idlist_t xid;
    m_mid->ways_get_list(xid2, xid, xtags, xnodes);

    if (cmp_waterway) {
        geometry_builder::maybe_wkts_t wkts = builder.build_both(xnodes, 1, 1, 1000000, id);
        for (const auto& wkt: *wkts) {
            if (boost::starts_with(wkt.geom,  "POLYGON")
                    || boost::starts_with(wkt.geom,  "MULTIPOLYGON")) {
                places.copy_out('R', id, wkt.geom, buffer);
                flush_place_buffer();
            } else {
                /* add_polygon_error('R', id, "boundary", "adminitrative", &names, countrycode, wkt); */
            }
        }
    } else {
        /* waterways result in multilinestrings */
        geometry_builder::maybe_wkt_t wkt = builder.build_multilines(xnodes, id);
        if ((wkt->geom).length() > 0) {
            places.copy_out('R', id, wkt->geom, buffer);
            flush_place_buffer();
        }
    }

    return 0;
}
Пример #4
0
void middle_pgsql_t::relations_set(osmid_t id, const memberlist_t &members, const taglist_t &tags)
{
    // Params: id, way_off, rel_off, parts, members, tags */
    const char *paramValues[6];
    char *buffer;
    taglist_t member_list;
    char buf[64];

    idlist_t all_parts, node_parts, way_parts, rel_parts;
    all_parts.reserve(members.size());
    node_parts.reserve(members.size());
    way_parts.reserve(members.size());
    rel_parts.reserve(members.size());

    for (memberlist_t::const_iterator it = members.begin(); it != members.end(); ++it) {
        char type = 0;
        switch (it->type)
        {
        case OSMTYPE_NODE:
            node_parts.push_back(it->id);
            type = 'n';
            break;
        case OSMTYPE_WAY:
            way_parts.push_back(it->id);
            type = 'w';
            break;
        case OSMTYPE_RELATION:
            rel_parts.push_back(it->id);
            type = 'r';
            break;
        default:
            fprintf(stderr, "Internal error: Unknown member type %d\n", it->type);
            util::exit_nicely();
        }
        sprintf( buf, "%c%" PRIdOSMID, type, it->id );
        member_list.push_back(tag(buf, it->role));
    }

    all_parts.insert(all_parts.end(), node_parts.begin(), node_parts.end());
    all_parts.insert(all_parts.end(), way_parts.begin(), way_parts.end());
    all_parts.insert(all_parts.end(), rel_parts.begin(), rel_parts.end());

    if (rel_table->copyMode)
    {
        char *tag_buf = strdup(pgsql_store_tags(tags,1));
        const char *member_buf = pgsql_store_tags(member_list,1);
        char *parts_buf = pgsql_store_nodes(all_parts);
        int length = strlen(member_buf) + strlen(tag_buf) + strlen(parts_buf) + 64;
        buffer = (char *)alloca(length);
        if (snprintf( buffer, length, "%" PRIdOSMID "\t%zu\t%zu\t%s\t%s\t%s\n",
                      id, node_parts.size(), node_parts.size() + way_parts.size(),
                      parts_buf, member_buf, tag_buf ) > (length-10)) {
            throw std::runtime_error((boost::format("Buffer overflow relation id %1%") % id).str());
        }
        free(tag_buf);
        pgsql_CopyData(__FUNCTION__, rel_table->sql_conn, buffer);
    } else {
        buffer = (char *)alloca(64);
        char *ptr = buffer;
        paramValues[0] = ptr;
        ptr += sprintf(ptr, "%" PRIdOSMID, id ) + 1;
        paramValues[1] = ptr;
        ptr += sprintf(ptr, "%zu", node_parts.size() ) + 1;
        paramValues[2] = ptr;
        sprintf( ptr, "%zu", node_parts.size() + way_parts.size() );
        paramValues[3] = pgsql_store_nodes(all_parts);
        paramValues[4] = pgsql_store_tags(member_list,0);
        if (paramValues[4]) {
            paramValues[4] = strdup(paramValues[4]);
        }
        paramValues[5] = pgsql_store_tags(tags,0);
        pgsql_execPrepared(rel_table->sql_conn, "insert_rel", 6, (const char * const *)paramValues, PGRES_COMMAND_OK);
        if (paramValues[4]) {
            free((void *)paramValues[4]);
        }
    }
}