Add and test box_t class and envelope(geom) function
parent
81954f0333
commit
27ae4652af
|
@ -8,6 +8,7 @@ target_sources(osm2pgsql_lib PRIVATE
|
|||
expire-tiles.cpp
|
||||
gazetteer-style.cpp
|
||||
geom.cpp
|
||||
geom-box.cpp
|
||||
geom-from-osm.cpp
|
||||
geom-functions.cpp
|
||||
input.cpp
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/**
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* This file is part of osm2pgsql (https://osm2pgsql.org/).
|
||||
*
|
||||
* Copyright (C) 2006-2022 by the osm2pgsql developer community.
|
||||
* For a full list of authors see the git log.
|
||||
*/
|
||||
|
||||
#include "geom-box.hpp"
|
||||
|
||||
namespace geom {
|
||||
|
||||
box_t &box_t::extend(point_t const &point) noexcept
|
||||
{
|
||||
if (point.x() < m_min_x) {
|
||||
m_min_x = point.x();
|
||||
}
|
||||
if (point.y() < m_min_y) {
|
||||
m_min_y = point.y();
|
||||
}
|
||||
if (point.x() > m_max_x) {
|
||||
m_max_x = point.x();
|
||||
}
|
||||
if (point.y() > m_max_y) {
|
||||
m_max_y = point.y();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void box_t::extend(point_list_t const &list) noexcept
|
||||
{
|
||||
for (auto const &point : list) {
|
||||
extend(point);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class envelope_visitor
|
||||
{
|
||||
public:
|
||||
box_t operator()(geom::nullgeom_t const & /*geom*/) const
|
||||
{
|
||||
return box_t{};
|
||||
}
|
||||
|
||||
box_t operator()(geom::point_t const &geom) const
|
||||
{
|
||||
box_t box;
|
||||
box.extend(geom);
|
||||
return box;
|
||||
}
|
||||
|
||||
box_t operator()(geom::linestring_t const &geom) const
|
||||
{
|
||||
box_t box;
|
||||
box.extend(geom);
|
||||
return box;
|
||||
}
|
||||
|
||||
box_t operator()(geom::polygon_t const &geom) const
|
||||
{
|
||||
box_t box;
|
||||
box.extend(geom.outer());
|
||||
return box;
|
||||
}
|
||||
|
||||
box_t operator()(geom::multipoint_t const & /*geom*/) const
|
||||
{
|
||||
assert(false);
|
||||
return {}; // XXX not implemented
|
||||
}
|
||||
|
||||
box_t operator()(geom::multilinestring_t const &geom) const
|
||||
{
|
||||
box_t box;
|
||||
|
||||
for (auto const &line : geom) {
|
||||
box.extend(line);
|
||||
}
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
box_t operator()(geom::multipolygon_t const &geom) const
|
||||
{
|
||||
box_t box;
|
||||
|
||||
for (auto const &polygon : geom) {
|
||||
box.extend(polygon.outer());
|
||||
}
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
box_t operator()(geom::collection_t const & /*geom*/) const
|
||||
{
|
||||
assert(false);
|
||||
return {}; // XXX not implemented
|
||||
}
|
||||
}; // class envelope_visitor
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
box_t envelope(geometry_t const &geom)
|
||||
{
|
||||
return geom.visit(envelope_visitor{});
|
||||
}
|
||||
|
||||
} // namespace geom
|
|
@ -0,0 +1,76 @@
|
|||
#ifndef OSM2PGSQL_GEOM_BOX_HPP
|
||||
#define OSM2PGSQL_GEOM_BOX_HPP
|
||||
|
||||
/**
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* This file is part of osm2pgsql (https://osm2pgsql.org/).
|
||||
*
|
||||
* Copyright (C) 2006-2022 by the osm2pgsql developer community.
|
||||
* For a full list of authors see the git log.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Class and functions for creating bounding boxes of geometries.
|
||||
*/
|
||||
|
||||
#include "geom.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
namespace geom {
|
||||
|
||||
class box_t
|
||||
{
|
||||
public:
|
||||
constexpr box_t() noexcept = default;
|
||||
|
||||
constexpr box_t(double min_x, double min_y, double max_x,
|
||||
double max_y) noexcept
|
||||
: m_min_x(min_x), m_min_y(min_y), m_max_x(max_x), m_max_y(max_y)
|
||||
{
|
||||
assert(min_x <= max_x);
|
||||
assert(min_y <= max_y);
|
||||
}
|
||||
|
||||
box_t &extend(point_t const &point) noexcept;
|
||||
void extend(point_list_t const &list) noexcept;
|
||||
|
||||
constexpr double min_x() const noexcept { return m_min_x; }
|
||||
constexpr double min_y() const noexcept { return m_min_y; }
|
||||
constexpr double max_x() const noexcept { return m_max_x; }
|
||||
constexpr double max_y() const noexcept { return m_max_y; }
|
||||
|
||||
constexpr double width() const noexcept { return m_max_x - m_min_x; }
|
||||
constexpr double height() const noexcept { return m_max_y - m_min_y; }
|
||||
|
||||
constexpr friend bool operator==(box_t const &a, box_t const &b)
|
||||
{
|
||||
return a.min_x() == b.min_x() && a.min_y() == b.min_y() &&
|
||||
a.max_x() == b.max_x() && a.max_y() == b.max_y();
|
||||
}
|
||||
|
||||
constexpr friend bool operator!=(box_t const &a, box_t const &b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
private:
|
||||
double m_min_x = std::numeric_limits<double>::max();
|
||||
double m_min_y = std::numeric_limits<double>::max();
|
||||
double m_max_x = std::numeric_limits<double>::lowest();
|
||||
double m_max_y = std::numeric_limits<double>::lowest();
|
||||
|
||||
}; // class box_t
|
||||
|
||||
/**
|
||||
* Calculate the envelope of a geometry.
|
||||
*/
|
||||
box_t envelope(geometry_t const &geom);
|
||||
|
||||
} // namespace geom
|
||||
|
||||
#endif // OSM2PGSQL_GEOM_BOX_HPP
|
|
@ -43,6 +43,7 @@ set_test(test-db-copy-mgr)
|
|||
set_test(test-domain-matcher LABELS NoDB)
|
||||
set_test(test-expire-tiles LABELS NoDB)
|
||||
set_test(test-geom LABELS NoDB)
|
||||
set_test(test-geom-box LABELS NoDB)
|
||||
set_test(test-middle)
|
||||
set_test(test-node-locations LABELS NoDB)
|
||||
set_test(test-options-database LABELS NoDB)
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* This file is part of osm2pgsql (https://osm2pgsql.org/).
|
||||
*
|
||||
* Copyright (C) 2006-2022 by the osm2pgsql developer community.
|
||||
* For a full list of authors see the git log.
|
||||
*/
|
||||
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "geom-box.hpp"
|
||||
|
||||
TEST_CASE("Extend box_t with points", "[NoDB]")
|
||||
{
|
||||
geom::box_t box;
|
||||
|
||||
box.extend(geom::point_t{1.0, 2.0});
|
||||
|
||||
REQUIRE(box.min_x() == Approx(1.0));
|
||||
REQUIRE(box.max_x() == Approx(1.0));
|
||||
REQUIRE(box.min_y() == Approx(2.0));
|
||||
REQUIRE(box.max_y() == Approx(2.0));
|
||||
|
||||
REQUIRE(box.width() == Approx(0.0));
|
||||
REQUIRE(box.height() == Approx(0.0));
|
||||
|
||||
box.extend(geom::point_t{3.0, -2.0});
|
||||
|
||||
REQUIRE(box.min_x() == Approx(1.0));
|
||||
REQUIRE(box.max_x() == Approx(3.0));
|
||||
REQUIRE(box.min_y() == Approx(-2.0));
|
||||
REQUIRE(box.max_y() == Approx(2.0));
|
||||
|
||||
REQUIRE(box.width() == Approx(2.0));
|
||||
REQUIRE(box.height() == Approx(4.0));
|
||||
}
|
||||
|
||||
TEST_CASE("Extend box_t with linestring", "[NoDB]")
|
||||
{
|
||||
geom::box_t box;
|
||||
|
||||
geom::linestring_t const ls{{1.0, 2.0}, {2.0, 2.0}, {-5.0, 3.0}};
|
||||
|
||||
box.extend(ls);
|
||||
|
||||
REQUIRE(box.min_x() == Approx(-5.0));
|
||||
REQUIRE(box.max_x() == Approx(2.0));
|
||||
REQUIRE(box.min_y() == Approx(2.0));
|
||||
REQUIRE(box.max_y() == Approx(3.0));
|
||||
|
||||
REQUIRE(box.width() == Approx(7.0));
|
||||
REQUIRE(box.height() == Approx(1.0));
|
||||
}
|
||||
|
||||
TEST_CASE("Calculate envelope of null geometry")
|
||||
{
|
||||
geom::geometry_t const geom{};
|
||||
REQUIRE(geom::envelope(geom) == geom::box_t{});
|
||||
}
|
||||
|
||||
TEST_CASE("Calculate envelope of point geometry")
|
||||
{
|
||||
geom::geometry_t const geom{geom::point_t{2.3, 1.4}};
|
||||
REQUIRE(geom::envelope(geom) == geom::box_t{2.3, 1.4, 2.3, 1.4});
|
||||
}
|
||||
|
||||
TEST_CASE("Calculate envelope of linestring geometry")
|
||||
{
|
||||
geom::geometry_t const geom{geom::linestring_t{{2.3, 1.4}, {2.5, 1.0}}};
|
||||
REQUIRE(geom::envelope(geom) == geom::box_t{2.3, 1.0, 2.5, 1.4});
|
||||
}
|
||||
|
||||
TEST_CASE("Calculate envelope of polygon geometry")
|
||||
{
|
||||
geom::geometry_t const geom{geom::polygon_t{geom::ring_t{
|
||||
{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}}}};
|
||||
REQUIRE(geom::envelope(geom) == geom::box_t{0.0, 0.0, 1.0, 1.0});
|
||||
}
|
||||
|
||||
TEST_CASE("Calculate envelope of multilinestring geometry")
|
||||
{
|
||||
geom::geometry_t geom{geom::multilinestring_t{}};
|
||||
|
||||
auto &mls = geom.get<geom::multilinestring_t>();
|
||||
|
||||
mls.add_geometry(geom::linestring_t{{2.3, 1.4}, {2.5, 1.0}});
|
||||
mls.add_geometry(geom::linestring_t{{7.3, 0.4}, {2.4, 1.8}});
|
||||
|
||||
REQUIRE(geom::envelope(geom) == geom::box_t{2.3, 0.4, 7.3, 1.8});
|
||||
}
|
||||
|
||||
TEST_CASE("Calculate envelope of multipolygon geometry")
|
||||
{
|
||||
geom::geometry_t geom{geom::multipolygon_t{}};
|
||||
|
||||
auto &mp = geom.get<geom::multipolygon_t>();
|
||||
|
||||
mp.add_geometry(geom::polygon_t{geom::ring_t{
|
||||
{1.1, 1.1}, {1.1, 3.3}, {2.2, 3.3}, {2.2, 1.1}, {1.1, 1.1}}});
|
||||
mp.add_geometry(geom::polygon_t{geom::ring_t{
|
||||
{2.2, 2.2}, {2.2, 3.3}, {4.4, 3.3}, {4.4, 2.2}, {2.2, 2.2}}});
|
||||
|
||||
REQUIRE(geom::envelope(geom) == geom::box_t{1.1, 1.1, 4.4, 3.3});
|
||||
}
|
Loading…
Reference in New Issue