This repository has been archived by the owner on Dec 26, 2017. It is now read-only.
forked from omniscale/imposm3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tile.go
125 lines (105 loc) · 2.84 KB
/
tile.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
118
119
120
121
122
123
124
125
package expire
import (
"fmt"
"io"
"sync"
"github.com/omniscale/imposm3/element"
"github.com/omniscale/imposm3/geom/geojson"
"github.com/omniscale/imposm3/proj"
)
type Tile struct {
X int
Y int
Z int
}
func NewTile(x, y float64, z int) Tile {
return Tile{X: int(x), Y: int(y), Z: z}
}
type ByID []Tile
func (t ByID) Len() int { return len(t) }
func (t ByID) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
func (t ByID) Less(i, j int) bool { return t[i].toID() < t[j].toID() }
type TileFraction struct {
X float64
Y float64
}
type ByYX []TileFraction
func (t ByYX) Len() int { return len(t) }
func (t ByYX) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
func (t ByYX) Less(i, j int) bool {
return t[i].Y < t[j].Y || (t[i].Y == t[j].Y && t[i].X < t[j].X)
}
// The tile expireor keeps a list of dirty XYZ tiles
// that are covered by the expired polygons, linestring and points
func NewTileExpireor(maxZoom int) *TileExpireor {
return &TileExpireor{
tiles: make(TileHash, 200),
minZoom: 0,
maxZoom: maxZoom,
}
}
type TileExpireor struct {
// Space efficient tile store
tiles TileHash
// Min zoom level to calculate parents for
minZoom int
// Max zoom level to evaluate
maxZoom int
// Allow writing to tile hash
tileAccess sync.Mutex
}
func (te *TileExpireor) ExpireLinestring(nodes []element.Node) {
linestring := geojson.LineString{}
for _, n := range nodes {
long, lat := proj.MercToWgs(n.Long, n.Lat)
linestring = append(linestring, geojson.Point{long, lat})
}
tiles, _ := CoverLinestring(linestring, te.maxZoom)
te.tileAccess.Lock()
te.tiles.MergeTiles(tiles)
te.tileAccess.Unlock()
}
func (te *TileExpireor) ExpirePolygon(nodes []element.Node) {
outerRing := geojson.LineString{}
for _, n := range nodes {
long, lat := proj.MercToWgs(n.Long, n.Lat)
outerRing = append(outerRing, geojson.Point{long, lat})
}
poly := geojson.Polygon{outerRing}
tiles := CoverPolygon(poly, te.maxZoom)
te.tileAccess.Lock()
te.tiles.MergeTiles(tiles)
te.tileAccess.Unlock()
}
func (te *TileExpireor) Expire(long, lat float64) {
long, lat = proj.MercToWgs(long, lat)
tile := CoverPoint(geojson.Point{long, lat}, te.maxZoom)
te.tileAccess.Lock()
te.tiles.AddTile(tile)
te.tileAccess.Unlock()
}
func (te *TileExpireor) CalculateParentTiles() {
te.tiles.CalculateParents(te.minZoom)
}
func (te *TileExpireor) WriteTiles(w io.Writer) {
for id, _ := range te.tiles {
tile := fromID(id)
fmt.Fprintf(w, "%d/%d/%d\n", tile.X, tile.Y, tile.Z)
}
}
func (t Tile) Parent() Tile {
// top left
if t.X%2 == 0 && t.Y%2 == 0 {
return Tile{t.X / 2, t.Y / 2, t.Z - 1}
}
// bottom left
if (t.X%2 == 0) && !(t.Y%2 == 0) {
return Tile{t.X / 2, (t.Y - 1) / 2, t.Z - 1}
}
// top right
if !(t.X%2 == 0) && (t.Y%2 == 0) {
return Tile{(t.X - 1) / 2, (t.Y) / 2, t.Z - 1}
}
// bottom right
return Tile{(t.X - 1) / 2, (t.Y - 1) / 2, t.Z - 1}
}