NOTICE: help.openstreetmap.org is no longer in use from 1st March 2024. Please use the OpenStreetMap Community Forum

Given a city name, I'm trying to extract all nodes and ways that are located inside this city. But instead of a polygon shaped region, I want all elements inside the bounding box that surrounds this polygon shaped city region.

I checked out Osmium-tool, but it only provides two functionalities:

  • tags-filter: extract data filtered by tags (i.e. city name)
  • extract: extract data given bounding box coordinates

The first only returns the data inside the polygon shaped region and the second requires bounding box coordinates.

So is there a lib or a tool to extract that data or at least finds bounding box coordinates for a given city?

Thanks in advance!

asked 16 Dec '21, 10:32

PoRouS's gravatar image

PoRouS
11112
accept rate: 0%


Thank you both for the very fast answers!

@SimonPoole Yes, given the coordinates of the polygon nodes would make it easy to calculate a bounding box. But osmium tags-filter just filters and extracts the nodes into a file, so I don't have direct access to the coordinates, only afterwards. I was hoping that there is a functionality that handles that for me.

@Jochen Topf If I filter the country map for the city relation, then the bounding box of the resulting OSM file still contains the values of the whole country and not that of the extracted relation.

So probably I can solve it that way:
- use libosmium to filter the data for the relation of the city
- extract all nodes of that relation
- determine min and max longitude and latitude coordinates to determine city bounding box
- use osmium-tool to extract the data within this bounding box

But unfortunately, I'm struggling to access the nodes of a relation in libosmium. I hope you can give me a hint.
I'm trying to use the following handler for that, but I'm stuck here:

class NamesHandler : public osmium::handler::Handler {
public:
static void relation(const osmium::Relation& relation)
{
    osmium::TagsFilter filter { false };
    filter.add_rule(true, "name", "Friedrichshafen");
    if (!osmium::tags::match_any_of(relation.tags(), filter))
        return;

    for (const auto& member : relation.members()) {
        const auto& object = member.get_object();
        if (!object.is_compatible_to(osmium::item_type::node))
            continue;

        // TODO: convert osmium::OSMObject to osmium::Node to access the location function
    }
}
};

int main()
{
    NamesHandler names_handler;
    osmium::io::Reader reader { "input.pbf", osmium::osm_entity_bits::relation };
    osmium::apply(reader, names_handler);

}

permanent link

answered 17 Dec '21, 11:04

PoRouS's gravatar image

PoRouS
11112
accept rate: 0%

edited 17 Dec '21, 12:37

You can use osmium getid -r to get everything belonging to a relation out of an OSM file. You can use a link like https://www.openstreetmap.org/api/0.6/relation/65606/full (here for the London relation) to get that data from the API. There are so many different ways of doing these things depening on what exactly you want to do that this goes beyond what can be answered here in a simple way.

(17 Dec '21, 12:57) Jochen Topf

Thanks again for the hint.

I found another way using libosmium to find the nodes for a specified relation. My code is based on this example: https://github.com/osmcode/libosmium/blob/master/examples/osmium_area_test.cpp

I adapted the area callback to the following to gather the bounding box:

static void area(const osmium::Area& area)
{
    double lonMin = 180;
    double lonMax = -180;
    double latMin = 90;
    double latMax = -90;
    for (auto oit = area.cbegin<osmium::OuterRing>(); oit != area.cend<osmium::OuterRing>(); ++oit) {
        const osmium::NodeRefList& nodes = *oit;
        for (const auto& node : nodes) {
            lonMin = std::min(lonMin, node.lon());
            lonMax = std::max(lonMax, node.lon());
            latMin = std::min(latMin, node.lat());
            latMax = std::max(latMax, node.lat());
        }
    }

    std::cout << "Bounding box:\n";
    std::cout << "(" << lonMin << "," << latMin << "," << lonMax << "," << latMax << ")\n";
}

For the germany map this query takes pretty long, so I reduced the map beforehand with osmium-tool by filtering out relations that I need:

osmium tags-filter germany-latest.osm.pbf wr/boundary=administrative -o germany_filtered.pbf --overwrite
(20 Dec '21, 09:33) PoRouS

Determining a bounding box for a polygon is kind of trivial. If you have the polygon in any kind of textual representation it should only take minutes in your favorite scripting language to determine the required values.

So the problem is more finding the polygon data for the specific city, in many countries you should be able to get that from OSM itself, in other places you might need to use 3rd party sources or simply draw a bounding box yourself.

permanent link

answered 16 Dec '21, 18:48

SimonPoole's gravatar image

SimonPoole ♦
44.7k13326701
accept rate: 18%

osmium fileinfo will also give you the bounding box of an OSM file. So if you have a relation for your city, Osmium can help you.

(16 Dec '21, 18:55) Jochen Topf

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Question tags:

×66
×38

question asked: 16 Dec '21, 10:32

question was seen: 2,582 times

last updated: 20 Dec '21, 10:26

NOTICE: help.openstreetmap.org is no longer in use from 1st March 2024. Please use the OpenStreetMap Community Forum