void relation(const osmium::Relation& relation) {
                    if (m_write_change_ops) {
                        open_close_op_tag(relation.visible() ? (relation.version() == 1 ? operation::op_create : operation::op_modify) : operation::op_delete);
                    }

                    write_prefix();
                    m_out += "<relation";
                    write_meta(relation);

                    if (relation.tags().empty() && relation.members().empty()) {
                        m_out += "/>\n";
                        return;
                    }

                    m_out += ">\n";

                    for (const auto& member : relation.members()) {
                        write_prefix();
                        m_out += "  <member type=\"";
                        m_out += item_type_to_name(member.type());
                        oprintf(m_out, "\" ref=\"%" PRId64 "\" role=\"", member.ref());
                        xml_string(m_out, member.role());
                        m_out += "\"/>\n";
                    }

                    write_tags(relation.tags());

                    write_prefix();
                    m_out += "</relation>\n";
                }
示例#2
0
	void relation( osmium::Relation& relation ) {
		const char* bus = relation.tags()["route"];
		if(bus && !strcmp(bus, "bus")) {
			const char* name = relation.tags().get_value_by_key("ref");
			if(!name) name = relation.tags().get_value_by_key("name");
			
			std::cout << name;
			
			osmium::unsigned_object_id_type temp1, temp2;
			int db = 0;
			for( auto &member : relation.members()){
				if(db == 0 && member.type() == osmium::item_type::node) {
					temp1 = member.positive_ref();
					db++;
				} else if(db !=0 && member.type() == osmium::item_type::node){
					temp2 = member.positive_ref();
				}				
			}
			
			std::cout << " (" << map[temp1] << " - " << map[temp2] << ")" << std::endl;
			
			for ( auto &member : relation.members()) {
				if( member.type() == osmium::item_type::node){
					std::cout << " " << locations.get(member.positive_ref()).lat() << ", " << locations.get(member.positive_ref()).lon() << " " << map[member.positive_ref()] << std::endl;
				}
				
			}
			std::cout << std::endl;
		}
	}
osmium::osm_entity_bits::type CommandAddRefs::add_members(const osmium::Relation& relation) {
    osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::nothing;

    for (const auto& member : relation.members()) {
        switch (member.type()) {
            case osmium::item_type::node:
                m_node_ids.insert(member.ref());
                break;
            case osmium::item_type::way:
                if (m_way_ids.count(member.ref()) == 0) {
                    m_way_ids.insert(member.ref());
                    read_types |= osmium::osm_entity_bits::way;
                }
                break;
            case osmium::item_type::relation:
                if (m_relation_ids.count(member.ref()) == 0) {
                    m_relation_ids.insert(member.ref());
                    read_types |= osmium::osm_entity_bits::relation;
                }
                break;
            default:
                break;
        }
    }

    return read_types;
}
            /**
             * We are interested in all relations tagged with type=multipolygon
             * or type=boundary with at least one way member.
             */
            bool new_relation(const osmium::Relation& relation) const {
                const char* type = relation.tags().get_value_by_key("type");

                // ignore relations without "type" tag
                if (!type) {
                    return false;
                }

                if ((!std::strcmp(type, "multipolygon")) || (!std::strcmp(type, "boundary"))) {
                    return std::any_of(relation.members().cbegin(), relation.members().cend(), [](const RelationMember& member) {
                        return member.type() == osmium::item_type::way;
                    });
                }

                return false;
            }
    void relation(osmium::Relation& rel) {
        const char* bus = rel.tags() ["route"];
        if (bus && !strcmp(bus, "bus")) {
            const char* busRef = rel.tags()["ref"];
            if (busRef) {
                buses.push_back(Bus(busRef, id));
                id++;

                osmium::RelationMemberList& rml = rel.members();
                for (osmium::RelationMember& rm : rml) {
                    if (rm.type() == osmium::item_type::way) {
                        std::vector<osmium::Location> tmpVec;
                        for (auto& nd : ways[rm.ref()]) {
                            osmium::Location loc = locations.get(nd);
                            tmpVec.push_back(loc);
                        }
                        buses.at(id - 1).locs.push_back(tmpVec);
                    } else if(rm.type() == osmium::item_type::node && 
                                !strcmp(rm.role(), "stop")) {
                        buses.at(id - 1).busStopNames[rm.ref()] = nodes[rm.ref()];
                    }
                }
            }
        }
    }
    // - walk over all relations-versions
    //   - walk over all relations-nodes
    //     - Adds the nodes and ways that aren't in node-tracker to a vector
    //     - if node or way is in the box hit becames true
    //   - if hit is true and the vector is not empty (it means their are nodes or ways that belong to a relation that has at least one node or way inside the box)
    //     - Records the id of node or way to outside_node_tracker or outside_way_tracker
    void relation(const osmium::Relation& relation) {
	
    	bool hit = false;

        if (debug) {
            std::cerr << "cut_administrative relation " << relation.id() << " v" << relation.version() << "\n";
        }
    	
        std::vector<const osmium::RelationMember*> members;
        std::vector<const osmium::TagList*> tags;

        for (auto& tag : relation.tags()) {
            if (strcmp(tag.key(), "boundary") == 0 && strcmp(tag.value(), "administrative") == 0)
                hit = true;
        }

    	for (const auto& extract : info->extracts) {
            if (hit){
                if(!extract->relation_tracker.get(relation.id())){
                    extract->relation_tracker.set(relation.id());
                }
                //Add only the nodes and ways that were not yet in the respective trackers if hit is true
                for (const auto& member : relation.members()) {
                    if (member.type() == osmium::item_type::way && !extract->way_tracker.get(member.ref())){
                            extract->way_tracker.set(member.ref());
                    } 
                }
            }
        }
    }
