4

I'm parsing the mayotte pbf with osmium, and my handler is looking for ways. When I find one I process its barycentre and print it. The issue I ran into is that all of the ways I process have invalid location. And if print the location I get undefined for both latitude and longitude.

Is there an issue with my PBF file, or with my understanding of the osmium library?

Here is a mcve:

/**
 * To compile this script, you should first install `libosmium` and its
 * dependencies. Then:
 *   g++ -std=c++11 -lz -lexpat -lbz2 mcve.cpp -o mcve
 */
#include <iostream>

#include <osmium/handler.hpp>
#include <osmium/io/any_input.hpp>
#include <osmium/osm/node.hpp>
#include <osmium/osm/way.hpp>
#include <osmium/visitor.hpp>

class ParkingAndCarpoolingAreasHandler : public osmium::handler::Handler {
public:
    void way(const osmium::Way& way) {
      double lng;
      double lat;
      double count = 0.0;
      for (const osmium::NodeRef& nr : way.nodes()) {
          if (!nr.location().valid()) {
            std::cerr << "Way (id=" << way.id()
                      << " version=" << way.version()
                      << " timestamp=" << way.timestamp()
                      << " visible=" << (way.visible() ? "true" : "false")
                      << " changeset=" << way.changeset()
                      << " uid=" << way.uid()
                      << " user=" << way.user() << ")\n";
            std::cerr << "NodeRef (ref=" << nr.ref() << " location=" << nr.location() << ")\n";
            std::cerr << std::endl;
            return;
          }
          count++;
          lng += nr.location().lon();
          lat += nr.location().lat();
      }
      lng /= count;
      lat /= count;
      std::cout << "POINT(" << lat << ' ' << lng << ")\n";
    }
};

int main() {
    auto otypes = osmium::osm_entity_bits::node | osmium::osm_entity_bits::way;
    osmium::io::Reader reader{"tmp/mayotte-latest.osm.pbf", otypes};
    ParkingAndCarpoolingAreasHandler handler;
    osmium::apply(reader, handler);
    reader.close();
}
Ulysse BN
  • 10,116
  • 7
  • 54
  • 82

1 Answers1

3

In OSM a way typically stores only references to the node it consists of. These references just contain the node ID but no additional information (such as coordinates and tags). To obtain node coordinates you have to look at the actual nodes, not just at their reference.

See OSM XML and PBF Format for more information.

Since I have no experience with osmium I can't tell you how to retrieve the corresponding nodes by their IDs. However according to the Osmium Concepts Manual you can use a NodeLocationsForWays handler to populate your NodeRef objects with locations. examples/osmium_road_length.cpp contains an example.

scai
  • 20,297
  • 4
  • 56
  • 72
  • Thank you, I noticed that as well during my tests. But then I really wonder about the usage of `node_ref.location()` (See example from the doc: https://osmcode.org/libosmium/manual.html#ways). – Ulysse BN Apr 17 '19 at 08:39
  • See my updated answer, looks like you will need a `NodeLocationsForWays` handler. – scai Apr 17 '19 at 08:42
  • 1
    With your advices I even came accross [examples/osmium_location_cache_create](https://github.com/osmcode/libosmium/blob/master/examples/osmium_location_cache_create.cpp) and [examples/osmium_location_cache_use.cpp](https://github.com/osmcode/libosmium/blob/master/examples/osmium_location_cache_use.cpp). It looks like this is exactly what I need! – Ulysse BN Apr 17 '19 at 09:00