nakarte

Source code of https://map.sikmir.ru (fork)
git clone git://git.sikmir.ru/nakarte
Log | Files | Refs | LICENSE

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