示例#7
0
 /**
  * Extract all segments from all ways that make up this
  * multipolygon relation and add them to the list.
  */
 void extract_segments_from_ways(const osmium::Relation& relation, const std::vector<size_t>& members, const osmium::memory::Buffer& in_buffer) {
     auto member_it = relation.members().begin();
     for (size_t offset : members) {
         const osmium::Way& way = in_buffer.get<const osmium::Way>(offset);
         extract_segments_from_way(way, member_it->role());
         ++member_it;
     }
 }
                void relation(const osmium::Relation& relation) {
                    *m_out += 'r';
                    write_meta(relation);

                    *m_out += " M";

                    if (!relation.members().empty()) {
                        auto it = relation.members().begin();
                        relation_member(*it);
                        for (++it; it != relation.members().end(); ++it) {
                            *m_out += ',';
                            relation_member(*it);
                        }
                    }

                    *m_out += '\n';
                }
            /**
             * This is called when a relation is complete, ie. all members
             * were found in the input. It will build the area using the
             * assembler.
             */
            void complete_relation(const osmium::Relation& relation) {
                std::vector<const osmium::Way*> ways;
                ways.reserve(relation.members().size());
                for (const auto& member : relation.members()) {
                    if (member.ref() != 0) {
                        ways.push_back(this->get_member_way(member.ref()));
                        assert(ways.back() != nullptr);
                    }
                }

                try {
                    TAssembler assembler{m_assembler_config};
                    assembler(relation, ways, this->buffer());
                    m_stats += assembler.stats();
                } catch (const osmium::invalid_location&) {
                    // XXX ignore
                }
            }
示例#10
0
 inline void for_each_member(const osmium::Relation& relation, const std::vector<const osmium::Way*>& ways, F&& func) {
     auto way_it = ways.cbegin();
     for (const osmium::RelationMember& member : relation.members()) {
         if (member.type() == osmium::item_type::way) {
             assert(way_it != ways.cend());
             func(member, **way_it);
             ++way_it;
         }
     }
 }
 void complete_relation(const osmium::Relation& relation) noexcept {
     for (const auto& member : relation.members()) {
         if (member.type() == osmium::item_type::node) {
             ++count_nodes;
             const auto* node = get_member_node(member.ref());
             REQUIRE(node);
             buffer().add_item(*node);
             buffer().commit();
         }
     }
 }
示例#12
0
    // The relation handler is called for each node in the input data.
    void relation(const osmium::Relation& relation) {
        {
            osmium::builder::RelationBuilder builder{m_buffer};
            copy_attributes(builder, relation);
            copy_tags(builder, relation.tags());

            // Copy the relation member list over to the new way.
            builder.add_item(relation.members());
        }
        m_buffer.commit();
    }
