-
Notifications
You must be signed in to change notification settings - Fork 108
/
Copy pathline_string.go
117 lines (95 loc) · 1.94 KB
/
line_string.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package tilecover
import (
"math"
"github.com/paulmach/orb"
"github.com/paulmach/orb/maptile"
)
// LineString creates a tile cover for the line string.
func LineString(ls orb.LineString, z maptile.Zoom) maptile.Set {
set := make(maptile.Set)
line(set, ls, z, nil)
return set
}
// MultiLineString creates a tile cover for the line strings.
func MultiLineString(mls orb.MultiLineString, z maptile.Zoom) maptile.Set {
set := make(maptile.Set)
for _, ls := range mls {
line(set, ls, z, nil)
}
return set
}
func line(
set maptile.Set,
line orb.LineString,
zoom maptile.Zoom,
ring [][2]uint32,
) [][2]uint32 {
inf := math.Inf(1)
prevX := -1.0
prevY := -1.0
var x, y float64
for i := 0; i < len(line)-1; i++ {
start := maptile.Fraction(line[i], zoom)
stop := maptile.Fraction(line[i+1], zoom)
dx := stop[0] - start[0]
dy := stop[1] - start[1]
if dy == 0 && dx == 0 {
continue
}
sx := -1.0
if dx > 0 {
sx = 1.0
}
sy := -1.0
if dy > 0 {
sy = 1.0
}
x = math.Floor(start[0])
y = math.Floor(start[1])
tMaxX := inf
if dx != 0 {
d := 0.0
if dx > 0 {
d = 1.0
}
tMaxX = math.Abs((d + x - start[0]) / dx)
}
tMaxY := inf
if dy != 0 {
d := 0.0
if dy > 0 {
d = 1.0
}
tMaxY = math.Abs((d + y - start[1]) / dy)
}
tdx := math.Abs(sx / dx)
tdy := math.Abs(sy / dy)
if x != prevX || y != prevY {
set[maptile.New(uint32(x), uint32(y), zoom)] = true
if ring != nil && y != prevY {
ring = append(ring, [2]uint32{uint32(x), uint32(y)})
}
prevX = x
prevY = y
}
for tMaxX < 1 || tMaxY < 1 {
if tMaxX < tMaxY {
tMaxX += tdx
x += sx
} else {
tMaxY += tdy
y += sy
}
set[maptile.New(uint32(x), uint32(y), zoom)] = true
if ring != nil && y != prevY {
ring = append(ring, [2]uint32{uint32(x), uint32(y)})
}
prevX = x
prevY = y
}
}
if ring != nil && uint32(y) == ring[0][1] {
ring = ring[:len(ring)-1]
}
return ring
}