@@ -344,4 +344,50 @@ def png_pack(png_tag, data):
344344 png_pack (b'IHDR' , struct .pack ("!2I5B" , width , height , 8 , 6 , 0 , 0 , 0 )),
345345 png_pack (b'IDAT' , zlib .compress (raw_data , 9 )),
346346 png_pack (b'IEND' , b'' )])
347+
348+ def _row2lat (row ):
349+ return 180.0 / np .pi * (2.0 * np .arctan (np .exp (row * np .pi / 180.0 ))- np .pi / 2.0 )
350+
351+ def geodetic_to_mercator (geodetic ):
352+ """This function takes an 2D array in geodetic coordinates (ie: lat x
353+ lon unprojected) and converts it to web mercator. This is needed
354+ to correctly overlay an image on a leaflet map, which uses web
355+ mercator by default.
356+
357+ This code works with arrays that match the relative proportions of
358+ latitude and longitude of the earth, meaning that they have twice
359+ as many points in longitude as latitude (i.e.: (180, 360) for 1
360+ degree resolution).
361+
362+ The code for this is from:
363+ http://stackoverflow.com/questions/25058880/convert-to-web-mercator-with-numpy
364+
365+ Parameters
366+ ----------
367+ geodetic: numpy image array
368+ Latitude x Longitude array, in mono (NxM), rgb (NxMx3) or RGBA (NxMx4)
369+
370+ Returns
371+ -------
372+ meractor: projected numpy image array
373+
374+ """
375+
376+ geo = np .repeat (np .atleast_3d (geodetic ), 2 , axis = 0 )
377+ merc = np .zeros_like (geo )
378+ side = geo .shape [0 ]
379+
380+ for row in range (side ):
381+ lat = _row2lat (180 - ((row * 1.0 )/ side ) * 360 )
382+ g_row = (abs (90 - lat )/ 180 )* side
383+ fraction = g_row - np .floor (g_row )
384+
385+ # Here I optimized the code by using the numpy vector operations
386+ # instead of the for loop:
387+
388+ high_row = geo [np .floor (g_row ), :, :] * (fraction )
389+ low_row = geo [np .ceil (g_row ), :, :] * (1 - fraction )
390+ merc [row , :, :] = high_row + low_row
391+
392+ return np .squeeze (merc )
347393
0 commit comments