示例#13
0
    /***
     * Iterate through members. Create linestrings of each. First as GEOS
     * linestring to union them later. Then as ORG linestring to insert
     * them into table ways.
     */
    void create_ways(const osmium::Relation &relation,
                     const osmium::object_id_type relation_id,
                     bool &contains_nowaterway_ways,
                     vector<geos::geom::Geometry *> *linestrings) {
        
        for (auto& member : relation.members()) {
            if (member_is_valid(member)) {
                const osmium::Way& way = way_from(member);
                linestring_type *linestr = nullptr;
                try {
                    linestr = osmium_geos_factory.create_linestring(way,
                            osmium::geom::use_nodes::unique,
                            osmium::geom::direction::forward).release();
                } catch (osmium::geometry_error) {
                    insert_way_error(way);
                    continue;
                } catch (...) {
                    cerr << "Error at way: " << way.id() << endl;
                    cerr << "  Unexpected error" << endl;
                    continue;
                }
                if (linestr) {
                    linestrings->push_back(linestr);
                } else {
                    continue;
                }

                if (TagCheck::has_waterway_tag(way)) {
                    contains_nowaterway_ways = true;
                }

                OGRGeometry *ogr_linestring = nullptr;
                ogr_linestring = geos2ogr(linestr);

                try {
                    ds.insert_way_feature(ogr_linestring, way, relation_id);
                } catch (osmium::geometry_error&) {
                    cerr << "Inserting to table failed for way: "
                         << way.id() << endl;
                } catch (...) {
                    cerr << "Inserting to table failed for way: "
                         << way.id() << endl;;
                    cerr << "  Unexpected error" << endl;
                }
                OGRGeometryFactory::destroyGeometry(ogr_linestring);
            }
        }
    }
示例#14
0
size_t middle_ram_t::rel_way_members_get(osmium::Relation const &rel,
                                         rolelist_t *roles,
                                         osmium::memory::Buffer &buffer) const
{
    size_t count = 0;
    for (auto const &m : rel.members()) {
        if (m.type() == osmium::item_type::way && ways_get(m.ref(), buffer)) {
            if (roles) {
                roles->emplace_back(m.role());
            }
            ++count;
        }
    }

    return count;
}
示例#15
0
                /**
                 * Extract all segments from all ways that make up this
                 * multipolygon relation and add them to the list.
                 */
                uint32_t extract_segments_from_ways(osmium::area::ProblemReporter* problem_reporter, const osmium::Relation& relation, const std::vector<const osmium::Way*>& members) {
                    assert(relation.members().size() >= members.size());

                    const size_t num_segments = get_num_segments(members);
                    if (problem_reporter) {
                        problem_reporter->set_nodes(num_segments);
                    }
                    m_segments.reserve(num_segments);

                    uint32_t duplicate_nodes = 0;
                    for_each_member(relation, members, [this, &problem_reporter, &duplicate_nodes](const osmium::RelationMember& member, const osmium::Way& way) {
                        duplicate_nodes += extract_segments_from_way_impl(problem_reporter, way, parse_role(member.role()));
                    });

                    return duplicate_nodes;
                }
示例#16
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;
            }
 void relation(const osmium::Relation& relation) {
     for (const auto& member : relation.members()) {
         switch (member.type()) {
             case osmium::item_type::node:
                 m_index_n2r.set(member.positive_ref(), relation.positive_id());
                 break;
             case osmium::item_type::way:
                 m_index_w2r.set(member.positive_ref(), relation.positive_id());
                 break;
             case osmium::item_type::relation:
                 m_index_r2r.set(member.positive_ref(), relation.positive_id());
                 break;
             default:
                 break;
         }
     }
 }
示例#18
0
                /**
                 * Extract all segments from all ways that make up this
                 * multipolygon relation and add them to the list.
                 */
                uint32_t extract_segments_from_ways(osmium::area::ProblemReporter* problem_reporter, uint64_t& duplicate_nodes, const osmium::Relation& relation, const std::vector<const osmium::Way*>& members) {
                    assert(relation.members().size() >= members.size());

                    const size_t num_segments = get_num_segments(members);
                    if (problem_reporter) {
                        problem_reporter->set_nodes(num_segments);
                    }
                    m_segments.reserve(num_segments);

                    uint32_t invalid_locations = 0;
                    for_each_member(relation, members, [&](const osmium::RelationMember& member, const osmium::Way& way) {
                        const auto role = parse_role(member.role());
                        invalid_locations += extract_segments_from_way_impl(problem_reporter, duplicate_nodes, way, role);
                    });

                    return invalid_locations;
                }
