Skip to content

Commit 846f3ae

Browse files
authored
Merge pull request #1805 from joto/box-envelope
Add functionality around box_t class and envelope()
2 parents ac51627 + b53915c commit 846f3ae

3 files changed

Lines changed: 117 additions & 53 deletions

File tree

src/geom-box.cpp

Lines changed: 60 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -36,77 +36,84 @@ void box_t::extend(point_list_t const &list) noexcept
3636
}
3737
}
3838

39-
namespace {
40-
41-
class envelope_visitor
39+
void box_t::extend(box_t const &box) noexcept
4240
{
43-
public:
44-
box_t operator()(geom::nullgeom_t const & /*geom*/) const
45-
{
46-
return box_t{};
47-
}
48-
49-
box_t operator()(geom::point_t const &geom) const
50-
{
51-
box_t box;
52-
box.extend(geom);
53-
return box;
41+
if (box.min_x() < m_min_x) {
42+
m_min_x = box.min_x();
5443
}
55-
56-
box_t operator()(geom::linestring_t const &geom) const
57-
{
58-
box_t box;
59-
box.extend(geom);
60-
return box;
44+
if (box.min_y() < m_min_y) {
45+
m_min_y = box.min_y();
6146
}
62-
63-
box_t operator()(geom::polygon_t const &geom) const
64-
{
65-
box_t box;
66-
box.extend(geom.outer());
67-
return box;
47+
if (box.max_x() > m_max_x) {
48+
m_max_x = box.max_x();
6849
}
69-
70-
box_t operator()(geom::multipoint_t const & /*geom*/) const
71-
{
72-
assert(false);
73-
return {}; // XXX not implemented
50+
if (box.max_y() > m_max_y) {
51+
m_max_y = box.max_y();
7452
}
53+
}
7554

76-
box_t operator()(geom::multilinestring_t const &geom) const
77-
{
78-
box_t box;
55+
box_t envelope(geom::nullgeom_t const & /*geom*/) { return box_t{}; }
7956

80-
for (auto const &line : geom) {
81-
box.extend(line);
82-
}
57+
box_t envelope(geom::point_t const &geom)
58+
{
59+
box_t box;
60+
box.extend(geom);
61+
return box;
62+
}
8363

84-
return box;
85-
}
64+
box_t envelope(geom::linestring_t const &geom)
65+
{
66+
box_t box;
67+
box.extend(geom);
68+
return box;
69+
}
8670

87-
box_t operator()(geom::multipolygon_t const &geom) const
88-
{
89-
box_t box;
71+
box_t envelope(geom::polygon_t const &geom)
72+
{
73+
box_t box;
74+
box.extend(geom.outer());
75+
return box;
76+
}
9077

91-
for (auto const &polygon : geom) {
92-
box.extend(polygon.outer());
93-
}
78+
box_t envelope(geom::multipoint_t const &geom)
79+
{
80+
box_t box;
81+
for (auto const &point : geom) {
82+
box.extend(point);
83+
}
84+
return box;
85+
}
9486

95-
return box;
87+
box_t envelope(geom::multilinestring_t const &geom)
88+
{
89+
box_t box;
90+
for (auto const &line : geom) {
91+
box.extend(line);
9692
}
93+
return box;
94+
}
9795

98-
box_t operator()(geom::collection_t const & /*geom*/) const
99-
{
100-
assert(false);
101-
return {}; // XXX not implemented
96+
box_t envelope(geom::multipolygon_t const &geom)
97+
{
98+
box_t box;
99+
for (auto const &polygon : geom) {
100+
box.extend(polygon.outer());
102101
}
103-
}; // class envelope_visitor
102+
return box;
103+
}
104104

105-
} // anonymous namespace
105+
box_t envelope(geom::collection_t const &geom)
106+
{
107+
box_t box;
108+
for (auto const &sgeom : geom) {
109+
box.extend(envelope(sgeom));
110+
}
111+
return box;
112+
}
106113

107114
box_t envelope(geometry_t const &geom)
108115
{
109-
return geom.visit(envelope_visitor{});
116+
return geom.visit([&](auto const &g) { return envelope(g); });
110117
}
111118

112119
} // namespace geom

src/geom-box.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class box_t
3838

3939
box_t &extend(point_t const &point) noexcept;
4040
void extend(point_list_t const &list) noexcept;
41+
void extend(box_t const &box) noexcept;
4142

4243
constexpr double min_x() const noexcept { return m_min_x; }
4344
constexpr double min_y() const noexcept { return m_min_y; }
@@ -47,6 +48,9 @@ class box_t
4748
constexpr double width() const noexcept { return m_max_x - m_min_x; }
4849
constexpr double height() const noexcept { return m_max_y - m_min_y; }
4950

51+
constexpr point_t min() const noexcept { return {m_min_x, m_min_y}; }
52+
constexpr point_t max() const noexcept { return {m_max_x, m_max_y}; }
53+
5054
constexpr friend bool operator==(box_t const &a, box_t const &b)
5155
{
5256
return a.min_x() == b.min_x() && a.min_y() == b.min_y() &&
@@ -66,6 +70,15 @@ class box_t
6670

6771
}; // class box_t
6872

73+
box_t envelope(geom::nullgeom_t const & /*geom*/);
74+
box_t envelope(geom::point_t const &geom);
75+
box_t envelope(geom::linestring_t const &geom);
76+
box_t envelope(geom::polygon_t const &geom);
77+
box_t envelope(geom::multipoint_t const &geom);
78+
box_t envelope(geom::multilinestring_t const &geom);
79+
box_t envelope(geom::multipolygon_t const &geom);
80+
box_t envelope(geom::collection_t const &geom);
81+
6982
/**
7083
* Calculate the envelope of a geometry.
7184
*/

tests/test-geom-box.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,25 @@ TEST_CASE("Extend box_t with points", "[NoDB]")
3434

3535
REQUIRE(box.width() == Approx(2.0));
3636
REQUIRE(box.height() == Approx(4.0));
37+
38+
REQUIRE(box.min() == geom::point_t{1.0, -2.0});
39+
REQUIRE(box.max() == geom::point_t{3.0, 2.0});
40+
}
41+
42+
TEST_CASE("Extend box_t with box_t", "[NoDB]")
43+
{
44+
geom::box_t box;
45+
box.extend(geom::box_t{1.0, 2.0, 3.0, 4.0});
46+
REQUIRE(box.min_x() == Approx(1.0));
47+
REQUIRE(box.max_x() == Approx(3.0));
48+
REQUIRE(box.min_y() == Approx(2.0));
49+
REQUIRE(box.max_y() == Approx(4.0));
50+
51+
box.extend(geom::box_t{-1.0, 2.0, 2.0, 5.0});
52+
REQUIRE(box.min_x() == Approx(-1.0));
53+
REQUIRE(box.max_x() == Approx(3.0));
54+
REQUIRE(box.min_y() == Approx(2.0));
55+
REQUIRE(box.max_y() == Approx(5.0));
3756
}
3857

3958
TEST_CASE("Extend box_t with linestring", "[NoDB]")
@@ -78,6 +97,18 @@ TEST_CASE("Calculate envelope of polygon geometry")
7897
REQUIRE(geom::envelope(geom) == geom::box_t{0.0, 0.0, 1.0, 1.0});
7998
}
8099

100+
TEST_CASE("Calculate envelope of multipoint geometry")
101+
{
102+
geom::geometry_t geom{geom::multipoint_t{}};
103+
104+
auto &mpt = geom.get<geom::multipoint_t>();
105+
106+
mpt.add_geometry({2.3, 1.4});
107+
mpt.add_geometry({7.3, 0.4});
108+
109+
REQUIRE(geom::envelope(geom) == geom::box_t{2.3, 0.4, 7.3, 1.4});
110+
}
111+
81112
TEST_CASE("Calculate envelope of multilinestring geometry")
82113
{
83114
geom::geometry_t geom{geom::multilinestring_t{}};
@@ -103,3 +134,16 @@ TEST_CASE("Calculate envelope of multipolygon geometry")
103134

104135
REQUIRE(geom::envelope(geom) == geom::box_t{1.1, 1.1, 4.4, 3.3});
105136
}
137+
138+
TEST_CASE("Calculate envelope of geometry collection")
139+
{
140+
geom::geometry_t geom{geom::collection_t{}};
141+
142+
auto &c = geom.get<geom::collection_t>();
143+
144+
c.add_geometry(geom::geometry_t{geom::point_t{2.1, 1.2}});
145+
c.add_geometry(geom::geometry_t{geom::polygon_t{geom::ring_t{
146+
{2.2, 2.2}, {2.2, 3.3}, {4.4, 3.3}, {4.4, 2.2}, {2.2, 2.2}}}});
147+
148+
REQUIRE(geom::envelope(geom) == geom::box_t{2.1, 1.2, 4.4, 3.3});
149+
}

0 commit comments

Comments
 (0)