KawgKawgKawg commited on
Commit
706ed73
·
verified ·
1 Parent(s): d593951

Upload 3 files

Browse files
Files changed (3) hide show
  1. network_analysis.py +141 -0
  2. shortest_path.gpkg +0 -0
  3. symbology-style.db +0 -0
network_analysis.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #Libraries To Import For Doing Network Analysis using QGis
2
+ #Using The Core QGIS functions and we're using PyQT classes for graph building and layer manipulation to learn 2 points to another
3
+ import sys
4
+ import os
5
+ from qgis.analysis import QgsGraphBuilder #Used To analyze two points
6
+ from qgis.analysis import QgsGraphAnalyzer #Uses Djikstra's Algorithm to find the most optimal path between 2 points
7
+
8
+ from qgis.core import (
9
+ QgsApplication,
10
+ QgsWkbTypes,
11
+ QgsProject, #Project Manager
12
+ QgsVectorLayer, #To Load Shapefiles and geopackages
13
+ QgsFeature, #Single row in a vector layer
14
+ QgsGeometry, #For mathematical geometry operations
15
+ QgsPointXY, #Makes a 2D point
16
+ QgsPoint,
17
+ QgsFields,
18
+ QgsField, #For multple attribute schemas and individual attribute field
19
+ QgsVectorFileWriter #For Package Export
20
+ )
21
+
22
+ from qgis.PyQt.QtCore import QVariant # Used to define field data types
23
+
24
+ #Now we load the Philippine roads dataset from a non-profit organization called Humanitarian Open Street map team
25
+ #This will give us an open dataset about roads in NCR and give us the shortest path between two points
26
+ #Setup QGIS Paths
27
+ QGIS_PREFIX_PATH = "/usr" # Common for Ubuntu QGIS installs
28
+ QGIS_PLUGIN_PATH = "/usr/lib/qgis/plugins"
29
+
30
+ qgs = QgsApplication([], False)
31
+ qgs.setPrefixPath(QGIS_PREFIX_PATH, True)
32
+ qgs.initQgis()
33
+
34
+
35
+ layer = QgsVectorLayer("phl_roads_lines.gpkg", "roads", "ogr")
36
+
37
+ #print("Layer loaded:", layer.name())
38
+
39
+ #We are going to find shortest path for Quezon city
40
+ start_point = QgsPointXY(121.0365, 14.6760)
41
+ end_point = QgsPointXY(121.0000, 14.5550)
42
+
43
+ tolerance = 0.001 #to snap nearest vortex
44
+ builder = QgsGraphBuilder(layer.sourceCrs())
45
+
46
+ points = [start_point, end_point]
47
+
48
+ graph = builder.graph()
49
+
50
+ #getting the feature graphs
51
+ for feature in layer.getFeatures():
52
+ geom = feature.geometry()
53
+ if geom.isMultipart():
54
+ lines = geom.asMultiPolyline()
55
+ else:
56
+ lines = [geom.asPolyline()]
57
+ for line in lines:
58
+ for i in range(len(line) - 1):
59
+ #Then we convert it to a QgisPoint
60
+ p1 = QgsPointXY(line[i].x(), line[i].y())
61
+ p2 = QgsPointXY(line[i + 1].x(), line[i + 1].y())
62
+
63
+ builder.addVertex(-1, p1)
64
+ builder.addVertex(-1, p2)
65
+
66
+ id1 = builder.graph().findVertex(p1)
67
+ id2 = builder.graph().findVertex(p2)
68
+
69
+ distance = p1.distance(p2)
70
+
71
+ builder.addEdge(id1, p1, id2, p2, [distance])
72
+
73
+ graph = builder.graph()
74
+
75
+
76
+ # Convert the coordinates (start_point and end_point) into node indexes in the graph
77
+ start_idx = graph.findVertex(start_point)
78
+ end_idx = graph.findVertex(end_point)
79
+
80
+ # Use Dijkstra's algorithm to compute the shortest path tree from the start node
81
+ # 0 is the index for cost (in our case: distance)
82
+ tree, cost = QgsGraphAnalyzer.dijkstra(graph, start_idx, 0)
83
+
84
+ # If cost is infinite, it means there’s no possible path between start and end
85
+ if cost[end_idx] == float('inf'):
86
+ print("No Path Found")
87
+ sys.exit(1)
88
+
89
+ # Backtrack from end point to start to extract the shortest path
90
+ route = []
91
+ cur_pos = end_idx
92
+ while cur_pos != start_idx:
93
+ incoming_edge = tree[cur_pos] # The edge that leads to current vertex
94
+ if incoming_edge == -1:
95
+ print("No Route!")
96
+ sys.exit(1)
97
+
98
+ # Get the source vertex of this edge, and retrieve its point
99
+ from_vertex = graph.edge(incoming_edge).fromVertex()
100
+ point = graph.vertex(from_vertex).point()
101
+ route.append(point)
102
+
103
+ # Move to the previous vertex
104
+ cur_pos = from_vertex
105
+
106
+ # Add the final starting point to complete the route
107
+ route.append(start_point)
108
+ route.reverse() # Reverse because we built the route from end to start
109
+
110
+ # Define fields for the output layer
111
+ fields = QgsFields()
112
+ fields.append(QgsField("id", QVariant.Int)) # We'll assign an ID = 1 to this feature
113
+
114
+ # Define the GeoPackage file path for saving the shortest path result
115
+ output_path = "shortest_path.gpkg"
116
+
117
+ # Create the output vector layer writer (LineString geometry, same CRS as roads layer)
118
+ output_layer = QgsVectorFileWriter.create(
119
+ output_path, # File to save
120
+ fields, # Attribute schema
121
+ QgsWkbTypes.LineString, # Geometry type
122
+ layer.sourceCrs(), # Coordinate reference system
123
+ "GPKG" # Format
124
+ )
125
+
126
+ # Create a feature from the route geometry
127
+ feat = QgsFeature()
128
+ feat.setFields(fields)
129
+ feat.setAttribute("id", 1)
130
+ feat.setGeometry(QgsGeometry.fromPolylineXY(route))
131
+
132
+ # Add the feature to the output file
133
+ output_layer.addFeature(feat)
134
+
135
+ # Close and save the layer to disk
136
+ del output_layer
137
+
138
+ print(f"✅ Shortest path successfully saved to: {output_path}")
139
+
140
+ # Exit QGIS to clean up resources and avoid memory leaks
141
+ qgs.exitQgis()
shortest_path.gpkg ADDED
Binary file (98.3 kB). View file
 
symbology-style.db ADDED
Binary file (86 kB). View file