示例#19
0
     void relation ( osmium::Relation& rel ) {
          const char* bus = rel.tags() ["route"];
          const char* nev;
          if ( bus && !strcmp ( bus, "bus" ) ) {
               if( rel.tags()["name"])
               {
                    nev = rel.tags()["name"];
               }
               else
               {
                    nev = rel.tags()["ref"];
               }
               ++stops;
               //TODO asdasd


               int i {1};
               osmium::RelationMemberList& rml = rel.members();
               int szam=0;
               for ( osmium::RelationMember& rm : rml ) {
                    i = 1;
                    if (rm.type() == osmium::item_type::way ) {

                         for( auto it : way_node_map[rm.ref()] )
                         {
                              try {
                                   osmium::Location loc = locations.get ( it );

                                   if ( i++>1 ) {
                                        osmium::geom::Coordinates coords {loc};
                                        szam++;
                                        printf("%.8f %.8f\n",double(coords.y),double(coords.x) );

                                   }
                              } catch ( std::exception& e ) {
                                   std::cout << "No such node on the map. "<< e.what() << std::endl;
                              }
                         }
                    std::cout << "way\n";
                    }
               }
               //std::cout << "way\n";
               std::cout << nev << " busz\n";
          }

     }
示例#20
0
                void relation(const osmium::Relation& relation) {
                    *m_out += 'r';
                    write_meta(relation);

                    *m_out += " M";
                    bool first = true;
                    for (const auto& member : relation.members()) {
                        if (first) {
                            first = false;
                        } else {
                            *m_out += ',';
                        }
                        *m_out += item_type_to_char(member.type());
                        output_formatted("%" PRId64 "@", member.ref());
                        append_encoded_string(member.role());
                    }
                    *m_out += '\n';
                }
    void relation(const osmium::Relation& relation) {
        m_check_order.relation(relation);

        if (m_relation_count == 0) {
            m_progress_bar.remove();
            m_vout << "Reading relations...\n";
        }
        ++m_relation_count;

        if (m_check_relations) {
            set(osmium::item_type::relation, relation.id());
            for (const auto& member : relation.members()) {
                switch (member.type()) {
                    case osmium::item_type::node:
                        if (!get(osmium::item_type::node, member.ref())) {
                            ++m_missing_nodes_in_relations;
                            set(osmium::item_type::node, member.ref());
                            if (m_show_ids) {
                                std::cout << "n" << member.ref() << " in r" << relation.id() << "\n";
                            }
                        }
                        break;
                    case osmium::item_type::way:
                        if (!get(osmium::item_type::way, member.ref())) {
                            ++m_missing_ways_in_relations;
                            set(osmium::item_type::way, member.ref());
                            if (m_show_ids) {
                                std::cout << "w" << member.ref() << " in r" << relation.id() << "\n";
                            }
                        }
                        break;
                    case osmium::item_type::relation:
                        if (member.ref() > relation.id() || !get(osmium::item_type::relation, member.ref())) {
                            m_relation_refs.emplace_back(member.ref(), relation.id());
                        }
                        break;
                    default:
                        break;
                }
            }
        }
    }
 void erelation(extract_data& e, const osmium::Relation& relation) {
     for (const auto& member : relation.members()) {
         switch (member.type()) {
             case osmium::item_type::node:
                 if (e.node_ids.get(member.positive_ref())) {
                     e.relation_ids.set(relation.positive_id());
                     return;
                 }
                 break;
             case osmium::item_type::way:
                 if (e.way_ids.get(member.positive_ref())) {
                     e.relation_ids.set(relation.positive_id());
                     return;
                 }
                 break;
             default:
                 break;
         }
     }
 }
示例#23
0
  void relation ( osmium::Relation& rel )
  {

    ++nOSM_relations;

    const char* bus = rel.tags() ["route"];
    if ( bus && !strcmp ( bus, "bus" ) )
      {

        ++nbuses;

        std::string ref_key;

        try
          {
            const char* ref = rel.tags() ["ref"];
            if ( ref )
              ref_key.append ( ref );
            else
              ref_key.append ( "Not specified" );

          }
        catch ( std::exception& e )
          {
            std::cout << "There is no bus number."<< e.what() << std::endl;
          }

        osmium::RelationMemberList& rml = rel.members();
        for ( osmium::RelationMember& rm : rml )
          {

            if ( rm.type() == osmium::item_type::way )
              {

                busWayNodesMap[ref_key].push_back ( rm.ref() );

              }
          }

      }
  }
