Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for importing non-area relations as MultiLineString #176

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions database/postgis/postgis.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ func addGeometryColumn(tx *sql.Tx, tableName string, spec TableSpec) error {
}

geomType := strings.ToUpper(spec.GeometryType)
if geomType == "POLYGON" {
geomType = "GEOMETRY" // for multipolygon support
if geomType == "POLYGON" || geomType == "LINESTRING" {
geomType = "GEOMETRY" // for multigeometry support
}
sql := fmt.Sprintf("SELECT AddGeometryColumn('%s', '%s', '%s', '%d', '%s', 2);",
spec.Schema, tableName, colName, spec.Srid, geomType)
Expand Down
37 changes: 37 additions & 0 deletions geom/geom.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package geom
import (
"errors"
"math"
"runtime"

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

func MultiLinestring(rel *osm.Relation, srid int) (*geos.Geom, error) {
g := geos.NewGeos()
g.SetHandleSrid(srid)
defer g.Finish()

var lines []*geos.Geom

for _, member := range rel.Members {
if member.Way == nil {
continue
}

line, err := LineString(g, member.Way.Nodes)

if err != nil {
return nil, err
}

if line != nil {
// Clear the finalizer created in LineString()
// as we want to make the object a part of MultiLineString.
runtime.SetFinalizer(line, nil)
lines = append(lines, line)
}
}

result := g.MultiLineString(lines)
if result == nil {
return nil, errors.New("Error while building multi-linestring.")
}

g.DestroyLater(result)

return result, nil
}

func AsGeomElement(g *geos.Geos, geom *geos.Geom) (Geometry, error) {
wkb := g.AsEwkbHex(geom)
if wkb == nil {
Expand Down
35 changes: 35 additions & 0 deletions geom/multipolygon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -659,3 +659,38 @@ func TestClosedAndOpenRing(t *testing.T) {
t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
}
}

func TestSimpleMultiLineString(t *testing.T) {
w1 := makeWay(1, osm.Tags{}, []coord{
{1, 1, 0},
{2, 2, 0},
})
w2 := makeWay(2, osm.Tags{}, []coord{
{3, 2, 0},
{4, 3, 0},
})

rel := osm.Relation{
Element: osm.Element{ID: 1, Tags: osm.Tags{}}}
rel.Members = []osm.Member{
{ID: 1, Type: osm.WayMember, Role: "", Way: &w1},
{ID: 2, Type: osm.WayMember, Role: "", Way: &w2},
}

geom, err := MultiLinestring(&rel, 3857)

if err != nil {
t.Fatal(err)
}

g := geos.NewGeos()
defer g.Finish()

if !g.IsValid(geom) {
t.Fatal("geometry not valid", g.AsWkt(geom))
}

if length := geom.Length(); length != 2 {
t.Fatal("length invalid", length)
}
}
1 change: 1 addition & 0 deletions import_/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ func Import(importOpts config.Import) {
tagmapping.Conf.SingleIDSpace,
relations,
db, progress,
tagmapping.LineStringMatcher,
tagmapping.PolygonMatcher,
tagmapping.RelationMatcher,
tagmapping.RelationMemberMatcher,
Expand Down
7 changes: 6 additions & 1 deletion mapping/mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const (
type Mapping struct {
Conf config.Mapping
PointMatcher NodeMatcher
LineStringMatcher WayMatcher
LineStringMatcher RelWayMatcher
PolygonMatcher RelWayMatcher
RelationMatcher RelationMatcher
RelationMemberMatcher RelationMatcher
Expand Down Expand Up @@ -356,6 +356,11 @@ func (m *Mapping) addRelationFilters(tableType TableType, filters tableElementFi
return false
}
filters[name] = append(filters[name], f)
} else if TableType(t.Type) == LineStringTable {
f := func(tags osm.Tags, key Key, closed bool) bool {
return false
}
filters[name] = append(filters[name], f)
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions mapping/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,20 @@ func (m *Mapping) pointMatcher() (NodeMatcher, error) {
}, err
}

func (m *Mapping) lineStringMatcher() (WayMatcher, error) {
func (m *Mapping) lineStringMatcher() (RelWayMatcher, error) {
mappings := make(TagTableMapping)
m.mappings(LineStringTable, mappings)
filters := make(tableElementFilters)
m.addFilters(filters)
m.addTypedFilters(LineStringTable, filters)
relFilters := make(tableElementFilters)
m.addRelationFilters(LineStringTable, relFilters)
tables, err := m.tables(LineStringTable)
return &tagMatcher{
mappings: mappings,
filters: filters,
tables: tables,
relFilters: relFilters,
matchAreas: false,
}, err
}
Expand Down Expand Up @@ -155,7 +158,7 @@ func (tm *tagMatcher) MatchWay(way *osm.Way) []Match {
}

func (tm *tagMatcher) MatchRelation(rel *osm.Relation) []Match {
return tm.match(rel.Tags, true, true)
return tm.match(rel.Tags, tm.matchAreas, true)
}

type orderedMatch struct {
Expand Down
37 changes: 37 additions & 0 deletions test/multilinestring.osc
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version='1.0' encoding='UTF-8'?>
<osmChange version="1">
<create>
<node id="10009" version="1" timestamp="2016-01-01T00:00:00Z" lat="51.5512379" lon="-0.0405630"/>
<node id="10010" version="1" timestamp="2016-01-01T00:00:00Z" lat="51.5515113" lon="-0.0406333"/>
<way id="1006" version="1" timestamp="2016-01-01T00:00:00Z">
<nd ref="10009"/>
<nd ref="10010"/>
</way>

<node id="10008" version="1" timestamp="2016-01-01T00:00:00Z" lat="51.5515683" lon="-0.0406486"/>
<node id="10007" version="1" timestamp="2016-01-01T00:00:00Z" lat="51.5515883" lon="-0.0406757"/>
<way id="1007" version="1" timestamp="2016-01-01T00:00:00Z">
<nd ref="10008"/>
<nd ref="10007"/>
</way>

<relation id="102" version="1" timestamp="2016-01-01T00:00:00Z">
<member type="way" ref="1006" role=""/>
<member type="way" ref="1007" role=""/>
<tag k="network" v="lcn"/>
<tag k="route" v="bicycle"/>
<tag k="type" v="route"/>
</relation>
</create>

<modify>
<way id="1004" version="2" timestamp="2016-01-01T00:00:00Z">
<nd ref="10004"/>
<nd ref="10005"/>
<nd ref="10006"/>
<nd ref="10004"/>
<tag k="building" v="residential"/>
<!-- tag with area=yes removed -->
</way>
</modify>
</osmChange>
52 changes: 52 additions & 0 deletions test/multilinestring.osm
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?xml version='1.0' encoding='UTF-8'?>
<osm version="1">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better. Thanks!

<node id="10002" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5107973" lon="-0.0930300" />
<node id="10003" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5108542" lon="-0.0930091" />
<way id="1000" version="1" timestamp="2015-12-31T23:59:99Z">
<nd ref="10002"/>
<nd ref="10003"/>
<tag k="highway" v="trunk"/>
</way>

<node id="10000" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5107776" lon="-0.0930375"/>
<way id="1005" version="1" timestamp="2015-12-31T23:59:99Z">
<nd ref="10000"/>
<nd ref="10002"/>
</way>

<node id="10001" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5106434" lon="-0.0930826" />
<way id="1001" version="1" timestamp="2015-12-31T23:59:99Z">
<nd ref="10001"/>
<nd ref="10000"/>
</way>
<relation id="100" version="1" timestamp="2015-12-31T23:59:99Z">
<member type="way" ref="1000" role=""/>
<member type="way" ref="1005" role=""/>
<member type="way" ref="1001" role=""/>
<tag k="route" v="bicycle"/>
<tag k="type" v="route"/>
</relation>

<node id="10004" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.4860918" lon="-0.0873508"/>
<node id="10006" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.4860020" lon="-0.0875372"/>
<node id="10005" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.4853370" lon="-0.0864133"/>
<way id="1004" version="1" timestamp="2015-12-31T23:59:99Z">
<nd ref="10004"/>
<nd ref="10005"/>
<nd ref="10006"/>
<nd ref="10004"/>
<tag k="building" v="residential"/>
<tag k="area" v="yes"/>
</way>

<node id="10011" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5004084" lon="-0.0824810"/>
<node id="10012" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5003998" lon="-0.0833872"/>
<node id="10013" version="1" timestamp="2015-12-31T23:59:99Z" lat="51.5003917" lon="-0.0836970"/>
<way id="1008" version="1" timestamp="2015-12-31T23:59:99Z">
<nd ref="10011"/>
<nd ref="10012"/>
<nd ref="10013"/>
<nd ref="10011"/>
<tag k="leisure" v="park"/>
</way>
</osm>
42 changes: 42 additions & 0 deletions test/multilinestring_mapping.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
areas:
area_tags:
- leisure
tables:
multilinestring:
type: linestring
columns:
- name: osm_id
type: id
- name: geometry
type: geometry
- name: name
type: string
key: name
- name: type
type: mapping_value
relation_types:
- route
mapping:
type:
- route
highway:
- trunk
building:
- residential
leisure:
- park
multilinestring_no_relations:
type: linestring
columns:
- name: osm_id
type: id
- name: geometry
type: geometry
- name: name
type: string
key: name
- name: type
type: mapping_value
mapping:
type:
- route
Loading