-
-
Save praeclarum/10428983 to your computer and use it in GitHub Desktop.
using System; | |
using System.Net; | |
using System.IO; | |
using Gdk; | |
namespace TileSticher | |
{ | |
class App | |
{ | |
public static int Main (string[] args) | |
{ | |
if (args.Length != 5) { | |
Console.WriteLine ("TileSticher.exe latitude longitude zoom numHorizontal numVertical"); | |
return 1; | |
} | |
// | |
// Get the root tile | |
// | |
var latitude = double.Parse (args [0]); | |
var longitude = double.Parse (args [1]); | |
var zoom = int.Parse (args [2]); | |
var numHorizontal = int.Parse (args [3]); | |
var numVertical = int.Parse (args [4]); | |
var t = GetTileIndex (latitude, longitude, zoom); | |
// | |
// Download all the tiles | |
// | |
var style = SatelliteUrlTemplate; | |
var xo = -numHorizontal / 2; | |
var yo = -numVertical / 2; | |
for (var i = 0; i < numHorizontal; i++) { | |
for (var j = 0; j < numVertical; j++) { | |
var index = new Point (t.X + i + xo, t.Y + j + yo); | |
DownloadTile (style, index, zoom); | |
} | |
} | |
// | |
// Merge them | |
// | |
var rootImage = LoadTile (style, t, zoom); | |
var width = rootImage.Width; | |
var height = rootImage.Height; | |
var outputWidth = width * numHorizontal; | |
var outputHeight = height * numVertical; | |
var output = new Pixbuf (Colorspace.Rgb, false, 8, outputWidth, outputHeight); | |
for (var i = 0; i < numHorizontal; i++) { | |
for (var j = 0; j < numVertical; j++) { | |
var index = new Point (t.X + i + xo, t.Y + j + yo); | |
using (var image = LoadTile (style, index, zoom)) { | |
image.Composite ( | |
output, | |
width * i, height * j, | |
width, height, | |
width * i, height * j, | |
1, 1, | |
InterpType.Bilinear, 255); | |
} | |
} | |
} | |
output.Save ("Poop.png", "png"); | |
Console.WriteLine ("Created {0}x{1} Poop.png", outputWidth, outputHeight); | |
return 0; | |
} | |
static Pixbuf LoadTile (string style, Point index, int zoom) | |
{ | |
return new Pixbuf (GetTileFilename (style, index, zoom)); | |
} | |
static string GetTileFilename (string style, Point index, int zoom) | |
{ | |
return string.Format ("{0}-{1}-{2}-{3}.png", index.X, index.Y, zoom, style.Length); | |
} | |
static void DownloadTile (string style, Point index, int zoom) | |
{ | |
var filename = GetTileFilename (style, index, zoom); | |
if (File.Exists (filename)) | |
return; | |
var url = string.Format (style, index.X, index.Y, zoom); | |
Console.WriteLine ("Downloading {0}", url); | |
var web = new WebClient (); | |
web.Headers.Add ("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"); | |
web.DownloadFile (url, filename); | |
} | |
const string MapUrlTemplate = "https://www.google.com/maps/vt/pb=!1m4!1m3!1i{2}!2i{0}!3i{1}!2m3!1e0!2sm!3i258145710"; | |
const string SatelliteUrlTemplate = "https://khms2.google.com/kh/v=147&x={0}&y={1}&z={2}"; | |
static Point GetTileIndex (double latitude, double longitude, int zoom) | |
{ | |
var lat_rad = latitude / 180 * Math.PI; | |
var n = 1 << zoom; | |
var xtile = n * ((longitude + 180) / 360); | |
var ytile = n * (1 - (Math.Log (Math.Tan (lat_rad) + 1/Math.Cos (lat_rad)) / Math.PI)) / 2; | |
return new Point ((int)xtile, (int)ytile); | |
} | |
} | |
} |
@sleirgoevy Can you please post 2 example URLs, one for the normal map tile and one for the satellite map tile, which when accessed with the browser serve an image correctly? Any coordinates, I just want some baseline for comparison. I must be doing something wrong on my end, but when I tried this, all I got were 404/403 responses.
Normal map: https://www.google.com/maps/vt/pb=!1m4!1m3!1i0!2i0!3i0!2m3!1e0!2sm!3i0
Satellite: https://khms3.google.com/kh/v=845?x=0&y=0&z=0
The normal link works (for me) both in browser and using cURL. The second only worked in browser, however spoofing the User-Agent header seems to be enough to retrieve the image.
I suppose Google may be restricting these APIs to specific countries, so you may be able to query these URLs via a VPN or proxy.
Thank you!
I believe the v parameter may be a version number. If I check a loaded tile in the browser inspector, and bump the version of the URL in the comment above, the URL loads correctly. Otherwise, it 404s. There are also several KHMS domains. I don't know if they're based on location, and thus may have different availability for different folks, or functioning as a simple load-balancer.
I have forked into javascript in case of any use; it can be used from Google Apps Script from e.g. a spreadsheet.
@TomasHubelbauer, you are wrong. The URL in question still works and returns plain images.