GEO Tiles Downloader
[GeoTiles] / geotiles.sh
1 #!/bin/bash
2
3 if [ $# -lt 6 ]; then
4         echo "GEO Tiles Downloader. Written by Dmitry Shalnov (c) 2018. Apache License, Version 2.0"
5         echo "Specify 2 points and zoom level diapasone of rectangular part of the map you targeted."
6         echo "Usage: $0 <lat1> <lon1> <lat2> <lon2> <zoom level 1> <zoom level 2> [other options]"
7         echo "-d        path to map directory (MAP/ by default)"
8         echo "-m        tiles source (https://tile.openstreetmap.org by default)"
9         echo "-v        verbose"
10         echo "-o        overwrite"
11         echo "WARNNING: Please use reasonably. Don't abuse tile servers!"
12         exit 1
13 fi
14
15 LAT1=$1
16 LONG1=$2
17 LAT2=$3
18 LONG2=$4
19 ZOOM1=$5
20 ZOOM2=$6
21
22 MAP_DEF="https://tile.openstreetmap.org"
23 TMP_TILELIST_FILE="/tmp/tileList"
24
25 : > $TMP_TILELIST_FILE
26
27 shift 6
28
29 while [ "$#" -gt 0 ]; do
30         case "$1" in
31                 -v) VERBOSE=1; shift 1;;
32                 -o) OVERWRITE=1; shift 1;;
33                 -d) MAP_DIR="$2"; shift 2;;
34                 -m) MAP_SRC="$2"; shift 2;;
35                 -*) echo "unknown option: $1" >&2; exit 1;;
36                 *) shift 1;;
37         esac
38 done
39
40 # ------------------------------------------------------------------------
41
42 # tech details https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
43
44 xtile2long() {
45         xtile=$1
46         zoom=$2
47         echo "${xtile} ${zoom}" | awk '{printf("%.9f", $1 / 2.0^$2 * 360.0 - 180)}'
48
49
50 long2xtile() { 
51         long=$1
52         zoom=$2
53         echo "${long} ${zoom}" | awk '{ xtile = ($1 + 180.0) / 360 * 2.0^$2; 
54                 xtile+=xtile<0?-0.5:0.5;
55                 printf("%d", xtile ) }'
56 }
57
58 ytile2lat() {
59         ytile=$1;
60         zoom=$2;
61         tms=$3;
62         if [ ! -z "${tms}" ]
63         then
64         #               from tms_numbering into osm_numbering
65                 ytile=`echo "${ytile}" ${zoom} | awk '{printf("%d\n",((2.0^$2)-1)-$1)}'`;
66         fi
67         lat=`echo "${ytile} ${zoom}" | awk -v PI=3.14159265358979323846 '{ 
68                                                  num_tiles = PI - 2.0 * PI * $1 / 2.0^$2;
69                                                  printf("%.9f", 180.0 / PI * atan2(0.5 * (exp(num_tiles) - exp(-num_tiles)),1)); }'`;
70         echo "${lat}";
71 }
72
73 lat2ytile() { 
74         lat=$1;
75         zoom=$2;
76         tms=$3;
77         ytile=`echo "${lat} ${zoom}" | awk -v PI=3.14159265358979323846 '{ 
78                  tan_x=sin($1 * PI / 180.0)/cos($1 * PI / 180.0);
79                  ytile = (1 - log(tan_x + 1/cos($1 * PI/ 180))/PI)/2 * 2.0^$2; 
80                  ytile+=ytile<0?-0.5:0.5;
81                  printf("%d", ytile ) }'`;
82         if [ ! -z "${tms}" ]
83         then
84                 # from oms_numbering into tms_numbering
85                 ytile=`echo "${ytile}" ${zoom} | awk '{printf("%d\n",((2.0^$2)-1)-$1)}'`;
86         fi
87         echo "${ytile}";
88 }
89
90 average() {
91         echo "$1" "$2" | awk '{printf( "%f\n", $1 + ($2 - $1)/2 ) }'
92 }
93
94 flat(){
95         echo "$1" | awk '{printf( "%d\n", $1 )}'
96 }
97
98 RAND() {
99         awk -v MAX="$1"  'BEGIN{ srand(); print int(rand() * MAX ); }'
100 }
101
102
103 # ------------------------------------------------------------------------
104
105 if [ -z "$MAP_DIR" ]; then 
106         MAP_DIR=MAP
107 fi
108
109 if [ -z "$MAP_SRC" ]; then 
110         MAP_SRC=$MAP_DEF
111 else 
112         if [ -z "$(curl -Is "$MAP_SRC" | head -1)" ]; then 
113                 echo "Could not resolve $MAP_SRC. Please check URL." >&2
114                 exit 0
115         fi 
116 fi
117
118 # add coordinates and zoom to the Map Directory 
119
120 latAverage=$( average $LAT1 $LAT2 )
121 lonAverage=$( average $LONG1 $LONG2 )
122 zoomAverage=$( flat $( average $ZOOM1 $ZOOM2 ))
123
124 MAP_DIR="MAP/$MAP_DIR|$latAverage|$lonAverage|$zoomAverage"
125
126 if [ ! -d "$MAP_DIR" ]; then 
127         if mkdir -p $MAP_DIR 2>/dev/null; then 
128                 echo "$MAP_DIR has been created"
129         else 
130                 echo "$MAP_DIR has not been created" >&2
131                 exit 0
132         fi
133 fi
134
135 # ------------------------------------------------------------------------
136
137 # seq zoom order prefixes setup 
138
139 if [ $ZOOM1 -gt $ZOOM2 ]; then SEQ_ZOOM_STEP='-1'; fi 
140
141 # avoid infinities
142
143 #if [ "$LONG1" == "180" ]; then LONG1="179.999"; fi
144 if [ "$LAT1" == "90" ]; then LAT1="85.0511"; fi
145
146 #if [ "$LONG2" == "180" ]; then LONG2="179.999"; fi
147 if [ "$LAT2" == "90" ]; then LAT2="85.0511"; fi
148
149 #if [ "$LONG1" == "-180" ]; then LONG1="-179.999"; fi
150 if [ "$LAT1" == "-90" ]; then LAT1="-85.0511"; fi
151
152 #if [ "$LONG2" == "-180" ]; then LONG2="-179.999"; fi
153 if [ "$LAT2" == "-90" ]; then LAT2="-85.0511"; fi
154
155
156 # main loop of tiles collection
157
158 for ZOOM in $(seq $ZOOM1 $SEQ_ZOOM_STEP $ZOOM2); do
159
160         mkdir -p $MAP_DIR/$ZOOM/
161
162         TILE1_X=$( long2xtile ${LONG1} ${ZOOM} );
163         TILE1_Y=$( lat2ytile ${LAT1} ${ZOOM} ${TMS} );
164         TILE2_X=$( long2xtile ${LONG2} ${ZOOM} );
165         TILE2_Y=$( lat2ytile ${LAT2} ${ZOOM} ${TMS} );
166
167         # seq order prefixes setup + wrong tile remove
168
169         if [ "$TILE1_X" -gt "$TILE2_X" ]; then 
170                 SEQ_X_STEP='-1'; 
171                 TILE1_X=$(( $TILE1_X - 1 ))
172         else 
173                 TILE2_X=$(( $TILE2_X - 1 ))
174         fi 
175
176         if [ "$TILE1_Y" -gt "$TILE2_Y" ]; then 
177                 SEQ_Y_STEP='-1'; 
178                 TILE1_Y=$(( $TILE1_Y - 1 ))
179         else 
180                 TILE2_Y=$(( $TILE2_Y - 1 ))
181         fi 
182
183         # collecting the list of tiles 
184
185         for tileX in $(seq $TILE1_X $SEQ_X_STEP $TILE2_X); do
186
187                 mkdir -p $MAP_DIR/$ZOOM/$tileX/ 2>/dev/null
188
189                 for tileY in $(seq $TILE1_Y $SEQ_Y_STEP $TILE2_Y); do
190                         echo $ZOOM/$tileX/$tileY >> $TMP_TILELIST_FILE
191                 done
192         done
193 done
194
195 sort --random-sort $TMP_TILELIST_FILE -o $TMP_TILELIST_FILE
196
197 lines=$(cat $TMP_TILELIST_FILE | wc -l)
198
199 echo Total: $lines tiles
200
201 while read line; do
202
203         r=$(RAND 4)
204         sleep $r # not be too abusive to server
205
206         if [ ! -z "$OVERWRITE" ] || [ ! -f $MAP_DIR/$line.png ]; then 
207
208                 if [ ! -z "$VERBOSE" ]; then postFix=" $line\n"; else postFix=''; fi
209
210                 if ! curl -sS "$MAP_SRC/$line.png" -o "$MAP_DIR/$line.png" ; then 
211                         echo "Something went wrong"
212                         exit 0
213                 fi 
214
215                 printf "+$postFix"
216         else 
217                 printf ".$postFix"                              
218         fi
219
220 done < $TMP_TILELIST_FILE
221
222 echo ''
223 exit 0
224
225
Contact me: dev (at) shalnoff (dot) com
PGP fingerprint: A6B8 3B23 6013 F18A 0C71 198B 83D8 C64D 917A 5717