size_t middle_ram_t::ways_get_list(const idlist_t &ids, idlist_t &way_ids, multitaglist_t &tags, multinodelist_t &nodes) const { if (ids.empty()) { return 0; } assert(way_ids.empty()); tags.assign(ids.size(), taglist_t()); nodes.assign(ids.size(), nodelist_t()); size_t count = 0; for (idlist_t::const_iterator it = ids.begin(); it != ids.end(); ++it) { if (ways_get(*it, tags[count], nodes[count])) { way_ids.push_back(*it); count++; } else { tags[count].clear(); nodes[count].clear(); } } if (count < ids.size()) { tags.resize(count); nodes.resize(count); } return int(count); }
/* 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; }
int output_multi_t::process_relation(osmid_t id, const memberlist_t &members, const taglist_t &tags, bool exists, bool pending) { //if it may exist already, delete it first if(exists) relation_delete(id); //does this relation have anything interesting to us taglist_t rel_outtags; unsigned filter = m_tagtransform->filter_rel_tags(tags, *m_export_list.get(), rel_outtags, true); if (!filter) { //TODO: move this into geometry processor, figure a way to come back for tag transform //grab ways/nodes of the members in the relation, bail if none were used if(m_relation_helper.set(&members, (middle_t*)m_mid) < 1) return 0; //filter the tags on each member because we got them 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 has all original tags //so we filter here because each individual outputs cares about different tags int polygon, roads; multitaglist_t filtered(m_relation_helper.tags.size(), taglist_t()); for(size_t i = 0; i < m_relation_helper.tags.size(); ++i) { m_tagtransform->filter_way_tags(m_relation_helper.tags[i], &polygon, &roads, *m_export_list.get(), filtered[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 } //do the members of this relation have anything interesting to us //NOTE: make_polygon is preset here this is to force the tag matching/superseeded stuff //normally this wouldnt work but we tell the tag transform to allow typeless relations //this is needed because the type can get stripped off by the rel_tag filter above //if the export list did not include the type tag. //TODO: find a less hacky way to do the matching/superseeded and tag copying stuff without //all this trickery int make_boundary, make_polygon = 1; taglist_t outtags; filter = m_tagtransform->filter_rel_member_tags(rel_outtags, filtered, m_relation_helper.roles, &m_relation_helper.superseeded.front(), &make_boundary, &make_polygon, &roads, *m_export_list.get(), outtags, true); if (!filter) { geometry_builder::maybe_wkts_t wkts = m_processor->process_relation(m_relation_helper.nodes); if (wkts) { for(geometry_builder::wkt_itr wkt = wkts->begin(); wkt != wkts->end(); ++wkt) { //TODO: we actually have the nodes in the m_relation_helper and could use them //instead of having to reparse the wkt in the expiry code m_expire->from_wkt(wkt->geom.c_str(), -id); //what part of the code relies on relation members getting negative ids? copy_to_table(-id, wkt->geom.c_str(), outtags); } } //TODO: should this loop be inside the if above just in case? //take a look at each member to see if its superseeded (tags on it matched the tags on the relation) for(size_t i = 0; i < m_relation_helper.ways.size(); ++i) { //tags matched so we are keeping this one with this relation if (m_relation_helper.superseeded[i]) { //just in case it wasnt previously with this relation we get rid of them way_delete(m_relation_helper.ways[i]); //the other option is that we marked them pending in the way processing so here we mark them //done so when we go back over the pendings we can just skip it because its in the done list //TODO: dont do this when working with pending relations to avoid thread races if(!pending) ways_done_tracker->mark(m_relation_helper.ways[i]); } } } } return 0; }