remove Geom from OSMElem

removes GEOS depenency from pbf parser
Oliver Tonnhofer 2015-04-30 09:42:49 +02:00
parent dc4f320dd5
commit 7c438fb867
13 changed files with 221 additions and 190 deletions

View File

@ -2,9 +2,11 @@ package database
import (
"errors"
"github.com/omniscale/imposm3/element"
"github.com/omniscale/imposm3/mapping"
"strings"
"github.com/omniscale/imposm3/element"
"github.com/omniscale/imposm3/geom"
"github.com/omniscale/imposm3/mapping"
)
type Config struct {
@ -31,9 +33,9 @@ type BulkBeginner interface {
type Inserter interface {
// InsertXxx inserts element of that type into the database.
// element.Geom is set to that type.
InsertPoint(element.OSMElem, []mapping.Match) error
InsertLineString(element.OSMElem, []mapping.Match) error
InsertPolygon(element.OSMElem, []mapping.Match) error
InsertPoint(element.OSMElem, geom.Geometry, []mapping.Match) error
InsertLineString(element.OSMElem, geom.Geometry, []mapping.Match) error
InsertPolygon(element.OSMElem, geom.Geometry, []mapping.Match) error
}
type Deployer interface {
@ -93,14 +95,14 @@ func Open(conf Config, m *mapping.Mapping) (DB, error) {
// nullDb is a dummy database that imports into /dev/null
type nullDb struct{}
func (n *nullDb) Init() error { return nil }
func (n *nullDb) Begin() error { return nil }
func (n *nullDb) End() error { return nil }
func (n *nullDb) Close() error { return nil }
func (n *nullDb) Abort() error { return nil }
func (n *nullDb) InsertPoint(element.OSMElem, []mapping.Match) error { return nil }
func (n *nullDb) InsertLineString(element.OSMElem, []mapping.Match) error { return nil }
func (n *nullDb) InsertPolygon(element.OSMElem, []mapping.Match) error { return nil }
func (n *nullDb) Init() error { return nil }
func (n *nullDb) Begin() error { return nil }
func (n *nullDb) End() error { return nil }
func (n *nullDb) Close() error { return nil }
func (n *nullDb) Abort() 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) InsertPolygon(element.OSMElem, geom.Geometry, []mapping.Match) error { return nil }
func newNullDb(conf Config, m *mapping.Mapping) (DB, error) {
return &nullDb{}, nil

View File

@ -10,6 +10,7 @@ import (
pq "github.com/lib/pq"
"github.com/omniscale/imposm3/database"
"github.com/omniscale/imposm3/element"
"github.com/omniscale/imposm3/geom"
"github.com/omniscale/imposm3/logging"
"github.com/omniscale/imposm3/mapping"
)
@ -422,9 +423,9 @@ func (pg *PostGIS) Open() error {
return nil
}
func (pg *PostGIS) InsertPoint(elem element.OSMElem, matches []mapping.Match) error {
func (pg *PostGIS) InsertPoint(elem element.OSMElem, geom geom.Geometry, matches []mapping.Match) error {
for _, match := range matches {
row := match.Row(&elem)
row := match.Row(&elem, &geom)
if err := pg.txRouter.Insert(match.Table.Name, row); err != nil {
return err
}
@ -432,9 +433,9 @@ func (pg *PostGIS) InsertPoint(elem element.OSMElem, matches []mapping.Match) er
return nil
}
func (pg *PostGIS) InsertLineString(elem element.OSMElem, matches []mapping.Match) error {
func (pg *PostGIS) InsertLineString(elem element.OSMElem, geom geom.Geometry, matches []mapping.Match) error {
for _, match := range matches {
row := match.Row(&elem)
row := match.Row(&elem, &geom)
if err := pg.txRouter.Insert(match.Table.Name, row); err != nil {
return err
}
@ -447,9 +448,9 @@ func (pg *PostGIS) InsertLineString(elem element.OSMElem, matches []mapping.Matc
return nil
}
func (pg *PostGIS) InsertPolygon(elem element.OSMElem, matches []mapping.Match) error {
func (pg *PostGIS) InsertPolygon(elem element.OSMElem, geom geom.Geometry, matches []mapping.Match) error {
for _, match := range matches {
row := match.Row(&elem)
row := match.Row(&elem, &geom)
if err := pg.txRouter.Insert(match.Table.Name, row); err != nil {
return err
}

View File

@ -4,8 +4,6 @@ import (
"fmt"
"math"
"sort"
"github.com/omniscale/imposm3/geom/geos"
)
type Tags map[string]string
@ -15,9 +13,8 @@ func (t *Tags) String() string {
}
type OSMElem struct {
Id int64 `json:"-"`
Tags Tags `json:"tags,omitempty"`
Geom *Geometry `json:"-"`
Id int64 `json:"-"`
Tags Tags `json:"tags,omitempty"`
}
type Node struct {
@ -32,11 +29,6 @@ type Way struct {
Nodes []Node `json:"nodes,omitempty"`
}
type Geometry struct {
Geom *geos.Geom
Wkb []byte
}
func (w *Way) IsClosed() bool {
return len(w.Refs) >= 4 && w.Refs[0] == w.Refs[len(w.Refs)-1]
}

View File

@ -2,9 +2,10 @@ package geom
import (
"errors"
"math"
"github.com/omniscale/imposm3/element"
"github.com/omniscale/imposm3/geom/geos"
"math"
)
type GeomError struct {
@ -12,6 +13,11 @@ type GeomError struct {
level int
}
type Geometry struct {
Geom *geos.Geom
Wkb []byte
}
func (e *GeomError) Error() string {
return e.message
}
@ -130,13 +136,13 @@ func Polygon(g *geos.Geos, nodes []element.Node) (*geos.Geom, error) {
return geom, nil
}
func AsGeomElement(g *geos.Geos, geom *geos.Geom) (*element.Geometry, error) {
func AsGeomElement(g *geos.Geos, geom *geos.Geom) (Geometry, error) {
wkb := g.AsEwkbHex(geom)
if wkb == nil {
return nil, errors.New("could not create wkb")
return Geometry{}, errors.New("could not create wkb")
}
return &element.Geometry{
return Geometry{
Wkb: wkb,
Geom: geom,
}, nil

View File

@ -8,30 +8,42 @@ import (
"github.com/omniscale/imposm3/geom/geos"
)
type preparedRelation struct {
type PreparedRelation struct {
rings []*Ring
rel *element.Relation
srid int
}
func PrepareRelation(rel *element.Relation, srid int, maxRingGap float64) (*preparedRelation, error) {
rings, err := BuildRings(rel, maxRingGap)
// PrepareRelation is the first step in building a (multi-)polygon of a Relation.
// It builds rings from all ways and returns an error if there are unclosed rings.
// It also merges the Relation.Tags with the Tags of the outer way.
func PrepareRelation(rel *element.Relation, srid int, maxRingGap float64) (PreparedRelation, error) {
rings, err := buildRings(rel, maxRingGap)
if err != nil {
return nil, err
return PreparedRelation{}, err
}
rel.Tags = relationTags(rel.Tags, rings[0].ways[0].Tags)
return &preparedRelation{rings, rel, srid}, nil
return PreparedRelation{rings, rel, srid}, nil
}
func (prep *preparedRelation) Build() (*element.Relation, error) {
_, err := BuildRelGeometry(prep.rel, prep.rings, prep.srid)
if err != nil {
return nil, err
}
return prep.rel, nil
// Build creates the (multi)polygon Geometry of the Relation.
func (prep *PreparedRelation) Build() (Geometry, error) {
g := geos.NewGeos()
g.SetHandleSrid(prep.srid)
defer g.Finish()
geom, err := buildRelGeometry(g, prep.rel, prep.rings)
if err != nil {
return Geometry{}, err
}
wkb := g.AsEwkbHex(geom)
if wkb == nil {
return Geometry{}, errors.New("unable to create WKB for relation")
}
return Geometry{Geom: geom, Wkb: wkb}, nil
}
func destroyRings(g *geos.Geos, rings []*Ring) {
@ -43,7 +55,7 @@ func destroyRings(g *geos.Geos, rings []*Ring) {
}
}
func BuildRings(rel *element.Relation, maxRingGap float64) ([]*Ring, error) {
func buildRings(rel *element.Relation, maxRingGap float64) ([]*Ring, error) {
var rings []*Ring
var incompleteRings []*Ring
var completeRings []*Ring
@ -114,13 +126,9 @@ func (r SortableRingsDesc) Len() int { return len(r) }
func (r SortableRingsDesc) Less(i, j int) bool { return r[i].area > r[j].area }
func (r SortableRingsDesc) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
// BuildRelGeometry builds the geometry of rel by creating a multipolygon of all rings.
// buildRelGeometry builds the geometry of rel by creating a multipolygon of all rings.
// rings need to be sorted by area (large to small).
func BuildRelGeometry(rel *element.Relation, rings []*Ring, srid int) (*geos.Geom, error) {
g := geos.NewGeos()
g.SetHandleSrid(srid)
defer g.Finish()
func buildRelGeometry(g *geos.Geos, rel *element.Relation, rings []*Ring) (*geos.Geom, error) {
totalRings := len(rings)
shells := map[*Ring]bool{rings[0]: true}
for i := 0; i < totalRings; i++ {
@ -216,12 +224,6 @@ func BuildRelGeometry(rel *element.Relation, rings []*Ring, srid int) (*geos.Geo
}
}
wkb := g.AsEwkbHex(result)
if wkb == nil {
return nil, errors.New("unable to create WKB for relation")
}
rel.Geom = &element.Geometry{Geom: result, Wkb: wkb}
return result, nil
}

View File

@ -26,14 +26,13 @@ func makeWay(id int64, tags element.Tags, coords []coord) element.Way {
return way
}
func buildRelation(rel *element.Relation, srid int) error {
func buildRelation(rel *element.Relation, srid int) (Geometry, error) {
prep, err := PrepareRelation(rel, srid, 0.1)
if err != nil {
return err
return Geometry{}, err
}
_, err = prep.Build()
return err
return prep.Build()
}
func TestSimplePolygonWithHole(t *testing.T) {
@ -59,7 +58,10 @@ func TestSimplePolygonWithHole(t *testing.T) {
{2, element.WAY, "inner", &w2},
}
buildRelation(&rel, 3857)
geom, err := buildRelation(&rel, 3857)
if err != nil {
t.Fatal(err)
}
g := geos.NewGeos()
defer g.Finish()
@ -67,11 +69,11 @@ func TestSimplePolygonWithHole(t *testing.T) {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(rel.Geom.Geom))
if !g.IsValid(geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
}
if area := rel.Geom.Geom.Area(); area != 100-36 {
if area := geom.Geom.Area(); area != 100-36 {
t.Fatal("area invalid", area)
}
}
@ -99,7 +101,10 @@ func TestMultiPolygonWithHoleAndRelName(t *testing.T) {
{2, element.WAY, "inner", &w2},
}
buildRelation(&rel, 3857)
geom, err := buildRelation(&rel, 3857)
if err != nil {
t.Fatal(err)
}
g := geos.NewGeos()
defer g.Finish()
@ -110,11 +115,11 @@ func TestMultiPolygonWithHoleAndRelName(t *testing.T) {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(rel.Geom.Geom))
if !g.IsValid(geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
}
if area := rel.Geom.Geom.Area(); area != 64 {
if area := geom.Geom.Area(); area != 64 {
t.Fatal("aread not 64", area)
}
}
@ -150,7 +155,10 @@ func TestMultiPolygonWithMultipleHoles(t *testing.T) {
{3, element.WAY, "inner", &w3},
}
buildRelation(&rel, 3857)
geom, err := buildRelation(&rel, 3857)
if err != nil {
t.Fatal(err)
}
g := geos.NewGeos()
defer g.Finish()
@ -161,11 +169,11 @@ func TestMultiPolygonWithMultipleHoles(t *testing.T) {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(rel.Geom.Geom))
if !g.IsValid(geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
}
if area := rel.Geom.Geom.Area(); area != 100-1-1 {
if area := geom.Geom.Area(); area != 100-1-1 {
t.Fatal("area invalid", area)
}
}
@ -216,7 +224,10 @@ func TestMultiPolygonWithNeastedHoles(t *testing.T) {
{5, element.WAY, "inner", &w5},
}
buildRelation(&rel, 3857)
geom, err := buildRelation(&rel, 3857)
if err != nil {
t.Fatal(err)
}
g := geos.NewGeos()
defer g.Finish()
@ -227,11 +238,11 @@ func TestMultiPolygonWithNeastedHoles(t *testing.T) {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(rel.Geom.Geom))
if !g.IsValid(geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
}
if area := rel.Geom.Geom.Area(); area != 100-64+36-16+4 {
if area := geom.Geom.Area(); area != 100-64+36-16+4 {
t.Fatal("area invalid", area)
}
}
@ -258,7 +269,10 @@ func TestPolygonFromThreeWays(t *testing.T) {
{3, element.WAY, "inner", &w3},
}
buildRelation(&rel, 3857)
geom, err := buildRelation(&rel, 3857)
if err != nil {
t.Fatal(err)
}
g := geos.NewGeos()
defer g.Finish()
@ -269,11 +283,11 @@ func TestPolygonFromThreeWays(t *testing.T) {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(rel.Geom.Geom))
if !g.IsValid(geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
}
if area := rel.Geom.Geom.Area(); area != 100 {
if area := geom.Geom.Area(); area != 100 {
t.Fatal("area invalid", area)
}
}
@ -307,7 +321,10 @@ func TestTouchingPolygonsWithHole(t *testing.T) {
{2, element.WAY, "outer", &w2},
{3, element.WAY, "inner", &w3},
}
buildRelation(&rel, 3857)
geom, err := buildRelation(&rel, 3857)
if err != nil {
t.Fatal(err)
}
g := geos.NewGeos()
defer g.Finish()
@ -319,11 +336,11 @@ func TestTouchingPolygonsWithHole(t *testing.T) {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(rel.Geom.Geom))
if !g.IsValid(geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
}
if area := rel.Geom.Geom.Area(); area != 100+200-36 {
if area := geom.Geom.Area(); area != 100+200-36 {
t.Fatal("area invalid", area)
}
}
@ -346,7 +363,10 @@ func TestInsertedWaysDifferentTags(t *testing.T) {
{2, element.WAY, "inner", &w2},
}
buildRelation(&rel, 3857)
geom, err := buildRelation(&rel, 3857)
if err != nil {
t.Fatal(err)
}
g := geos.NewGeos()
defer g.Finish()
@ -358,11 +378,11 @@ func TestInsertedWaysDifferentTags(t *testing.T) {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(rel.Geom.Geom))
if !g.IsValid(geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
}
if area := rel.Geom.Geom.Area(); area != 100 {
if area := geom.Geom.Area(); area != 100 {
t.Fatal("area invalid", area)
}
}
@ -385,7 +405,10 @@ func TestInsertMultipleTags(t *testing.T) {
{2, element.WAY, "inner", &w2},
}
buildRelation(&rel, 3857)
geom, err := buildRelation(&rel, 3857)
if err != nil {
t.Fatal(err)
}
g := geos.NewGeos()
defer g.Finish()
@ -393,11 +416,11 @@ func TestInsertMultipleTags(t *testing.T) {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(rel.Geom.Geom))
if !g.IsValid(geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
}
if area := rel.Geom.Geom.Area(); area != 100 {
if area := geom.Geom.Area(); area != 100 {
t.Fatal("area invalid", area)
}
}
@ -431,7 +454,7 @@ func TestBrokenPolygonSelfIntersect(t *testing.T) {
{2, element.WAY, "inner", &w2},
}
err := buildRelation(&rel1, 3857)
geom1, err := buildRelation(&rel1, 3857)
if err != nil {
t.Fatal(err)
}
@ -442,11 +465,11 @@ func TestBrokenPolygonSelfIntersect(t *testing.T) {
t.Fatal("wrong rel tags", rel1.Tags)
}
if !g.IsValid(rel1.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(rel1.Geom.Geom))
if !g.IsValid(geom1.Geom) {
t.Fatal("geometry not valid", g.AsWkt(geom1.Geom))
}
if area := rel1.Geom.Geom.Area(); area != 200-36 {
if area := geom1.Geom.Area(); area != 200-36 {
t.Fatal("area invalid", area)
}
@ -472,7 +495,7 @@ func TestBrokenPolygonSelfIntersect(t *testing.T) {
{2, element.WAY, "inner", &w2},
}
err = buildRelation(&rel2, 3857)
geom2, err := buildRelation(&rel2, 3857)
if err != nil {
t.Fatal(err)
}
@ -484,11 +507,11 @@ func TestBrokenPolygonSelfIntersect(t *testing.T) {
t.Fatal("wrong rel tags", rel2.Tags)
}
if !g.IsValid(rel2.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(rel2.Geom.Geom))
if !g.IsValid(geom2.Geom) {
t.Fatal("geometry not valid", g.AsWkt(geom2.Geom))
}
if area := rel2.Geom.Geom.Area(); area != 200-36 {
if area := geom2.Geom.Area(); area != 200-36 {
t.Fatal("area invalid", area)
}
}
@ -521,7 +544,7 @@ func TestBrokenPolygonSelfIntersectTriangle(t *testing.T) {
{2, element.WAY, "inner", &w2},
}
err := buildRelation(&rel, 3857)
geom, err := buildRelation(&rel, 3857)
if err != nil {
t.Fatal(err)
}
@ -529,11 +552,11 @@ func TestBrokenPolygonSelfIntersectTriangle(t *testing.T) {
g := geos.NewGeos()
defer g.Finish()
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(rel.Geom.Geom))
if !g.IsValid(geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
}
area := rel.Geom.Geom.Area()
area := geom.Geom.Area()
// as for python assertAlmostEqual(a, b) round(a-b, 7) == 0
if math.Abs(area-(100*100/2-100)) > 0.01 {
t.Fatal("area invalid", area)
@ -561,16 +584,16 @@ func TestBrokenPolygonSelfIntersectTriangle(t *testing.T) {
{2, element.WAY, "inner", &w4},
}
err = buildRelation(&rel, 3857)
geom, err = buildRelation(&rel, 3857)
if err != nil {
t.Fatal(err)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(rel.Geom.Geom))
if !g.IsValid(geom.Geom) {
t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
}
area = rel.Geom.Geom.Area()
area = geom.Geom.Area()
if math.Abs((area - (100*98/2 - 100))) > 10 {
t.Fatal("area invalid", area)

View File

@ -7,6 +7,7 @@ import (
"strings"
"github.com/omniscale/imposm3/element"
"github.com/omniscale/imposm3/geom"
"github.com/omniscale/imposm3/logging"
)
@ -34,7 +35,7 @@ func init() {
}
}
type MakeValue func(string, *element.OSMElem, Match) interface{}
type MakeValue func(string, *element.OSMElem, *geom.Geometry, Match) interface{}
type MakeMakeValue func(string, FieldType, Field) (MakeValue, error)
@ -46,9 +47,9 @@ type FieldSpec struct {
Type FieldType
}
func (f *FieldSpec) Value(elem *element.OSMElem, match Match) interface{} {
func (f *FieldSpec) Value(elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
if f.Type.Func != nil {
return f.Type.Func(elem.Tags[string(f.Key)], elem, match)
return f.Type.Func(elem.Tags[string(f.Key)], elem, geom, match)
}
return nil
}
@ -57,10 +58,10 @@ type TableFields struct {
fields []FieldSpec
}
func (t *TableFields) MakeRow(elem *element.OSMElem, match Match) []interface{} {
func (t *TableFields) MakeRow(elem *element.OSMElem, geom *geom.Geometry, match Match) []interface{} {
var row []interface{}
for _, field := range t.fields {
row = append(row, field.Value(elem, match))
row = append(row, field.Value(elem, geom, match))
}
return row
}
@ -105,25 +106,25 @@ type FieldType struct {
MakeFunc MakeMakeValue
}
func Bool(val string, elem *element.OSMElem, match Match) interface{} {
func Bool(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
if val == "" || val == "0" || val == "false" || val == "no" {
return false
}
return true
}
func BoolInt(val string, elem *element.OSMElem, match Match) interface{} {
func BoolInt(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
if val == "" || val == "0" || val == "false" || val == "no" {
return 0
}
return 1
}
func String(val string, elem *element.OSMElem, match Match) interface{} {
func String(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
return val
}
func Integer(val string, elem *element.OSMElem, match Match) interface{} {
func Integer(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
v, err := strconv.ParseInt(val, 10, 32)
if err != nil {
return nil
@ -131,19 +132,19 @@ func Integer(val string, elem *element.OSMElem, match Match) interface{} {
return v
}
func Id(val string, elem *element.OSMElem, match Match) interface{} {
func Id(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
return elem.Id
}
func KeyName(val string, elem *element.OSMElem, match Match) interface{} {
func KeyName(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
return match.Key
}
func ValueName(val string, elem *element.OSMElem, match Match) interface{} {
func ValueName(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
return match.Value
}
func Direction(val string, elem *element.OSMElem, match Match) interface{} {
func Direction(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
if val == "1" || val == "yes" || val == "true" {
return 1
} else if val == "-1" {
@ -153,12 +154,12 @@ func Direction(val string, elem *element.OSMElem, match Match) interface{} {
}
}
func Geometry(val string, elem *element.OSMElem, match Match) interface{} {
return string(elem.Geom.Wkb)
func Geometry(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
return string(geom.Wkb)
}
func PseudoArea(val string, elem *element.OSMElem, match Match) interface{} {
area := elem.Geom.Geom.Area()
func PseudoArea(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
area := geom.Geom.Area()
if area == 0.0 {
return nil
}
@ -167,7 +168,7 @@ func PseudoArea(val string, elem *element.OSMElem, match Match) interface{} {
var hstoreReplacer = strings.NewReplacer("\\", "\\\\", "\"", "\\\"")
func HstoreString(val string, elem *element.OSMElem, match Match) interface{} {
func HstoreString(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
tags := make([]string, 0, len(elem.Tags))
for k, v := range elem.Tags {
tags = append(tags, `"`+hstoreReplacer.Replace(k)+`"=>"`+hstoreReplacer.Replace(v)+`"`)
@ -196,7 +197,7 @@ func init() {
}
}
func WayZOrder(val string, elem *element.OSMElem, match Match) interface{} {
func WayZOrder(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
var z int32
layer, _ := strconv.ParseInt(elem.Tags["layer"], 10, 64)
z += int32(layer) * 10
@ -252,7 +253,7 @@ func MakeZOrder(fieldName string, fieldType FieldType, field Field) (MakeValue,
ranks[rankName] = len(rankList) - i
}
zOrder := func(val string, elem *element.OSMElem, match Match) interface{} {
zOrder := func(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
if key != "" {
if r, ok := ranks[elem.Tags[key]]; ok {
return r
@ -290,7 +291,7 @@ func MakeSuffixReplace(fieldName string, fieldType FieldType, field Field) (Make
return changes[match].(string)
}
suffixReplace := func(val string, elem *element.OSMElem, match Match) interface{} {
suffixReplace := func(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
if val != "" {
return re.ReplaceAllStringFunc(val, replFunc)
}

View File

@ -8,31 +8,31 @@ import (
func TestBool(t *testing.T) {
match := Match{}
if false != Bool("", nil, match) {
if false != Bool("", nil, nil, match) {
t.Fatal()
}
if false != Bool("false", nil, match) {
if false != Bool("false", nil, nil, match) {
t.Fatal()
}
if false != Bool("no", nil, match) {
if false != Bool("no", nil, nil, match) {
t.Fatal()
}
if false != Bool("0", nil, match) {
if false != Bool("0", nil, nil, match) {
t.Fatal()
}
if true != Bool("yes", nil, match) {
if true != Bool("yes", nil, nil, match) {
t.Fatal()
}
if true != Bool("1", nil, match) {
if true != Bool("1", nil, nil, match) {
t.Fatal()
}
if true != Bool("true", nil, match) {
if true != Bool("true", nil, nil, match) {
t.Fatal()
}
// Bool defaults to true
if true != Bool("other", nil, match) {
if true != Bool("other", nil, nil, match) {
t.Fatal()
}
@ -40,30 +40,30 @@ func TestBool(t *testing.T) {
func TestInteger(t *testing.T) {
match := Match{}
if v := Integer("", nil, match); v != nil {
if v := Integer("", nil, nil, match); v != nil {
t.Errorf(" -> %v", v)
}
if v := Integer("bar", nil, match); v != nil {
if v := Integer("bar", nil, nil, match); v != nil {
t.Errorf("bar -> %v", v)
}
if v := Integer("1e6", nil, match); v != nil {
if v := Integer("1e6", nil, nil, match); v != nil {
t.Errorf("1e6 -> %v", v)
}
if v := Integer("0", nil, match); v.(int64) != 0 {
if v := Integer("0", nil, nil, match); v.(int64) != 0 {
t.Errorf("0 -> %v", v)
}
if v := Integer("123456", nil, match); v.(int64) != 123456 {
if v := Integer("123456", nil, nil, match); v.(int64) != 123456 {
t.Errorf("123456 -> %v", v)
}
if v := Integer("-123456", nil, match); v.(int64) != -123456 {
if v := Integer("-123456", nil, nil, match); v.(int64) != -123456 {
t.Errorf("-123456 -> %v", v)
}
// >2^32, but <2^64, Integer type defaults to int32
if v := Integer("1000000000000000000", nil, match); v != nil {
if v := Integer("1000000000000000000", nil, nil, match); v != nil {
t.Errorf("1000000000000000000 -> %v", v)
}
// >2^64
if v := Integer("19082139812039812093908123", nil, match); v != nil {
if v := Integer("19082139812039812093908123", nil, nil, match); v != nil {
t.Errorf("19082139812039812093908123 -> %v", v)
}
}
@ -86,23 +86,23 @@ func TestZOrder(t *testing.T) {
elem := &element.OSMElem{}
elem.Tags = element.Tags{} // missing
if v := zOrder("", elem, match); v != 0 {
if v := zOrder("", elem, nil, match); v != 0 {
t.Errorf(" -> %v", v)
}
elem.Tags = element.Tags{"fips": "ABCD"} // unknown
if v := zOrder("", elem, match); v != 0 {
if v := zOrder("", elem, nil, match); v != 0 {
t.Errorf(" -> %v", v)
}
elem.Tags = element.Tags{"fips": "AA"}
if v := zOrder("", elem, match); v != 4 {
if v := zOrder("", elem, nil, match); v != 4 {
t.Errorf(" -> %v", v)
}
elem.Tags = element.Tags{"fips": "CC"}
if v := zOrder("", elem, match); v != 3 {
if v := zOrder("", elem, nil, match); v != 3 {
t.Errorf(" -> %v", v)
}
elem.Tags = element.Tags{"fips": "ZZ"}
if v := zOrder("", elem, match); v != 1 {
if v := zOrder("", elem, nil, match); v != 1 {
t.Errorf(" -> %v", v)
}
}
@ -117,13 +117,13 @@ func TestMakeSuffixReplace(t *testing.T) {
t.Fatal(err)
}
if result := suffixReplace("Hauptstraße", nil, Match{}); result != "Hauptstr." {
if result := suffixReplace("Hauptstraße", nil, nil, Match{}); result != "Hauptstr." {
t.Fatal(result)
}
if result := suffixReplace("", nil, Match{}); result != "" {
if result := suffixReplace("", nil, nil, Match{}); result != "" {
t.Fatal(result)
}
if result := suffixReplace("Foostraßeee", nil, Match{}); result != "Foostraßeee" {
if result := suffixReplace("Foostraßeee", nil, nil, Match{}); result != "Foostraßeee" {
t.Fatal(result)
}
}
@ -136,8 +136,8 @@ func assertEq(t *testing.T, a, b string) {
func TestHstoreString(t *testing.T) {
match := Match{}
assertEq(t, HstoreString("", &element.OSMElem{Tags: element.Tags{"key": "value"}}, match).(string), `"key"=>"value"`)
assertEq(t, HstoreString("", &element.OSMElem{Tags: element.Tags{`"key"`: `'"value"'`}}, match).(string), `"\"key\""=>"'\"value\"'"`)
assertEq(t, HstoreString("", &element.OSMElem{Tags: element.Tags{`\`: `\\\\`}}, match).(string), `"\\"=>"\\\\\\\\"`)
assertEq(t, HstoreString("", &element.OSMElem{Tags: element.Tags{"Ümlåütê=>": ""}}, match).(string), `"Ümlåütê=>"=>""`)
assertEq(t, HstoreString("", &element.OSMElem{Tags: element.Tags{"key": "value"}}, nil, match).(string), `"key"=>"value"`)
assertEq(t, HstoreString("", &element.OSMElem{Tags: element.Tags{`"key"`: `'"value"'`}}, nil, match).(string), `"\"key\""=>"'\"value\"'"`)
assertEq(t, HstoreString("", &element.OSMElem{Tags: element.Tags{`\`: `\\\\`}}, nil, match).(string), `"\\"=>"\\\\\\\\"`)
assertEq(t, HstoreString("", &element.OSMElem{Tags: element.Tags{"Ümlåütê=>": ""}}, nil, match).(string), `"Ümlåütê=>"=>""`)
}

View File

@ -1,6 +1,9 @@
package mapping
import "github.com/omniscale/imposm3/element"
import (
"github.com/omniscale/imposm3/element"
"github.com/omniscale/imposm3/geom"
)
func (m *Mapping) PointMatcher() NodeMatcher {
mappings := make(TagTables)
@ -53,8 +56,8 @@ type tagMatcher struct {
matchAreas bool
}
func (m *Match) Row(elem *element.OSMElem) []interface{} {
return m.tableFields.MakeRow(elem, *m)
func (m *Match) Row(elem *element.OSMElem, geom *geom.Geometry) []interface{} {
return m.tableFields.MakeRow(elem, geom, *m)
}
func (tm *tagMatcher) MatchNode(node *element.Node) []Match {

View File

@ -23,7 +23,7 @@ func BenchmarkTagMatch(b *testing.B) {
func makeMember(id int64, tags element.Tags) element.Member {
way := &element.Way{
element.OSMElem{id, tags, nil},
element.OSMElem{id, tags},
[]int64{0, 1, 2, 0}, // fake closed way, req. for SelectRelationPolygons
nil}
return element.Member{Id: id, Type: element.WAY, Role: "", Way: way}
@ -31,7 +31,7 @@ func makeMember(id int64, tags element.Tags) element.Member {
func makeMemberRole(id int64, tags element.Tags, role string) element.Member {
way := &element.Way{
element.OSMElem{id, tags, nil},
element.OSMElem{id, tags},
[]int64{0, 1, 2, 0}, // fake closed way, req. for SelectRelationPolygons
nil}
return element.Member{Id: id, Type: element.WAY, Role: role, Way: way}

View File

@ -1,14 +1,15 @@
package writer
import (
"sync"
"github.com/omniscale/imposm3/cache"
"github.com/omniscale/imposm3/database"
"github.com/omniscale/imposm3/element"
"github.com/omniscale/imposm3/geom"
geomp "github.com/omniscale/imposm3/geom"
"github.com/omniscale/imposm3/geom/geos"
"github.com/omniscale/imposm3/mapping"
"github.com/omniscale/imposm3/stats"
"sync"
)
type NodeWriter struct {
@ -52,7 +53,7 @@ func (nw *NodeWriter) loop() {
if nw.expireor != nil {
nw.expireor.Expire(n.Long, n.Lat)
}
point, err := geom.Point(geos, *n)
point, err := geomp.Point(geos, *n)
if err != nil {
if errl, ok := err.(ErrorLevel); !ok || errl.Level() > 0 {
log.Warn(err)
@ -60,26 +61,26 @@ func (nw *NodeWriter) loop() {
continue
}
n.Geom, err = geom.AsGeomElement(geos, point)
geom, err := geomp.AsGeomElement(geos, point)
if err != nil {
log.Warn(err)
continue
}
if nw.limiter != nil {
parts, err := nw.limiter.Clip(n.Geom.Geom)
parts, err := nw.limiter.Clip(geom.Geom)
if err != nil {
log.Warn(err)
continue
}
if len(parts) >= 1 {
if err := nw.inserter.InsertPoint(n.OSMElem, matches); err != nil {
if err := nw.inserter.InsertPoint(n.OSMElem, geom, matches); err != nil {
log.Warn(err)
continue
}
}
} else {
if err := nw.inserter.InsertPoint(n.OSMElem, matches); err != nil {
if err := nw.inserter.InsertPoint(n.OSMElem, geom, matches); err != nil {
log.Warn(err)
continue
}

View File

@ -8,7 +8,7 @@ import (
"github.com/omniscale/imposm3/database"
"github.com/omniscale/imposm3/element"
"github.com/omniscale/imposm3/expire"
"github.com/omniscale/imposm3/geom"
geomp "github.com/omniscale/imposm3/geom"
"github.com/omniscale/imposm3/geom/geos"
"github.com/omniscale/imposm3/mapping"
"github.com/omniscale/imposm3/stats"
@ -96,7 +96,7 @@ NextRel:
// prepare relation first (build rings and compute actual
// relation tags)
prepedRel, err := geom.PrepareRelation(r, rw.srid, rw.maxGap)
prepedRel, err := geomp.PrepareRelation(r, rw.srid, rw.maxGap)
if err != nil {
if errl, ok := err.(ErrorLevel); !ok || errl.Level() > 0 {
log.Warn(err)
@ -111,10 +111,10 @@ NextRel:
}
// build the multipolygon
r, err = prepedRel.Build()
geom, err := prepedRel.Build()
if err != nil {
if r.Geom != nil && r.Geom.Geom != nil {
geos.Destroy(r.Geom.Geom)
if geom.Geom != nil {
geos.Destroy(geom.Geom)
}
if errl, ok := err.(ErrorLevel); !ok || errl.Level() > 0 {
log.Warn(err)
@ -124,7 +124,7 @@ NextRel:
if rw.limiter != nil {
start := time.Now()
parts, err := rw.limiter.Clip(r.Geom.Geom)
parts, err := rw.limiter.Clip(geom.Geom)
if err != nil {
log.Warn(err)
continue NextRel
@ -135,8 +135,8 @@ NextRel:
for _, g := range parts {
rel := element.Relation(*r)
rel.Id = rw.relId(r.Id)
rel.Geom = &element.Geometry{Geom: g, Wkb: geos.AsEwkbHex(g)}
err := rw.inserter.InsertPolygon(rel.OSMElem, matches)
geom = geomp.Geometry{Geom: g, Wkb: geos.AsEwkbHex(g)}
err := rw.inserter.InsertPolygon(rel.OSMElem, geom, matches)
if err != nil {
if errl, ok := err.(ErrorLevel); !ok || errl.Level() > 0 {
log.Warn(err)
@ -147,7 +147,7 @@ NextRel:
} else {
rel := element.Relation(*r)
rel.Id = rw.relId(r.Id)
err := rw.inserter.InsertPolygon(rel.OSMElem, matches)
err := rw.inserter.InsertPolygon(rel.OSMElem, geom, matches)
if err != nil {
if errl, ok := err.(ErrorLevel); !ok || errl.Level() > 0 {
log.Warn(err)
@ -177,7 +177,7 @@ NextRel:
}
}
}
geos.Destroy(r.Geom.Geom)
geos.Destroy(geom.Geom)
}
rw.wg.Done()
}

View File

@ -7,7 +7,7 @@ import (
"github.com/omniscale/imposm3/database"
"github.com/omniscale/imposm3/element"
"github.com/omniscale/imposm3/expire"
"github.com/omniscale/imposm3/geom"
geomp "github.com/omniscale/imposm3/geom"
"github.com/omniscale/imposm3/geom/geos"
"github.com/omniscale/imposm3/mapping"
"github.com/omniscale/imposm3/stats"
@ -128,44 +128,44 @@ func (ww *WayWriter) buildAndInsert(g *geos.Geos, w *element.Way, matches []mapp
way := element.Way(*w)
if isPolygon {
geosgeom, err = geom.Polygon(g, way.Nodes)
geosgeom, err = geomp.Polygon(g, way.Nodes)
} else {
geosgeom, err = geom.LineString(g, way.Nodes)
geosgeom, err = geomp.LineString(g, way.Nodes)
}
if err != nil {
return err
}
way.Geom, err = geom.AsGeomElement(g, geosgeom)
geom, err := geomp.AsGeomElement(g, geosgeom)
if err != nil {
return err
}
if ww.limiter != nil {
parts, err := ww.limiter.Clip(way.Geom.Geom)
parts, err := ww.limiter.Clip(geom.Geom)
if err != nil {
return err
}
for _, p := range parts {
way := element.Way(*w)
way.Geom = &element.Geometry{Geom: p, Wkb: g.AsEwkbHex(p)}
geom = geomp.Geometry{Geom: p, Wkb: g.AsEwkbHex(p)}
if isPolygon {
if err := ww.inserter.InsertPolygon(way.OSMElem, matches); err != nil {
if err := ww.inserter.InsertPolygon(way.OSMElem, geom, matches); err != nil {
return err
}
} else {
if err := ww.inserter.InsertLineString(way.OSMElem, matches); err != nil {
if err := ww.inserter.InsertLineString(way.OSMElem, geom, matches); err != nil {
return err
}
}
}
} else {
if isPolygon {
if err := ww.inserter.InsertPolygon(way.OSMElem, matches); err != nil {
if err := ww.inserter.InsertPolygon(way.OSMElem, geom, matches); err != nil {
return err
}
} else {
if err := ww.inserter.InsertLineString(way.OSMElem, matches); err != nil {
if err := ww.inserter.InsertLineString(way.OSMElem, geom, matches); err != nil {
return err
}
}