Skip to content

Commit 18a7fe9

Browse files
committed
Support for importing non-area relations as MultiLineString
1 parent 4758cf4 commit 18a7fe9

File tree

12 files changed

+386
-9
lines changed

12 files changed

+386
-9
lines changed

database/postgis/postgis.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ func addGeometryColumn(tx *sql.Tx, tableName string, spec TableSpec) error {
7272
}
7373

7474
geomType := strings.ToUpper(spec.GeometryType)
75-
if geomType == "POLYGON" {
76-
geomType = "GEOMETRY" // for multipolygon support
75+
if geomType == "POLYGON" || geomType == "LINESTRING" {
76+
geomType = "GEOMETRY" // for multigeometry support
7777
}
7878
sql := fmt.Sprintf("SELECT AddGeometryColumn('%s', '%s', '%s', '%d', '%s', 2);",
7979
spec.Schema, tableName, colName, spec.Srid, geomType)

geom/geom.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package geom
33
import (
44
"errors"
55
"math"
6+
"runtime"
67

78
osm "github.com/omniscale/go-osm"
89
"github.com/omniscale/imposm3/geom/geos"
@@ -136,6 +137,42 @@ func Polygon(g *geos.Geos, nodes []osm.Node) (*geos.Geom, error) {
136137
return geom, nil
137138
}
138139

140+
func MultiLinestring(rel *osm.Relation, srid int) (*geos.Geom, error) {
141+
g := geos.NewGeos()
142+
g.SetHandleSrid(srid)
143+
defer g.Finish()
144+
145+
var lines []*geos.Geom
146+
147+
for _, member := range rel.Members {
148+
if member.Way == nil {
149+
continue
150+
}
151+
152+
line, err := LineString(g, member.Way.Nodes)
153+
154+
if err != nil {
155+
return nil, err
156+
}
157+
158+
if line != nil {
159+
// Clear the finalizer created in LineString()
160+
// as we want to make the object a part of MultiLineString.
161+
runtime.SetFinalizer(line, nil)
162+
lines = append(lines, line)
163+
}
164+
}
165+
166+
result := g.MultiLineString(lines)
167+
if result == nil {
168+
return nil, errors.New("Error while building multi-linestring.")
169+
}
170+
171+
g.DestroyLater(result)
172+
173+
return result, nil
174+
}
175+
139176
func AsGeomElement(g *geos.Geos, geom *geos.Geom) (Geometry, error) {
140177
wkb := g.AsEwkbHex(geom)
141178
if wkb == nil {

geom/multipolygon_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,3 +659,38 @@ func TestClosedAndOpenRing(t *testing.T) {
659659
t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
660660
}
661661
}
662+
663+
func TestSimpleMultiLineString(t *testing.T) {
664+
w1 := makeWay(1, osm.Tags{}, []coord{
665+
{1, 1, 0},
666+
{2, 2, 0},
667+
})
668+
w2 := makeWay(2, osm.Tags{}, []coord{
669+
{3, 2, 0},
670+
{4, 3, 0},
671+
})
672+
673+
rel := osm.Relation{
674+
Element: osm.Element{ID: 1, Tags: osm.Tags{}}}
675+
rel.Members = []osm.Member{
676+
{ID: 1, Type: osm.WayMember, Role: "", Way: &w1},
677+
{ID: 2, Type: osm.WayMember, Role: "", Way: &w2},
678+
}
679+
680+
geom, err := MultiLinestring(&rel, 3857)
681+
682+
if err != nil {
683+
t.Fatal(err)
684+
}
685+
686+
g := geos.NewGeos()
687+
defer g.Finish()
688+
689+
if !g.IsValid(geom) {
690+
t.Fatal("geometry not valid", g.AsWkt(geom))
691+
}
692+
693+
if length := geom.Length(); length != 2 {
694+
t.Fatal("length invalid", length)
695+
}
696+
}

import_/import.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ func Import(importOpts config.Import) {
182182
tagmapping.Conf.SingleIDSpace,
183183
relations,
184184
db, progress,
185+
tagmapping.LineStringMatcher,
185186
tagmapping.PolygonMatcher,
186187
tagmapping.RelationMatcher,
187188
tagmapping.RelationMemberMatcher,

mapping/mapping.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ const (
8484
type Mapping struct {
8585
Conf config.Mapping
8686
PointMatcher NodeMatcher
87-
LineStringMatcher WayMatcher
87+
LineStringMatcher RelWayMatcher
8888
PolygonMatcher RelWayMatcher
8989
RelationMatcher RelationMatcher
9090
RelationMemberMatcher RelationMatcher
@@ -356,6 +356,11 @@ func (m *Mapping) addRelationFilters(tableType TableType, filters tableElementFi
356356
return false
357357
}
358358
filters[name] = append(filters[name], f)
359+
} else if TableType(t.Type) == LineStringTable {
360+
f := func(tags osm.Tags, key Key, closed bool) bool {
361+
return false
362+
}
363+
filters[name] = append(filters[name], f)
359364
}
360365
}
361366
}

mapping/matcher.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,20 @@ func (m *Mapping) pointMatcher() (NodeMatcher, error) {
2020
}, err
2121
}
2222

23-
func (m *Mapping) lineStringMatcher() (WayMatcher, error) {
23+
func (m *Mapping) lineStringMatcher() (RelWayMatcher, error) {
2424
mappings := make(TagTableMapping)
2525
m.mappings(LineStringTable, mappings)
2626
filters := make(tableElementFilters)
2727
m.addFilters(filters)
2828
m.addTypedFilters(LineStringTable, filters)
29+
relFilters := make(tableElementFilters)
30+
m.addRelationFilters(LineStringTable, relFilters)
2931
tables, err := m.tables(LineStringTable)
3032
return &tagMatcher{
3133
mappings: mappings,
3234
filters: filters,
3335
tables: tables,
36+
relFilters: relFilters,
3437
matchAreas: false,
3538
}, err
3639
}
@@ -155,7 +158,7 @@ func (tm *tagMatcher) MatchWay(way *osm.Way) []Match {
155158
}
156159

157160
func (tm *tagMatcher) MatchRelation(rel *osm.Relation) []Match {
158-
return tm.match(rel.Tags, true, true)
161+
return tm.match(rel.Tags, tm.matchAreas, true)
159162
}
160163

161164
type orderedMatch struct {

test/multilinestring.osc

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<osmChange version="1">
3+
<create>
4+
<node id="10009" version="1" timestamp="2016-01-01T00:00:00Z" lat="51.5512379" lon="-0.0405630"/>
5+
<node id="10010" version="1" timestamp="2016-01-01T00:00:00Z" lat="51.5515113" lon="-0.0406333"/>
6+
<way id="1006" version="1" timestamp="2016-01-01T00:00:00Z">
7+
<nd ref="10009"/>
8+
<nd ref="10010"/>
9+
</way>
10+
11+
<node id="10008" version="1" timestamp="2016-01-01T00:00:00Z" lat="51.5515683" lon="-0.0406486"/>
12+
<node id="10007" version="1" timestamp="2016-01-01T00:00:00Z" lat="51.5515883" lon="-0.0406757"/>
13+
<way id="1007" version="1" timestamp="2016-01-01T00:00:00Z">
14+
<nd ref="10008"/>
15+
<nd ref="10007"/>
16+
</way>
17+
18+
<relation id="102" version="1" timestamp="2016-01-01T00:00:00Z">
19+
<member type="way" ref="1006" role=""/>
20+
<member type="way" ref="1007" role=""/>
21+
<tag k="network" v="lcn"/>
22+
<tag k="route" v="bicycle"/>
23+
<tag k="type" v="route"/>
24+
</relation>
25+
</create>
26+
27+
<modify>
28+
<way id="1004" version="2" timestamp="2016-01-01T00:00:00Z">
29+
<nd ref="10004"/>
30+
<nd ref="10005"/>
31+
<nd ref="10006"/>
32+
<nd ref="10004"/>
33+
<tag k="building" v="residential"/>
34+
<!-- tag with area=yes removed -->
35+
</way>
36+
</modify>
37+
</osmChange>

test/multilinestring.osm

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<osm version="1">
3+
<node id="10002" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5107973" lon="-0.0930300" />
4+
<node id="10003" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5108542" lon="-0.0930091" />
5+
<way id="1000" version="1" timestamp="2015-12-31T23:59:99Z">
6+
<nd ref="10002"/>
7+
<nd ref="10003"/>
8+
<tag k="highway" v="trunk"/>
9+
</way>
10+
11+
<node id="10000" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5107776" lon="-0.0930375"/>
12+
<way id="1005" version="1" timestamp="2015-12-31T23:59:99Z">
13+
<nd ref="10000"/>
14+
<nd ref="10002"/>
15+
</way>
16+
17+
<node id="10001" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5106434" lon="-0.0930826" />
18+
<way id="1001" version="1" timestamp="2015-12-31T23:59:99Z">
19+
<nd ref="10001"/>
20+
<nd ref="10000"/>
21+
</way>
22+
<relation id="100" version="1" timestamp="2015-12-31T23:59:99Z">
23+
<member type="way" ref="1000" role=""/>
24+
<member type="way" ref="1005" role=""/>
25+
<member type="way" ref="1001" role=""/>
26+
<tag k="route" v="bicycle"/>
27+
<tag k="type" v="route"/>
28+
</relation>
29+
30+
<node id="10004" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.4860918" lon="-0.0873508"/>
31+
<node id="10006" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.4860020" lon="-0.0875372"/>
32+
<node id="10005" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.4853370" lon="-0.0864133"/>
33+
<way id="1004" version="1" timestamp="2015-12-31T23:59:99Z">
34+
<nd ref="10004"/>
35+
<nd ref="10005"/>
36+
<nd ref="10006"/>
37+
<nd ref="10004"/>
38+
<tag k="building" v="residential"/>
39+
<tag k="area" v="yes"/>
40+
</way>
41+
42+
<node id="10011" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5004084" lon="-0.0824810"/>
43+
<node id="10012" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5003998" lon="-0.0833872"/>
44+
<node id="10013" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5003917" lon="-0.0836970"/>
45+
<way id="1008" version="1" timestamp="2015-12-31T23:59:99Z">
46+
<nd ref="10011"/>
47+
<nd ref="10012"/>
48+
<nd ref="10013"/>
49+
<nd ref="10011"/>
50+
<tag k="leisure" v="park"/>
51+
</way>
52+
</osm>

test/multilinestring_mapping.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
areas:
2+
area_tags:
3+
- leisure
4+
tables:
5+
multilinestring:
6+
type: linestring
7+
columns:
8+
- name: osm_id
9+
type: id
10+
- name: geometry
11+
type: geometry
12+
- name: name
13+
type: string
14+
key: name
15+
- name: type
16+
type: mapping_value
17+
relation_types:
18+
- route
19+
mapping:
20+
type:
21+
- route
22+
highway:
23+
- trunk
24+
building:
25+
- residential
26+
leisure:
27+
- park
28+
multilinestring_no_relations:
29+
type: linestring
30+
columns:
31+
- name: osm_id
32+
type: id
33+
- name: geometry
34+
type: geometry
35+
- name: name
36+
type: string
37+
key: name
38+
- name: type
39+
type: mapping_value
40+
mapping:
41+
type:
42+
- route

0 commit comments

Comments
 (0)