Skip to content

Commit b53915c

Browse files
committed
Fully implement envelope() function for all geometry types
And implement them as independent functions so we can call them individually if needed.
1 parent c81716a commit b53915c

3 files changed

Lines changed: 111 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: 10 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; }
@@ -69,6 +70,15 @@ class box_t
6970

7071
}; // class box_t
7172

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+
7282
/**
7383
* Calculate the envelope of a geometry.
7484
*/

tests/test-geom-box.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ TEST_CASE("Extend box_t with points", "[NoDB]")
3939
REQUIRE(box.max() == geom::point_t{3.0, 2.0});
4040
}
4141

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));
56+
}
57+
4258
TEST_CASE("Extend box_t with linestring", "[NoDB]")
4359
{
4460
geom::box_t box;
@@ -81,6 +97,18 @@ TEST_CASE("Calculate envelope of polygon geometry")
8197
REQUIRE(geom::envelope(geom) == geom::box_t{0.0, 0.0, 1.0, 1.0});
8298
}
8399

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+
84112
TEST_CASE("Calculate envelope of multilinestring geometry")
85113
{
86114
geom::geometry_t geom{geom::multilinestring_t{}};
@@ -106,3 +134,16 @@ TEST_CASE("Calculate envelope of multipolygon geometry")
106134

107135
REQUIRE(geom::envelope(geom) == geom::box_t{1.1, 1.1, 4.4, 3.3});
108136
}
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)