From 5da9766da659a0d738bad9e82b9e764114c9af51 Mon Sep 17 00:00:00 2001 From: Koa Wells Date: Fri, 15 Dec 2023 13:50:41 -0500 Subject: [PATCH] Add initial version of building selection tool --- building_region_selector.py | 52 +++++++++++++++++++++++++++++++++++++ data/.gitignore | 2 ++ main.py | 34 ++++++++++++++++++++++++ map_view_simple_example.py | 27 +++++++++++++++++++ 4 files changed, 115 insertions(+) create mode 100644 building_region_selector.py create mode 100644 data/.gitignore create mode 100644 main.py create mode 100644 map_view_simple_example.py diff --git a/building_region_selector.py b/building_region_selector.py new file mode 100644 index 0000000..82a7c1c --- /dev/null +++ b/building_region_selector.py @@ -0,0 +1,52 @@ +import json + +from pathlib import Path +from shapely.geometry import Polygon + +""" +BuildingSelectionTool is a tool that allows for a subset of buildings to be selected from a larger geojson dataset. +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2023 Concordia CERC group +Project Coder Koa Wells kekoa.wells@concordia.ca +""" + +class BuildingSelectionTool: + def __init__(self, city_file, output_file): + self._city_file = city_file + self._city = json.load(city_file) + self._buildings = self._city['features'] + self._polygon_points = [] + + def _assign_buildings_to_regions(self): + for building in self._buildings: + if building['geometry']['type'] == 'Polygon': + building_centroid = Polygon(building["geometry"]["coordinates"][0]).centroid + elif building['geometry']['type'] == 'MultiPolygon': + # use the centroid of the first polygon inside of the multipolygon + building_centroid = Polygon(building["geometry"]["coordinates"][0][0]).centroid + + building['properties']['centroid'] = [building_centroid.x, building_centroid.y] + building['properties']['district_property'] = [] + + target_regions = [] + region_assigned = False + + target_region = self._regions[len(self._regions) / 2] + while not region_assigned: + if building_centroid.within(Polygon(target_region['geometry']['coordinates'])): + region_assigned = True + break + + target_region_centroid = Polygon(target_region['geometry']['coordinates']).centroid + + if building_centroid.x <= target_region_centroid.x: + if building_centroid.y >= target_region_centroid.y: + regions = regions[0:len(regions) / 2] + elif building_centroid.y < target_region_centroid.y: + regions = regions[len(regions) / 2:len(regions) - 1] + elif building_centroid.x > target_region_centroid.x: + if building_centroid.y >= target_region_centroid.y: + regions = regions[0:len(regions) / 2] + elif building_centroid.y < target_region_centroid.y: + regions = regions[len(regions) / 2:len(regions) - 1] + diff --git a/data/.gitignore b/data/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/data/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..0e23d69 --- /dev/null +++ b/main.py @@ -0,0 +1,34 @@ +import json +from shapely import Polygon +from shapely import Point +from pathlib import Path + +# Make sure to enter your points in the clockwise direction +# and in the longitude, latitude format +selection_box = Polygon([[-73.543833, 45.575932] , + [-73.541834, 45.575245], + [-73.542275, 45.574652], + [-73.544235, 45.575329], + [-73.543833, 45.575932]]) + +geojson_file = Path('./data/collinear_clean.geojson').resolve() +output_file = Path('./output_buildings.geojson').resolve() +buildings_in_region = [] + +with open(geojson_file, 'r') as file: + city = json.load(file) + buildings = city['features'] + +for building in buildings: + coordinates = building['geometry']['coordinates'][0] + building_polygon = Polygon(coordinates) + centroid = Point(building_polygon.centroid) + + if centroid.within(selection_box): + buildings_in_region.append(building) + +output_region = {"type": "FeatureCollection", + "features": buildings_in_region} + +with open(output_file, 'w') as file: + file.write(json.dumps(output_region, indent=2)) diff --git a/map_view_simple_example.py b/map_view_simple_example.py new file mode 100644 index 0000000..fabc09f --- /dev/null +++ b/map_view_simple_example.py @@ -0,0 +1,27 @@ +import tkinter +import tkintermapview + +# create tkinter window +root_tk = tkinter.Tk() +root_tk.geometry(f"{1000}x{700}") +root_tk.title("Building Selection Tool") + +# create map widget +map_widget = tkintermapview.TkinterMapView(root_tk, width=1000, height=700, corner_radius=0) +map_widget.pack(fill="both", expand=True) + +# set other tile server (standard is OpenStreetMap) +map_widget.set_tile_server("https://mt0.google.com/vt/lyrs=m&hl=en&x={x}&y={y}&z={z}&s=Ga", max_zoom=22) # google normal +# map_widget.set_tile_server("https://mt0.google.com/vt/lyrs=s&hl=en&x={x}&y={y}&z={z}&s=Ga", max_zoom=22) # google satellite + +# set current position and zoom +map_widget.set_position(45.497059, -73.578451, marker=False) # Berlin, Germany +map_widget.set_zoom(11) + +# set current position with address +# map_widget.set_address("Berlin Germany", marker=False) + +def marker_click(marker): + print(f"marker clicked - text: {marker.text} position: {marker.position}") + +root_tk.mainloop()