Compare commits

..

8 Commits

6 changed files with 134 additions and 76 deletions

View File

@ -0,0 +1,86 @@
"""
Building Selection Tool
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Koa Wells kekoa.wells@concordia.ca
"""
import json
from pathlib import Path
from shapely import Polygon
from shapely import Point
import helpers
class BuildingSelectionTool:
"""
BuildingSelectionTool class
"""
def __init__(self, geojson_file_path):
geojson_file = Path(geojson_file_path).resolve()
with open(geojson_file, 'r') as file:
self.city = json.load(file)
self.buildings = self.city['features']
self.selected_buildings = []
def select_by_polygon(self, selection_polygon_coordinates):
"""
Get all buildings within a specified polygon and write the output to output_file_path
:param selection_polygon_coordinates: list of coordinates forming the selection polygon
:return: None
"""
selection_polygon = Polygon(selection_polygon_coordinates)
for building in self.buildings:
coordinates = building['geometry']['coordinates'][0]
building_polygon = Polygon(coordinates)
centroid = Point(building_polygon.centroid)
if centroid.within(selection_polygon):
self.selected_buildings.append(building)
def select_by_coordinate(self, coordinate):
"""
:param coordinate: longitude, latitude coordinate of selected
:return: None
"""
longitude = coordinate[0]
latitude = coordinate[1]
point = Point([longitude, latitude])
for building in self.buildings:
building_coordinates = building['geometry']['coordinates'][0]
building_polygon = Polygon(building_coordinates)
if point.within(building_polygon):
self.selected_buildings.append(building)
def select_by_address(self, address):
"""
Select a building by inputting an address
:param address:
:return: None
"""
coordinates = helpers.get_gps_coordinate_by_address(address)
longitude = coordinates[1]
latitude = coordinates[0]
point = Point([longitude, latitude])
for building in self.buildings:
building_coordinates = building['geometry']['coordinates'][0]
building_polygon = Polygon(building_coordinates)
if point.within(building_polygon):
self.selected_buildings.append(building)
def save_selected_buildings(self, output_file_path):
"""
Save all selected buildings to an output file.
:param output_file_path: destination file path including file name and extension
:return: None
"""
output_file = Path(output_file_path).resolve()
output_region = {"type": "FeatureCollection",
"features": self.selected_buildings}
with open(output_file, 'w') as file:
file.write(json.dumps(output_region, indent=2))

24
helpers.py Normal file
View File

@ -0,0 +1,24 @@
"""
Helpers
"""
import requests
#OpenCage Geocoding API key
API_KEY = '744ad0d2d58e49d1ac57d6fb04fe5d82'
def get_gps_coordinate_by_address(address):
base_url = "https://api.opencagedata.com/geocode/v1/json"
params = {
'q': address,
'key': API_KEY,
}
response = requests.get(base_url, params=params)
data = response.json()
if response.status_code == 200 and data['status']['code'] == 200:
location = data['results'][0]['geometry']
return location['lat'], location['lng']
else:
print(f"Error: {data['status']['message']}")
return None, None

View File

@ -1,42 +0,0 @@
import requests
def get_lat_lng(api_key, address):
base_url = "https://api.opencagedata.com/geocode/v1/json"
params = {
'q': address,
'key': api_key,
}
response = requests.get(base_url, params=params)
data = response.json()
if response.status_code == 200 and data['status']['code'] == 200:
location = data['results'][0]['geometry']
return location['lat'], location['lng']
else:
print(f"Error: {data['status']['message']}")
return None, None
def get_lat_lng_for_addresses(api_key, addresses):
coordinates = []
for address in addresses:
lat, lng = get_lat_lng(api_key, address)
if lat is not None and lng is not None:
coordinates.append((lat, lng))
return coordinates
# Replace 'YOUR_API_KEY' with your OpenCage Geocoding API key
api_key = '744ad0d2d58e49d1ac57d6fb04fe5d82'
# Example list of addresses
addresses = ["1600 Amphitheatre Parkway, Mountain View, CA",
"Eiffel Tower, Paris, France",
"Big Ben, London, UK"]
coordinates = get_lat_lng_for_addresses(api_key, addresses)
# Print the coordinates
for address, coord in zip(addresses, coordinates):
print(f"{address} -> Latitude: {coord[0]}, Longitude: {coord[1]}")

52
main.py
View File

@ -1,40 +1,24 @@
import json from building_selection_tool import BuildingSelectionTool
from shapely import Polygon
from shapely import Point
from pathlib import Path
# Make sure to enter your points in the clockwise direction selection_tool = BuildingSelectionTool('./data/collinear_clean.geojson')
# 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]])
x=-73.61574532884296
y=45.603911965131
diff=0.001
selection_box = Polygon([[x+diff, y-diff],
[x-diff, y-diff],
[x-diff, y+diff],
[x+diff, y+diff]])
geojson_file = Path('./data/collinear_clean 1.geojson').resolve()
output_file = Path('./output_buildings.geojson').resolve()
buildings_in_region = []
with open(geojson_file, 'r') as file: # select all buildings within a polygon
city = json.load(file) sample_polygon_coordinates = [[-73.543833, 45.575932],
buildings = city['features'] [-73.541834, 45.575245],
[-73.542275, 45.574652],
[-73.544235, 45.575329],
[-73.543833, 45.575932]]
for building in buildings: selection_tool.select_by_polygon(sample_polygon_coordinates)
coordinates = building['geometry']['coordinates'][0]
building_polygon = Polygon(coordinates)
centroid = Point(building_polygon.centroid)
if centroid.within(selection_box): # select building by address
buildings_in_region.append(building) sample_address = "2155 Rue Guy, Montreal, Quebec"
selection_tool.select_by_address(sample_address)
output_region = {"type": "FeatureCollection", # select building by [longitude, latitude] coordinate
"features": buildings_in_region} sample_coordinate = [-73.5790796, 45.4972906]
selection_tool.select_by_coordinate(sample_coordinate)
with open(output_file, 'w') as file: # save selected buildings in geojson format to specified output_file_path
file.write(json.dumps(output_region, indent=2)) output_file_path = "./output_files/sample_output.geojson"
selection_tool.save_selected_buildings(output_file_path)

2
output_files/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

4
requirements.txt Normal file
View File

@ -0,0 +1,4 @@
json
shapely
pathlib
requests