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
|
|
|
)
|
|
|
|
|
|
|
|
type Ring struct {
|
2013-05-16 14:17:21 +04:00
|
|
|
ways []*element.Way
|
|
|
|
refs []int64
|
|
|
|
nodes []element.Node
|
|
|
|
geom *geos.Geom
|
|
|
|
holes map[*Ring]bool
|
|
|
|
containedBy int
|
|
|
|
area float64
|
2015-01-05 17:49:11 +03:00
|
|
|
outer bool
|
2013-05-16 17:15:58 +04:00
|
|
|
inserted map[int64]bool
|
2013-05-16 14:17:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Ring) IsClosed() bool {
|
|
|
|
return len(r.refs) >= 4 && r.refs[0] == r.refs[len(r.refs)-1]
|
|
|
|
}
|
|
|
|
|
2014-10-21 19:08:56 +04:00
|
|
|
func (r *Ring) TryClose(maxRingGap float64) bool {
|
2014-10-22 15:36:06 +04:00
|
|
|
return element.TryCloseWay(r.refs, r.nodes, maxRingGap)
|
2014-10-21 19:08:56 +04:00
|
|
|
}
|
|
|
|
|
2013-05-16 14:17:21 +04:00
|
|
|
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
|
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]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-06 17:34:09 +04:00
|
|
|
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]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func mergeRings(rings []*Ring) []*Ring {
|
|
|
|
endpoints := make(map[int64]*Ring)
|
2013-05-06 17:34:09 +04:00
|
|
|
|
2013-04-29 21:36:30 +04:00
|
|
|
for _, ring := range rings {
|
2014-01-14 15:06:43 +04:00
|
|
|
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)
|
2013-05-06 17:34:09 +04:00
|
|
|
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 {
|
2013-05-06 17:34:09 +04:00
|
|
|
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
|
|
|
}
|
2013-05-06 17:34:09 +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)
|
2013-05-06 17:34:09 +04:00
|
|
|
origRing.refs = append(origRing.refs[:len(origRing.refs)-1], ring.refs...)
|
2013-04-29 21:36:30 +04:00
|
|
|
reverseNodes(ring.nodes)
|
2013-05-06 17:34:09 +04:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uniqueRings := make(map[*Ring]bool)
|
|
|
|
for _, ring := range endpoints {
|
|
|
|
uniqueRings[ring] = true
|
|
|
|
}
|
2013-04-30 16:01:28 +04: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
|
|
|
|
}
|