Skip to content

Commit f0aac2b

Browse files
committed
Add n_points() member function to all geometry types
Returns the number of points in a geometry.
1 parent ee2f4b0 commit f0aac2b

10 files changed

Lines changed: 71 additions & 0 deletions

src/geom.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,25 @@ bool operator!=(polygon_t const &a, polygon_t const &b) noexcept
3030
return !(a == b);
3131
}
3232

33+
[[nodiscard]] std::size_t polygon_t::n_points() const
34+
{
35+
return m_outer.size() +
36+
std::accumulate(m_inners.cbegin(), m_inners.cend(), std::size_t{0},
37+
[](std::size_t sum, ring_t const &ring) {
38+
return sum + ring.size();
39+
});
40+
}
41+
42+
[[nodiscard]] std::size_t geometry_t::n_points() const
43+
{
44+
return visit([](auto const &input) { return input.n_points(); });
45+
}
46+
47+
std::size_t n_points(geometry_t const &geom)
48+
{
49+
return geom.visit([](auto const &input) { return input.n_points(); });
50+
}
51+
3352
std::size_t dimension(collection_t const &geom)
3453
{
3554
return std::accumulate(geom.cbegin(), geom.cend(), 0ULL,

src/geom.hpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <cassert>
2525
#include <cmath>
2626
#include <initializer_list>
27+
#include <numeric>
2728
#include <type_traits>
2829
#include <utility>
2930
#include <variant>
@@ -39,6 +40,11 @@ class nullgeom_t
3940
return 0;
4041
}
4142

43+
[[nodiscard]] constexpr static std::size_t n_points() noexcept
44+
{
45+
return 0;
46+
}
47+
4248
[[nodiscard]] constexpr friend bool operator==(nullgeom_t,
4349
nullgeom_t) noexcept
4450
{
@@ -69,6 +75,11 @@ class point_t
6975
return 1;
7076
}
7177

78+
[[nodiscard]] constexpr static std::size_t n_points() noexcept
79+
{
80+
return 1;
81+
}
82+
7283
[[nodiscard]] constexpr double x() const noexcept { return m_x; }
7384
[[nodiscard]] constexpr double y() const noexcept { return m_y; }
7485

@@ -148,6 +159,11 @@ class linestring_t : public point_list_t
148159
return 1;
149160
}
150161

162+
[[nodiscard]] std::size_t n_points() const noexcept
163+
{
164+
return size();
165+
}
166+
151167
}; // class linestring_t
152168

153169
class ring_t : public point_list_t
@@ -186,6 +202,8 @@ class polygon_t
186202

187203
friend bool operator!=(polygon_t const &a, polygon_t const &b) noexcept;
188204

205+
[[nodiscard]] std::size_t n_points() const;
206+
189207
private:
190208
ring_t m_outer;
191209
std::vector<ring_t> m_inners;
@@ -257,6 +275,15 @@ class multigeometry_t
257275

258276
void reserve(std::size_t size) { m_geometry.reserve(size); }
259277

278+
[[nodiscard]] std::size_t n_points() const
279+
{
280+
return std::accumulate(m_geometry.cbegin(), m_geometry.cend(),
281+
std::size_t{0},
282+
[](std::size_t sum, auto const &geom) {
283+
return sum + geom.n_points();
284+
});
285+
}
286+
260287
private:
261288
std::vector<GEOM> m_geometry;
262289

@@ -400,6 +427,8 @@ class geometry_t
400427
return !(a == b);
401428
}
402429

430+
[[nodiscard]] std::size_t n_points() const;
431+
403432
private:
404433
std::variant<nullgeom_t, point_t, linestring_t, polygon_t, multipoint_t,
405434
multilinestring_t, multipolygon_t, collection_t>

tests/test-geom-collections.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ TEST_CASE("geometry collection with point", "[NoDB]")
2424
c.add_geometry(geom::geometry_t{geom::point_t{1, 1}});
2525

2626
REQUIRE(geometry_type(geom) == "GEOMETRYCOLLECTION");
27+
REQUIRE(geom.n_points() == 1);
2728
REQUIRE(dimension(geom) == 0);
2829
REQUIRE(num_geometries(geom) == 1);
2930
REQUIRE(area(geom) == Approx(0.0));
@@ -46,6 +47,7 @@ TEST_CASE("geometry collection with multipoint", "[NoDB]")
4647
c.add_geometry(std::move(mpgeom));
4748

4849
REQUIRE(geometry_type(geom) == "GEOMETRYCOLLECTION");
50+
REQUIRE(geom.n_points() == 4);
4951
REQUIRE(dimension(geom) == 0);
5052
REQUIRE(num_geometries(geom) == 1);
5153
REQUIRE(area(geom) == Approx(0.0));
@@ -62,6 +64,7 @@ TEST_CASE("geometry collection with several geometries", "[NoDB]")
6264
c.add_geometry(geom::geometry_t{geom::point_t{2, 2}});
6365

