feature/add-conversion-to-meters-and-geojson #3
@ -4,6 +4,26 @@ from shapely.geometry import Polygon, Point, LineString
|
||||
import networkx as nx
|
||||
from typing import List, Tuple
|
||||
from rtree import index
|
||||
import math
|
||||
|
||||
|
||||
def haversine(lon1, lat1, lon2, lat2):
|
||||
"""
|
||||
Calculate the great-circle distance between two points
|
||||
on the Earth specified by their longitude and latitude.
|
||||
"""
|
||||
R = 6371000 # Radius of the Earth in meters
|
||||
phi1 = math.radians(lat1)
|
||||
phi2 = math.radians(lat2)
|
||||
delta_phi = math.radians(lat2 - lat1)
|
||||
delta_lambda = math.radians(lon2 - lon1)
|
||||
|
||||
a = math.sin(delta_phi / 2.0) ** 2 + \
|
||||
math.cos(phi1) * math.cos(phi2) * \
|
||||
math.sin(delta_lambda / 2.0) ** 2
|
||||
|
||||
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
||||
return R * c # Output distance in meters
|
||||
|
||||
|
||||
class DistrictHeatingNetworkCreator:
|
||||
@ -29,7 +49,8 @@ class DistrictHeatingNetworkCreator:
|
||||
self._create_graph()
|
||||
self._create_mst()
|
||||
self._iteratively_remove_edges()
|
||||
self.add_centroids_to_mst() # Add centroids to the MST
|
||||
self._add_centroids_to_mst()
|
||||
self._convert_edge_weights_to_meters()
|
||||
return self.final_mst
|
||||
|
||||
def _load_and_process_data(self):
|
||||
@ -217,7 +238,7 @@ class DistrictHeatingNetworkCreator:
|
||||
single_connection_street_nodes = find_single_connection_street_nodes(self.final_mst)
|
||||
self.final_mst_steps.append(list(self.final_mst.edges(data=True)))
|
||||
|
||||
def add_centroids_to_mst(self):
|
||||
def _add_centroids_to_mst(self):
|
||||
"""
|
||||
Add centroids to the final MST graph and connect them to their associated node on the graph.
|
||||
"""
|
||||
@ -238,6 +259,16 @@ class DistrictHeatingNetworkCreator:
|
||||
if nearest_point:
|
||||
self.final_mst.add_edge(centroid_tuple, nearest_point, weight=min_distance)
|
||||
|
||||
def _convert_edge_weights_to_meters(self):
|
||||
"""
|
||||
Convert all edge weights in the final MST graph to meters using the Haversine formula.
|
||||
"""
|
||||
for u, v, data in self.final_mst.edges(data=True):
|
||||
lon1, lat1 = u
|
||||
lon2, lat2 = v
|
||||
distance = haversine(lon1, lat1, lon2, lat2)
|
||||
self.final_mst[u][v]['weight'] = distance
|
||||
|
||||
def plot_network_graph(self):
|
||||
"""
|
||||
Plot the network graph using matplotlib and networkx.
|
||||
|
54
Scripts/geojson_graph_creator.py
Normal file
54
Scripts/geojson_graph_creator.py
Normal file
@ -0,0 +1,54 @@
|
||||
import json
|
||||
from shapely import LineString, Point
|
||||
import networkx as nx
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def networkx_to_geojson(graph: nx.Graph) -> Path:
|
||||
"""
|
||||
Convert a NetworkX graph to GeoJSON format.
|
||||
|
||||
:param graph: A NetworkX graph.
|
||||
:return: GeoJSON formatted dictionary.
|
||||
"""
|
||||
features = []
|
||||
|
||||
for u, v, data in graph.edges(data=True):
|
||||
line = LineString([u, v])
|
||||
feature = {
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": list(line.coords)
|
||||
},
|
||||
"properties": {
|
||||
"weight": data.get("weight", 1.0)
|
||||
}
|
||||
}
|
||||
features.append(feature)
|
||||
|
||||
for node, data in graph.nodes(data=True):
|
||||
point = Point(node)
|
||||
feature = {
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": list(point.coords)[0]
|
||||
},
|
||||
"properties": {
|
||||
"type": data.get("type", "unknown"),
|
||||
"id": data.get("id", "N/A")
|
||||
}
|
||||
}
|
||||
features.append(feature)
|
||||
|
||||
geojson = {
|
||||
"type": "FeatureCollection",
|
||||
"features": features
|
||||
}
|
||||
|
||||
output_geojson_file = Path('./output_files/network_graph.geojson').resolve()
|
||||
with open(output_geojson_file, 'w') as file:
|
||||
json.dump(geojson, file, indent=4)
|
||||
|
||||
return output_geojson_file
|
4
main.py
4
main.py
@ -2,6 +2,7 @@ from DistrictHeatingNetworkCreator import DistrictHeatingNetworkCreator
|
||||
from Scripts.road_processor import road_processor
|
||||
from pathlib import Path
|
||||
import time
|
||||
from Scripts.geojson_graph_creator import networkx_to_geojson
|
||||
location = [45.51663850312751, -73.59854314961274]
|
||||
start_time = time.perf_counter()
|
||||
roads_file = road_processor(location[1], location[0], 0.001)
|
||||
@ -16,7 +17,6 @@ elapsed_time = end_time - start_time
|
||||
|
||||
print(f"The simulation took {elapsed_time:.4f} seconds to run.")
|
||||
|
||||
for node in network_graph.nodes(data=True):
|
||||
print(f"Node: {node[0]}, Type: {node[1].get('type', 'unknown')}, ID: {node[1].get('id', 'N/A')}")
|
||||
networkx_to_geojson(network_graph)
|
||||
|
||||
dhn_creator.plot_network_graph()
|
||||
|
2923
output_files/network_graph.geojson
Normal file
2923
output_files/network_graph.geojson
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user