示例#24
0
            void relation(const osmium::Relation& relation) {
                m_out << "r";
                write_meta(relation);

                m_out << " M";
                int n=0;
                for (const auto& member : relation.members()) {
                    if (n++ != 0) {
                        m_out << ",";
                    }
                    m_out << item_type_to_char(member.type())
                          << member.ref()
                          << "!"
                          << member.role();
                }

                write_tags(relation.tags());
                m_out << "\n";
                ::write(this->fd(), m_out.str().c_str(), m_out.str().size());
                m_out.str("");
            }
示例#25
0
    // - walk over all relation-versions
    //   - walk over all bboxes
    //     - walk over all relation-members
    //       - if the relation-member is recorded in the bboxes node- or way-tracker
    //         - record its id in the bboxes relation-tracker
    void relation(const osmium::Relation& relation) {
        if (first_relation) {
            write_way_extra_nodes();
            first_relation = false;
        }

        if (debug) {
            std::cerr << "softcut relation " << relation.positive_id() << " v" << relation.version() << "\n";
        }

        for (const auto& extract : info->extracts) {
            bool hit = false;

            for (const auto& member : relation.members()) {

                if (!hit && (
                    (member.type() == osmium::item_type::node && extract->node_tracker.get(member.positive_ref())) ||
                    (member.type() == osmium::item_type::way && extract->way_tracker.get(member.positive_ref())) ||
                    (member.type() == osmium::item_type::relation && extract->relation_tracker.get(member.positive_ref()))
                )) {

                    if (debug) std::cerr << "relation has a member (" << member.type() << " " << member.positive_ref() << ") inside extract, recording in relation_tracker\n";
                    hit = true;

                    extract->relation_tracker.set(relation.positive_id());
                }

                if (member.type() == osmium::item_type::relation) {
                    if (debug) {
                        std::cerr << "recording cascading-pair: " << member.positive_ref() << " -> " << relation.positive_id() << "\n";
                    }
                    info->cascading_relations_tracker.insert(std::make_pair(member.positive_ref(), relation.positive_id()));
                }
            }

            if (hit) {
                cascading_relations(extract, relation.positive_id());
            }
        }
    }
示例#26
0
 void update(const osmium::Relation& relation) {
     update(static_cast<const osmium::OSMObject&>(relation));
     update(relation.members());
 }
