Skip to content

Commit b29e6ab

Browse files
authored
Merge pull request #1779 from joto/area-for-collection
Area function for collection and switch to using boost::geometry
2 parents 6c132c6 + 6327a63 commit b29e6ab

2 files changed

Lines changed: 28 additions & 40 deletions

File tree

src/geom-functions.cpp

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <algorithm>
1414
#include <cmath>
1515
#include <iterator>
16+
#include <numeric>
1617
#include <tuple>
1718
#include <utility>
1819

@@ -334,48 +335,19 @@ geometry_t segmentize(geometry_t const &input, double max_segment_length)
334335
return output;
335336
}
336337

337-
static double get_ring_area(ring_t const &ring) noexcept
338-
{
339-
assert(ring.size() > 3);
340-
341-
double total = 0.0;
342-
auto it = ring.begin();
343-
auto prev = *it++;
344-
345-
while (it != ring.end()) {
346-
auto const cur = *it;
347-
total += prev.x() * cur.y() - cur.x() * prev.y();
348-
prev = cur;
349-
++it;
350-
}
351-
352-
return total;
353-
}
354-
355-
static double get_polygon_area(polygon_t const &polygon)
356-
{
357-
double total = get_ring_area(polygon.outer());
358-
359-
for (auto const &ring : polygon.inners()) {
360-
total += get_ring_area(ring);
361-
}
362-
363-
return total * 0.5;
364-
}
365-
366338
double area(geometry_t const &geom)
367339
{
368-
double total = 0.0;
369-
370-
if (geom.is_polygon()) {
371-
total = get_polygon_area(geom.get<polygon_t>());
372-
} else if (geom.is_multipolygon()) {
373-
for (auto const &polygon : geom.get<multipolygon_t>()) {
374-
total += get_polygon_area(polygon);
375-
}
376-
}
377-
378-
return std::abs(total);
340+
return std::abs(geom.visit(
341+
overloaded{[&](geom::nullgeom_t const & /*input*/) { return 0.0; },
342+
[&](geom::collection_t const &input) {
343+
return std::accumulate(input.cbegin(), input.cend(), 0.0,
344+
[](double sum, auto const &geom) {
345+
return sum + area(geom);
346+
});
347+
},
348+
[&](auto const &input) {
349+
return static_cast<double>(boost::geometry::area(input));
350+
}}));
379351
}
380352

381353
double length(geometry_t const &geom)

tests/test-geom-collections.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,22 @@ TEST_CASE("geometry collection with several geometries", "[NoDB]")
7272
REQUIRE(geometry_n(geom, 3) == geom::geometry_t{geom::point_t{2, 2}});
7373
}
7474

75+
TEST_CASE("geometry collection with polygon", "[NoDB]")
76+
{
77+
geom::geometry_t geom{geom::collection_t{}};
78+
auto &c = geom.get<geom::collection_t>();
79+
80+
c.add_geometry(geom::geometry_t{geom::point_t{1, 1}});
81+
c.add_geometry(geom::geometry_t{
82+
geom::polygon_t{geom::ring_t{{1, 1}, {1, 2}, {2, 2}, {2, 1}, {1, 1}}}});
83+
84+
REQUIRE(geometry_type(geom) == "GEOMETRYCOLLECTION");
85+
REQUIRE(num_geometries(geom) == 2);
86+
REQUIRE(area(geom) == Approx(1.0));
87+
REQUIRE(length(geom) == Approx(0.0));
88+
REQUIRE(centroid(geom) == geom::geometry_t{geom::point_t{1.5, 1.5}});
89+
}
90+
7591
TEST_CASE("create_collection from OSM data", "[NoDB]")
7692
{
7793
test_buffer_t buffer;

0 commit comments

Comments
 (0)