Пример #1
0
 /**
  * Check whether the location is inside the box.
  *
  * @pre Location must be defined.
  * @pre Box must be defined.
  */
 bool contains(const osmium::Location& location) const noexcept {
     assert(bottom_left());
     assert(top_right());
     assert(location);
     return location.x() >= bottom_left().x() && location.y() >= bottom_left().y() &&
            location.x() <= top_right().x() && location.y() <= top_right().y();
 }
Пример #2
0
 /**
  * Create box from bottom left and top right locations.
  *
  * @pre Either both locations must be defined or neither.
  * @pre If both locations are defined, the
  *      bottom left location must actually be to the left and below
  *      the top right location. Same coordinates for bottom/top or
  *      left/right are also okay.
  */
 Box(const osmium::Location& bottom_left, const osmium::Location& top_right) :
     m_bottom_left(bottom_left),
     m_top_right(top_right) {
     assert(
         (!!bottom_left && !!top_right) ||
         (bottom_left.x() <= top_right.x() && bottom_left.y() <= top_right.y())
     );
 }
Пример #3
0
            Coordinates operator()(osmium::Location location) const {
                Coordinates c {location.lon(), location.lat()};

                if (m_epsg != 4326) {
                    c = transform(m_crs_wgs84, m_crs_user, Coordinates(deg_to_rad(location.lon()), deg_to_rad(location.lat())));
                    if (m_crs_user.is_latlong()) {
                        c.x = rad_to_deg(c.x);
                        c.y = rad_to_deg(c.y);
                    }
                }

                return c;
            }
Пример #4
0
 /**
  * Create a tile with the given zoom level that contains the given
  * location.
  *
  * The values are not checked for validity.
  *
  * @pre @code location.valid() && zoom <= 30 @endcode
  */
 explicit Tile(uint32_t zoom, const osmium::Location& location) :
     z(zoom) {
     assert(zoom <= 30u);
     assert(location.valid());
     const auto coordinates = lonlat_to_mercator(location);
     x = mercx_to_tilex(zoom, coordinates.x);
     y = mercy_to_tiley(zoom, coordinates.y);
 }
Пример #5
0
 void write_location(const osmium::Location& location, const char x, const char y) {
     if (location) {
         output_formatted(" %c%.7f %c%.7f", x, location.lon_without_check(), y, location.lat_without_check());
     } else {
         *m_out += ' ';
         *m_out += x;
         *m_out += ' ';
         *m_out += y;
     }
 }
Пример #6
0
 /**
  * Create a tile with the given zoom level that contains the given
  * location.
  *
  * The values are not checked for validity.
  *
  * @pre @code location.valid() && zoom <= 30 @endcode
  */
 explicit Tile(uint32_t zoom, const osmium::Location& location) :
     z(zoom) {
     assert(zoom <= 30u);
     assert(location.valid());
     const osmium::geom::Coordinates c = lonlat_to_mercator(location);
     const int32_t n = 1 << zoom;
     const double scale = detail::max_coordinate_epsg3857 * 2 / n;
     x = uint32_t(detail::restrict_to_range<int32_t>(int32_t((c.x + detail::max_coordinate_epsg3857) / scale), 0, n-1));
     y = uint32_t(detail::restrict_to_range<int32_t>(int32_t((detail::max_coordinate_epsg3857 - c.y) / scale), 0, n-1));
 }
Пример #7
0
                bool to_left_of(const osmium::Location& location) const {
    //                std::cerr << "segment " << first() << "--" << second() << " to_left_of(" << location << "\n";

                    if (first().location() == location || second().location() == location) {
                        return false;
                    }

                    const std::pair<osmium::Location, osmium::Location> mm = std::minmax(first().location(), second().location(), [](const osmium::Location a, const osmium::Location b) {
                        return a.y() < b.y();
                    });

                    if (mm.first.y() >= location.y() || mm.second.y() < location.y() || first().location().x() > location.x()) {
    //                    std::cerr << "  false\n";
                        return false;
                    }

                    int64_t ax = mm.first.x();
                    int64_t bx = mm.second.x();
                    int64_t lx = location.x();
                    int64_t ay = mm.first.y();
                    int64_t by = mm.second.y();
                    int64_t ly = location.y();
                    return ((bx - ax)*(ly - ay) - (by - ay)*(lx - ax)) <= 0;
                }