示例#27
0
mapbox::util::optional<InputRestrictionContainer>
RestrictionParser::TryParse(const osmium::Relation &relation) const
{
    // return if turn restrictions should be ignored
    if (!use_turn_restrictions)
    {
        return mapbox::util::optional<InputRestrictionContainer>();
    }

    osmium::tags::KeyPrefixFilter filter(false);
    filter.add(true, "restriction");

    const osmium::TagList &tag_list = relation.tags();

    osmium::tags::KeyPrefixFilter::iterator fi_begin(filter, tag_list.begin(), tag_list.end());
    osmium::tags::KeyPrefixFilter::iterator fi_end(filter, tag_list.end(), tag_list.end());

    // if it's a restriction, continue;
    if (std::distance(fi_begin, fi_end) == 0)
    {
        return mapbox::util::optional<InputRestrictionContainer>();
    }

    // check if the restriction should be ignored
    const char *except = relation.get_value_by_key("except");
    if (except != nullptr && ShouldIgnoreRestriction(except))
    {
        return mapbox::util::optional<InputRestrictionContainer>();
    }

    bool is_only_restriction = false;

    for (auto iter = fi_begin; iter != fi_end; ++iter)
    {
        if (std::string("restriction") == iter->key() ||
            std::string("restriction::hgv") == iter->key())
        {
            const std::string restriction_value(iter->value());

            if (restriction_value.find("only_") == 0)
            {
                is_only_restriction = true;
            }
        }
    }

    InputRestrictionContainer restriction_container(is_only_restriction);

    for (const auto &member : relation.members())
    {
        const char *role = member.role();
        if (strcmp("from", role) != 0 && strcmp("to", role) != 0 && strcmp("via", role) != 0)
        {
            continue;
        }

        switch (member.type())
        {
        case osmium::item_type::node:
            // Make sure nodes appear only in the role if a via node
            if (0 == strcmp("from", role) || 0 == strcmp("to", role))
            {
                continue;
            }
            BOOST_ASSERT(0 == strcmp("via", role));

            // set via node id
            restriction_container.restriction.via.node = member.ref();
            break;

        case osmium::item_type::way:
            BOOST_ASSERT(0 == strcmp("from", role) || 0 == strcmp("to", role) ||
                         0 == strcmp("via", role));
            if (0 == strcmp("from", role))
            {
                restriction_container.restriction.from.way = member.ref();
            }
            else if (0 == strcmp("to", role))
            {
                restriction_container.restriction.to.way = member.ref();
            }
            // else if (0 == strcmp("via", role))
            // {
            //     not yet suppported
            //     restriction_container.restriction.via.way = member.ref();
            // }
            break;
        case osmium::item_type::relation:
            // not yet supported, but who knows what the future holds...
            break;
        default:
            // shouldn't ever happen
            break;
        }
    }
    return mapbox::util::optional<InputRestrictionContainer>(restriction_container);
}
示例#28
0
void middle_pgsql_t::relations_set(osmium::Relation const &rel)
{
    idlist_t parts[3];

    for (auto const &m : rel.members()) {
        parts[osmium::item_type_to_nwr_index(m.type())].push_back(m.ref());
    }

    copy_buffer.reserve(rel.members().byte_size() * 2 + rel.tags().byte_size() + 128);

    // 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(rel.id());
    copy_buffer+= delim;

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

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

    paramValues[3] = paramValues[0] + copy_buffer.size();
    if (rel.members().empty()) {
        copy_buffer += "{}";
    } else {
        copy_buffer += "{";
        for (int i = 0; i < 3; ++i) {
            for (auto it : parts[i]) {
                copy_buffer += std::to_string(it);
                copy_buffer += ',';
            }
        }
        copy_buffer[copy_buffer.size() - 1] = '}';
    }
    copy_buffer+= delim;

    if (rel.members().empty()) {
        paramValues[4] = nullptr;
        copy_buffer += "\\N";
    } else {
        paramValues[4] = paramValues[0] + copy_buffer.size();
        copy_buffer += "{";
        for (auto const &m : rel.members()) {
            copy_buffer += '"';
            copy_buffer += osmium::item_type_to_char(m.type());
            copy_buffer += std::to_string(m.ref());
            copy_buffer += "\",\"";
            buffer_store_string(m.role(), copy);
            copy_buffer += "\",";
        }
        copy_buffer[copy_buffer.size() - 1] = '}';
    }
    copy_buffer+= delim;

    if (rel.tags().empty() && !out_options->extra_attributes) {
        paramValues[5] = nullptr;
        copy_buffer += "\\N";
    } else {
        paramValues[5] = paramValues[0] + copy_buffer.size();
        buffer_store_tags(rel, out_options->extra_attributes, 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);
    }
}
/**
 * Tries to parse a relation as a turn restriction. This can fail for a number of
 * reasons. The return type is a boost::optional<T>.
 *
 * Some restrictions can also be ignored: See the ```get_restrictions``` function
 * in the corresponding profile. We use it for both namespacing restrictions, as in
 * restriction:motorcar as well as whitelisting if its in except:motorcar.
 */
