Add new relation_members table type
parent
1aff01cc9e
commit
423390ea71
|
@ -36,6 +36,7 @@ type Inserter interface {
|
||||||
InsertPoint(element.OSMElem, geom.Geometry, []mapping.Match) error
|
InsertPoint(element.OSMElem, geom.Geometry, []mapping.Match) error
|
||||||
InsertLineString(element.OSMElem, geom.Geometry, []mapping.Match) error
|
InsertLineString(element.OSMElem, geom.Geometry, []mapping.Match) error
|
||||||
InsertPolygon(element.OSMElem, geom.Geometry, []mapping.Match) error
|
InsertPolygon(element.OSMElem, geom.Geometry, []mapping.Match) error
|
||||||
|
InsertRelationMember(element.Relation, element.Member, geom.Geometry, []mapping.Match) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type Deployer interface {
|
type Deployer interface {
|
||||||
|
@ -103,6 +104,9 @@ func (n *nullDb) Abort() error
|
||||||
func (n *nullDb) InsertPoint(element.OSMElem, geom.Geometry, []mapping.Match) error { return nil }
|
func (n *nullDb) InsertPoint(element.OSMElem, geom.Geometry, []mapping.Match) error { return nil }
|
||||||
func (n *nullDb) InsertLineString(element.OSMElem, geom.Geometry, []mapping.Match) error { return nil }
|
func (n *nullDb) InsertLineString(element.OSMElem, geom.Geometry, []mapping.Match) error { return nil }
|
||||||
func (n *nullDb) InsertPolygon(element.OSMElem, geom.Geometry, []mapping.Match) error { return nil }
|
func (n *nullDb) InsertPolygon(element.OSMElem, geom.Geometry, []mapping.Match) error { return nil }
|
||||||
|
func (n *nullDb) InsertRelationMember(element.Relation, element.Member, geom.Geometry, []mapping.Match) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func newNullDb(conf Config, m *mapping.Mapping) (DB, error) {
|
func newNullDb(conf Config, m *mapping.Mapping) (DB, error) {
|
||||||
return &nullDb{}, nil
|
return &nullDb{}, nil
|
||||||
|
|
|
@ -58,7 +58,7 @@ func createTable(tx *sql.Tx, spec TableSpec) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func addGeometryColumn(tx *sql.Tx, tableName string, spec TableSpec) error {
|
func addGeometryColumn(tx *sql.Tx, tableName string, spec TableSpec) error {
|
||||||
colName := "geometry"
|
colName := ""
|
||||||
for _, col := range spec.Columns {
|
for _, col := range spec.Columns {
|
||||||
if col.Type.Name() == "GEOMETRY" {
|
if col.Type.Name() == "GEOMETRY" {
|
||||||
colName = col.Name
|
colName = col.Name
|
||||||
|
@ -66,6 +66,10 @@ func addGeometryColumn(tx *sql.Tx, tableName string, spec TableSpec) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if colName == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
geomType := strings.ToUpper(spec.GeometryType)
|
geomType := strings.ToUpper(spec.GeometryType)
|
||||||
if geomType == "POLYGON" {
|
if geomType == "POLYGON" {
|
||||||
geomType = "GEOMETRY" // for multipolygon support
|
geomType = "GEOMETRY" // for multipolygon support
|
||||||
|
@ -480,6 +484,16 @@ func (pg *PostGIS) InsertPolygon(elem element.OSMElem, geom geom.Geometry, match
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pg *PostGIS) InsertRelationMember(rel element.Relation, m element.Member, geom geom.Geometry, matches []mapping.Match) error {
|
||||||
|
for _, match := range matches {
|
||||||
|
row := match.MemberRow(&rel, &m, &geom)
|
||||||
|
if err := pg.txRouter.Insert(match.Table.Name, row); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (pg *PostGIS) Delete(id int64, matches interface{}) error {
|
func (pg *PostGIS) Delete(id int64, matches interface{}) error {
|
||||||
if matches, ok := matches.([]mapping.Match); ok {
|
if matches, ok := matches.([]mapping.Match); ok {
|
||||||
for _, match := range matches {
|
for _, match := range matches {
|
||||||
|
|
|
@ -125,11 +125,19 @@ func (spec *TableSpec) DeleteSQL() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTableSpec(pg *PostGIS, t *mapping.Table) *TableSpec {
|
func NewTableSpec(pg *PostGIS, t *mapping.Table) *TableSpec {
|
||||||
|
var geomType string
|
||||||
|
switch t.Type {
|
||||||
|
case mapping.RelationMemberTable:
|
||||||
|
geomType = "geometry"
|
||||||
|
default:
|
||||||
|
geomType = string(t.Type)
|
||||||
|
}
|
||||||
|
|
||||||
spec := TableSpec{
|
spec := TableSpec{
|
||||||
Name: t.Name,
|
Name: t.Name,
|
||||||
FullName: pg.Prefix + t.Name,
|
FullName: pg.Prefix + t.Name,
|
||||||
Schema: pg.Config.ImportSchema,
|
Schema: pg.Config.ImportSchema,
|
||||||
GeometryType: string(t.Type),
|
GeometryType: geomType,
|
||||||
Srid: pg.Config.Srid,
|
Srid: pg.Config.Srid,
|
||||||
}
|
}
|
||||||
for _, field := range t.Fields {
|
for _, field := range t.Fields {
|
||||||
|
|
|
@ -149,6 +149,8 @@ func Update(oscFile string, geometryLimiter *limit.Limiter, expireor expire.Expi
|
||||||
relations,
|
relations,
|
||||||
db, progress,
|
db, progress,
|
||||||
tagmapping.PolygonMatcher(),
|
tagmapping.PolygonMatcher(),
|
||||||
|
tagmapping.RelationMatcher(),
|
||||||
|
tagmapping.RelationMemberMatcher(),
|
||||||
config.BaseOptions.Srid)
|
config.BaseOptions.Srid)
|
||||||
relWriter.SetLimiter(geometryLimiter)
|
relWriter.SetLimiter(geometryLimiter)
|
||||||
relWriter.SetExpireor(expireor)
|
relWriter.SetExpireor(expireor)
|
||||||
|
|
|
@ -72,6 +72,8 @@ type Member struct {
|
||||||
Type MemberType `json:"type"`
|
Type MemberType `json:"type"`
|
||||||
Role string `json:"role"`
|
Role string `json:"role"`
|
||||||
Way *Way `json:"-"`
|
Way *Way `json:"-"`
|
||||||
|
Node *Node `json:"-"`
|
||||||
|
Elem *OSMElem `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Relation struct {
|
type Relation struct {
|
||||||
|
|
|
@ -182,6 +182,8 @@ func Import() {
|
||||||
relations,
|
relations,
|
||||||
db, progress,
|
db, progress,
|
||||||
tagmapping.PolygonMatcher(),
|
tagmapping.PolygonMatcher(),
|
||||||
|
tagmapping.RelationMatcher(),
|
||||||
|
tagmapping.RelationMemberMatcher(),
|
||||||
config.BaseOptions.Srid)
|
config.BaseOptions.Srid)
|
||||||
relWriter.SetLimiter(geometryLimiter)
|
relWriter.SetLimiter(geometryLimiter)
|
||||||
relWriter.EnableConcurrent()
|
relWriter.EnableConcurrent()
|
||||||
|
|
|
@ -11,11 +11,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Field struct {
|
type Field struct {
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name"`
|
||||||
Key Key `yaml:"key"`
|
Key Key `yaml:"key"`
|
||||||
Keys []Key `yaml:"keys"`
|
Keys []Key `yaml:"keys"`
|
||||||
Type string `yaml:"type"`
|
Type string `yaml:"type"`
|
||||||
Args map[string]interface{} `yaml:"args"`
|
Args map[string]interface{} `yaml:"args"`
|
||||||
|
FromMembers bool `yaml:"from_members"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Table struct {
|
type Table struct {
|
||||||
|
@ -133,6 +134,10 @@ func (tt *TableType) UnmarshalJSON(data []byte) error {
|
||||||
*tt = PolygonTable
|
*tt = PolygonTable
|
||||||
case `"geometry"`:
|
case `"geometry"`:
|
||||||
*tt = GeometryTable
|
*tt = GeometryTable
|
||||||
|
case `"relation"`:
|
||||||
|
*tt = RelationTable
|
||||||
|
case `"relation_member"`:
|
||||||
|
*tt = RelationMemberTable
|
||||||
default:
|
default:
|
||||||
return errors.New("unknown type " + string(data))
|
return errors.New("unknown type " + string(data))
|
||||||
}
|
}
|
||||||
|
@ -140,10 +145,12 @@ func (tt *TableType) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PolygonTable TableType = "polygon"
|
PolygonTable TableType = "polygon"
|
||||||
LineStringTable TableType = "linestring"
|
LineStringTable TableType = "linestring"
|
||||||
PointTable TableType = "point"
|
PointTable TableType = "point"
|
||||||
GeometryTable TableType = "geometry"
|
GeometryTable TableType = "geometry"
|
||||||
|
RelationTable TableType = "relation"
|
||||||
|
RelationMemberTable TableType = "relation_member"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewMapping(filename string) (*Mapping, error) {
|
func NewMapping(filename string) (*Mapping, error) {
|
||||||
|
|
|
@ -17,26 +17,31 @@ var AvailableFieldTypes map[string]FieldType
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
AvailableFieldTypes = map[string]FieldType{
|
AvailableFieldTypes = map[string]FieldType{
|
||||||
"bool": {"bool", "bool", Bool, nil},
|
"bool": {"bool", "bool", Bool, nil, nil, false},
|
||||||
"boolint": {"boolint", "int8", BoolInt, nil},
|
"boolint": {"boolint", "int8", BoolInt, nil, nil, false},
|
||||||
"id": {"id", "int64", Id, nil},
|
"id": {"id", "int64", Id, nil, nil, false},
|
||||||
"string": {"string", "string", String, nil},
|
"string": {"string", "string", String, nil, nil, false},
|
||||||
"direction": {"direction", "int8", Direction, nil},
|
"direction": {"direction", "int8", Direction, nil, nil, false},
|
||||||
"integer": {"integer", "int32", Integer, nil},
|
"integer": {"integer", "int32", Integer, nil, nil, false},
|
||||||
"mapping_key": {"mapping_key", "string", KeyName, nil},
|
"mapping_key": {"mapping_key", "string", KeyName, nil, nil, false},
|
||||||
"mapping_value": {"mapping_value", "string", ValueName, nil},
|
"mapping_value": {"mapping_value", "string", ValueName, nil, nil, false},
|
||||||
"geometry": {"geometry", "geometry", Geometry, nil},
|
"relation_member_id": {"relation_member_id", "int64", nil, nil, RelationMemberID, true},
|
||||||
"validated_geometry": {"validated_geometry", "validated_geometry", Geometry, nil},
|
"relation_member_role": {"relation_member_role", "string", nil, nil, RelationMemberRole, true},
|
||||||
"hstore_tags": {"hstore_tags", "hstore_string", HstoreString, nil},
|
"relation_member_type": {"relation_member_type", "int8", nil, nil, RelationMemberType, true},
|
||||||
"wayzorder": {"wayzorder", "int32", WayZOrder, nil},
|
"relation_member_index": {"relation_member_index", "int32", nil, nil, RelationMemberIndex, true},
|
||||||
"pseudoarea": {"pseudoarea", "float32", PseudoArea, nil},
|
"geometry": {"geometry", "geometry", Geometry, nil, nil, false},
|
||||||
"zorder": {"zorder", "int32", nil, MakeZOrder},
|
"validated_geometry": {"validated_geometry", "validated_geometry", Geometry, nil, nil, false},
|
||||||
"enumerate": {"enumerate", "int32", nil, MakeEnumerate},
|
"hstore_tags": {"hstore_tags", "hstore_string", HstoreString, nil, nil, false},
|
||||||
"string_suffixreplace": {"string_suffixreplace", "string", nil, MakeSuffixReplace},
|
"wayzorder": {"wayzorder", "int32", WayZOrder, nil, nil, false},
|
||||||
|
"pseudoarea": {"pseudoarea", "float32", PseudoArea, nil, nil, false},
|
||||||
|
"zorder": {"zorder", "int32", nil, MakeZOrder, nil, false},
|
||||||
|
"enumerate": {"enumerate", "int32", nil, MakeEnumerate, nil, false},
|
||||||
|
"string_suffixreplace": {"string_suffixreplace", "string", nil, MakeSuffixReplace, nil, false},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type MakeValue func(string, *element.OSMElem, *geom.Geometry, Match) interface{}
|
type MakeValue func(string, *element.OSMElem, *geom.Geometry, Match) interface{}
|
||||||
|
type MakeMemberValue func(*element.Relation, *element.Member, Match) interface{}
|
||||||
|
|
||||||
type MakeMakeValue func(string, FieldType, Field) (MakeValue, error)
|
type MakeMakeValue func(string, FieldType, Field) (MakeValue, error)
|
||||||
|
|
||||||
|
@ -55,6 +60,22 @@ func (f *FieldSpec) Value(elem *element.OSMElem, geom *geom.Geometry, match Matc
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FieldSpec) MemberValue(rel *element.Relation, member *element.Member, geom *geom.Geometry, match Match) interface{} {
|
||||||
|
if f.Type.Func != nil {
|
||||||
|
if f.Type.FromMembers {
|
||||||
|
if member.Elem == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return f.Type.Func(member.Elem.Tags[string(f.Key)], member.Elem, geom, match)
|
||||||
|
}
|
||||||
|
return f.Type.Func(rel.Tags[string(f.Key)], &rel.OSMElem, geom, match)
|
||||||
|
}
|
||||||
|
if f.Type.MemberFunc != nil {
|
||||||
|
return f.Type.MemberFunc(rel, member, match)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type TableFields struct {
|
type TableFields struct {
|
||||||
fields []FieldSpec
|
fields []FieldSpec
|
||||||
}
|
}
|
||||||
|
@ -67,6 +88,14 @@ func (t *TableFields) MakeRow(elem *element.OSMElem, geom *geom.Geometry, match
|
||||||
return row
|
return row
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TableFields) MakeMemberRow(rel *element.Relation, member *element.Member, geom *geom.Geometry, match Match) []interface{} {
|
||||||
|
var row []interface{}
|
||||||
|
for _, field := range t.fields {
|
||||||
|
row = append(row, field.MemberValue(rel, member, geom, match))
|
||||||
|
}
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
|
||||||
func (field *Field) FieldType() *FieldType {
|
func (field *Field) FieldType() *FieldType {
|
||||||
if fieldType, ok := AvailableFieldTypes[field.Type]; ok {
|
if fieldType, ok := AvailableFieldTypes[field.Type]; ok {
|
||||||
if fieldType.MakeFunc != nil {
|
if fieldType.MakeFunc != nil {
|
||||||
|
@ -75,8 +104,9 @@ func (field *Field) FieldType() *FieldType {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
fieldType = FieldType{fieldType.Name, fieldType.GoType, makeValue, nil}
|
fieldType = FieldType{fieldType.Name, fieldType.GoType, makeValue, nil, nil, fieldType.FromMembers}
|
||||||
}
|
}
|
||||||
|
fieldType.FromMembers = field.FromMembers
|
||||||
return &fieldType
|
return &fieldType
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -101,10 +131,12 @@ func (t *Table) TableFields() *TableFields {
|
||||||
}
|
}
|
||||||
|
|
||||||
type FieldType struct {
|
type FieldType struct {
|
||||||
Name string
|
Name string
|
||||||
GoType string
|
GoType string
|
||||||
Func MakeValue
|
Func MakeValue
|
||||||
MakeFunc MakeMakeValue
|
MakeFunc MakeMakeValue
|
||||||
|
MemberFunc MakeMemberValue
|
||||||
|
FromMembers bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func Bool(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
|
func Bool(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
|
||||||
|
@ -145,6 +177,27 @@ func ValueName(val string, elem *element.OSMElem, geom *geom.Geometry, match Mat
|
||||||
return match.Value
|
return match.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RelationMemberType(rel *element.Relation, member *element.Member, match Match) interface{} {
|
||||||
|
return member.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func RelationMemberRole(rel *element.Relation, member *element.Member, match Match) interface{} {
|
||||||
|
return member.Role
|
||||||
|
}
|
||||||
|
|
||||||
|
func RelationMemberID(rel *element.Relation, member *element.Member, match Match) interface{} {
|
||||||
|
return member.Id
|
||||||
|
}
|
||||||
|
|
||||||
|
func RelationMemberIndex(rel *element.Relation, member *element.Member, match Match) interface{} {
|
||||||
|
for i := range rel.Members {
|
||||||
|
if rel.Members[i].Id == member.Id {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
func Direction(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
|
func Direction(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
|
||||||
if val == "1" || val == "yes" || val == "true" {
|
if val == "1" || val == "yes" || val == "true" {
|
||||||
return 1
|
return 1
|
||||||
|
|
|
@ -1,29 +1,47 @@
|
||||||
package mapping
|
package mapping
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "log"
|
||||||
|
|
||||||
"github.com/omniscale/imposm3/element"
|
"github.com/omniscale/imposm3/element"
|
||||||
"github.com/omniscale/imposm3/geom"
|
"github.com/omniscale/imposm3/geom"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *Mapping) PointMatcher() NodeMatcher {
|
func (m *Mapping) PointMatcher() NodeMatcher {
|
||||||
mappings := make(TagTables)
|
mappings := make(TagTables)
|
||||||
m.mappings("point", mappings)
|
m.mappings(PointTable, mappings)
|
||||||
filters := m.ElementFilters()
|
filters := m.ElementFilters()
|
||||||
return &tagMatcher{mappings, m.tables("point"), filters, false}
|
return &tagMatcher{mappings, m.tables(PointTable), filters, false}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mapping) LineStringMatcher() WayMatcher {
|
func (m *Mapping) LineStringMatcher() WayMatcher {
|
||||||
mappings := make(TagTables)
|
mappings := make(TagTables)
|
||||||
m.mappings("linestring", mappings)
|
m.mappings(LineStringTable, mappings)
|
||||||
filters := m.ElementFilters()
|
filters := m.ElementFilters()
|
||||||
return &tagMatcher{mappings, m.tables("linestring"), filters, false}
|
return &tagMatcher{mappings, m.tables(LineStringTable), filters, false}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mapping) PolygonMatcher() RelWayMatcher {
|
func (m *Mapping) PolygonMatcher() RelWayMatcher {
|
||||||
mappings := make(TagTables)
|
mappings := make(TagTables)
|
||||||
m.mappings("polygon", mappings)
|
m.mappings(PolygonTable, mappings)
|
||||||
filters := m.ElementFilters()
|
filters := m.ElementFilters()
|
||||||
return &tagMatcher{mappings, m.tables("polygon"), filters, true}
|
return &tagMatcher{mappings, m.tables(PolygonTable), filters, true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mapping) RelationMatcher() RelationMatcher {
|
||||||
|
mappings := make(TagTables)
|
||||||
|
m.mappings(RelationTable, mappings)
|
||||||
|
filters := m.ElementFilters()
|
||||||
|
log.Print(mappings)
|
||||||
|
return &tagMatcher{mappings, m.tables(RelationTable), filters, true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mapping) RelationMemberMatcher() RelationMatcher {
|
||||||
|
mappings := make(TagTables)
|
||||||
|
m.mappings(RelationMemberTable, mappings)
|
||||||
|
filters := m.ElementFilters()
|
||||||
|
log.Print(mappings)
|
||||||
|
return &tagMatcher{mappings, m.tables(RelationMemberTable), filters, true}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Match struct {
|
type Match struct {
|
||||||
|
@ -61,6 +79,10 @@ func (m *Match) Row(elem *element.OSMElem, geom *geom.Geometry) []interface{} {
|
||||||
return m.tableFields.MakeRow(elem, geom, *m)
|
return m.tableFields.MakeRow(elem, geom, *m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Match) MemberRow(rel *element.Relation, member *element.Member, geom *geom.Geometry) []interface{} {
|
||||||
|
return m.tableFields.MakeMemberRow(rel, member, geom, *m)
|
||||||
|
}
|
||||||
|
|
||||||
func (tm *tagMatcher) MatchNode(node *element.Node) []Match {
|
func (tm *tagMatcher) MatchNode(node *element.Node) []Match {
|
||||||
return tm.match(&node.Tags)
|
return tm.match(&node.Tags)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.PHONY: all test clean
|
.PHONY: all test clean files
|
||||||
|
|
||||||
ifdef VERBOSE
|
ifdef VERBOSE
|
||||||
TESTOPTS = -v
|
TESTOPTS = -v
|
||||||
|
@ -16,12 +16,16 @@ OSCGZ_FILES=$(addprefix build/,$(patsubst %.osc,%.osc.gz,$(wildcard *.osc)))
|
||||||
|
|
||||||
build/%.pbf: %.osm
|
build/%.pbf: %.osm
|
||||||
@mkdir -p build
|
@mkdir -p build
|
||||||
osmosis --read-xml $< --sort TypeThenId --write-pbf $@ omitmetadata=true
|
osmosis --read-xml $< --sort type="TypeThenId" --write-pbf $@ omitmetadata=true
|
||||||
|
|
||||||
build/%.osc.gz: %.osc
|
build/%.osc.gz: %.osc
|
||||||
@mkdir -p build
|
@mkdir -p build
|
||||||
gzip --stdout $< > $@
|
gzip --stdout $< > $@
|
||||||
|
|
||||||
test: $(PBF_FILES) $(OSCGZ_FILES)
|
files: $(PBF_FILES) $(OSCGZ_FILES)
|
||||||
|
|
||||||
|
test: files
|
||||||
(cd .. && godep go test ./test $(TESTOPTS))
|
(cd .. && godep go test ./test $(TESTOPTS))
|
||||||
|
|
||||||
|
route_relation: files
|
||||||
|
(cd .. && godep go test -test.run TestRouteRelation_ ./test $(TESTOPTS))
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<osmChange version="0.6" generator="Osmosis 0.41">
|
||||||
|
</osmChange>
|
|
@ -0,0 +1,113 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<osm version="0.6" generator="CGImap 0.4.0 (2097 thorn-01.openstreetmap.org)" copyright="OpenStreetMap and contributors" attribution="http://www.openstreetmap.org/copyright" license="http://opendatacommons.org/licenses/odbl/1-0/">
|
||||||
|
<node id="100101" version="1" timestamp="2015-12-31T23:59:99Z" lat="53.0" lon="8.200"/>
|
||||||
|
<node id="100102" version="1" timestamp="2015-12-31T23:59:99Z" lat="53.0" lon="8.201"/>
|
||||||
|
<node id="100103" version="1" timestamp="2015-12-31T23:59:99Z" lat="53.0" lon="8.202"/>
|
||||||
|
<node id="100104" version="1" timestamp="2015-12-31T23:59:99Z" lat="53.0" lon="8.203"/>
|
||||||
|
|
||||||
|
<node id="100201" version="1" timestamp="2015-12-31T23:59:99Z" lat="53.0001" lon="8.2000"/>
|
||||||
|
<node id="100211" version="1" timestamp="2015-12-31T23:59:99Z" lat="53.0001" lon="8.2001"/>
|
||||||
|
<node id="100202" version="1" timestamp="2015-12-31T23:59:99Z" lat="53.0001" lon="8.2010"/>
|
||||||
|
<node id="100212" version="1" timestamp="2015-12-31T23:59:99Z" lat="53.0001" lon="8.2011"/>
|
||||||
|
<node id="100203" version="1" timestamp="2015-12-31T23:59:99Z" lat="53.0001" lon="8.2020"/>
|
||||||
|
<node id="100213" version="1" timestamp="2015-12-31T23:59:99Z" lat="53.0001" lon="8.2021"/>
|
||||||
|
<node id="100204" version="1" timestamp="2015-12-31T23:59:99Z" lat="53.0001" lon="8.2030"/>
|
||||||
|
<node id="100214" version="1" timestamp="2015-12-31T23:59:99Z" lat="53.0001" lon="8.2031"/>
|
||||||
|
|
||||||
|
|
||||||
|
<way id="100501" version="1" timestamp="2015-12-31T23:59:99Z">
|
||||||
|
<nd ref="100101"/>
|
||||||
|
<nd ref="100102"/>
|
||||||
|
<tag k="highway" v="residential"/>
|
||||||
|
<tag k="name" v="Residential Street"/>
|
||||||
|
</way>
|
||||||
|
|
||||||
|
<way id="100502" version="1" timestamp="2015-12-31T23:59:99Z">
|
||||||
|
<nd ref="100102"/>
|
||||||
|
<nd ref="100103"/>
|
||||||
|
<tag k="highway" v="residential"/>
|
||||||
|
<tag k="name" v="Residential Street"/>
|
||||||
|
</way>
|
||||||
|
|
||||||
|
<way id="100503" version="1" timestamp="2015-12-31T23:59:99Z">
|
||||||
|
<nd ref="100103"/>
|
||||||
|
<nd ref="100104"/>
|
||||||
|
<!-- untagged -->
|
||||||
|
</way>
|
||||||
|
|
||||||
|
<way id="100511" version="1" timestamp="2015-12-31T23:59:99Z">
|
||||||
|
<nd ref="100201"/>
|
||||||
|
<nd ref="100211"/>
|
||||||
|
</way>
|
||||||
|
|
||||||
|
<way id="100512" version="1" timestamp="2015-12-31T23:59:99Z">
|
||||||
|
<nd ref="100202"/>
|
||||||
|
<nd ref="100212"/>
|
||||||
|
</way>
|
||||||
|
|
||||||
|
<way id="100513" version="1" timestamp="2015-12-31T23:59:99Z">
|
||||||
|
<nd ref="100203"/>
|
||||||
|
<nd ref="100213"/>
|
||||||
|
</way>
|
||||||
|
|
||||||
|
<way id="100514" version="1" timestamp="2015-12-31T23:59:99Z">
|
||||||
|
<nd ref="100204"/>
|
||||||
|
<nd ref="100214"/>
|
||||||
|
</way>
|
||||||
|
|
||||||
|
<relation id="100901" version="23" timestamp="2015-06-02T04:13:19Z">
|
||||||
|
<member type="node" ref="100101" role="stop_entry_only"/>
|
||||||
|
<member type="way" ref="100511" role="platform_entry_only"/>
|
||||||
|
<member type="node" ref="100102" role="stop"/>
|
||||||
|
<member type="way" ref="100512" role="platform"/>
|
||||||
|
<member type="node" ref="100103" role="stop"/>
|
||||||
|
<member type="way" ref="100513" role="platform"/>
|
||||||
|
<member type="node" ref="100104" role="stop_exit_only"/>
|
||||||
|
<member type="way" ref="100514" role="platform_exit_only"/>
|
||||||
|
<member type="way" ref="100501" role=""/>
|
||||||
|
<member type="way" ref="100502" role=""/>
|
||||||
|
<member type="way" ref="100503" role=""/>
|
||||||
|
<tag k="colour" v="#F5A9E1"/>
|
||||||
|
<tag k="from" v="A"/>
|
||||||
|
<tag k="name" v="Bus 301: A => B"/>
|
||||||
|
<tag k="network" v="ABC"/>
|
||||||
|
<tag k="ref" v="301"/>
|
||||||
|
<tag k="route" v="bus"/>
|
||||||
|
<tag k="to" v="B"/>
|
||||||
|
<tag k="type" v="route"/>
|
||||||
|
</relation>
|
||||||
|
|
||||||
|
<relation id="100902" version="23" timestamp="2015-06-02T04:13:19Z">
|
||||||
|
<member type="node" ref="100104" role="stop_entry_only"/>
|
||||||
|
<member type="way" ref="100514" role="platform_entry_only"/>
|
||||||
|
<member type="node" ref="100103" role="stop"/>
|
||||||
|
<member type="way" ref="100513" role="platform"/>
|
||||||
|
<member type="node" ref="100102" role="stop"/>
|
||||||
|
<member type="way" ref="100512" role="platform"/>
|
||||||
|
<member type="node" ref="100101" role="stop_exit_only"/>
|
||||||
|
<member type="way" ref="100511" role="platform_exit_only"/>
|
||||||
|
<member type="way" ref="100503" role=""/>
|
||||||
|
<member type="way" ref="100502" role=""/>
|
||||||
|
<member type="way" ref="100501" role=""/>
|
||||||
|
<tag k="colour" v="#F5A9E1"/>
|
||||||
|
<tag k="from" v="B"/>
|
||||||
|
<tag k="name" v="Bus 301: B => A"/>
|
||||||
|
<tag k="network" v="ABC"/>
|
||||||
|
<tag k="ref" v="301"/>
|
||||||
|
<tag k="route" v="bus"/>
|
||||||
|
<tag k="to" v="A"/>
|
||||||
|
<tag k="type" v="route"/>
|
||||||
|
</relation>
|
||||||
|
|
||||||
|
<relation id="100903" version="23" timestamp="2015-06-02T04:13:19Z">
|
||||||
|
<member type="relation" ref="100901" role=""/>
|
||||||
|
<member type="relation" ref="100902" role=""/>
|
||||||
|
<tag k="colour" v="#F5A9E1"/>
|
||||||
|
<tag k="name" v="Bus 301"/>
|
||||||
|
<tag k="network" v="ABC"/>
|
||||||
|
<tag k="ref" v="301"/>
|
||||||
|
<tag k="route_master" v="bus"/>
|
||||||
|
<tag k="type" v="route_master"/>
|
||||||
|
</relation>
|
||||||
|
|
||||||
|
</osm>
|
|
@ -0,0 +1,128 @@
|
||||||
|
{
|
||||||
|
"tags": {
|
||||||
|
"load_all": true,
|
||||||
|
"exclude": [
|
||||||
|
"created_by",
|
||||||
|
"source"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tables": {
|
||||||
|
"route_members": {
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"type": "id",
|
||||||
|
"name": "osm_id"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"name": "ref",
|
||||||
|
"key": "ref"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation_member_id",
|
||||||
|
"name": "member"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation_member_index",
|
||||||
|
"name": "index"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation_member_role",
|
||||||
|
"name": "role"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation_member_type",
|
||||||
|
"name": "type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "geometry",
|
||||||
|
"name": "geometry"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"name": "name",
|
||||||
|
"key": "name",
|
||||||
|
"from_members": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "relation_member",
|
||||||
|
"mapping": {
|
||||||
|
"route": [
|
||||||
|
"bus",
|
||||||
|
"tram",
|
||||||
|
"rail"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"routes": {
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"type": "id",
|
||||||
|
"name": "osm_id"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"name": "ref",
|
||||||
|
"key": "ref"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hstore_tags",
|
||||||
|
"name": "tags"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "relation",
|
||||||
|
"mapping": {
|
||||||
|
"route": [
|
||||||
|
"bus",
|
||||||
|
"tram",
|
||||||
|
"rail"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"master_routes": {
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"type": "id",
|
||||||
|
"name": "osm_id"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation_member_id",
|
||||||
|
"name": "member"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation_member_index",
|
||||||
|
"name": "index"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation_member_role",
|
||||||
|
"name": "role"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation_member_type",
|
||||||
|
"name": "type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "geometry",
|
||||||
|
"name": "geometry"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"name": "subname",
|
||||||
|
"key": "name",
|
||||||
|
"from_members": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"name": "name",
|
||||||
|
"key": "name"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "relation_member",
|
||||||
|
"mapping": {
|
||||||
|
"route_master": [
|
||||||
|
"bus"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/omniscale/imposm3/geom/geos"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRouteRelation_Prepare(t *testing.T) {
|
||||||
|
ts.dir = "/tmp/imposm3test"
|
||||||
|
ts.config = importConfig{
|
||||||
|
connection: "postgis://",
|
||||||
|
cacheDir: ts.dir,
|
||||||
|
osmFileName: "build/route_relation.pbf",
|
||||||
|
mappingFileName: "route_relation_mapping.json",
|
||||||
|
}
|
||||||
|
ts.g = geos.NewGeos()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
ts.db, err = sql.Open("postgres", "sslmode=disable")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ts.dropSchemas()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRouteRelation_Import(t *testing.T) {
|
||||||
|
if ts.tableExists(t, dbschemaImport, "osm_routes") != false {
|
||||||
|
t.Fatalf("table osm_routes exists in schema %s", dbschemaImport)
|
||||||
|
}
|
||||||
|
ts.importOsm(t)
|
||||||
|
if ts.tableExists(t, dbschemaImport, "osm_routes") != true {
|
||||||
|
t.Fatalf("table osm_routes does not exists in schema %s", dbschemaImport)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRouteRelation_Deploy(t *testing.T) {
|
||||||
|
ts.deployOsm(t)
|
||||||
|
if ts.tableExists(t, dbschemaImport, "osm_routes") != false {
|
||||||
|
t.Fatalf("table osm_routes exists in schema %s", dbschemaImport)
|
||||||
|
}
|
||||||
|
if ts.tableExists(t, dbschemaProduction, "osm_routes") != true {
|
||||||
|
t.Fatalf("table osm_routes does not exists in schema %s", dbschemaProduction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #######################################################################
|
||||||
|
|
||||||
|
func TestRouteRelation_Update(t *testing.T) {
|
||||||
|
ts.updateOsm(t, "./build/route_relation.osc.gz")
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
import psycopg2
|
||||||
|
import psycopg2.extras
|
||||||
|
|
||||||
|
import helper as t
|
||||||
|
|
||||||
|
psycopg2.extras.register_hstore(psycopg2.connect(**t.db_conf), globally=True)
|
||||||
|
|
||||||
|
mapping_file = 'route_relation_mapping.json'
|
||||||
|
|
||||||
|
def setup():
|
||||||
|
t.setup()
|
||||||
|
|
||||||
|
def teardown():
|
||||||
|
t.teardown()
|
||||||
|
|
||||||
|
RELOFFSET = int(-1e17)
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
def test_import():
|
||||||
|
"""Import succeeds"""
|
||||||
|
t.drop_schemas()
|
||||||
|
assert not t.table_exists('osm_routes', schema=t.TEST_SCHEMA_IMPORT)
|
||||||
|
t.imposm3_import(t.db_conf, './build/route_relation.pbf', mapping_file)
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_IMPORT)
|
||||||
|
|
||||||
|
def test_deploy():
|
||||||
|
"""Deploy succeeds"""
|
||||||
|
assert not t.table_exists('osm_routes', schema=t.TEST_SCHEMA_PRODUCTION)
|
||||||
|
t.imposm3_deploy(t.db_conf, mapping_file)
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_PRODUCTION)
|
||||||
|
assert not t.table_exists('osm_routes', schema=t.TEST_SCHEMA_IMPORT)
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
def test_update():
|
||||||
|
"""Diff import applies"""
|
||||||
|
t.imposm3_update(t.db_conf, './build/route_relation.osc.gz', mapping_file)
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
def test_deploy_and_revert_deploy():
|
||||||
|
"""Revert deploy succeeds"""
|
||||||
|
assert not t.table_exists('osm_routes', schema=t.TEST_SCHEMA_IMPORT)
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_PRODUCTION)
|
||||||
|
assert not t.table_exists('osm_routes', schema=t.TEST_SCHEMA_BACKUP)
|
||||||
|
|
||||||
|
# import again to have a new import schema
|
||||||
|
t.imposm3_import(t.db_conf, './build/route_relation.pbf', mapping_file)
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_IMPORT)
|
||||||
|
|
||||||
|
t.imposm3_deploy(t.db_conf, mapping_file)
|
||||||
|
assert not t.table_exists('osm_routes', schema=t.TEST_SCHEMA_IMPORT)
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_PRODUCTION)
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_BACKUP)
|
||||||
|
|
||||||
|
t.imposm3_revert_deploy(t.db_conf, mapping_file)
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_IMPORT)
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_PRODUCTION)
|
||||||
|
assert not t.table_exists('osm_routes', schema=t.TEST_SCHEMA_BACKUP)
|
||||||
|
|
||||||
|
def test_remove_backup():
|
||||||
|
"""Remove backup succeeds"""
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_IMPORT)
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_PRODUCTION)
|
||||||
|
assert not t.table_exists('osm_routes', schema=t.TEST_SCHEMA_BACKUP)
|
||||||
|
|
||||||
|
t.imposm3_deploy(t.db_conf, mapping_file)
|
||||||
|
|
||||||
|
assert not t.table_exists('osm_routes', schema=t.TEST_SCHEMA_IMPORT)
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_PRODUCTION)
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_BACKUP)
|
||||||
|
|
||||||
|
t.imposm3_remove_backups(t.db_conf, mapping_file)
|
||||||
|
|
||||||
|
assert not t.table_exists('osm_routes', schema=t.TEST_SCHEMA_IMPORT)
|
||||||
|
assert t.table_exists('osm_routes', schema=t.TEST_SCHEMA_PRODUCTION)
|
||||||
|
assert not t.table_exists('osm_routes', schema=t.TEST_SCHEMA_BACKUP)
|
||||||
|
|
|
@ -9,17 +9,19 @@ import (
|
||||||
"github.com/omniscale/imposm3/element"
|
"github.com/omniscale/imposm3/element"
|
||||||
"github.com/omniscale/imposm3/expire"
|
"github.com/omniscale/imposm3/expire"
|
||||||
geomp "github.com/omniscale/imposm3/geom"
|
geomp "github.com/omniscale/imposm3/geom"
|
||||||
"github.com/omniscale/imposm3/geom/geos"
|
geosp "github.com/omniscale/imposm3/geom/geos"
|
||||||
"github.com/omniscale/imposm3/mapping"
|
"github.com/omniscale/imposm3/mapping"
|
||||||
"github.com/omniscale/imposm3/stats"
|
"github.com/omniscale/imposm3/stats"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RelationWriter struct {
|
type RelationWriter struct {
|
||||||
OsmElemWriter
|
OsmElemWriter
|
||||||
singleIdSpace bool
|
singleIdSpace bool
|
||||||
rel chan *element.Relation
|
rel chan *element.Relation
|
||||||
polygonMatcher mapping.RelWayMatcher
|
polygonMatcher mapping.RelWayMatcher
|
||||||
maxGap float64
|
relationMatcher mapping.RelationMatcher
|
||||||
|
relationMemberMatcher mapping.RelationMatcher
|
||||||
|
maxGap float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRelationWriter(
|
func NewRelationWriter(
|
||||||
|
@ -30,6 +32,8 @@ func NewRelationWriter(
|
||||||
inserter database.Inserter,
|
inserter database.Inserter,
|
||||||
progress *stats.Statistics,
|
progress *stats.Statistics,
|
||||||
matcher mapping.RelWayMatcher,
|
matcher mapping.RelWayMatcher,
|
||||||
|
relMatcher mapping.RelationMatcher,
|
||||||
|
relMemberMatcher mapping.RelationMatcher,
|
||||||
srid int,
|
srid int,
|
||||||
) *OsmElemWriter {
|
) *OsmElemWriter {
|
||||||
maxGap := 1e-1 // 0.1m
|
maxGap := 1e-1 // 0.1m
|
||||||
|
@ -45,10 +49,12 @@ func NewRelationWriter(
|
||||||
inserter: inserter,
|
inserter: inserter,
|
||||||
srid: srid,
|
srid: srid,
|
||||||
},
|
},
|
||||||
singleIdSpace: singleIdSpace,
|
singleIdSpace: singleIdSpace,
|
||||||
polygonMatcher: matcher,
|
polygonMatcher: matcher,
|
||||||
rel: rel,
|
relationMatcher: relMatcher,
|
||||||
maxGap: maxGap,
|
relationMemberMatcher: relMemberMatcher,
|
||||||
|
rel: rel,
|
||||||
|
maxGap: maxGap,
|
||||||
}
|
}
|
||||||
rw.OsmElemWriter.writer = &rw
|
rw.OsmElemWriter.writer = &rw
|
||||||
return &rw.OsmElemWriter
|
return &rw.OsmElemWriter
|
||||||
|
@ -62,7 +68,7 @@ func (rw *RelationWriter) relId(id int64) int64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rw *RelationWriter) loop() {
|
func (rw *RelationWriter) loop() {
|
||||||
geos := geos.NewGeos()
|
geos := geosp.NewGeos()
|
||||||
geos.SetHandleSrid(rw.srid)
|
geos.SetHandleSrid(rw.srid)
|
||||||
defer geos.Finish()
|
defer geos.Finish()
|
||||||
|
|
||||||
|
@ -76,7 +82,7 @@ NextRel:
|
||||||
}
|
}
|
||||||
continue NextRel
|
continue NextRel
|
||||||
}
|
}
|
||||||
for _, m := range r.Members {
|
for i, m := range r.Members {
|
||||||
if m.Way == nil {
|
if m.Way == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -88,6 +94,76 @@ NextRel:
|
||||||
continue NextRel
|
continue NextRel
|
||||||
}
|
}
|
||||||
rw.NodesToSrid(m.Way.Nodes)
|
rw.NodesToSrid(m.Way.Nodes)
|
||||||
|
r.Members[i].Elem = &m.Way.OSMElem
|
||||||
|
}
|
||||||
|
|
||||||
|
relMemberMatches := rw.relationMemberMatcher.MatchRelation(r)
|
||||||
|
if len(relMemberMatches) > 0 {
|
||||||
|
for i, m := range r.Members {
|
||||||
|
if m.Type == element.RELATION {
|
||||||
|
mrel, err := rw.osmCache.Relations.GetRelation(m.Id)
|
||||||
|
if err != nil {
|
||||||
|
if err == cache.NotFound {
|
||||||
|
log.Warn(err)
|
||||||
|
continue NextRel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.Members[i].Elem = &mrel.OSMElem
|
||||||
|
} else if m.Type == element.NODE {
|
||||||
|
nd, err := rw.osmCache.Nodes.GetNode(m.Id)
|
||||||
|
if err != nil {
|
||||||
|
if err == cache.NotFound {
|
||||||
|
nd, err = rw.osmCache.Coords.GetCoord(m.Id)
|
||||||
|
if err != nil {
|
||||||
|
if err != cache.NotFound {
|
||||||
|
log.Warn(err)
|
||||||
|
}
|
||||||
|
continue NextRel
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Warn(err)
|
||||||
|
continue NextRel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rw.NodeToSrid(nd)
|
||||||
|
r.Members[i].Node = nd
|
||||||
|
r.Members[i].Elem = &nd.OSMElem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range r.Members {
|
||||||
|
var g *geosp.Geom
|
||||||
|
var err error
|
||||||
|
if m.Node != nil {
|
||||||
|
g, err = geomp.Point(geos, *m.Node)
|
||||||
|
} else if m.Way != nil {
|
||||||
|
g, err = geomp.LineString(geos, m.Way.Nodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Warn(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var gelem geomp.Geometry
|
||||||
|
if g == nil {
|
||||||
|
g = geos.FromWkt("POLYGON EMPTY")
|
||||||
|
gelem = geomp.Geometry{Geom: g, Wkb: geos.AsEwkbHex(g)}
|
||||||
|
} else {
|
||||||
|
gelem, err = geomp.AsGeomElement(geos, g)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rw.inserter.InsertRelationMember(*r, m, gelem, relMemberMatches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
relMatches := rw.relationMatcher.MatchRelation(r)
|
||||||
|
if len(relMatches) > 0 {
|
||||||
|
rw.inserter.InsertPolygon(r.OSMElem, geomp.Geometry{}, relMatches)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildRelation updates r.Members but we need all of them
|
// BuildRelation updates r.Members but we need all of them
|
||||||
|
|
Loading…
Reference in New Issue