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; }