boost::optional<InputRestrictionContainer>
RestrictionParser::TryParse(const osmium::Relation &relation) const
{
    // return if turn restrictions should be ignored
    if (!use_turn_restrictions)
    {
        return {};
    }

    osmium::tags::KeyFilter filter(false);
    filter.add(true, "restriction");

    // Not only use restriction= but also e.g. restriction:motorcar=
    for (const auto &namespaced : restrictions)
        filter.add(true, "restriction:" + namespaced);

    const osmium::TagList &tag_list = relation.tags();

    osmium::tags::KeyFilter::iterator fi_begin(filter, tag_list.begin(), tag_list.end());
    osmium::tags::KeyFilter::iterator fi_end(filter, tag_list.end(), tag_list.end());

    // if it's not a restriction, continue;
    if (std::distance(fi_begin, fi_end) == 0)
    {
        return {};
    }

    // check if the restriction should be ignored
    const char *except = relation.get_value_by_key("except");
    if (except != nullptr && ShouldIgnoreRestriction(except))
    {
        return {};
    }

    bool is_only_restriction = false;

    for (; fi_begin != fi_end; ++fi_begin)
    {
        const std::string key(fi_begin->key());
        const std::string value(fi_begin->value());

        // documented OSM restriction tags start either with only_* or no_*;
        // check and return on these values, and ignore unrecognized values
        if (value.find("only_") == 0)
        {
            is_only_restriction = true;
        }
        else if (value.find("no_") == 0)
        {
            is_only_restriction = false;
        }
        else // unrecognized value type
        {
            return {};
        }
    }

    InputRestrictionContainer restriction_container(is_only_restriction);

    for (const auto &member : relation.members())
    {
        const char *role = member.role();
        if (strcmp("from", role) != 0 && strcmp("to", role) != 0 && strcmp("via", role) != 0)
        {
            continue;
        }

        switch (member.type())
        {
        case osmium::item_type::node:
            // Make sure nodes appear only in the role if a via node
            if (0 == strcmp("from", role) || 0 == strcmp("to", role))
            {
                continue;
            }
            BOOST_ASSERT(0 == strcmp("via", role));

            // set via node id
            restriction_container.restriction.via.node = member.ref();
            break;

        case osmium::item_type::way:
            BOOST_ASSERT(0 == strcmp("from", role) || 0 == strcmp("to", role) ||
                         0 == strcmp("via", role));
            if (0 == strcmp("from", role))
            {
                restriction_container.restriction.from.way = member.ref();
            }
            else if (0 == strcmp("to", role))
            {
                restriction_container.restriction.to.way = member.ref();
            }
            // else if (0 == strcmp("via", role))
            // {
            //     not yet suppported
            //     restriction_container.restriction.via.way = member.ref();
            // }
            break;
        case osmium::item_type::relation:
            // not yet supported, but who knows what the future holds...
            break;
        default:
            // shouldn't ever happen
            break;
        }
    }
    return boost::make_optional(std::move(restriction_container));
}
示例#30
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(osmium::Relation const &rel)
{
    taglist_t prefiltered_tags;
    if (m_tagtransform->filter_tags(rel, nullptr, nullptr, prefiltered_tags)) {
        return 1;
    }

    idlist_t xid2;
    for (auto const &m : rel.members()) {
        /* Need to handle more than just ways... */
        if (m.type() == osmium::item_type::way) {
            xid2.push_back(m.ref());
        }
    }

    buffer.clear();
    rolelist_t xrole;
    auto num_ways = m_mid->rel_way_members_get(rel, &xrole, buffer);

    if (num_ways == 0)
        return 0;

  int roads = 0;
  int make_polygon = 0;
  int make_boundary = 0;
  taglist_t outtags;

  // If it's 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(prefiltered_tags, buffer, xrole,
                                             &make_boundary, &make_polygon,
                                             &roads, outtags)) {
      return 0;
  }

  for (auto &w : buffer.select<osmium::Way>()) {
      m_mid->nodes_get_list(&(w.nodes()));
  }

  // linear features and boundaries
  // Needs to be done before the polygon treatment below because
  // for boundaries the way_area tag may be added.
  if (!make_polygon) {
      double const split_at = m_options.projection->target_latlon() ? 1 : 100 * 1000;
      auto wkbs = m_builder.get_wkb_multiline(buffer, split_at);
      for (auto const &wkb : wkbs) {
          expire.from_wkb(wkb.c_str(), -rel.id());
          m_tables[t_line]->write_row(-rel.id(), outtags, wkb);
          if (roads)
              m_tables[t_roads]->write_row(-rel.id(), outtags, wkb);
      }
  }

  // multipolygons and boundaries
  if (make_boundary || make_polygon) {
      auto wkbs = m_builder.get_wkb_multipolygon(rel, buffer);

      char tmp[32];
      for (auto const &wkb : wkbs) {
          expire.from_wkb(wkb.c_str(), -rel.id());
          if (m_enable_way_area) {
              auto const area =
                  m_options.reproject_area
                      ? ewkb::parser_t(wkb).get_area<reprojection>(
                            m_options.projection.get())
                      : ewkb::parser_t(wkb)
                            .get_area<osmium::geom::IdentityProjection>();
              snprintf(tmp, sizeof(tmp), "%g", area);
              outtags.push_override(tag_t("way_area", tmp));
          }
          m_tables[t_poly]->write_row(-rel.id(), outtags, wkb);
      }
  }

  return 0;
}