Select to view content in your preferred language

Determining main trail on a line network

298
2
10-24-2024 01:52 PM
LeoSync727
New Contributor
0 Kudos
2 Replies
Kaone3000
New Contributor

import arcpy
import math

# Input layers
trail_lines = "TrailSegments" # Line feature class
fork_points = "ForkPoints" # Point feature class

# Add fields to store trail classification
arcpy.AddField_management(trail_lines, "TrailType", "TEXT")

# Function to calculate angle between two line segments
def calculate_angle(line1, line2):
# Get angle in radians between two lines
angle1 = math.atan2(line1.lastPoint.Y - line1.firstPoint.Y,
line1.lastPoint.X - line1.firstPoint.X)
angle2 = math.atan2(line2.lastPoint.Y - line2.firstPoint.Y,
line2.lastPoint.X - line2.firstPoint.X)
angle = math.degrees(angle2 - angle1)
return angle if angle >= 0 else angle + 360

# Loop through each fork
with arcpy.da.UpdateCursor(trail_lines, ["SHAPE@", "TrailType"]) as line_cursor:
for line in line_cursor:
line_geometry = line[0]
closest_fork = None
min_distance = float('inf')

# Find closest fork to determine which direction the line takes at the fork
with arcpy.da.SearchCursor(fork_points, ["SHAPE@"]) as fork_cursor:
for fork in fork_cursor:
distance = line_geometry.distanceTo(fork[0])
if distance < min_distance:
min_distance = distance
closest_fork = fork[0]

# For each line segment connected to the fork, calculate angle
if closest_fork:
main_angle = calculate_angle(line_geometry, closest_fork)

# Classify based on angle thresholds (you may adjust these as needed)
if 0 <= main_angle < 30 or main_angle > 330:
line[1] = "Main"
elif 30 <= main_angle <= 180:
line[1] = "Left"
else:
line[1] = "Right"

line_cursor.updateRow(line)

print("Trail classification completed.")

0 Kudos
RobertKrisher
Esri Regular Contributor

The above script is pretty good, although there are a few issues you'll need to adjust to suit your data. Consider this crudely drawn example:

RobertKrisher_0-1730119119063.png

 

  • Instead of using the entire trail line you will likely need to break each line into multiple segments, so you only consider the angles of the line segments that intersect each other.
  • The orientation of these line segments may not always be consistent, you may need to periodically flip the orientation of a segment when doing your calculation.

If you found all the locations where trails intersected, buffered those points out slightly, and calculated the angle of each line intersection that would solve most of these issues. You would just need to flip the angle of the line that represents the angle of travel.

RobertKrisher_2-1730119724666.png

 

 

0 Kudos