/** * 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()) ); }
/** * 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(); }
/** * 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; }
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; }
void update(const osmium::Location& location) { update_int32(location.x()); update_int32(location.y()); }
constexpr explicit vec(const osmium::Location& l) noexcept : x(l.x()), y(l.y()) { }
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()); } }
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()); }
inline size_t hash(const osmium::Location& location) noexcept { return location.x() ^ location.y(); }
/** * Get internal x value of the location in this NodeRef. */ constexpr int32_t x() const noexcept { return m_location.x(); }