refactor geom api: make ring private

Oliver Tonnhofer 2015-04-30 10:05:22 +02:00
parent 7c438fb867
commit 171e1c24fa
4 changed files with 55 additions and 55 deletions

View File

@ -26,19 +26,19 @@ func (e *GeomError) Level() int {
return e.level return e.level
} }
func NewGeomError(message string, level int) *GeomError { func newGeomError(message string, level int) *GeomError {
return &GeomError{message, level} return &GeomError{message, level}
} }
var ( var (
ErrorOneNodeWay = NewGeomError("need at least two separate nodes for way", 0) ErrorOneNodeWay = newGeomError("need at least two separate nodes for way", 0)
ErrorNoRing = NewGeomError("linestrings do not form ring", 0) ErrorNoRing = newGeomError("linestrings do not form ring", 0)
) )
func Point(g *geos.Geos, node element.Node) (*geos.Geom, error) { func Point(g *geos.Geos, node element.Node) (*geos.Geom, error) {
geom := g.Point(node.Long, node.Lat) geom := g.Point(node.Long, node.Lat)
if geom == nil { if geom == nil {
return nil, NewGeomError("couldn't create point", 1) return nil, newGeomError("couldn't create point", 1)
} }
g.DestroyLater(geom) g.DestroyLater(geom)
return geom, nil return geom, nil

View File

@ -9,7 +9,7 @@ import (
) )
type PreparedRelation struct { type PreparedRelation struct {
rings []*Ring rings []*ring
rel *element.Relation rel *element.Relation
srid int srid int
} }
@ -46,7 +46,7 @@ func (prep *PreparedRelation) Build() (Geometry, error) {
return Geometry{Geom: geom, Wkb: wkb}, nil return Geometry{Geom: geom, Wkb: wkb}, nil
} }
func destroyRings(g *geos.Geos, rings []*Ring) { func destroyRings(g *geos.Geos, rings []*ring) {
for _, r := range rings { for _, r := range rings {
if r.geom != nil { if r.geom != nil {
g.Destroy(r.geom) g.Destroy(r.geom)
@ -55,11 +55,11 @@ 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 rings []*ring
var incompleteRings []*Ring var incompleteRings []*ring
var completeRings []*Ring var completeRings []*ring
var mergedRings []*Ring var mergedRings []*ring
var err error var err error
g := geos.NewGeos() g := geos.NewGeos()
defer g.Finish() defer g.Finish()
@ -76,12 +76,12 @@ func buildRings(rel *element.Relation, maxRingGap float64) ([]*Ring, error) {
if member.Way == nil { if member.Way == nil {
continue continue
} }
rings = append(rings, NewRing(member.Way)) rings = append(rings, newRing(member.Way))
} }
// create geometries for closed rings, collect incomplete rings // create geometries for closed rings, collect incomplete rings
for _, r := range rings { for _, r := range rings {
if r.IsClosed() { if r.isClosed() {
r.geom, err = Polygon(g, r.nodes) r.geom, err = Polygon(g, r.nodes)
if err != nil { if err != nil {
return nil, err return nil, err
@ -99,7 +99,7 @@ func buildRings(rel *element.Relation, maxRingGap float64) ([]*Ring, error) {
} }
// create geometries for merged rings // create geometries for merged rings
for _, ring := range mergedRings { for _, ring := range mergedRings {
if !ring.IsClosed() && !ring.TryClose(maxRingGap) { if !ring.isClosed() && !ring.tryClose(maxRingGap) {
err = ErrorNoRing // for defer err = ErrorNoRing // for defer
return nil, err return nil, err
} }
@ -115,22 +115,22 @@ func buildRings(rel *element.Relation, maxRingGap float64) ([]*Ring, error) {
for _, r := range completeRings { for _, r := range completeRings {
r.area = r.geom.Area() r.area = r.geom.Area()
} }
sort.Sort(SortableRingsDesc(completeRings)) sort.Sort(sortableRingsDesc(completeRings))
return completeRings, nil return completeRings, nil
} }
type SortableRingsDesc []*Ring type sortableRingsDesc []*ring
func (r SortableRingsDesc) Len() int { return len(r) } 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) 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] } 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). // rings need to be sorted by area (large to small).
func buildRelGeometry(g *geos.Geos, rel *element.Relation, rings []*Ring) (*geos.Geom, error) { func buildRelGeometry(g *geos.Geos, rel *element.Relation, rings []*ring) (*geos.Geom, error) {
totalRings := len(rings) totalRings := len(rings)
shells := map[*Ring]bool{rings[0]: true} shells := map[*ring]bool{rings[0]: true}
for i := 0; i < totalRings; i++ { for i := 0; i < totalRings; i++ {
testGeom := g.Prepare(rings[i].geom) testGeom := g.Prepare(rings[i].geom)
if testGeom == nil { if testGeom == nil {
@ -252,7 +252,7 @@ func relationTags(relTags, wayTags element.Tags) element.Tags {
// ringIsHole returns true if rings[idx] is a hole, False if it is a // ringIsHole returns true if rings[idx] is a hole, False if it is a
// shell (also if hole in a hole, etc) // shell (also if hole in a hole, etc)
func ringIsHole(rings []*Ring, idx int) bool { func ringIsHole(rings []*ring, idx int) bool {
containedCounter := 0 containedCounter := 0
for { for {

View File

@ -5,36 +5,36 @@ import (
"github.com/omniscale/imposm3/geom/geos" "github.com/omniscale/imposm3/geom/geos"
) )
type Ring struct { type ring struct {
ways []*element.Way ways []*element.Way
refs []int64 refs []int64
nodes []element.Node nodes []element.Node
geom *geos.Geom geom *geos.Geom
holes map[*Ring]bool holes map[*ring]bool
containedBy int containedBy int
area float64 area float64
outer bool outer bool
inserted map[int64]bool inserted map[int64]bool
} }
func (r *Ring) IsClosed() bool { func (r *ring) isClosed() bool {
return len(r.refs) >= 4 && r.refs[0] == r.refs[len(r.refs)-1] return len(r.refs) >= 4 && r.refs[0] == r.refs[len(r.refs)-1]
} }
func (r *Ring) TryClose(maxRingGap float64) bool { func (r *ring) tryClose(maxRingGap float64) bool {
return element.TryCloseWay(r.refs, r.nodes, maxRingGap) return element.TryCloseWay(r.refs, r.nodes, maxRingGap)
} }
func NewRing(way *element.Way) *Ring { func newRing(way *element.Way) *ring {
ring := Ring{} r := ring{}
ring.ways = []*element.Way{way} r.ways = []*element.Way{way}
ring.refs = make([]int64, len(way.Refs)) r.refs = make([]int64, len(way.Refs))
ring.nodes = make([]element.Node, len(way.Nodes)) r.nodes = make([]element.Node, len(way.Nodes))
ring.containedBy = -1 r.containedBy = -1
ring.holes = make(map[*Ring]bool) r.holes = make(map[*ring]bool)
copy(ring.refs, way.Refs) copy(r.refs, way.Refs)
copy(ring.nodes, way.Nodes) copy(r.nodes, way.Nodes)
return &ring return &r
} }
func reverseRefs(refs []int64) { func reverseRefs(refs []int64) {
@ -49,8 +49,8 @@ func reverseNodes(nodes []element.Node) {
} }
} }
func mergeRings(rings []*Ring) []*Ring { func mergeRings(rings []*ring) []*ring {
endpoints := make(map[int64]*Ring) endpoints := make(map[int64]*ring)
for _, ring := range rings { for _, ring := range rings {
if len(ring.refs) < 2 { if len(ring.refs) < 2 {
@ -114,11 +114,11 @@ func mergeRings(rings []*Ring) []*Ring {
endpoints[right] = ring endpoints[right] = ring
} }
} }
uniqueRings := make(map[*Ring]bool) uniqueRings := make(map[*ring]bool)
for _, ring := range endpoints { for _, ring := range endpoints {
uniqueRings[ring] = true uniqueRings[ring] = true
} }
result := make([]*Ring, 0, len(uniqueRings)) result := make([]*ring, 0, len(uniqueRings))
for ring, _ := range uniqueRings { for ring, _ := range uniqueRings {
result = append(result, ring) result = append(result, ring)
} }

View File

@ -16,7 +16,7 @@ func TestRingMerge(t *testing.T) {
element.Node{}, element.Node{},
element.Node{}, element.Node{},
} }
r1 := NewRing(&w1) r1 := newRing(&w1)
w2 := element.Way{} w2 := element.Way{}
w2.Id = 2 w2.Id = 2
@ -26,8 +26,8 @@ func TestRingMerge(t *testing.T) {
element.Node{}, element.Node{},
element.Node{}, element.Node{},
} }
r2 := NewRing(&w2) r2 := newRing(&w2)
rings := []*Ring{r1, r2} rings := []*ring{r1, r2}
result := mergeRings(rings) result := mergeRings(rings)
if len(result) != 1 { if len(result) != 1 {
@ -52,14 +52,14 @@ func TestRingMergeMissingRefs(t *testing.T) {
element.Node{}, element.Node{},
element.Node{}, element.Node{},
} }
r1 := NewRing(&w1) r1 := newRing(&w1)
w2 := element.Way{} w2 := element.Way{}
w2.Id = 2 w2.Id = 2
w2.Refs = []int64{} w2.Refs = []int64{}
w2.Nodes = []element.Node{} w2.Nodes = []element.Node{}
r2 := NewRing(&w2) r2 := newRing(&w2)
rings := []*Ring{r1, r2} rings := []*ring{r1, r2}
result := mergeRings(rings) result := mergeRings(rings)
if len(result) != 1 { if len(result) != 1 {
@ -80,7 +80,7 @@ func TestRingMergeReverseEndpoints(t *testing.T) {
element.Node{}, element.Node{},
element.Node{}, element.Node{},
} }
r1 := NewRing(&w1) r1 := newRing(&w1)
w2 := element.Way{} w2 := element.Way{}
w2.Id = 2 w2.Id = 2
@ -90,7 +90,7 @@ func TestRingMergeReverseEndpoints(t *testing.T) {
element.Node{}, element.Node{},
element.Node{}, element.Node{},
} }
r2 := NewRing(&w2) r2 := newRing(&w2)
w3 := element.Way{} w3 := element.Way{}
w3.Id = 3 w3.Id = 3
@ -100,9 +100,9 @@ func TestRingMergeReverseEndpoints(t *testing.T) {
element.Node{}, element.Node{},
element.Node{}, element.Node{},
} }
r3 := NewRing(&w3) r3 := newRing(&w3)
rings := []*Ring{r1, r2, r3} rings := []*ring{r1, r2, r3}
result := mergeRings(rings) result := mergeRings(rings)
if len(result) != 1 { if len(result) != 1 {
@ -168,11 +168,11 @@ func TestRingMergePermutations(t *testing.T) {
w4.Refs = ways[indices[3]] w4.Refs = ways[indices[3]]
w4.Nodes = []element.Node{element.Node{}, element.Node{}, element.Node{}, element.Node{}} w4.Nodes = []element.Node{element.Node{}, element.Node{}, element.Node{}, element.Node{}}
rings := []*Ring{ rings := []*ring{
&Ring{ways: []*element.Way{&w1}, refs: w1.Refs, nodes: w1.Nodes}, &ring{ways: []*element.Way{&w1}, refs: w1.Refs, nodes: w1.Nodes},
&Ring{ways: []*element.Way{&w2}, refs: w2.Refs, nodes: w2.Nodes}, &ring{ways: []*element.Way{&w2}, refs: w2.Refs, nodes: w2.Nodes},
&Ring{ways: []*element.Way{&w3}, refs: w3.Refs, nodes: w3.Nodes}, &ring{ways: []*element.Way{&w3}, refs: w3.Refs, nodes: w3.Nodes},
&Ring{ways: []*element.Way{&w4}, refs: w4.Refs, nodes: w4.Nodes}, &ring{ways: []*element.Way{&w4}, refs: w4.Refs, nodes: w4.Nodes},
} }
result := mergeRings(rings) result := mergeRings(rings)
if len(result) != 1 { if len(result) != 1 {