Skip to content

Commit 0df433b

Browse files
authored
Merge pull request #1705 from joto/geom-improvements
Geometry processing improvements
2 parents 337d0ba + 2eac636 commit 0df433b

File tree

14 files changed

+677
-139
lines changed

14 files changed

+677
-139
lines changed

.github/actions/win-install/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ runs:
55

66
steps:
77
- name: Install packages
8-
run: vcpkg install bzip2:x64-windows expat:x64-windows zlib:x64-windows proj4:x64-windows boost-system:x64-windows boost-filesystem:x64-windows boost-property-tree:x64-windows lua:x64-windows libpq:x64-windows
8+
run: vcpkg install bzip2:x64-windows expat:x64-windows zlib:x64-windows proj4:x64-windows boost-geometry:x64-windows boost-system:x64-windows boost-filesystem:x64-windows boost-property-tree:x64-windows lua:x64-windows libpq:x64-windows
99
shell: bash
1010

1111
- name: Install psycopg2 and beahve

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ Required libraries are
4848
* [proj](https://proj.org/)
4949
* [bzip2](http://www.bzip.org/)
5050
* [zlib](https://www.zlib.net/)
51-
* [Boost libraries](https://www.boost.org/), including system and filesystem
51+
* [Boost libraries](https://www.boost.org/), including geometry, system and
52+
filesystem
5253
* [PostgreSQL](https://www.postgresql.org/) client libraries
5354
* [Lua](https://www.lua.org/) (Optional, used for Lua tag transforms
5455
and the flex output)

src/geom-boost-adaptor.hpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#ifndef OSM2PGSQL_GEOM_BOOST_ADAPTOR_HPP
2+
#define OSM2PGSQL_GEOM_BOOST_ADAPTOR_HPP
3+
4+
/**
5+
* SPDX-License-Identifier: GPL-2.0-or-later
6+
*
7+
* This file is part of osm2pgsql (https://osm2pgsql.org/).
8+
*
9+
* Copyright (C) 2006-2022 by the osm2pgsql developer community.
10+
* For a full list of authors see the git log.
11+
*/
12+
13+
#include "geom.hpp"
14+
15+
#include <boost/geometry.hpp>
16+
#include <boost/geometry/geometries/register/linestring.hpp>
17+
#include <boost/geometry/geometries/register/multi_linestring.hpp>
18+
#include <boost/geometry/geometries/register/multi_point.hpp>
19+
#include <boost/geometry/geometries/register/multi_polygon.hpp>
20+
#include <boost/geometry/geometries/register/point.hpp>
21+
#include <boost/geometry/geometries/register/ring.hpp>
22+
23+
BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(geom::point_t, double, cs::cartesian,
24+
x, y, set_x, set_y)
25+
BOOST_GEOMETRY_REGISTER_LINESTRING(geom::linestring_t)
26+
BOOST_GEOMETRY_REGISTER_RING(geom::ring_t)
27+
28+
BOOST_GEOMETRY_REGISTER_MULTI_POINT(geom::multipoint_t)
29+
BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING(geom::multilinestring_t)
30+
BOOST_GEOMETRY_REGISTER_MULTI_POLYGON(geom::multipolygon_t)
31+
32+
namespace boost {
33+
namespace geometry {
34+
namespace traits {
35+
template <>
36+
struct point_order<::geom::ring_t>
37+
{
38+
static const order_selector value = counterclockwise;
39+
};
40+
41+
template <>
42+
struct tag<::geom::polygon_t>
43+
{
44+
using type = polygon_tag;
45+
};
46+
template <>
47+
struct ring_const_type<::geom::polygon_t>
48+
{
49+
using type = ::geom::ring_t const &;
50+
};
51+
template <>
52+
struct ring_mutable_type<::geom::polygon_t>
53+
{
54+
using type = ::geom::ring_t &;
55+
};
56+
template <>
57+
struct interior_const_type<::geom::polygon_t>
58+
{
59+
using type = std::vector<::geom::ring_t> const;
60+
};
61+
template <>
62+
struct interior_mutable_type<::geom::polygon_t>
63+
{
64+
using type = std::vector<::geom::ring_t>;
65+
};
66+
67+
template <>
68+
struct exterior_ring<::geom::polygon_t>
69+
{
70+
// NOLINTNEXTLINE(google-runtime-references)
71+
static auto &get(::geom::polygon_t &p) { return p.outer(); }
72+
static auto &get(::geom::polygon_t const &p) { return p.outer(); }
73+
};
74+
75+
template <>
76+
struct interior_rings<::geom::polygon_t>
77+
{
78+
// NOLINTNEXTLINE(google-runtime-references)
79+
static auto get(::geom::polygon_t &p) { return p.inners(); }
80+
static auto get(::geom::polygon_t const &p) { return p.inners(); }
81+
};
82+
} // namespace traits
83+
} // namespace geometry
84+
} // namespace boost
85+
86+
#endif // OSM2PGSQL_GEOM_BOOST_ADAPTOR_HPP

src/geom-functions.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* For a full list of authors see the git log.
88
*/
99

10+
#include "geom-boost-adaptor.hpp"
1011
#include "geom-functions.hpp"
1112

1213
#include <algorithm>
@@ -30,6 +31,32 @@ point_t interpolate(point_t p1, point_t p2, double frac) noexcept
3031
frac * (p1.y() - p2.y()) + p2.y()};
3132
}
3233

34+
std::string_view geometry_type(geometry_t const &geom)
35+
{
36+
using namespace std::literals::string_view_literals;
37+
return geom.visit(overloaded{
38+
[&](geom::nullgeom_t const & /*input*/) { return "NULL"sv; },
39+
[&](geom::point_t const & /*input*/) { return "POINT"sv; },
40+
[&](geom::linestring_t const & /*input*/) { return "LINESTRING"sv; },
41+
[&](geom::polygon_t const & /*input*/) { return "POLYGON"sv; },
42+
[&](geom::multipoint_t const & /*input*/) { return "MULTIPOINT"sv; },
43+
[&](geom::multilinestring_t const & /*input*/) {
44+
return "MULTILINESTRING"sv;
45+
},
46+
[&](geom::multipolygon_t const & /*input*/) {
47+
return "MULTIPOLYGON"sv;
48+
},
49+
[&](geom::collection_t const & /*input*/) {
50+
return "GEOMETRYCOLLECTION"sv;
51+
}});
52+
}
53+
54+
std::size_t num_geometries(geometry_t const &geom)
55+
{
56+
return geom.visit(
57+
overloaded{[&](auto const &input) { return input.num_geometries(); }});
58+
}
59+
3360
namespace {
3461

3562
class transform_visitor
@@ -274,7 +301,7 @@ double area(geometry_t const &geom)
274301
}
275302
}
276303

277-
return total;
304+
return std::abs(total);
278305
}
279306

280307
namespace {
@@ -519,4 +546,19 @@ geometry_t line_merge(geometry_t geom)
519546
return output;
520547
}
521548

549+
geometry_t centroid(geometry_t const &geom)
550+
{
551+
geom::geometry_t output{point_t{}, geom.srid()};
552+
auto &center = output.get<point_t>();
553+
554+
geom.visit(overloaded{
555+
[&](geom::nullgeom_t const & /*input*/) { output.reset(); },
556+
[&](geom::collection_t const & /*input*/) {
557+
throw std::runtime_error{"not implemented yet"};
558+
},
559+
[&](auto const &input) { boost::geometry::centroid(input, center); }});
560+
561+
return output;
562+
}
563+
522564
} // namespace geom

src/geom-functions.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "geom.hpp"
1414
#include "reprojection.hpp"
1515

16+
#include <string_view>
1617
#include <utility>
1718
#include <vector>
1819

@@ -51,6 +52,18 @@ void for_each_segment(point_list_t const &list, FUNC&& func)
5152
}
5253
}
5354

