cutline.py (2432B)
1 #!/usr/bin/env python3 2 import argparse 3 import json 4 5 from shapely.geometry import MultiPolygon, Point, Polygon, shape 6 7 OUTPUT_PRECISION = 5 8 9 10 def simplify_line(line, tolerance): 11 return line.simplify(tolerance, preserve_topology=True) 12 13 14 def round_coordinates(line, precision): 15 return [(round(x, precision), round(y, precision)) for x, y in line.coords] 16 17 18 def main(input_file, output_file, tolerance): 19 with open(input_file, "r") as f: 20 data = json.load(f) 21 22 total_nodes = 0 23 simplified_geometries = [] 24 for feature in data["features"]: 25 geom = shape(feature["geometry"]) 26 if isinstance(geom, Point): 27 print("Skipping point geometry") 28 continue 29 if isinstance(geom, Polygon): 30 polygons = [geom] 31 elif isinstance(geom, MultiPolygon): 32 polygons = geom.geoms 33 else: 34 print(f"Error: Unsupported geometry type '{geom.geom_type}' encountered.") 35 exit(1) 36 37 for polygon in polygons: 38 if polygon.interiors: 39 print("Error: Polygons with holes not supported") 40 exit(1) 41 linestring = polygon.exterior 42 simplified_linestring = simplify_line(linestring, tolerance) 43 simplified_geometries.append( 44 round_coordinates(simplified_linestring, OUTPUT_PRECISION) 45 ) 46 47 polygon_index = len(simplified_geometries) 48 orig_nodes_count = len(linestring.coords) 49 result_nodes_count = len(simplified_linestring.coords) 50 51 print( 52 f"Polygon #{polygon_index}: {orig_nodes_count} -> {result_nodes_count} nodes." 53 ) 54 total_nodes += len(simplified_linestring.coords) 55 56 with open(output_file, "w") as f: 57 data = {"cutline": simplified_geometries} 58 json.dump(data, f) 59 print(f"Total nodes: {total_nodes}") 60 61 62 if __name__ == "__main__": 63 parser = argparse.ArgumentParser(description="Create boundary from a GeoJSON.") 64 parser.add_argument("input_file", type=str, help="Input GeoJSON file") 65 parser.add_argument("output_file", type=str, help="Output JSON file") 66 parser.add_argument( 67 "-t", 68 "--tolerance", 69 default=0.01, 70 type=float, 71 help="Tolerance for simplifying geometries, default=0.01", 72 ) 73 args = parser.parse_args() 74 main(args.input_file, args.output_file, args.tolerance) 75