-
Notifications
You must be signed in to change notification settings - Fork 2
/
NG911_flip_RCLs_UTRANS_fixes.py
170 lines (134 loc) · 5.16 KB
/
NG911_flip_RCLs_UTRANS_fixes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# -*- coding: utf-8 -*-
"""
Created on Mon Aug 30 13:01:42 2021
@author: eneemann
Script to fix UTRANS errors where RCLs are pointed in the wrong direction
Uses Python 2 and ArcCatalog Database Connection
"""
import arcpy
import os
import time
from datetime import datetime
import pandas as pd
import math
# Start timer and print start time in UTC
start_time = time.time()
readable_start = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
print("The script start time is {}".format(readable_start))
######################
# Set up variables #
######################
# Set up databases (SGID must be changed based on user's path)
utrans_db = r"Database Connections\eneemann@[email protected]"
arcpy.env.workspace = utrans_db
arcpy.env.overwriteOutput = True
arcpy.env.qualifiedFieldNames = False
today = time.strftime("%Y%m%d")
RCLs = os.path.join(utrans_db, r'UTRANS.TRANSADMIN.Centerlines_Edit\UTRANS.TRANSADMIN.Roads_Edit')
## Make a copy of the data to work on
#arcpy.management.CopyFeatures(RCLs, RCLs_working)
# Get the spatial reference for later use
sr = arcpy.Describe(RCLs).spatialReference
print(sr)
def angle_calc(line):
angle = math.degrees(math.atan2((line.lastPoint.X - line.firstPoint.X),(line.lastPoint.Y - line.firstPoint.Y)))
if angle < 0:
angle += 360.0
return angle
def reversed_check(line, predir):
status = False
# Calculate angle
angle = angle_calc(line)
# Compare angle to expected range based on predir
# If angle doesn't align with predir, change status to True
# if predir == 'N' and (angle > 90 and angle < 270):
# status = True
# elif predir == 'S' and (angle > 270 or angle < 90):
# status = True
# elif predir == 'E' and (angle > 180 and angle < 360):
# status = True
# elif predir == 'W' and (angle > 0 and angle < 180):
# status = True
if predir == 'N' and (angle > 100 and angle < 260):
status = True
elif predir == 'S' and (angle > 280 or angle < 80):
status = True
elif predir == 'E' and (angle > 190 and angle < 350):
status = True
elif predir == 'W' and (angle > 10 and angle < 170):
status = True
# if not status:
# print(f'predir is {predir}, angle is {angle}')
return status, angle
def reverse_line(line):
multi = False
pts_orig = []
if shape_obj.partCount > 1:
print("Warning: multiple parts! extra parts are automatically trimmed!")
print("Line has {} parts".format(shape_obj.partCount))
multi = True
# Step through and use first part of the feature
part = line.getPart(0)
# put the points into a list, then reverse the list
for pnt in part:
pts_orig.append((pnt.X, pnt.Y))
pts_rev = pts_orig[::-1]
# rebuild geometry of reversed line
arc_pts = [arcpy.Point(item[0], item[1]) for item in pts_rev]
array= arcpy.Array(arc_pts)
geom_rev = arcpy.Polyline(array, sr)
return geom_rev, multi
# Start an edit session
edit = arcpy.da.Editor(utrans_db)
edit.startEditing(False, True)
edit.startOperation()
# Loop through data and flip roads that have bad directions
multi_parts = []
flips = []
checks = 0
flip_count = 0
multi_count = 0
#query = "TOADDR_L <> 0 AND TOADDR_R <> 0"
query = "UTRANS_NOTES LIKE '%python flip%'"
# 0 1 2 3 4 5 6
fields = ['UNIQUE_ID', 'SHAPE@', 'PREDIR', 'UTRANS_NOTES', 'OBJECTID', 'TOADDR_L', 'TOADDR_R']
with arcpy.da.UpdateCursor(RCLs, fields, query) as update_cursor:
print("Looping through rows in FC to check for flipped segments ...")
for row in update_cursor:
if row[4] % 10000 == 0:
print('working on OBJECTID: {}'.format(row[4]))
# if row[5] == 0 and row[6] == 0:
# continue
shape_obj = row[1]
predir = row[2]
if shape_obj.partCount > 1:
print("OBJECTID {} has multiple parts!".format(row[4]))
multi_parts.append(row[4])
multi_count += 1
continue
is_reversed, ang = reversed_check(shape_obj, predir)
checks += 1
if is_reversed:
# print("flipping OBJECTID {}".format(row[0]))
shape_rev, multipart = reverse_line(shape_obj)
row[1] = shape_rev
row[3] = 'python flip: {0} {1}'.format(predir, round(ang, 1))
flip_count += 1
flips.append(row[4])
else:
row[3] = 'might need flipped: {0} {1}'.format(predir, round(ang, 1))
update_cursor.updateRow(row)
print("Total number of checks is: {}".format(checks))
print("Total count of flipped segments is: {}".format(flip_count))
print("Total count of multipart segments is: {}".format(len(multi_parts)))
# Stop edit session
edit.stopOperation()
edit.stopEditing(True)
##########################
# Call Functions Below #
##########################
print("Script shutting down ...")
# Stop timer and print end time in UTC
readable_end = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
print("The script end time is {}".format(readable_end))
print("Time elapsed: {:.2f}s".format(time.time() - start_time))