55+
/**
56+
* Return the type of a geometry as string: NULL, (MULTI)POINT,
57+
* (MULTI)LINESTRING, (MULTI)POLYGON, or GEOMETRYCOLLECTION.
58+
*/
59+
std::string_view geometry_type(geometry_t const &geom);
60+
61+
/**
62+
* Return the number of geometries in this geometry. For the null geometry
63+
* this is always 0, for other non-multi geometries this is always 1.
64+
*/
65+
std::size_t num_geometries(geometry_t const &geom);
66+
5467
/**
5568
* Transform a geometry in 4326 into some other projection.
5669
*
@@ -105,6 +118,14 @@ std::vector<geometry_t> split_multi(geometry_t geom, bool split_multi = true);
105118
*/
106119
geometry_t line_merge(geometry_t geom);
107120

121+
/**
122+
* Calculate the centroid of a geometry.
123+
*
124+
* \param geom Input geometry.
125+
* \returns Resulting point geometry.
126+
*/
127+
geometry_t centroid(geometry_t const &geom);
128+
108129
} // namespace geom
109130

110131
#endif // OSM2PGSQL_GEOM_FUNCTIONS_HPP

src/geom.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,16 @@ bool operator!=(point_list_t const &a, point_list_t const &b) noexcept
2323
return !(a == b);
2424
}
2525

26+
bool operator==(polygon_t const &a, polygon_t const &b) noexcept
27+
{
28+
return (a.outer() == b.outer()) &&
29+
std::equal(a.inners().cbegin(), a.inners().cend(),
30+
b.inners().cbegin(), b.inners().cend());
31+
}
32+
33+
bool operator!=(polygon_t const &a, polygon_t const &b) noexcept
34+
{
35+
return !(a == b);
36+
}
37+
2638
} // namespace geom

0 commit comments

Comments
 (0)