Commit a1cb6c53 authored by Eric Duminil's avatar Eric Duminil
Browse files

Able to export Shapefile now

parent a5b79d6b
cache cache
*.html
*.csv
*.png
\ No newline at end of file
...@@ -17,6 +17,8 @@ import overpy ...@@ -17,6 +17,8 @@ import overpy
from pyproj import Transformer from pyproj import Transformer
from shapely import LineString, geometry, wkt from shapely import LineString, geometry, wkt
from shapely.ops import transform from shapely.ops import transform
import pandas as pd
import geopandas as gpd
from tree import Forest from tree import Forest
from import_existing_trees import get_existing_forest from import_existing_trees import get_existing_forest
...@@ -47,11 +49,13 @@ IGNORE_ROADS = set(['primary', 'unclassified', 'secondary', ...@@ -47,11 +49,13 @@ IGNORE_ROADS = set(['primary', 'unclassified', 'secondary',
SCRIPT_DIR = Path(__file__).resolve().parent SCRIPT_DIR = Path(__file__).resolve().parent
OUTPUT_DIR = SCRIPT_DIR / 'output'
Bounds = namedtuple("Bounds", "W S E N")
def load_region(wkt_polygon): def load_region(wkt_polygon):
region = wkt.loads(wkt_polygon) region = wkt.loads(wkt_polygon)
bounds = namedtuple("Bounds", "W S E N")(*region.bounds) bounds = Bounds(*region.bounds)
return region, bounds return region, bounds
...@@ -140,22 +144,23 @@ def place_trees(forest, ways, region, to_local, tree_distance, min_distance_2) - ...@@ -140,22 +144,23 @@ def place_trees(forest, ways, region, to_local, tree_distance, min_distance_2) -
color='#DFFF00', color='#DFFF00',
type='Fake Tree', type='Fake Tree',
description='Tilia tomentosa', description='Tilia tomentosa',
diameter=6 diameter=6,
source='add_trees.py'
) )
return forest return forest
def plot_trees(bounds, forest, tree_distance) -> None: def plot_trees(bounds: Bounds, forest: Forest, tree_distance: float) -> None:
print("Exporting diagram...") print("Exporting diagram...")
tree_xs, tree_ys, colors = forest.xs_ys_c6 tree_xs, tree_ys, colors = forest.xs_ys_cs
plt.scatter(tree_xs, tree_ys, s=2, c=colors) plt.scatter(tree_xs, tree_ys, s=2, c=colors)
plt.grid(True) plt.grid(True)
plt.title(f"{bounds}\nTree distance : {tree_distance} m") plt.title(f"{bounds}\nTree distance : {tree_distance} m")
plt.gcf().set_size_inches(15, 10) plt.gcf().set_size_inches(15, 10)
plt.savefig( plt.savefig(
SCRIPT_DIR / f"{get_basename(bounds)}.png", bbox_inches='tight', dpi=300) OUTPUT_DIR / f"{get_basename(bounds)}.png", bbox_inches='tight', dpi=300)
print(" DONE!") print(" DONE!")
...@@ -188,27 +193,49 @@ def export_map(bounds, forest, epsg_id) -> None: ...@@ -188,27 +193,49 @@ def export_map(bounds, forest, epsg_id) -> None:
control=True control=True
).add_to(interactive_map) ).add_to(interactive_map)
interactive_map.save(f"{get_basename(bounds)}_trees.html") interactive_map.save(OUTPUT_DIR / f"{get_basename(bounds)}_trees.html")
print(" DONE!") print(" DONE!")
def export_csv(bounds, forest, wkt_polygon, tree_distance, min_distance, epsg_id) -> None: def export_csv(bounds, forest, wkt_polygon, tree_distance, min_distance, epsg_id) -> None:
print("Exporting CSV...") print("Exporting CSV...")
with open(SCRIPT_DIR / f"{get_basename(bounds)}_trees.csv", "w") as csv: with open(OUTPUT_DIR / f"{get_basename(bounds)}_trees.csv", "w") as csv:
csv.write(f"# Fake trees for; {wkt_polygon}\n") csv.write(f"# Fake trees for; {wkt_polygon}\n")
csv.write(f"# Tree distance along roads; {tree_distance}; [m]\n") csv.write(f"# Tree distance along roads; {tree_distance}; [m]\n")
csv.write(f"# Minimum allowed distance between trees; {min_distance}; [m]\n") csv.write(f"# Minimum allowed distance between trees; {min_distance}; [m]\n")
csv.write(f"# EPSG; {epsg_id}\n") csv.write(f"# EPSG; {epsg_id}\n")
csv.write("# X; Y; Type; Description; Radius\n") csv.write("# X; Y; Type; Description; Radius; Source\n")
csv.write("# [m]; [m]; [?]; [?]; [m]\n") csv.write("# [m]; [m]; [-]; [-]; [m]; [-]\n")
for tree in forest: for tree in forest:
csv.write(f"{tree.x};{tree.y};{tree.type};{tree.description};{tree.radius}\n") csv.write(f"{tree.x};{tree.y};{tree.type};{tree.description};{tree.radius};{tree.source}\n")
print(" DONE!") print(" DONE!")
def export_shapefile(bounds, forest, tree_distance, epsg_id): def export_shapefile(bounds: Bounds, forest: Forest, tree_distance: float, epsg_id: str) -> None:
print("Exporting shapefile") print("Exporting shapefile")
data = [{
'x': t.x, 'y': t.y,
'Bezeichnun': t.description, 'Baumart': t.type,
'Baumhöhe': t.height, 'Kronenbrei': t.diameter,
'Quelle': t.source,
}
for t in forest]
df = pd.DataFrame.from_dict(data)
gdf = gpd.GeoDataFrame(
df.drop(columns=['x', 'y']),
geometry=gpd.points_from_xy(df.x, df.y), crs=epsg_id
)
print(gdf)
basename = get_basename(bounds)
shp_dir = OUTPUT_DIR / basename
shp_dir.mkdir(exist_ok=True)
gdf.to_file(shp_dir / f"trees.shp")
print(" DONE!") print(" DONE!")
......
from pathlib import Path
import geopandas as gpd import geopandas as gpd
from tree import Tree, Forest from tree import Tree, Forest
...@@ -11,7 +12,8 @@ def get_existing_forest(shp_input): ...@@ -11,7 +12,8 @@ def get_existing_forest(shp_input):
description=tree_row.Bezeichnun, description=tree_row.Bezeichnun,
diameter=tree_row.Kronenbrei, diameter=tree_row.Kronenbrei,
type=tree_row.Baumart, type=tree_row.Baumart,
trunk_diameter=tree_row.Stammumfan trunk_diameter=tree_row.Stammumfan,
source=Path(shp_input).name
)) ))
return Forest(trees) return Forest(trees)
......
*.png
*.html
*.csv
*.cpg
*.dbf
*.shp
*.prj
*.shx
*.geojson
\ No newline at end of file
...@@ -13,6 +13,7 @@ class Tree: ...@@ -13,6 +13,7 @@ class Tree:
trunk_diameter: float = None trunk_diameter: float = None
type: str = None type: str = None
description: str = '?' description: str = '?'
source: str = '?'
color: str = 'green' color: str = 'green'
def __len__(self): def __len__(self):
...@@ -26,7 +27,7 @@ class Tree: ...@@ -26,7 +27,7 @@ class Tree:
return self.diameter / 2 return self.diameter / 2
def __str__(self): def __str__(self):
return f"{self.type} ({self.description}), {self.radius or '?'} m (X={self.x:.1f}, Y={self.y:.1f})" return f"{self.type} ({self.description}), {self.radius} m (X={self.x:.1f}, Y={self.y:.1f})"
class Forest(UserList): class Forest(UserList):
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment