-
Notifications
You must be signed in to change notification settings - Fork 0
/
get_bing2.go
124 lines (112 loc) · 2.89 KB
/
get_bing2.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
package main
import (
gomapinfer "github.com/mitroadmaps/gomapinfer/common"
geocoords "github.com/mitroadmaps/gomapinfer/googlemaps"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
"sync"
"time"
)
const URL = "https://ecn.t%s.tiles.virtualearth.net/tiles/a%s.jpeg?g=587&mkt=en-gb&n=z"
var SERVERS []string = []string{"1", "2", "3", "4"}
func toBitString(x int, n int) string {
s := ""
for x > 0 {
s = strconv.Itoa(x % 2) + s
x /= 2
}
for len(s) < n {
s = "0" + s
}
return s
}
var binToBase4 map[string]string = map[string]string{
"00": "0",
"01": "1",
"10": "2",
"11": "3",
}
func GetSatelliteImage(server string, zoom int, x int, y int, fname string) {
// get bing quadkey
// 1) convert x/y to bit strings
// 2) interleave the bit strings
// 3) convert to base 4
xstr := toBitString(x, zoom)
ystr := toBitString(y, zoom)
quadkey := ""
for i := 0; i < zoom; i++ {
quadkey += binToBase4[string(ystr[i]) + string(xstr[i])]
}
url := fmt.Sprintf(URL, server, quadkey)
fmt.Println(url)
resp, err := http.Get(url)
if err != nil {
panic(err)
}
if resp.StatusCode != 200 || resp.Header.Get("Content-Type") != "image/jpeg" {
if resp.StatusCode == 500 {
fmt.Printf("warning: got 500 on %s (retrying later)\n", url)
time.Sleep(5 * time.Second)
GetSatelliteImage(server, zoom, x, y, fname)
} else {
var errdesc string
if resp.Header.Get("Content-Type") != "image/jpeg" {
if bytes, err := ioutil.ReadAll(resp.Body); err == nil {
errdesc = string(bytes)
}
}
panic(fmt.Errorf("got status code %d (errdesc=%s)", resp.StatusCode, errdesc))
}
}
imBytes, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
panic(err)
}
if err := ioutil.WriteFile(fname, imBytes, 0644); err != nil {
panic(err)
}
}
func main() {
// compute which mapbox tiles are needed
desiredZoom := 17
wantedTiles := make(map[[2]int]bool)
ll := gomapinfer.Point{-98.19589750268221, 28.619889335848324}
tile := geocoords.LonLatToMapboxTile(ll, desiredZoom)
for i := -16; i < 16; i++ {
for j := -16; j < 16; j++ {
wantedTiles[[2]int{tile[0]+i, tile[1]+j}] = true
}
}
// determine which ones haven't been downloaded yet
var neededTiles [][2]int
for tile := range wantedTiles {
fname := fmt.Sprintf("images2/%d_%d.jpg", tile[0], tile[1])
if _, err := os.Stat(fname); err == nil {
continue
}
neededTiles = append(neededTiles, tile)
}
fmt.Printf("found %d wanted tiles, %d still needed\n", len(wantedTiles), len(neededTiles))
ch := make(chan [2]int)
var wg sync.WaitGroup
for i := 0; i < len(SERVERS); i++ {
wg.Add(1)
go func(server string) {
defer wg.Done()
for tile := range ch {
fname := fmt.Sprintf("images2/%d_%d.jpg", tile[0], tile[1])
fmt.Printf("creating %s\n", fname)
GetSatelliteImage(server, desiredZoom, tile[0], tile[1], fname)
}
}(SERVERS[i])
}
for _, tile := range neededTiles {
ch <- tile
}
close(ch)
wg.Wait()
}