imposm3/geom/ring.go

127 lines
3.6 KiB
Go
Raw Permalink Normal View History

2013-04-29 21:36:30 +04:00
package geom
import (
2014-08-04 17:19:35 +04:00
"github.com/omniscale/imposm3/element"
"github.com/omniscale/imposm3/geom/geos"
2013-04-29 21:36:30 +04:00
)
2015-04-30 11:05:22 +03:00
type ring struct {
2013-05-16 14:17:21 +04:00
ways []*element.Way
refs []int64
nodes []element.Node
geom *geos.Geom
2015-04-30 11:05:22 +03:00
holes map[*ring]bool
2013-05-16 14:17:21 +04:00
containedBy int
area float64
outer bool
inserted map[int64]bool
2013-05-16 14:17:21 +04:00
}
2015-04-30 11:05:22 +03:00
func (r *ring) isClosed() bool {
2013-05-16 14:17:21 +04:00
return len(r.refs) >= 4 && r.refs[0] == r.refs[len(r.refs)-1]
}
2015-04-30 11:05:22 +03:00
func (r *ring) tryClose(maxRingGap float64) bool {
return element.TryCloseWay(r.refs, r.nodes, maxRingGap)
}
2015-04-30 11:05:22 +03:00
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
2013-04-29 21:36:30 +04:00
}
func reverseRefs(refs []int64) {
for i, j := 0, len(refs)-1; i < j; i, j = i+1, j-1 {
refs[i], refs[j] = refs[j], refs[i]
}
}
func reverseNodes(nodes []element.Node) {
2013-04-29 21:36:30 +04:00
for i, j := 0, len(nodes)-1; i < j; i, j = i+1, j-1 {
nodes[i], nodes[j] = nodes[j], nodes[i]
}
}
2015-04-30 11:05:22 +03:00
func mergeRings(rings []*ring) []*ring {
endpoints := make(map[int64]*ring)
2013-04-29 21:36:30 +04:00
for _, ring := range rings {
if len(ring.refs) < 2 {
continue
}
2013-04-29 21:36:30 +04:00
left := ring.refs[0]
right := ring.refs[len(ring.refs)-1]
2014-10-21 18:12:21 +04:00
2013-04-29 21:36:30 +04:00
if origRing, ok := endpoints[left]; ok {
2014-10-21 18:12:21 +04:00
// left node connects to..
2013-04-29 21:36:30 +04:00
delete(endpoints, left)
if left == origRing.refs[len(origRing.refs)-1] {
2014-10-21 18:12:21 +04:00
// .. right end
2013-04-29 21:36:30 +04:00
origRing.refs = append(origRing.refs, ring.refs[1:]...)
origRing.nodes = append(origRing.nodes, ring.nodes[1:]...)
} else {
2014-10-21 18:12:21 +04:00
// .. left end, reverse ring
2013-04-29 21:36:30 +04:00
reverseRefs(origRing.refs)
origRing.refs = append(origRing.refs, ring.refs[1:]...)
reverseNodes(origRing.nodes)
origRing.nodes = append(origRing.nodes, ring.nodes[1:]...)
}
origRing.ways = append(origRing.ways, ring.ways...)
if rightRing, ok := endpoints[right]; ok && rightRing != origRing {
2014-10-21 18:12:21 +04:00
// right node connects to another ring, close ring
2013-04-29 21:36:30 +04:00
delete(endpoints, right)
if right == rightRing.refs[0] {
origRing.refs = append(origRing.refs, rightRing.refs[1:]...)
origRing.nodes = append(origRing.nodes, rightRing.nodes[1:]...)
2013-04-29 21:36:30 +04:00
} else {
reverseRefs(rightRing.refs)
origRing.refs = append(origRing.refs[:len(origRing.refs)-1], rightRing.refs...)
reverseNodes(rightRing.nodes)
origRing.nodes = append(origRing.nodes[:len(origRing.nodes)-1], rightRing.nodes...)
2013-04-29 21:36:30 +04:00
}
origRing.ways = append(origRing.ways, rightRing.ways...)
2013-04-29 21:36:30 +04:00
right := origRing.refs[len(origRing.refs)-1]
endpoints[right] = origRing
} else {
endpoints[right] = origRing
}
} else if origRing, ok := endpoints[right]; ok {
2014-10-21 18:12:21 +04:00
// right node connects to..
2013-04-29 21:36:30 +04:00
delete(endpoints, right)
if right == origRing.refs[0] {
2014-10-21 18:12:21 +04:00
// .. left end
2013-04-29 21:36:30 +04:00
origRing.refs = append(ring.refs[:len(ring.refs)-1], origRing.refs...)
origRing.nodes = append(ring.nodes[:len(ring.nodes)-1], origRing.nodes...)
} else {
2014-10-21 18:12:21 +04:00
// .. right end, reverse ring
2013-04-29 21:36:30 +04:00
reverseRefs(ring.refs)
origRing.refs = append(origRing.refs[:len(origRing.refs)-1], ring.refs...)
2013-04-29 21:36:30 +04:00
reverseNodes(ring.nodes)
origRing.nodes = append(origRing.nodes[:len(origRing.nodes)-1], ring.nodes...)
2013-04-29 21:36:30 +04:00
}
origRing.ways = append(origRing.ways, ring.ways...)
endpoints[left] = origRing
} else {
2014-10-21 18:12:21 +04:00
// ring is not connected (yet)
2013-04-29 21:36:30 +04:00
endpoints[left] = ring
endpoints[right] = ring
}
}
2015-04-30 11:05:22 +03:00
uniqueRings := make(map[*ring]bool)
2013-04-29 21:36:30 +04:00
for _, ring := range endpoints {
uniqueRings[ring] = true
}
2015-04-30 11:05:22 +03:00
result := make([]*ring, 0, len(uniqueRings))
2013-04-29 21:36:30 +04:00
for ring, _ := range uniqueRings {
result = append(result, ring)
}
return result
}