Advertisement
aghoshpro

geo2grid03

Mar 23rd, 2025 (edited)
372
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- FUNCTION: rasdaman_op.geo2gridX(text, double precision, double precision, double precision, double precision)
  2.  
  3. CREATE OR REPLACE FUNCTION rasdaman_op.geo2grid_final(
  4.     "geoPOLY" text,
  5.     min_lon double precision,
  6.     max_lat double precision,
  7.     resolution_lon double precision,
  8.     resolution_lat double precision,
  9.     OUT "gridPOLY" text)
  10.     RETURNS text
  11.     LANGUAGE 'plpython3u'
  12.     COST 100
  13.     VOLATILE PARALLEL UNSAFE
  14. AS $BODY$
  15. import numpy as np
  16. import re
  17. from affine import Affine
  18. from shapely.geometry import Polygon, LinearRing, MultiPolygon
  19. from shapely.ops import unary_union
  20. from shapely import wkt
  21.  
  22. def grid2WKT_ring(y_grid, x_grid):
  23.     coordinates = list(zip(y_grid, x_grid))
  24.     if coordinates[0] != coordinates[-1]:
  25.         coordinates.append(coordinates[0])
  26.     ring_wkt = "LINEARRING(" + ", ".join(f"{x} {y}" for x, y in coordinates) + ")"
  27.     return ring_wkt
  28.  
  29. def grid2WKT_polygon(y_grid, x_grid):
  30.     coordinates = list(zip(y_grid, x_grid))
  31.     if coordinates[0] != coordinates[-1]:
  32.         coordinates.append(coordinates[0])
  33.     polygon_wkt = "POLYGON((" + ", ".join(f"{x} {y}" for x, y in coordinates) + "))"
  34.     return polygon_wkt
  35.  
  36. def geo2grid(lons, lats, xmin, ymax, x_scale, y_scale, xskew = 0.0, yskew = 0.0):
  37.     aff_gdal = Affine.from_gdal(xmin, x_scale, xskew, ymax, 0.0, -y_scale)
  38.     lons = np.array(lons)
  39.     lats = np.array(lats)
  40.     xs, ys = ~aff_gdal*(lons, lats)
  41.     xs = np.int64(xs)
  42.     ys = np.int64(ys)
  43.     return xs, ys
  44.  
  45. def process_boundary(boundary):
  46.     coords = np.dstack(boundary.xy).tolist()[0]
  47.     coordinates = [{"long": x, "lat": y} for x, y in coords]
  48.    
  49.     lat_arr = []
  50.     long_arr = []
  51.     for coord in coordinates:
  52.         long_arr = np.append(long_arr, coord['long'])
  53.         lat_arr = np.append(lat_arr, coord['lat'])
  54.  
  55.     long_list = long_arr.tolist()
  56.     lat_list = lat_arr.tolist()
  57.  
  58.     x_grid, y_grid = geo2grid(long_list, lat_list, xmin, ymax, x_scale, y_scale)
  59.     return x_grid, y_grid
  60.  
  61. def processPOLYGON(inputPOLYGON):
  62.     if inputPOLYGON.area == 0:
  63.         return None
  64.    
  65.     ext_x_grid, ext_y_grid = process_boundary(inputPOLYGON.exterior)
  66.    
  67.     if len(inputPOLYGON.interiors) == 0:
  68.         gridPOLYGON_wkt = grid2WKT_polygon(ext_y_grid, ext_x_grid)
  69.         return gridPOLYGON_wkt
  70.    
  71.     else:
  72.         ext_coordinates = list(zip(ext_x_grid, ext_y_grid))
  73.         if ext_coordinates[0] != ext_coordinates[-1]:
  74.             ext_x_grid = np.append(ext_x_grid, ext_x_grid[0])
  75.             ext_y_grid = np.append(ext_y_grid, ext_y_grid[0])
  76.            
  77.         rings_wkt = "POLYGON((" + ", ".join(f"{x} {y}" for x, y in zip(ext_x_grid, ext_y_grid)) + ")"
  78.        
  79.         for interior in inputPOLYGON.interiors:
  80.             int_x_grid, int_y_grid = process_boundary(interior)
  81.             int_coordinates = list(zip(int_x_grid, int_y_grid))
  82.            
  83.             if int_coordinates[0] != int_coordinates[-1]:
  84.                 int_x_grid = np.append(int_x_grid, int_x_grid[0])
  85.                 int_y_grid = np.append(int_y_grid, int_y_grid[0])
  86.                
  87.             rings_wkt += ", (" + ", ".join(f"{x} {y}" for x, y in zip(int_x_grid, int_y_grid)) + ")"
  88.        
  89.         rings_wkt += ")"
  90.         return rings_wkt
  91.  
  92. def geoPOLYGON_to_gridPOLYGON(inputREGION, min_lon, max_lat, resolution_lon, resolution_lat):
  93.     global xmin, ymax, x_scale, y_scale
  94.     xmin = min_lon
  95.     ymax = max_lat
  96.     x_scale = resolution_lon
  97.     y_scale = resolution_lat
  98.    
  99.     try:
  100.         inputREGION = wkt.loads(inputREGION)
  101.        
  102.         if inputREGION.geom_type == 'Polygon':
  103.             return processPOLYGON(inputREGION)
  104.        
  105.         elif inputREGION.geom_type == 'MultiPolygon':
  106.             polygon_wkts = []
  107.            
  108.             for polygon in inputREGION.geoms:
  109.                 grid_polygon = processPOLYGON(polygon)
  110.                 if grid_polygon:
  111.                     polygon_wkts.append(grid_polygon)
  112.            
  113.             if not polygon_wkts:
  114.                 return None
  115.                
  116.             try:
  117.                 grid_polygons = [wkt.loads(poly_wkt) for poly_wkt in polygon_wkts if poly_wkt]
  118.                 merged = unary_union(grid_polygons)
  119.                 return merged.wkt
  120.             except Exception as e:
  121.                 return f"MULTIPOLYGON({','.join([p.replace('POLYGON', '') for p in polygon_wkts])})"
  122.        
  123.         else:
  124.             raise ValueError(f"Unsupported geometry type: {inputREGION.geom_type}")
  125.     except Exception as e:
  126.         return f"Error: {str(e)}"
  127.  
  128. gridPOLY = geoPOLYGON_to_gridPOLYGON(geoPOLY, min_lon, max_lat, resolution_lon, resolution_lat)
  129. return gridPOLY
  130. $BODY$;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement