Skip to content

Commit 5c7a66b

Browse files
committed
Complete and test implementation of geom::transform()
1 parent 8859bc4 commit 5c7a66b

File tree

4 files changed

+317
-42
lines changed

4 files changed

+317
-42
lines changed

src/geom-functions.cpp

Lines changed: 55 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -59,75 +59,76 @@ std::size_t num_geometries(geometry_t const &geom)
5959

6060
namespace {
6161

62+
void set_to_same_type(geometry_t *output, geometry_t const &input)
63+
{
64+
input.visit(overloaded{[&](auto in) { output->set<decltype(in)>(); }});
65+
}
66+
6267
class transform_visitor
6368
{
6469
public:
65-
explicit transform_visitor(reprojection const *reprojection)
66-
: m_reprojection(reprojection)
70+
explicit transform_visitor(geometry_t *output,
71+
reprojection const *reprojection)
72+
: m_output(output), m_reprojection(reprojection)
6773
{}
6874

69-
geometry_t operator()(geom::nullgeom_t const & /*geom*/) const
70-
{
71-
return {};
72-
}
75+
void operator()(nullgeom_t const & /*input*/) const {}
7376

74-
geometry_t operator()(geom::point_t const &geom) const
77+
void operator()(point_t const &input) const
7578
{
76-
return geometry_t{project(geom), srid()};
79+
m_output->get<point_t>() = project(input);
7780
}
7881

79-
geometry_t operator()(geom::linestring_t const &geom) const
82+
void operator()(linestring_t const &input) const
8083
{
81-
geometry_t output{linestring_t{}, srid()};
82-
transform_points(&output.get<linestring_t>(), geom);
83-
return output;
84+
transform_points(&m_output->get<linestring_t>(), input);
8485
}
8586

86-
geometry_t operator()(geom::polygon_t const &geom) const
87+
void operator()(polygon_t const &input) const
8788
{
88-
geometry_t output{polygon_t{}, srid()};
89-
transform_polygon(&output.get<polygon_t>(), geom);
90-
return output;
89+
transform_polygon(&m_output->get<polygon_t>(), input);
9190
}
9291

93-
geometry_t operator()(geom::multipoint_t const & /*geom*/) const
92+
void operator()(multipoint_t const &input) const
9493
{
95-
assert(false);
96-
return {};
94+
auto &m = m_output->get<multipoint_t>();
95+
m.reserve(input.num_geometries());
96+
for (auto const point : input) {
97+
m.add_geometry(project(point));
98+
}
9799
}
98100

99-
geometry_t operator()(geom::multilinestring_t const &geom) const
101+
void operator()(multilinestring_t const &input) const
100102
{
101-
geometry_t output{multilinestring_t{}, srid()};
102-
103-
for (auto const &line : geom) {
104-
transform_points(&output.get<multilinestring_t>().add_geometry(),
105-
line);
103+
auto &m = m_output->set<multilinestring_t>();
104+
m.reserve(input.num_geometries());
105+
for (auto const &line : input) {
106+
transform_points(&m.add_geometry(), line);
106107
}
107-
108-
return output;
109108
}
110109

111-
geometry_t operator()(geom::multipolygon_t const &geom) const
110+
void operator()(multipolygon_t const &input) const
112111
{
113-
geometry_t output{multipolygon_t{}, srid()};
114-
115-
for (auto const &polygon : geom) {
116-
transform_polygon(&output.get<multipolygon_t>().add_geometry(),
117-
polygon);
112+
auto &m = m_output->set<multipolygon_t>();
113+
m.reserve(input.num_geometries());
114+
for (auto const &polygon : input) {
115+
transform_polygon(&m.add_geometry(), polygon);
118116
}
119-
120-
return output;
121117
}
122118

123-
geometry_t operator()(geom::collection_t const & /*geom*/) const
119+
void operator()(collection_t const &input) const
124120
{
125-
return {}; // XXX not implemented
121+
auto &m = m_output->get<collection_t>();
122+
m.reserve(input.num_geometries());
123+
for (auto const &geom : input) {
124+
auto &new_geom = m.add_geometry();
125+
set_to_same_type(&new_geom, geom);
126+
new_geom.set_srid(0);
127+
geom.visit(transform_visitor{&new_geom, m_reprojection});
128+
}
126129
}
127130

128131
private:
129-
int srid() const noexcept { return m_reprojection->target_srs(); }
130-
131132
point_t project(point_t point) const
132133
{
133134
return m_reprojection->reproject(point);
@@ -152,16 +153,28 @@ class transform_visitor
152153
}
153154
}
154155

156+
geometry_t *m_output;
155157
reprojection const *m_reprojection;
156158

157159
}; // class transform_visitor
158160

159161
} // anonymous namespace
160162

161-
geometry_t transform(geometry_t const &geom, reprojection const &reprojection)
163+
void transform(geometry_t *output, geometry_t const &input,
164+
reprojection const &reprojection)
162165
{
163-
assert(geom.srid() == 4326);
164-
return geom.visit(transform_visitor{&reprojection});
166+
assert(input.srid() == 4326);
167+
168+
set_to_same_type(output, input);
169+
output->set_srid(reprojection.target_srs());
170+
input.visit(transform_visitor{output, &reprojection});
171+
}
172+
173+
geometry_t transform(geometry_t const &input, reprojection const &reprojection)
174+
{
175+
geometry_t output;
176+
transform(&output, input, reprojection);
177+
return output;
165178
}
166179

167180
namespace {

src/geom-functions.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ std::string_view geometry_type(geometry_t const &geom);
6464
*/
6565
std::size_t num_geometries(geometry_t const &geom);
6666

67+
/**
68+
* Transform a geometry in 4326 into some other projection.
69+
*
70+
* \param output Pointer to output geometry.
71+
* \param geom Input geometry.
72+
* \param reprojection Target projection.
73+
*
74+
* \pre \code geom.srid() == 4326 \endcode
75+
*/
76+
void transform(geometry_t *output, geometry_t const &geom,
77+
reprojection const &reprojection);
78+
6779
/**
6880
* Transform a geometry in 4326 into some other projection.
6981
*

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ set_test(test-geom-multipolygons LABELS NoDB)
5151
set_test(test-geom-null LABELS NoDB)
5252
set_test(test-geom-points LABELS NoDB)
5353
set_test(test-geom-polygons LABELS NoDB)
54+
set_test(test-geom-transform LABELS NoDB)
5455
set_test(test-middle)
5556
set_test(test-node-locations LABELS NoDB)
5657
set_test(test-options-database LABELS NoDB)

0 commit comments

Comments
 (0)