refactor geom api: make ring private
parent
7c438fb867
commit
171e1c24fa
|
@ -26,19 +26,19 @@ func (e *GeomError) Level() int {
|
|||
return e.level
|
||||
}
|
||||
|
||||
func NewGeomError(message string, level int) *GeomError {
|
||||
func newGeomError(message string, level int) *GeomError {
|
||||
return &GeomError{message, level}
|
||||
}
|
||||
|
||||
var (
|
||||
ErrorOneNodeWay = NewGeomError("need at least two separate nodes for way", 0)
|
||||
ErrorNoRing = NewGeomError("linestrings do not form ring", 0)
|
||||
ErrorOneNodeWay = newGeomError("need at least two separate nodes for way", 0)
|
||||
ErrorNoRing = newGeomError("linestrings do not form ring", 0)
|
||||
)
|
||||
|
||||
func Point(g *geos.Geos, node element.Node) (*geos.Geom, error) {
|
||||
geom := g.Point(node.Long, node.Lat)
|
||||
if geom == nil {
|
||||
return nil, NewGeomError("couldn't create point", 1)
|
||||
return nil, newGeomError("couldn't create point", 1)
|
||||
}
|
||||
g.DestroyLater(geom)
|
||||
return geom, nil
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
type PreparedRelation struct {
|
||||
rings []*Ring
|
||||
rings []*ring
|
||||
rel *element.Relation
|
||||
srid int
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ func (prep *PreparedRelation) Build() (Geometry, error) {
|
|||
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 {
|
||||
if r.geom != nil {
|
||||
g.Destroy(r.geom)
|
||||
|
@ -55,11 +55,11 @@ func destroyRings(g *geos.Geos, rings []*Ring) {
|
|||
}
|
||||
}
|
||||
|
||||
func buildRings(rel *element.Relation, maxRingGap float64) ([]*Ring, error) {
|
||||
var rings []*Ring
|
||||
var incompleteRings []*Ring
|
||||
var completeRings []*Ring
|
||||
var mergedRings []*Ring
|
||||
func buildRings(rel *element.Relation, maxRingGap float64) ([]*ring, error) {
|
||||
var rings []*ring
|
||||
var incompleteRings []*ring
|
||||
var completeRings []*ring
|
||||
var mergedRings []*ring
|
||||
var err error
|
||||
g := geos.NewGeos()
|
||||
defer g.Finish()
|
||||
|
@ -76,12 +76,12 @@ func buildRings(rel *element.Relation, maxRingGap float64) ([]*Ring, error) {
|
|||
if member.Way == nil {
|
||||
continue
|
||||
}
|
||||
rings = append(rings, NewRing(member.Way))
|
||||
rings = append(rings, newRing(member.Way))
|
||||
}
|
||||
|
||||
// create geometries for closed rings, collect incomplete rings
|
||||
for _, r := range rings {
|
||||
if r.IsClosed() {
|
||||
if r.isClosed() {
|
||||
r.geom, err = Polygon(g, r.nodes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -99,7 +99,7 @@ func buildRings(rel *element.Relation, maxRingGap float64) ([]*Ring, error) {
|
|||
}
|
||||
// create geometries for merged rings
|
||||
for _, ring := range mergedRings {
|
||||
if !ring.IsClosed() && !ring.TryClose(maxRingGap) {
|
||||
if !ring.isClosed() && !ring.tryClose(maxRingGap) {
|
||||
err = ErrorNoRing // for defer
|
||||
return nil, err
|
||||
}
|
||||
|
@ -115,22 +115,22 @@ func buildRings(rel *element.Relation, maxRingGap float64) ([]*Ring, error) {
|
|||
for _, r := range completeRings {
|
||||
r.area = r.geom.Area()
|
||||
}
|
||||
sort.Sort(SortableRingsDesc(completeRings))
|
||||
sort.Sort(sortableRingsDesc(completeRings))
|
||||
|
||||
return completeRings, nil
|
||||
}
|
||||
|
||||
type SortableRingsDesc []*Ring
|
||||
type sortableRingsDesc []*ring
|
||||
|
||||
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] }
|
||||
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.
|
||||
// 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)
|
||||
shells := map[*Ring]bool{rings[0]: true}
|
||||
shells := map[*ring]bool{rings[0]: true}
|
||||
for i := 0; i < totalRings; i++ {
|
||||
testGeom := g.Prepare(rings[i].geom)
|
||||
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
|
||||
// shell (also if hole in a hole, etc)
|
||||
func ringIsHole(rings []*Ring, idx int) bool {
|
||||
func ringIsHole(rings []*ring, idx int) bool {
|
||||
|
||||
containedCounter := 0
|
||||
for {
|
||||
|
|
36
geom/ring.go
36
geom/ring.go
|
@ -5,36 +5,36 @@ import (
|
|||
"github.com/omniscale/imposm3/geom/geos"
|
||||
)
|
||||
|
||||
type Ring struct {
|
||||
type ring struct {
|
||||
ways []*element.Way
|
||||
refs []int64
|
||||
nodes []element.Node
|
||||
geom *geos.Geom
|
||||
holes map[*Ring]bool
|
||||
holes map[*ring]bool
|
||||
containedBy int
|
||||
area float64
|
||||
outer 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]
|
||||
}
|
||||
|
||||
func (r *Ring) TryClose(maxRingGap float64) bool {
|
||||
func (r *ring) tryClose(maxRingGap float64) bool {
|
||||
return element.TryCloseWay(r.refs, r.nodes, maxRingGap)
|
||||
}
|
||||
|
||||
func NewRing(way *element.Way) *Ring {
|
||||
ring := Ring{}
|
||||
ring.ways = []*element.Way{way}
|
||||
ring.refs = make([]int64, len(way.Refs))
|
||||
ring.nodes = make([]element.Node, len(way.Nodes))
|
||||
ring.containedBy = -1
|
||||
ring.holes = make(map[*Ring]bool)
|
||||
copy(ring.refs, way.Refs)
|
||||
copy(ring.nodes, way.Nodes)
|
||||
return &ring
|
||||
func newRing(way *element.Way) *ring {
|
||||
r := ring{}
|
||||
r.ways = []*element.Way{way}
|
||||
r.refs = make([]int64, len(way.Refs))
|
||||
r.nodes = make([]element.Node, len(way.Nodes))
|
||||
r.containedBy = -1
|
||||
r.holes = make(map[*ring]bool)
|
||||
copy(r.refs, way.Refs)
|
||||
copy(r.nodes, way.Nodes)
|
||||
return &r
|
||||
}
|
||||
|
||||
func reverseRefs(refs []int64) {
|
||||
|
@ -49,8 +49,8 @@ func reverseNodes(nodes []element.Node) {
|
|||
}
|
||||
}
|
||||
|
||||
func mergeRings(rings []*Ring) []*Ring {
|
||||
endpoints := make(map[int64]*Ring)
|
||||
func mergeRings(rings []*ring) []*ring {
|
||||
endpoints := make(map[int64]*ring)
|
||||
|
||||
for _, ring := range rings {
|
||||
if len(ring.refs) < 2 {
|
||||
|
@ -114,11 +114,11 @@ func mergeRings(rings []*Ring) []*Ring {
|
|||
endpoints[right] = ring
|
||||
}
|
||||
}
|
||||
uniqueRings := make(map[*Ring]bool)
|
||||
uniqueRings := make(map[*ring]bool)
|
||||
for _, ring := range endpoints {
|
||||
uniqueRings[ring] = true
|
||||
}
|
||||
result := make([]*Ring, 0, len(uniqueRings))
|
||||
result := make([]*ring, 0, len(uniqueRings))
|
||||
for ring, _ := range uniqueRings {
|
||||
result = append(result, ring)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ func TestRingMerge(t *testing.T) {
|
|||
element.Node{},
|
||||
element.Node{},
|
||||
}
|
||||
r1 := NewRing(&w1)
|
||||
r1 := newRing(&w1)
|
||||
|
||||
w2 := element.Way{}
|
||||
w2.Id = 2
|
||||
|
@ -26,8 +26,8 @@ func TestRingMerge(t *testing.T) {
|
|||
element.Node{},
|
||||
element.Node{},
|
||||
}
|
||||
r2 := NewRing(&w2)
|
||||
rings := []*Ring{r1, r2}
|
||||
r2 := newRing(&w2)
|
||||
rings := []*ring{r1, r2}
|
||||
|
||||
result := mergeRings(rings)
|
||||
if len(result) != 1 {
|
||||
|
@ -52,14 +52,14 @@ func TestRingMergeMissingRefs(t *testing.T) {
|
|||
element.Node{},
|
||||
element.Node{},
|
||||
}
|
||||
r1 := NewRing(&w1)
|
||||
r1 := newRing(&w1)
|
||||
|
||||
w2 := element.Way{}
|
||||
w2.Id = 2
|
||||
w2.Refs = []int64{}
|
||||
w2.Nodes = []element.Node{}
|
||||
r2 := NewRing(&w2)
|
||||
rings := []*Ring{r1, r2}
|
||||
r2 := newRing(&w2)
|
||||
rings := []*ring{r1, r2}
|
||||
|
||||
result := mergeRings(rings)
|
||||
if len(result) != 1 {
|
||||
|
@ -80,7 +80,7 @@ func TestRingMergeReverseEndpoints(t *testing.T) {
|
|||
element.Node{},
|
||||
element.Node{},
|
||||
}
|
||||
r1 := NewRing(&w1)
|
||||
r1 := newRing(&w1)
|
||||
|
||||
w2 := element.Way{}
|
||||
w2.Id = 2
|
||||
|
@ -90,7 +90,7 @@ func TestRingMergeReverseEndpoints(t *testing.T) {
|
|||
element.Node{},
|
||||
element.Node{},
|
||||
}
|
||||
r2 := NewRing(&w2)
|
||||
r2 := newRing(&w2)
|
||||
|
||||
w3 := element.Way{}
|
||||
w3.Id = 3
|
||||
|
@ -100,9 +100,9 @@ func TestRingMergeReverseEndpoints(t *testing.T) {
|
|||
element.Node{},
|
||||
element.Node{},
|
||||
}
|
||||
r3 := NewRing(&w3)
|
||||
r3 := newRing(&w3)
|
||||
|
||||
rings := []*Ring{r1, r2, r3}
|
||||
rings := []*ring{r1, r2, r3}
|
||||
|
||||
result := mergeRings(rings)
|
||||
if len(result) != 1 {
|
||||
|
@ -168,11 +168,11 @@ func TestRingMergePermutations(t *testing.T) {
|
|||
w4.Refs = ways[indices[3]]
|
||||
w4.Nodes = []element.Node{element.Node{}, element.Node{}, element.Node{}, element.Node{}}
|
||||
|
||||
rings := []*Ring{
|
||||
&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{&w3}, refs: w3.Refs, nodes: w3.Nodes},
|
||||
&Ring{ways: []*element.Way{&w4}, refs: w4.Refs, nodes: w4.Nodes},
|
||||
rings := []*ring{
|
||||
&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{&w3}, refs: w3.Refs, nodes: w3.Nodes},
|
||||
&ring{ways: []*element.Way{&w4}, refs: w4.Refs, nodes: w4.Nodes},
|
||||
}
|
||||
result := mergeRings(rings)
|
||||
if len(result) != 1 {
|
||||
|
|
Loading…
Reference in New Issue