70 lines
2.9 KiB
Python
70 lines
2.9 KiB
Python
from geopy.distance import great_circle
|
|
from qgis.core import (QgsFeature, QgsField, QgsGeometry, QgsPoint, QgsPointXY, QgsVectorLayer, QgsProject, QgsSpatialIndex)
|
|
|
|
# Locate the aerial path layer
|
|
aerial_path_layer = QgsProject.instance().mapLayersByName('AERIAL_PATH')[0]
|
|
|
|
# Locate the edges layer
|
|
edges_layer = QgsProject.instance().mapLayersByName('EDGES')[0]
|
|
|
|
# Define the data provider
|
|
pr = edges_layer.dataProvider()
|
|
|
|
# Initialize spatial index
|
|
index = QgsSpatialIndex()
|
|
|
|
# List to hold new features and their IDs
|
|
new_edges = []
|
|
features_by_id = {}
|
|
|
|
# Iterate over every feature of the AERIAL_PATH layer
|
|
for feature in aerial_path_layer.getFeatures():
|
|
# Get the geometry of the feature
|
|
geom = feature.geometry()
|
|
|
|
# Handle both 2D and 3D geometries
|
|
if geom.isMultipart():
|
|
vertices = [v for part in geom.asMultiPolyline() for v in part]
|
|
else:
|
|
vertices = geom.asPolyline()
|
|
|
|
for i in range(1, len(vertices)):
|
|
# Calculate the distance between the two points in feet
|
|
pt1 = vertices[i - 1]
|
|
pt2 = vertices[i]
|
|
length = great_circle((pt1.y(), pt1.x()), (pt2.y(), pt2.x())).feet
|
|
|
|
# Create a new feature in the EDGES layer for each vertex pair
|
|
edge = QgsFeature()
|
|
new_geom = QgsGeometry.fromPolyline([QgsPoint(pt1), QgsPoint(pt2)])
|
|
edge.setGeometry(new_geom)
|
|
edge.setAttributes(['Aerial', length, length * 2.5])
|
|
|
|
new_edges.append(edge)
|
|
pr.addFeature(edge)
|
|
index.insertFeature(edge)
|
|
features_by_id[edge.id()] = edge
|
|
|
|
# Start editing the edges layer
|
|
edges_layer.startEditing()
|
|
|
|
# Adjust intersecting line endpoints to the average intersection point
|
|
for edge_id, edge in features_by_id.items():
|
|
endpoints = [QgsPoint(point) for point in edge.geometry().asPolyline()]
|
|
for i in [0, -1]: # Check both endpoints
|
|
# Find nearby endpoints (within a small threshold)
|
|
search_radius = 0.00005
|
|
nearby_ids = index.intersects(QgsGeometry.fromPointXY(QgsPointXY(endpoints[i])).buffer(search_radius, 8).boundingBox())
|
|
nearby_endpoints = [QgsPoint(point) for id in nearby_ids for point in features_by_id[id].geometry().asPolyline() if QgsPoint(point).distance(endpoints[i]) < search_radius]
|
|
if len(nearby_endpoints) > 2:
|
|
# Update endpoint to the average nearby endpoint
|
|
avg_x = sum(point.x() for point in nearby_endpoints) / len(nearby_endpoints)
|
|
avg_y = sum(point.y() for point in nearby_endpoints) / len(nearby_endpoints)
|
|
endpoints[i] = QgsPoint(avg_x, avg_y) # Create new QgsPoint object
|
|
# Update geometry in the layer
|
|
edges_layer.changeGeometry(edge.id(), QgsGeometry.fromPolyline(endpoints))
|
|
|
|
# Commit the changes and update the layer's extent when new features have been added
|
|
edges_layer.commitChanges()
|
|
edges_layer.updateExtents()
|
|
print("Done.") |