@@ -370,14 +370,6 @@ def validate(cls, v):
370370 def _is_simple (self , epsg : EPSG ) -> bool :
371371 return epsg == EPSG .SIMPLEPIXEL
372372
373- def geo_and_geo (self , src_epsg : EPSG , tgt_epsg : EPSG ) -> None :
374- if self ._is_simple (src_epsg ) or self ._is_simple (tgt_epsg ):
375- raise Exception (
376- f"Cannot be used for Simple transformations. Found { src_epsg } and { tgt_epsg } "
377- )
378- self .transform_function = Transformer .from_crs (src_epsg .value ,
379- tgt_epsg .value ).transform
380-
381373 def _get_ranges (self , bounds : np .ndarray ):
382374 """helper function to get the range between bounds.
383375
@@ -386,34 +378,97 @@ def _get_ranges(self, bounds: np.ndarray):
386378 y_range = np .max (bounds [:, 1 ]) - np .min (bounds [:, 1 ])
387379 return (x_range , y_range )
388380
381+ def _min_max_x_y (self , bounds : np .ndarray ):
382+ """returns the min x, max x, min y, max y of a numpy array
383+ """
384+ return np .min (bounds [:, 0 ]), np .max (bounds [:, 0 ]), np .min (
385+ bounds [:, 1 ]), np .max (bounds [:, 1 ])
386+
387+ def geo_and_geo (self , src_epsg : EPSG , tgt_epsg : EPSG ) -> None :
388+ """method to change from one projection to another projection.
389+
390+ supports EPSG transformations not Simple.
391+ """
392+ if self ._is_simple (src_epsg ) or self ._is_simple (tgt_epsg ):
393+ raise Exception (
394+ f"Cannot be used for Simple transformations. Found { src_epsg } and { tgt_epsg } "
395+ )
396+ self .transform_function = Transformer .from_crs (src_epsg .value ,
397+ tgt_epsg .value ,
398+ always_xy = True ).transform
399+
389400 def geo_and_pixel (self ,
390401 src_epsg ,
391402 pixel_bounds : TiledBounds ,
392403 geo_bounds : TiledBounds ,
393404 zoom = 0 ):
394- #TODO: pixel to geo
405+ """method to change from one projection to simple projection"""
406+
407+ pixel_bounds = pixel_bounds .bounds
408+ geo_bounds_epsg = geo_bounds .epsg
409+ geo_bounds = geo_bounds .bounds
410+
411+ #TODO: think about renaming local/global?
412+ #local = pixel
413+ #global = geo
414+ local_bounds = np .array ([(point .x , point .y ) for point in pixel_bounds ],
415+ dtype = np .int )
416+ #convert geo bounds to pixel bounds. assumes geo bounds are in wgs84/EPS4326 per leaflet
417+ global_bounds = np .array ([
418+ PygeoPoint .from_latitude_longitude (latitude = point .y ,
419+ longitude = point .x ).pixels (zoom )
420+ for point in geo_bounds
421+ ])
422+
423+ #get the range of pixels for both sets of bounds to use as a multiplification factor
424+ local_x_range , local_y_range = self ._get_ranges (local_bounds )
425+ global_x_range , global_y_range = self ._get_ranges (global_bounds )
426+
395427 if src_epsg == EPSG .SIMPLEPIXEL :
396- pass
428+
429+ def transform (x : int , y : int ):
430+ scaled_xy = (x * (global_x_range ) / (local_x_range ),
431+ y * (global_y_range ) / (local_y_range ))
432+
433+ minx , _ , miny , _ = self ._min_max_x_y (global_bounds )
434+ x , y = map (lambda i , j : i + j , scaled_xy , (minx , miny ))
435+
436+ point = PygeoPoint .from_pixel (pixel_x = x , pixel_y = y ,
437+ zoom = zoom ).latitude_longitude
438+ #convert to the desired epsg
439+ return Transformer .from_crs (EPSG .EPSG4326 .value ,
440+ geo_bounds_epsg .value ,
441+ always_xy = True ).transform (
442+ point [1 ], point [0 ])
443+
444+ self .transform_function = transform
397445
398446 #geo to pixel - converts a point in geo coords to pixel coords
399- else :
400- pixel_bounds = pixel_bounds .bounds
401- geo_bounds = geo_bounds .bounds
402-
403- local_bounds = np .array (
404- [(point .x , point .y ) for point in pixel_bounds ], dtype = np .int )
405- #convert geo bounds to pixel bounds. assumes geo bounds are in wgs84/EPS4326 per leaflet
406- global_bounds = np .array ([
407- PygeoPoint .from_latitude_longitude (
408- latitude = point .y , longitude = point .x ).pixels (zoom )
409- for point in geo_bounds
410- ])
411-
412- #get the range of pixels for both sets of bounds to use as a multiplification factor
413- global_x_range , global_y_range = self ._get_ranges (global_bounds )
414- local_x_range , local_y_range = self ._get_ranges (local_bounds )
447+ #handles 4326 from lat,lng
448+ elif src_epsg == EPSG .EPSG4326 :
449+
450+ def transform (x : int , y : int ):
451+ point_in_px = PygeoPoint .from_latitude_longitude (
452+ latitude = y , longitude = x ).pixels (zoom )
453+
454+ minx , _ , miny , _ = self ._min_max_x_y (global_bounds )
455+ x , y = map (lambda i , j : i - j , point_in_px , (minx , miny ))
456+
457+ return (x * (local_x_range ) / (global_x_range ),
458+ y * (local_y_range ) / (global_y_range ))
459+
460+ self .transform_function = transform
461+
462+ #handles 3857 from meters
463+ elif src_epsg == EPSG .EPSG3857 :
415464
416465 def transform (x : int , y : int ):
466+ point_in_px = PygeoPoint .from_meters (meter_y = y ,
467+ meter_x = x ).pixels (zoom )
468+
469+ minx , _ , miny , _ = self ._min_max_x_y (global_bounds )
470+ x , y = map (lambda i , j : i - j , point_in_px , (minx , miny ))
471+
417472 return (x * (local_x_range ) / (global_x_range ),
418473 y * (local_y_range ) / (global_y_range ))
419474
0 commit comments