Select to view content in your preferred language

Extend Line python script

225
1
03-03-2025 10:18 AM
Steven_Brewer
New Contributor

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.")




0 Kudos
1 Reply
TonyAlmeida
MVP Regular Contributor

 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))