I am trying to create a python script that automates extending a series of road lines. The survey for these roads that another team did cuts off at bridges and overpasses. I was wanting to see if there was a way to extend each lane to the next segment. I have calcuated the x and y start and end for each record and added them to fields in the attribute table. Here are the following fields I am using
Fields:
Route: Highway 5 for example
Lane: Lane of the highway
Dir_Name: Dir_Name i.e. North,South,East,West
X_Coord_Start: Using Calculate Geometry I created the start of the line X coordinate
Y_Coord_Start: same as above
X_Coord_End:same as above
Y_Coord_End:same as above
Segment_ID: this is a derived field where based on the three fields each record of each lane gets a segment ID. So that way to hopefully help the script match up the sequence of which each segment needs to be added. So Route 5 South, Lane 1, should have segments escalating in number for each individual segment.
Script so far
import arcpy
from arcpy import da
import logging
# Logging configuration
logging.basicConfig(filename=r"C:\temp\line_extension.log", level=logging.INFO, format='%(asctime)s - %(message)s')
# Define the workspace and feature class
arcpy.env.workspace = r"Hiding file path for security reasons"
feature_class = "District_01"
# Define the fields
fields = ['Route', 'Lane', 'Segment_ID', 'Dir_Name', 'X_Coord_Start', 'Y_Coord_Start', 'X_Coord_End', 'Y_Coord_End']
previous_segment = None
tolerance = 0.1 # Distance threshold
# Sorting the feature class by Route, Lane, Dir_Name, Segment_ID
arcpy.management.Sort(feature_class, r"C:\temp\sorted_shs_pavement.shp", ["Route", "Lane", "Dir_Name", "Segment_ID"])
# Now use the sorted shapefile for the update cursor
try:
with da.UpdateCursor(r"C:\temp\sorted_shs_pavement.shp", fields) as cursor:
for row in cursor:
route, lane, segment_id, dir_name, x_start, y_start, x_end, y_end = row
# Log current segment's coordinates
logging.info(f"Current Segment: {segment_id}, Start: ({x_start}, {y_start}), End: ({x_end}, {y_end})")
if None not in (x_start, y_start, x_end, y_end):
current_start = arcpy.Point(x_start, y_start)
# Check if there is a previous segment to compare
if previous_segment:
prev_route, prev_lane, prev_seg, prev_dir, prev_x, prev_y = previous_segment
# Log previous segment details
logging.info(f"Previous Segment: {previous_segment}")
# Check if we are comparing the same route, lane, and direction
if (route, lane, dir_name) == (prev_route, prev_lane, prev_dir):
prev_end = arcpy.Point(prev_x, prev_y)
# Use PointGeometry to calculate distance
prev_geom = arcpy.PointGeometry(prev_end)
current_geom = arcpy.PointGeometry(current_start)
distance = prev_geom.distanceTo(current_geom)
logging.info(f"Distance: {distance} meters")
if distance <= tolerance:
# Create the array for the polyline
array = arcpy.Array([prev_end, current_start])
logging.info(f"Array Count: {array.count}")
if array.count == 2:
extended_line = arcpy.Polyline(array)
if extended_line:
# Log the extended line creation
logging.info(f"Extended Line Created: {extended_line}")
# Update the segment with new endpoint coordinates
row[6] = extended_line.lastPoint.X
row[7] = extended_line.lastPoint.Y
cursor.updateRow(row)
logging.info(f"Updated Segment: {segment_id}")
# Set the current segment as the previous segment for the next iteration
previous_segment = (route, lane, segment_id, dir_name, x_end, y_end)
except Exception as e:
# Log any errors that occur during execution
logging.error(f"Script failed: {e}")
# Print a completion message
print("Line extension process completed.")
Add SHAPE@ to the fields list and see if you see the update and update some of your code to reflect the new geometry
new_geometry = geometry.union(extended_line)
row[8] = new_geometry
cursor.updateRow(row)
previous_segment = (route, lane, segment_id, dir_name, x_end, y_end, geometry))