c++openstreetmaposmium

Way containing NodeRefs with invalid location


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

Solution

  • 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.