6466
REQUIRE(geometry_type(geom) == "GEOMETRYCOLLECTION");
67+
REQUIRE(geom.n_points() == 4);
6568
REQUIRE(dimension(geom) == 1);
6669
REQUIRE(num_geometries(geom) == 3);
6770
REQUIRE(area(geom) == Approx(0.0));
@@ -83,6 +86,7 @@ TEST_CASE("geometry collection with polygon", "[NoDB]")
8386
geom::polygon_t{geom::ring_t{{1, 1}, {1, 2}, {2, 2}, {2, 1}, {1, 1}}}});
8487

8588
REQUIRE(geometry_type(geom) == "GEOMETRYCOLLECTION");
89+
REQUIRE(geom.n_points() == 6);
8690
REQUIRE(num_geometries(geom) == 2);
8791
REQUIRE(area(geom) == Approx(1.0));
8892
REQUIRE(length(geom) == Approx(0.0));
@@ -100,6 +104,7 @@ TEST_CASE("create_collection from OSM data", "[NoDB]")
100104
auto const geom = geom::create_collection(buffer.buffer());
101105

102106
REQUIRE(geometry_type(geom) == "GEOMETRYCOLLECTION");
107+
REQUIRE(geom.n_points() == 8);
103108
REQUIRE(dimension(geom) == 1);
104109
REQUIRE(num_geometries(geom) == 3);
105110

tests/test-geom-linestrings.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ TEST_CASE("line geometry", "[NoDB]")
5252
{
5353
geom::geometry_t const geom{geom::linestring_t{{1, 1}, {2, 2}}};
5454

55+
REQUIRE(geom.n_points() == 2);
5556
REQUIRE(dimension(geom) == 1);
5657
REQUIRE(num_geometries(geom) == 1);
5758
REQUIRE(area(geom) == Approx(0.0));

tests/test-geom-multilinestrings.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ TEST_CASE("create_multilinestring with single line", "[NoDB]")
3232

3333
REQUIRE(geom.is_multilinestring());
3434
REQUIRE(geometry_type(geom) == "MULTILINESTRING");
35+
REQUIRE(geom.n_points() == 2);
3536
REQUIRE(dimension(geom) == 1);
3637
REQUIRE(num_geometries(geom) == 1);
3738
REQUIRE(area(geom) == Approx(0.0));
@@ -59,6 +60,7 @@ TEST_CASE("create_multilinestring with single line and no force_multi",
5960

6061
REQUIRE(geom.is_linestring());
6162
REQUIRE(geometry_type(geom) == "LINESTRING");
63+
REQUIRE(geom.n_points() == 2);
6264
REQUIRE(num_geometries(geom) == 1);
6365
REQUIRE(area(geom) == Approx(0.0));
6466
REQUIRE(spherical_area(geom) == Approx(0.0));
@@ -132,6 +134,7 @@ TEST_CASE("create_multilinestring from two non-joined lines", "[NoDB]")
132134
geom::line_merge(geom::create_multilinestring(buffer.buffer()));
133135

134136
REQUIRE(geom.is_multilinestring());
137+
REQUIRE(geom.n_points() == 4);
135138
REQUIRE(dimension(geom) == 1);
136139
auto const &ml = geom.get<geom::multilinestring_t>();
137140
REQUIRE(ml.num_geometries() == 2);
@@ -152,6 +155,7 @@ TEST_CASE("create_multilinestring from two lines end to end", "[NoDB]")
152155

153156
REQUIRE(geom.is_multilinestring());
154157
auto const &ml = geom.get<geom::multilinestring_t>();
158+
REQUIRE(ml.n_points() == 3);
155159
REQUIRE(ml.num_geometries() == 1);
156160
REQUIRE(ml[0] == expected);
157161
}
@@ -292,6 +296,7 @@ TEST_CASE("create_multilinestring from Y shape", "[NoDB]")
292296
REQUIRE(geom.is_multilinestring());
293297
auto const &ml = geom.get<geom::multilinestring_t>();
294298
REQUIRE(ml.num_geometries() == 2);
299+
REQUIRE(ml.n_points() == 5);
295300
REQUIRE(ml[0] == expected[0]);
296301
REQUIRE(ml[1] == expected[1]);
297302
}

tests/test-geom-multipoints.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ TEST_CASE("multipoint_t with a single point", "[NoDB]")
2929

3030
REQUIRE(geom.is_multipoint());
3131
REQUIRE(geometry_type(geom) == "MULTIPOINT");
32+
REQUIRE(geom.n_points() == 1);
3233
REQUIRE(dimension(geom) == 0);
3334
REQUIRE(num_geometries(geom) == 1);
3435
REQUIRE(area(geom) == Approx(0.0));
@@ -54,6 +55,7 @@ TEST_CASE("multipoint_t with several points", "[NoDB]")
5455

