Skip to content

Commit 080e996

Browse files
committed
NULL geometry handling
1 parent 7b5a204 commit 080e996

File tree

3 files changed

+107
-9
lines changed

3 files changed

+107
-9
lines changed

src/output-flex.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ TRAMPOLINE(app_as_geometrycollection, as_geometrycollection)
8383
TRAMPOLINE(geom_len, __len)
8484
TRAMPOLINE(geom_tostring, __tostring)
8585
TRAMPOLINE(geom_geometrytype, geometrytype)
86+
TRAMPOLINE(geom_is_null, is_null)
8687
TRAMPOLINE(geom_srid, srid)
8788
TRAMPOLINE(geom_area, area)
8889
TRAMPOLINE(geom_centroid, centroid)
@@ -678,7 +679,7 @@ void output_flex_t::write_column(
678679
// called, because for 'add_row()' geometry columns are handled
679680
// earlier and 'write_column()' is not called.
680681
if (ltype == LUA_TUSERDATA) {
681-
auto const *geom = unpack_geometry(lua_state());
682+
auto const *const geom = unpack_geometry(lua_state());
682683
if (geom && !geom->is_null()) {
683684
if (geom->srid() == column.srid()) {
684685
// OSM id not available here, so use dummy 0, it is used
@@ -951,30 +952,40 @@ int output_flex_t::app_as_geometrycollection()
951952
return 1;
952953
}
953954

955+
// XXX Implementation for Lua __tostring function on geometries. Currently
956+
// just returns the type as string. This could be improved, for instance by
957+
// showing a WKT representation of the geometry.
954958
int output_flex_t::geom_tostring()
955959
{
956960
return geom_geometrytype();
957961
}
958962

959963
int output_flex_t::geom_geometrytype()
960964
{
961-
auto const *input_geometry = unpack_geometry(lua_state());
965+
auto const *const input_geometry = unpack_geometry(lua_state());
962966
auto const type = geometry_type(*input_geometry);
963967
lua_pushlstring(lua_state(), type.data(), type.size());
964968
return 1;
965969
}
966970

967971
int output_flex_t::geom_len()
968972
{
969-
auto const *input_geometry = unpack_geometry(lua_state());
973+
auto const *const input_geometry = unpack_geometry(lua_state());
970974
lua_pushinteger(lua_state(),
971975
static_cast<lua_Integer>(num_geometries(*input_geometry)));
972976
return 1;
973977
}
974978

979+
int output_flex_t::geom_is_null()
980+
{
981+
auto const *const input_geometry = unpack_geometry(lua_state());
982+
lua_pushboolean(lua_state(), input_geometry->is_null());
983+
return 1;
984+
}
985+
975986
int output_flex_t::geom_srid()
976987
{
977-
auto const *input_geometry = unpack_geometry(lua_state());
988+
auto const *const input_geometry = unpack_geometry(lua_state());
978989
lua_pushinteger(lua_state(),
979990
static_cast<lua_Integer>(input_geometry->srid()));
980991
return 1;
@@ -986,7 +997,7 @@ int output_flex_t::geom_area()
986997
throw std::runtime_error{"No parameter(s) needed for area()."};
987998
}
988999

989-
auto const *input_geometry = unpack_geometry(lua_state());
1000+
auto const *const input_geometry = unpack_geometry(lua_state());
9901001
double const area = geom::area(*input_geometry);
9911002
lua_pushnumber(lua_state(), area);
9921003

@@ -999,7 +1010,7 @@ int output_flex_t::geom_centroid()
9991010
throw std::runtime_error{"No parameter(s) needed for centroid()."};
10001011
}
10011012

1002-
auto const *input_geometry = unpack_geometry(lua_state());
1013+
auto const *const input_geometry = unpack_geometry(lua_state());
10031014

10041015
create_lua_geometry_object(lua_state(), [&](geom::geometry_t *geom) {
10051016
*geom = geom::centroid(*input_geometry);
@@ -1027,7 +1038,7 @@ int output_flex_t::geom_transform()
10271038
int const srid = lua_tointeger(lua_state(), -1);
10281039
lua_pop(lua_state(), 1); // srid parameter
10291040

1030-
auto const *input_geometry = unpack_geometry(lua_state());
1041+
auto const *const input_geometry = unpack_geometry(lua_state());
10311042

10321043
if (input_geometry->srid() != 4326) {
10331044
throw std::runtime_error{
@@ -1050,7 +1061,7 @@ int output_flex_t::geom_split_multi()
10501061
throw std::runtime_error{"No parameter(s) needed for split_multi()."};
10511062
}
10521063

1053-
auto const *input_geometry = unpack_geometry(lua_state());
1064+
auto const *const input_geometry = unpack_geometry(lua_state());
10541065
auto const geoms = geom::split_multi(*input_geometry, true);
10551066

10561067
lua_createtable(lua_state(), (int)geoms.size(), 0);
@@ -1081,7 +1092,7 @@ int output_flex_t::geom_simplify()
10811092
double const tolerance = lua_tonumber(lua_state(), -1);
10821093
lua_pop(lua_state(), 1); // tolerance parameter
10831094

1084-
auto const *input_geometry = unpack_geometry(lua_state());
1095+
auto const *const input_geometry = unpack_geometry(lua_state());
10851096

10861097
create_lua_geometry_object(lua_state(), [&](geom::geometry_t *geom) {
10871098
*geom = geom::simplify(*input_geometry, tolerance);
@@ -2237,6 +2248,7 @@ void output_flex_t::init_lua(std::string const &filename)
22372248
lua_trampoline_geom_tostring);
22382249
lua_pushvalue(lua_state(), -1);
22392250
lua_setfield(lua_state(), -2, "__index");
2251+
luaX_add_table_func(lua_state(), "is_null", lua_trampoline_geom_is_null);
22402252
luaX_add_table_func(lua_state(), "srid", lua_trampoline_geom_srid);
22412253
luaX_add_table_func(lua_state(), "area", lua_trampoline_geom_area);
22422254
luaX_add_table_func(lua_state(), "geometrytype",

src/output-flex.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ class output_flex_t : public output_t
168168
int geom_tostring();
169169
int geom_geometrytype();
170170
int geom_len();
171+
int geom_is_null();
171172
int geom_srid();
172173
int geom_area();
173174
int geom_centroid();

tests/bdd/flex/null-geom.feature

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
Feature: Null geometry handling
2+
3+
Scenario: Invalid geometries show up as NULL
4+
Given the lua style
5+
"""
6+
local tables = {}
7+
8+
tables.null = osm2pgsql.define_table{
9+
name = 'osm2pgsql_test_null',
10+
ids = { type = 'any', id_column = 'osm_id', type_column = 'osm_type' },
11+
columns = {
12+
{ column = 'name', type = 'text' },
13+
{ column = 'geom', type = 'geometry', projection = 4326 }
14+
}
15+
}
16+
17+
tables.not_null = osm2pgsql.define_table{
18+
name = 'osm2pgsql_test_not_null',
19+
ids = { type = 'any', id_column = 'osm_id', type_column = 'osm_type' },
20+
columns = {
21+
{ column = 'name', type = 'text' },
22+
{ column = 'geom', type = 'geometry', projection = 4326, not_null = true }
23+
}
24+
}
25+
26+
function osm2pgsql.process_node(object)
27+
local g = object.as_point()
28+
tables.null:insert({
29+
name = object.tags.name,
30+
geom = g
31+
})
32+
print("GEOM=", g)
33+
if g then
34+
tables.not_null:insert({
35+
name = object.tags.name,
36+
geom = g
37+
})
38+
end
39+
end
40+
41+
function osm2pgsql.process_way(object)
42+
local g = object.as_linestring()
43+
tables.null:insert({
44+
name = object.tags.name,
45+
geom = g
46+
})
47+
print("GEOM=", g)
48+
if not g:is_null() then
49+
tables.not_null:insert({
50+
name = object.tags.name,
51+
geom = g
52+
})
53+
end
54+
end
55+
"""
56+
57+
And the grid
58+
| 10 | | 11 |
59+
60+
And the OSM data
61+
"""
62+
n12 x3.4 y5.6 Tname=valid
63+
n13 x42 y42
64+
n14 x42 y42
65+
w20 Tname=valid Nn10,n11
66+
w21 Tname=invalid Nn10
67+
w22 Tname=invalid Nn13,n13
68+
w23 Tname=invalid Nn13,n14
69+
"""
70+
71+
When running osm2pgsql flex
72+
73+
Then table osm2pgsql_test_null contains exactly
74+
| osm_type | osm_id | ST_AsText(geom) |
75+
| N | 12 | 3.4 5.6 |
76+
| W | 20 | 10, 11 |
77+
| W | 21 | NULL |
78+
| W | 22 | NULL |
79+
| W | 23 | NULL |
80+
81+
And table osm2pgsql_test_not_null contains exactly
82+
| osm_type | osm_id | ST_AsText(geom) |
83+
| N | 12 | 3.4 5.6 |
84+
| W | 20 | 10, 11 |
85+

0 commit comments

Comments
 (0)