-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsuperelevation_interpolation.py
More file actions
81 lines (70 loc) · 3.06 KB
/
Copy pathsuperelevation_interpolation.py
File metadata and controls
81 lines (70 loc) · 3.06 KB
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
import csv
import sys
def load_table_from_csv(csv_path):
table_data = {}
with open(csv_path, 'r') as f:
reader = csv.DictReader(f)
speeds = [int(col[1:]) for col in reader.fieldnames if col.startswith('V')]
for row in reader:
e = float(row['e'])
for speed in speeds:
if speed not in table_data:
table_data[speed] = {'max_e': 8.0, 'data': []} # ASSUMING MAX 8.0
r = int(row[f'V{speed}'])
table_data[speed]['data'].append((e, r))
# SORT DATA BY E ASCENDING (SINCE HIGHER E, LOWER R)
for speed in table_data:
table_data[speed]['data'].sort(key=lambda x: x[0])
return table_data
# LOAD THE TABLE
green_book_table = load_table_from_csv('Green_Book_Table RADIUS vs Maximum Elevation.csv')
def find_design_superelevation(target_R, design_speed, table_data):
"""
Find the design superelevation (ed) by interpolating for the given radius and design speed.
:param target_R: Target radius in feet
:param design_speed: Design speed in mph
:param table_data: Dict of table data
:return: Design superelevation in %, or None if out of range
"""
if design_speed not in table_data:
raise ValueError(f"Design speed {design_speed} not in table data")
speed_data = table_data[design_speed]['data']
e_values = [e for e, r in speed_data]
r_values = [r for e, r in speed_data]
# SORT R_VALUES DESCENDING IF NOT ALREADY
if r_values != sorted(r_values, reverse=True):
# SORT BOTH LISTS BY R DESCENDING
combined = sorted(zip(e_values, r_values), key=lambda x: x[1], reverse=True)
e_values, r_values = zip(*combined)
e_values = list(e_values)
r_values = list(r_values)
if target_R >= r_values[0]: # LARGER THAN MAX R, USE MIN E
return round(e_values[0], 2)
elif target_R <= r_values[-1]: # SMALLER THAN MIN R, USE MAX E
return round(e_values[-1], 2)
else:
# INTERPOLATE
for i in range(len(r_values) - 1):
if r_values[i] >= target_R >= r_values[i+1]:
R1, R2 = r_values[i], r_values[i+1]
e1, e2 = e_values[i], e_values[i+1]
ed = e1 + (target_R - R1) * (e2 - e1) / (R2 - R1)
return round(ed, 2)
return None # SHOULD NOT REACH HERE
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: python3 superelevation_interpolation.py <radius> <speed>")
sys.exit(1)
try:
radius = float(sys.argv[1])
speed = int(sys.argv[2])
if speed not in green_book_table:
print(f"Design speed {speed} mph is not supported. Supported speeds: {sorted(green_book_table.keys())}")
sys.exit(1)
result = find_design_superelevation(radius, speed, green_book_table)
if result is not None:
print(f"DESIGN SUPERELEVATION (ED) FOR RADIUS {radius} AT {speed} MPH IS: {result}%")
else:
print(f"RADIUS {radius} IS OUT OF TABLE RANGE.")
except ValueError:
print("INVALID INPUT.")