5556
REQUIRE(geom.is_multipoint());
5657
REQUIRE(geometry_type(geom) == "MULTIPOINT");
58+
REQUIRE(geom.n_points() == 3);
5759
REQUIRE(num_geometries(geom) == 3);
5860
REQUIRE(area(geom) == Approx(0.0));
5961
REQUIRE(spherical_area(geom) == Approx(0.0));
@@ -85,6 +87,7 @@ TEST_CASE("create_multipoint from OSM data", "[NoDB]")
8587

8688
REQUIRE(geometry_type(geom) == "MULTIPOINT");
8789
REQUIRE(dimension(geom) == 0);
90+
REQUIRE(geom.n_points() == 4);
8891
REQUIRE(num_geometries(geom) == 4);
8992

9093
auto const &c = geom.get<geom::multipoint_t>();

tests/test-geom-multipolygons.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ TEST_CASE("multipolygon geometry with single outer, no inner", "[NoDB]")
2626
geom::polygon_t{geom::ring_t{{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}});
2727

2828
REQUIRE(geometry_type(geom) == "MULTIPOLYGON");
29+
REQUIRE(geom.n_points() == 5);
2930
REQUIRE(dimension(geom) == 2);
3031
REQUIRE(num_geometries(geom) == 1);
3132
REQUIRE(area(geom) == Approx(1.0));
@@ -56,6 +57,7 @@ TEST_CASE("multipolygon geometry with two polygons", "[NoDB]")
5657
mp.add_geometry(std::move(polygon));
5758

5859
REQUIRE(geometry_type(geom) == "MULTIPOLYGON");
60+
REQUIRE(geom.n_points() == 15);
5961
REQUIRE(dimension(geom) == 2);
6062
REQUIRE(num_geometries(geom) == 2);
6163
REQUIRE(area(geom) == Approx(9.0));
@@ -76,6 +78,7 @@ TEST_CASE("create_multipolygon creates simple polygon from OSM data", "[NoDB]")
7678

7779
REQUIRE(geom.is_polygon());
7880
REQUIRE(geometry_type(geom) == "POLYGON");
81+
REQUIRE(geom.n_points() == 5);
7982
REQUIRE(dimension(geom) == 2);
8083
REQUIRE(num_geometries(geom) == 1);
8184
REQUIRE(area(geom) == Approx(1.0));
@@ -99,6 +102,7 @@ TEST_CASE("create_multipolygon from OSM data", "[NoDB]")
99102
geom::create_multipolygon(relation, buffer.buffer(), &area_buffer);
100103

101104
REQUIRE(geom.is_multipolygon());
105+
REQUIRE(geom.n_points() == 9);
102106
REQUIRE(geometry_type(geom) == "MULTIPOLYGON");
103107
REQUIRE(num_geometries(geom) == 2);
104108
REQUIRE(area(geom) == Approx(51.0));

tests/test-geom-null.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ TEST_CASE("null geometry", "[NoDB]")
1818
{
1919
geom::geometry_t const geom{};
2020

21+
REQUIRE(geom.n_points() == 0);
2122
REQUIRE(dimension(geom) == 0);
2223
REQUIRE(num_geometries(geom) == 0);
2324
REQUIRE(area(geom) == Approx(0.0));

tests/test-geom-points.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ TEST_CASE("create_point from OSM data", "[NoDB]")
6565

6666
REQUIRE(geom.is_point());
6767
REQUIRE(geometry_type(geom) == "POINT");
68+
REQUIRE(geom.n_points() == 1);
6869
REQUIRE(dimension(geom) == 0);
6970
REQUIRE(num_geometries(geom) == 1);
7071
REQUIRE(area(geom) == Approx(0.0));

tests/test-geom-polygons.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ TEST_CASE("polygon geometry without inner", "[NoDB]")
2222
geom::geometry_t const geom{
2323
geom::polygon_t{geom::ring_t{{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}}};
2424

25+
REQUIRE(geom.n_points() == 5);
2526
REQUIRE(dimension(geom) == 2);
2627
REQUIRE(num_geometries(geom) == 1);
2728
REQUIRE(area(geom) == Approx(1.0));
@@ -38,6 +39,7 @@ TEST_CASE("polygon geometry without inner (reverse)", "[NoDB]")
3839
geom::geometry_t const geom{
3940
geom::polygon_t{geom::ring_t{{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}}}};
4041

42+
REQUIRE(geom.n_points() == 5);
4143
REQUIRE(dimension(geom) == 2);
4244
REQUIRE(num_geometries(geom) == 1);
4345
REQUIRE(area(geom) == Approx(1.0));
@@ -62,6 +64,7 @@ TEST_CASE("geom::polygon_t", "[NoDB]")
6264
REQUIRE(polygon.inners().size() == 1);
6365

6466
geom::geometry_t const geom{std::move(polygon)};
67+
REQUIRE(geom.n_points() == 10);
6568
REQUIRE(dimension(geom) == 2);
6669
REQUIRE(num_geometries(geom) == 1);
6770
REQUIRE(area(geom) == Approx(8.0));

0 commit comments

Comments
 (0)