Пример #8
0
 /**
  * Extend the bounding box by the given location. If the
  * location is undefined, the bounding box is unchanged.
  */
 Bounds& extend(const Location& location) noexcept {
     if (location) {
         if (m_bottom_left) {
             if (location.x() < m_bottom_left.x()) {
                 m_bottom_left.x(location.x());
             }
             if (location.x() > m_top_right.x()) {
                 m_top_right.x(location.x());
             }
             if (location.y() < m_bottom_left.y()) {
                 m_bottom_left.y(location.y());
             }
             if (location.y() > m_top_right.y()) {
                 m_top_right.y(location.y());
             }
         } else {
             m_bottom_left = location;
             m_top_right = location;
         }
     }
     return *this;
 }
Пример #9
0
 constexpr explicit vec(const osmium::Location& l) noexcept :
     x(l.x()),
     y(l.y()) {
 }
Пример #10
0
#include "catch.hpp"

#include <sstream>
#include <type_traits>

#include <osmium/osm/location.hpp>

TEST_CASE("Location") {

// fails on MSVC and doesn't really matter
// static_assert(std::is_literal_type<osmium::Location>::value, "osmium::Location not literal type");

    SECTION("instantiation_with_default_parameters") {
        osmium::Location loc;
        REQUIRE(!loc);
        REQUIRE_THROWS_AS(loc.lon(), osmium::invalid_location);
        REQUIRE_THROWS_AS(loc.lat(), osmium::invalid_location);
    }

    SECTION("instantiation_with_double_parameters") {
        osmium::Location loc1(1.2, 4.5);
        REQUIRE(!!loc1);
        REQUIRE(12000000 == loc1.x());
        REQUIRE(45000000 == loc1.y());
        REQUIRE(1.2 == loc1.lon());
        REQUIRE(4.5 == loc1.lat());

        osmium::Location loc2(loc1);
        REQUIRE(4.5 == loc2.lat());

        osmium::Location loc3 = loc1;
Пример #11
0
 void write_location(const osmium::Location& location, const char x, const char y) {
     *m_out += ' ';
     *m_out += x;
     if (location) {
         osmium::detail::append_location_coordinate_to_string(std::back_inserter(*m_out), location.x());
     }
     *m_out += ' ';
     *m_out += y;
     if (location) {
         osmium::detail::append_location_coordinate_to_string(std::back_inserter(*m_out), location.y());
     }
 }
Пример #12
0
 Coordinates(const osmium::Location& location) : x(location.lon()), y(location.lat()) {
 }
Пример #13
0
 inline size_t hash(const osmium::Location& location) noexcept {
     return location.x() ^ location.y();
 }
Пример #14
0
 inline size_t hash<8>(const osmium::Location& location) noexcept {
     uint64_t h = location.x();
     h <<= 32;
     return static_cast<size_t>(h ^ location.y());
 }
Пример #15
0
 void lon(double x) {
     m_location.lon(x);
 }
Пример #16
0
 /**
  * Get latitude of the location in this NodeRef.
  *
  * @throws osmium::invalid_location if the location is not set.
  */
 double lat() const {
     return m_location.lat();
 }
Пример #17
0
 /**
  * Calculate size of the box in square degrees.
  *
  * Note that this measure isn't very useful if you want to know the
  * real-world size of the bounding box!
  *
  * @throws osmium::invalid_location unless all coordinates are valid.
  */
 double size() const {
     return (m_top_right.lon() - m_bottom_left.lon()) *
            (m_top_right.lat() - m_bottom_left.lat());
 }
Пример #18
0
 void update(const osmium::Location& location) {
     update_int32(location.x());
     update_int32(location.y());
 }
Пример #19
0
#include "catch.hpp"

#include <osmium/osm/location.hpp>

#include <limits>
#include <sstream>
#include <type_traits>

// fails on MSVC and doesn't really matter
// static_assert(std::is_literal_type<osmium::Location>::value, "osmium::Location not literal type");

TEST_CASE("Location instantiation with default parameters") {
    const osmium::Location loc;
    REQUIRE_FALSE(loc);
    REQUIRE_FALSE(loc.is_defined());
    REQUIRE(loc.is_undefined());
    REQUIRE_THROWS_AS(loc.lon(), const osmium::invalid_location&);
    REQUIRE_THROWS_AS(loc.lat(), const osmium::invalid_location&);
}

TEST_CASE("Location instantiation with double parameters") {
    const osmium::Location loc1{1.2, 4.5};
    REQUIRE(bool(loc1));
    REQUIRE(loc1.is_defined());
    REQUIRE_FALSE(loc1.is_undefined());
    REQUIRE(12000000 == loc1.x());
    REQUIRE(45000000 == loc1.y());
    REQUIRE(1.2 == Approx(loc1.lon()));
    REQUIRE(4.5 == Approx(loc1.lat()));

    const osmium::Location loc2{loc1};
Пример #20
0
 /**
  * Get longitude of the location in this NodeRef.
  *
  * @throws osmium::invalid_location if the location is not set.
  */
 double lon() const {
     return m_location.lon();
 }
Пример #21
0
 /**
  * Get internal y value of the location in this NodeRef.
  */
 constexpr int32_t y() const noexcept {
     return m_location.y();
 }
Пример #22
0
 void lat(double y) {
     m_location.lat(y);
 }
 Coordinates operator()(osmium::Location location) const {
     return Coordinates {detail::lon_to_x(location.lon()), detail::lat_to_y(location.lat())};
 }
Пример #24
0
/**
 * Checks if there are intersections between any coastline segments.
 * Returns the number of intersections and overlaps.
 */
unsigned int CoastlineRingCollection::check_for_intersections(OutputDatabase& output, int segments_fd) {
    unsigned int overlaps = 0;

    std::vector<osmium::UndirectedSegment> segments;
    if (debug) std::cerr << "Setting up segments...\n";
    for (const auto& ring : m_list) {
        ring->add_segments_to_vector(segments);
    }

    if (debug) std::cerr << "Sorting...\n";
    std::sort(segments.begin(), segments.end());

    if (segments_fd >= 0) {
        if (debug) std::cerr << "Writing segments to file...\n";
        ssize_t length = segments.size() * sizeof(osmium::UndirectedSegment);
#ifndef _MSC_VER
        if (::write(segments_fd, segments.data(), length) != length) {
#else
        if (_write(segments_fd, segments.data(), length) != length) {
#endif
            throw std::runtime_error{"Write error"};
        }
    }

    if (debug) std::cerr << "Finding intersections...\n";
    std::vector<osmium::Location> intersections;
    for (auto it1 = segments.cbegin(); it1 != segments.cend()-1; ++it1) {
        const osmium::UndirectedSegment& s1 = *it1;
        for (auto it2 = it1+1; it2 != segments.cend(); ++it2) {
            const osmium::UndirectedSegment& s2 = *it2;
            if (s1 == s2) {
                std::unique_ptr<OGRLineString> line = create_ogr_linestring(s1);
                output.add_error_line(std::move(line), "overlap");
                overlaps++;
            } else {
                if (outside_x_range(s2, s1)) {
                    break;
                }
                if (y_range_overlap(s1, s2)) {
                    osmium::Location i = intersection(s1, s2);
                    if (i) {
                        intersections.push_back(i);
                    }
                }
            }
        }
    }

    for (const auto& intersection : intersections) {
        std::unique_ptr<OGRPoint> point{new OGRPoint(intersection.lon(), intersection.lat())};
        output.add_error_point(std::move(point), "intersection");
    }

    return intersections.size() + overlaps;
}

bool CoastlineRingCollection::close_antarctica_ring(int epsg) {
    for (const auto& ring : m_list) {
        const osmium::Location fpos = ring->first_position();
        const osmium::Location lpos = ring->last_position();
        if (fpos.lon() > 179.99 && lpos.lon() < -179.99 &&
            fpos.lat() <  -77.0 && fpos.lat() >  -78.0 &&
            lpos.lat() <  -77.0 && lpos.lat() >  -78.0) {

            m_end_nodes.erase(ring->last_node_id());
            m_start_nodes.erase(ring->first_node_id());
            ring->close_antarctica_ring(epsg);
            return true;
        }
    }
    return false;
}

void CoastlineRingCollection::close_rings(OutputDatabase& output, bool debug, double max_distance) {
    std::vector<Connection> connections;

    // Create vector with all possible combinations of connections between rings.
    for (idmap_type::iterator eit = m_end_nodes.begin(); eit != m_end_nodes.end(); ++eit) {
        for (idmap_type::iterator sit = m_start_nodes.begin(); sit != m_start_nodes.end(); ++sit) {
            const double distance = (*sit->second)->distance_to_start_position((*eit->second)->last_position());
            if (distance < max_distance) {
                connections.emplace_back(distance, eit->first, sit->first);
            }
        }
    }

    // Sort vector by distance, shortest at end.
    std::sort(connections.begin(), connections.end(), Connection::sort_by_distance);

    // Go through vector starting with the shortest connections and close rings
    // using the connections in turn.
    while (!connections.empty()) {
        Connection conn = connections.back();
        connections.pop_back();

        // Invalidate all other connections using one of the same end points.
        connections.erase(remove_if(connections.begin(), connections.end(), conn), connections.end());

        idmap_type::iterator eit = m_end_nodes.find(conn.start_id);
        idmap_type::iterator sit = m_start_nodes.find(conn.end_id);

        if (eit != m_end_nodes.end() && sit != m_start_nodes.end()) {
            if (debug) {
                std::cerr << "Closing ring between node " << conn.end_id << " and node " << conn.start_id << "\n";
            }

            m_fixed_rings++;

            CoastlineRing* e = eit->second->get();
            CoastlineRing* s = sit->second->get();

            output.add_error_point(e->ogr_last_point(), "fixed_end_point", e->last_node_id());
            output.add_error_point(s->ogr_first_point(), "fixed_end_point", s->first_node_id());

            if (e->last_position() != s->first_position()) {
                std::unique_ptr<OGRLineString> linestring{new OGRLineString};
                linestring->addPoint(e->last_position().lon(), e->last_position().lat());
                linestring->addPoint(s->first_position().lon(), s->first_position().lat());
                output.add_error_line(std::move(linestring), "added_line");
            }

            if (e == s) {
                // connect to itself by closing ring
                e->close_ring();

                m_end_nodes.erase(eit);
                m_start_nodes.erase(sit);
            } else {
                // connect to other ring
                e->join_over_gap(*s);

                m_list.erase(sit->second);
                if (e->first_position() == e->last_position()) {
                    output.add_error_point(e->ogr_first_point(), "double_node", e->first_node_id());
                    m_start_nodes.erase(e->first_node_id());
                    m_end_nodes.erase(eit);
                    m_start_nodes.erase(sit);
                    m_end_nodes.erase(e->last_node_id());
                    e->fake_close();
                } else {
                    m_end_nodes[e->last_node_id()] = eit->second;
                    m_end_nodes.erase(eit);
                    m_start_nodes.erase(sit);
                }
            }
        }
    }
}
Пример #25
0
 void add_location(const osmium::Location& location) {
     if (location.valid()) {
         m_dirty_tiles.emplace(m_zoom, location);
     }
 }
Пример #26
0
 Coordinates operator()(osmium::Location location) const {
     return Coordinates{location.lon(), location.lat()};
 }
Пример #27
0
 int32_t x() const noexcept {
     return m_location.x();
 }