Ejemplo n.º 1
0
int output_pgsql_t::pgsql_out_relation(osmid_t id, const taglist_t &rel_tags,
                           const multinodelist_t &xnodes, const multitaglist_t & xtags,
                           const idlist_t &xid, const rolelist_t &xrole,
                           bool pending)
{
    if (xnodes.empty())
        return 0;

    int roads = 0;
    int make_polygon = 0;
    int make_boundary = 0;
    double split_at;

    std::vector<int> members_superseeded(xnodes.size(), 0);
    taglist_t outtags;

    //if its a route relation make_boundary and make_polygon will be false otherwise one or the other will be true
    if (m_tagtransform->filter_rel_member_tags(rel_tags, xtags, xrole, 
              &(members_superseeded[0]), &make_boundary, &make_polygon, &roads,
              *m_export_list.get(), outtags)) {
        return 0;
    }

    /* Split long linear ways after around 1 degree or 100km (polygons not effected) */
    if (m_options.projection->get_proj_id() == PROJ_LATLONG)
        split_at = 1;
    else
        split_at = 100 * 1000;

    //this will either make lines or polygons (unless the lines arent a ring or are less than 3 pts) depending on the tag transform above
    //TODO: pick one or the other based on which we expect to care about
    geometry_builder::maybe_wkts_t wkts  = builder.build_both(xnodes, make_polygon, m_options.enable_multi, split_at, id);

    if (!wkts->size()) {
        return 0;
    }

    tag *areatag = 0;
    for (const auto& wkt: *wkts) {
        expire->from_wkt(wkt.geom.c_str(), -id);
        /* FIXME: there should be a better way to detect polygons */
        if (boost::starts_with(wkt.geom, "POLYGON") || boost::starts_with(wkt.geom, "MULTIPOLYGON")) {
            if ((wkt.area > 0.0) && m_enable_way_area) {
                char tmp[32];
                snprintf(tmp, sizeof(tmp), "%g", wkt.area);
                if (!areatag) {
                    outtags.push_dedupe(tag("way_area", tmp));
                    areatag = outtags.find("way_area");
                } else
                    areatag->value = tmp;
            }
            m_tables[t_poly]->write_wkt(-id, outtags, wkt.geom.c_str());
        } else {
            m_tables[t_line]->write_wkt(-id, outtags, wkt.geom.c_str());
            if (roads)
                m_tables[t_roads]->write_wkt(-id, outtags, wkt.geom.c_str());
        }
    }

    /* Tagtransform will have marked those member ways of the relation that
     * have fully been dealt with as part of the multi-polygon entry.
     * Set them in the database as done and delete their entry to not
     * have duplicates */
    //dont do this when working with pending relations as its not needed
    if (make_polygon) {
        for (size_t i=0; i < xid.size(); i++) {
            if (members_superseeded[i]) {
                pgsql_delete_way_from_output(xid[i]);
                if(!pending)
                    ways_done_tracker->mark(xid[i]);
            }
        }
    }

    // If the tag transform said the polygon looked like a boundary we want to make that as well
    // If we are making a boundary then also try adding any relations which form complete rings
    // The linear variants will have already been processed above
    if (make_boundary) {
        tag *areatag = 0;
        wkts = builder.build_polygons(xnodes, m_options.enable_multi, id);
        for (const auto& wkt: *wkts) {
            expire->from_wkt(wkt.geom.c_str(), -id);
            if ((wkt.area > 0.0) && m_enable_way_area) {
                char tmp[32];
                snprintf(tmp, sizeof(tmp), "%g", wkt.area);
                if (!areatag) {
                    outtags.push_dedupe(tag("way_area", tmp));
                    areatag = outtags.find("way_area");
                } else
                    areatag->value = tmp;
            }
            m_tables[t_poly]->write_wkt(-id, outtags, wkt.geom.c_str());
        }
    }

    return 0;
}