-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcreate_connectors.py
More file actions
261 lines (217 loc) · 17.8 KB
/
create_connectors.py
File metadata and controls
261 lines (217 loc) · 17.8 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
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
import arcpy
import datetime
import time
import os
from datetime import date
from datetime import datetime
#### User Note ####: change dates (only if you didn't run create_network_data.py on the same day) for fgdb to current dataset (ctrl + f for "#### Note ####:")
## use arcgispro-py3 (python 3)
#arcpy.env.workspace = 'C:\\Users\\gbunce\\Documents\\projects\\MultimodalNetwork'
# get the date
today = date.today()
strDate = str(today.month).zfill(2) + str(today.day).zfill(2) + str(today.year)
# global variables
#bike_ped_auto = r'C:\\Users\\gbunce\\Documents\\projects\\MultimodalNetwork\\MM_NetworkDataset_' + strDate + '.gdb\\NetworkDataset' + '\\BikePedAuto'
network_dataset = r'C:\Multimodal Network Data\MM_NetworkDataset_' + strDate + r'.gdb\NetworkDataset' #### Note ####: change dates for fgdb to current dataset
bike_ped_auto = r'C:\Multimodal Network Data\MM_NetworkDataset_' + strDate + r'.gdb\NetworkDataset\BikePedAuto' #### Note ####: change dates for fgdb to current dataset
### i'm doing this in the rallup script now... transit_stops_multipoint = r'C:\\Users\\gbunce\\Documents\\projects\\MultimodalNetwork\\MM_TransitData_02152019.gdb\\TransitStops' #### Note ####: change dates (if it's been updated) for fgdb to current dataset
transit_routes = r'C:\Multimodal Network Data\MM_TransitData_02152019.gdb\TransitRoutes' #### Note ####: change dates (if it's been updated) for fgdb to current dataset
transit_stops_singlepoints = r"C:\Multimodal Network Data\MultimodalScratchData.gdb\TranStops_" + strDate #### Note ####: change today's dates if rallyup script was not run today
transit_stops_buffered = ""
auto_lines_in_buffer = ""
bike_lines_in_buffer = ""
ped_lines_in_buffer = ""
MM_scratch_db = r'C:\Multimodal Network Data\MultimodalScratchData.gdb'
# main function
def main():
### i'm doing this rallyup data script in the impprt transit data function b/c i need the stop counts for route times
#### explode transit stops to single points (currently they are mulitpoints)
###print("explode multipoint stops to single points")
###transit_stops_singlepoints = "C:\\Users\\gbunce\\Documents\\projects\\MultimodalNetwork\\MultimodalScratchData.gdb\\TranStops_" + strDate
###arcpy.FeatureVerticesToPoints_management(transit_stops_multipoint, transit_stops_singlepoints, "ALL")
# create a buffer around the transit stops
print("buffer the transit stops single points")
transit_stops_buffered = os.path.join(MM_scratch_db, "TranStopBuff_" + strDate)
arcpy.Buffer_analysis(transit_stops_singlepoints, transit_stops_buffered, 100)
# get network lines that intersect the buffers, for each mode of travel
print("intersect the bike network with the buffers")
intersected_bike_network = get_SouceDataUsingSpatialQuery(transit_stops_buffered, bike_ped_auto, "Bike")
print("intersect the auto network with the buffers")
intersected_auto_network = get_SouceDataUsingSpatialQuery(transit_stops_buffered, bike_ped_auto, "Auto")
print("intersect the ped network with the buffers")
intersected_ped_network = get_SouceDataUsingSpatialQuery(transit_stops_buffered, bike_ped_auto, "Ped")
intersected_bike_network = os.path.join(MM_scratch_db, 'TranStopBike' + '_' + strDate)
intersected_auto_network = os.path.join(MM_scratch_db, 'TranStopAuto' + '_' + strDate)
intersected_ped_network = os.path.join(MM_scratch_db, 'TranStopPed' + '_' + strDate)
# convert the network line data (for each of the 3 modes) to vertices
outputVertsToPnts = os.path.join(MM_scratch_db, 'Verts')
print("convert the intersected bike verts to points layer")
intersected_bike_network_verts = arcpy.FeatureVerticesToPoints_management(intersected_bike_network, outputVertsToPnts + 'Bike' + '_' + strDate, "ALL")
print("convert the intersected auto verts to points layer")
intersected_auto_network_verts = arcpy.FeatureVerticesToPoints_management(intersected_auto_network, outputVertsToPnts + 'Auto' + '_' + strDate, "ALL")
print("convert the intersected ped verts to points layer")
intersected_ped_network_verts = arcpy.FeatureVerticesToPoints_management(intersected_ped_network, outputVertsToPnts + 'Ped' + '_' + strDate, "ALL")
# add a field to each of the vert point feature classes (for each of the 3 modes)
#print("add NEAR_FID field to transit stops")
#arcpy.AddField_management(transit_stops_singlepoints, "NEAR_FID", "LONG")
print("add NEAR_FID field to bike vert pnts layer")
arcpy.AddField_management(intersected_bike_network_verts, "NEAR_FID", "LONG")
print("add NEAR_FID field to auto vert pnts layer")
arcpy.AddField_management(intersected_auto_network_verts, "NEAR_FID", "LONG")
print("add NEAR_FID field to ped vert pnts layer")
arcpy.AddField_management(intersected_ped_network_verts, "NEAR_FID", "LONG")
# calculate the OID field values to the NEAR_FID fields
#print("calc OID values to the NEAR_FID field for bike vert pnts"
#arcpy.CalculateField_management(transit_stops_singlepoints, field="NEAR_FID", expression="!OBJECTID!", expression_type="PYTHON", code_block="")
print("calc OID values to the NEAR_FID field for bike vert pnts")
arcpy.CalculateField_management(intersected_bike_network_verts, field="NEAR_FID", expression="!OBJECTID!", expression_type="PYTHON", code_block="")
print("calc OID values to the NEAR_FID field for auto vert pnts")
arcpy.CalculateField_management(intersected_auto_network_verts, field="NEAR_FID", expression="!OBJECTID!", expression_type="PYTHON", code_block="")
print("calc OID values to the NEAR_FID field for ped vert pnts")
arcpy.CalculateField_management(intersected_ped_network_verts, field="NEAR_FID", expression="!OBJECTID!", expression_type="PYTHON", code_block="")
# create three seperate feature classs from the transit stop points - so each one can be used separatly in the near analysis and preserve the near data in the fields
print("create a separate feature class of transit stops for each near analysis")
arcpy.FeatureClassToFeatureClass_conversion(transit_stops_singlepoints, MM_scratch_db, 'StopNearBike_' + strDate)
arcpy.FeatureClassToFeatureClass_conversion(transit_stops_singlepoints, MM_scratch_db, 'StopNearAuto_' + strDate)
arcpy.FeatureClassToFeatureClass_conversion(transit_stops_singlepoints, MM_scratch_db, 'StopNearPed_' + strDate)
stops_near_bike = os.path.join(MM_scratch_db, 'StopNearBike_' + strDate)
stops_near_auto = os.path.join(MM_scratch_db, 'StopNearAuto_' + strDate)
stops_near_ped = os.path.join(MM_scratch_db, 'StopNearPed_' + strDate)
# run near analysis on the transit stops to see the nearest bike/auto/ped vertex
print("run near analysis on bike")
arcpy.Near_analysis(stops_near_bike, intersected_bike_network_verts, search_radius="200 Meters", location="LOCATION", angle="NO_ANGLE", method="PLANAR")
print("run near analysis on auto")
arcpy.Near_analysis(stops_near_auto, intersected_auto_network_verts, search_radius="200 Meters", location="LOCATION", angle="NO_ANGLE", method="PLANAR")
print("run near analysis on ped")
arcpy.Near_analysis(stops_near_ped, intersected_ped_network_verts, search_radius="200 Meters", location="LOCATION", angle="NO_ANGLE", method="PLANAR")
# append the near verts into the transit stop data, but only append the verts that found a nearby
#arcpy.Append_management(inputs="StopNearBike_02192019", target="VertsBike_02192019", schema_type="NO_TEST", field_mapping="""Name "Name" true true false 50 Text 0 0 ,First,#;Oneway "Oneway" true true false 2 Text 0 0 ,First,#;Speed "Speed" true true false 2 Short 0 0 ,First,#;AutoNetwork "AutoNetwork" true true false 1 Text 0 0 ,First,#;BikeNetwork "BikeNetwork" true true false 1 Text 0 0 ,First,#;PedNetwork "PedNetwork" true true false 1 Text 0 0 ,First,#;SourceData "SourceData" true true false 15 Text 0 0 ,First,#;DriveTime "DriveTime" true true false 8 Double 0 0 ,First,#;BikeTime "BikeTime" true true false 8 Double 0 0 ,First,#;PedestrianTime "PedestrianTime" true true false 8 Double 0 0 ,First,#;Length_Miles "Length_Miles" true true false 8 Double 0 0 ,First,#;ORIG_FID "ORIG_FID" true true false 4 Long 0 0 ,First,#,StopNearBike_02192019,ORIG_FID,-1,-1;NEAR_FID "NEAR_FID" true true false 4 Long 0 0 ,First,#,StopNearBike_02192019,NEAR_FID,-1,-1""", subtype="")
print("append the bike data")
arcpy.Append_management(stops_near_bike, intersected_bike_network_verts, schema_type="NO_TEST")
print("append the auto data")
arcpy.Append_management(stops_near_auto, intersected_auto_network_verts, schema_type="NO_TEST")
print("append the ped data")
arcpy.Append_management(stops_near_ped, intersected_ped_network_verts, schema_type="NO_TEST")
## remove the -1 from the NEAR_FID field, before creating the connector lines - by way of making a new feture class
print("remove -1 values from bike")
arcpy.FeatureClassToFeatureClass_conversion(intersected_bike_network_verts, MM_scratch_db, 'ConnPntsBike_' + strDate, "NEAR_FID <> -1")
print("remove -1 values from auto")
arcpy.FeatureClassToFeatureClass_conversion(intersected_auto_network_verts, MM_scratch_db, 'ConnPntsAuto_' + strDate, "NEAR_FID <> -1")
print("remove -1 values from auto")
arcpy.FeatureClassToFeatureClass_conversion(intersected_ped_network_verts, MM_scratch_db, 'ConnPntsPed_' + strDate, "NEAR_FID <> -1")
conn_pnts_bike = os.path.join(MM_scratch_db, 'ConnPntsBike_' + strDate)
conn_pnts_auto = os.path.join(MM_scratch_db, 'ConnPntsAuto_' + strDate)
conn_pnts_ped = os.path.join(MM_scratch_db, 'ConnPntsPed_' + strDate)
# create lines between the verts
print("create the connector lines for bike")
bike_connectors = os.path.join(MM_scratch_db, 'BikeConn_' + strDate)
arcpy.PointsToLine_management(conn_pnts_bike, bike_connectors, "NEAR_FID","NEAR_FID", "NO_CLOSE")
print("create the connector lines for auto")
auto_connectors = os.path.join(MM_scratch_db, 'AutoConn_' + strDate)
arcpy.PointsToLine_management(conn_pnts_auto, auto_connectors, Line_Field="NEAR_FID", Sort_Field="NEAR_FID", Close_Line="NO_CLOSE")
print("create the connector lines for ped")
ped_connectors = os.path.join(MM_scratch_db, 'PedConn_' + strDate)
arcpy.PointsToLine_management(conn_pnts_ped, ped_connectors, Line_Field="NEAR_FID", Sort_Field="NEAR_FID", Close_Line="NO_CLOSE")
# remove the identical connectors in each feature class
print("delete identical connector lines for bike")
arcpy.DeleteIdentical_management(bike_connectors, fields="Shape", xy_tolerance="", z_tolerance="0")
print("delete identical connector lines for auto")
arcpy.DeleteIdentical_management(auto_connectors, fields="Shape", xy_tolerance="", z_tolerance="0")
print("delete identical connector lines for ped")
arcpy.DeleteIdentical_management(ped_connectors, fields="Shape", xy_tolerance="", z_tolerance="0")
# call the function to add and calc network fields on the connectors
print("add fields and calc values for the bike connector data")
addAndCalcNetworkFields(bike_connectors, "Bike")
print("add fields and calc values for the auto connector data")
addAndCalcNetworkFields(auto_connectors, "Auto")
print("add fields and calc values for the ped connector data")
addAndCalcNetworkFields(ped_connectors, "Ped")
# append the connector data to the BikePedAuto feature class
print("append the bike connectors into the BikePedAuto feature class")
arcpy.Append_management(bike_connectors, bike_ped_auto, schema_type="NO_TEST")
print("append the auto connectors into the BikePedAuto feature class")
arcpy.Append_management(auto_connectors, bike_ped_auto, schema_type="NO_TEST")
print("append the ped connectors into the BikePedAuto feature class")
arcpy.Append_management(ped_connectors, bike_ped_auto, schema_type="NO_TEST")
# import the transit routes and transit tops into the netork dataset
###print("import transit stops")
###arcpy.FeatureClassToFeatureClass_conversion(transit_stops_singlepoints, r'C:\\Users\\gbunce\\Documents\\projects\\MultimodalNetwork\\MM_NetworkDataset_03192019.gdb\\NetworkDataset', 'TransitStops') #### Note ####: change dates for fgdb to current dataset
#arcpy.FeatureClassToFeatureClass_conversion(transit_routes, r'C:\\Users\\gbunce\\Documents\\projects\\MultimodalNetwork\\MM_NetworkDataset_02202019.gdb\\NetworkDataset', 'TransitRoutes')
# pull out the connectors (that we just appended) from the BikePedAuto to a separate feature class
print("creating separate connector network feature class")
arcpy.FeatureClassToFeatureClass_conversion(bike_ped_auto, network_dataset, 'ConnectorNetwork', "ConnectorNetwork = 'Y'")
### delete the connectors from the BikePedAuto feature class --- use this option if we're going the route of having the connector lines in their own connectivity group (which we currently are doing)
query_filter = "ConnectorNetwork = 'Y'"
with arcpy.da.UpdateCursor(bike_ped_auto, "*", query_filter) as uCur:
for dRow in uCur:
uCur.deleteRow()
print("create_connectors.py script is done!")
# this function returns either network line data that intersects the transit stop buffers
def get_SouceDataUsingSpatialQuery(spatial_boundary, networkFeatureClass, source):
# remove referernce of any feature layers from possible previous function run
if arcpy.Exists('spatialSelectPolygon_lyr'):
arcpy.Delete_management('spatialSelectPolygon_lyr')
if arcpy.Exists('linesIntersected_lyr'):
arcpy.Delete_management('linesIntersected_lyr')
# use the transit stop buffers to create a select by location on the network line data
arcpy.MakeFeatureLayer_management(spatial_boundary, 'spatialSelectPolygon_lyr')
# make feature layer of network data
if source == "Bike":
arcpy.MakeFeatureLayer_management(networkFeatureClass, 'linesIntersected_lyr', r"BikeNetwork = 'Y'")
if source == "Auto":
arcpy.MakeFeatureLayer_management(networkFeatureClass, 'linesIntersected_lyr', r"AutoNetwork = 'Y'")
if source == "Ped":
arcpy.MakeFeatureLayer_management(networkFeatureClass, 'linesIntersected_lyr', r"PedNetwork = 'Y'")
# instersect the network data with the transit stop buffers
arcpy.SelectLayerByLocation_management('linesIntersected_lyr', 'intersect', 'spatialSelectPolygon_lyr')
# make new feature layer from the intersected network line data
matchcount = int(arcpy.GetCount_management('linesIntersected_lyr')[0])
if matchcount == 0:
print('no features matched spatial and attribute criteria')
else:
intersected_roads = arcpy.CopyFeatures_management('linesIntersected_lyr', os.path.join(MM_scratch_db, 'TranStop' + source + '_' + strDate))
#print('{0} cities that matched criteria written to {0}'.format(matchcount, utrans_IntersectedRoads))
return 'linesIntersected_lyr'
def addAndCalcNetworkFields(connector_lines, connector_name):
# set local variables
source_data = "Connector" + connector_name
source_data_FieldLength = 15
network_FieldLength = 1
# Execute AddField twice for two new fields
# add source data field
arcpy.AddField_management(connector_lines, "SourceData", "TEXT", field_length=source_data_FieldLength)
# add network fields
arcpy.AddField_management(connector_lines, "AutoNetwork", "TEXT", field_length=network_FieldLength)
arcpy.AddField_management(connector_lines, "BikeNetwork", "TEXT", field_length=network_FieldLength)
arcpy.AddField_management(connector_lines, "PedNetwork", "TEXT", field_length=network_FieldLength)
arcpy.AddField_management(connector_lines, "ConnectorNetwork", "TEXT", field_length=network_FieldLength)
# add ped_time field
arcpy.AddField_management(connector_lines, "PedestrianTime", "DOUBLE", "", "", "", "", "NULLABLE")
# calc the new field values
# calc the netork fields
if connector_name == "Bike":
#arcpy.CalculateField_management(connector_lines, field="BikeNetwork", expression='"Y"')
arcpy.CalculateField_management(connector_lines, field="ConnectorNetwork", expression='"Y"')
arcpy.CalculateField_management(connector_lines, field="AutoNetwork", expression='"N"')
arcpy.CalculateField_management(connector_lines, field="BikeNetwork", expression='"N"')
arcpy.CalculateField_management(connector_lines, field="PedNetwork", expression='"N"')
arcpy.CalculateField_management(connector_lines, field="SourceData", expression='"Connector_Bike"')
if connector_name == "Auto":
#arcpy.CalculateField_management(connector_lines, field="AutoNetwork", expression='"Y"')
arcpy.CalculateField_management(connector_lines, field="ConnectorNetwork", expression='"Y"')
arcpy.CalculateField_management(connector_lines, field="AutoNetwork", expression='"N"')
arcpy.CalculateField_management(connector_lines, field="BikeNetwork", expression='"N"')
arcpy.CalculateField_management(connector_lines, field="PedNetwork", expression='"N"')
arcpy.CalculateField_management(connector_lines, field="SourceData", expression='"Connector_Auto"')
if connector_name == "Ped":
#arcpy.CalculateField_management(connector_lines, field="PedNetwork", expression='"Y"')
arcpy.CalculateField_management(connector_lines, field="ConnectorNetwork", expression='"Y"')
arcpy.CalculateField_management(connector_lines, field="AutoNetwork", expression='"N"')
arcpy.CalculateField_management(connector_lines, field="BikeNetwork", expression='"N"')
arcpy.CalculateField_management(connector_lines, field="PedNetwork", expression='"N"')
arcpy.CalculateField_management(connector_lines, field="SourceData", expression='"Connector_Ped"')
# calc the pedtime for all connectors
arcpy.CalculateField_management(connector_lines, field="PedestrianTime", expression="((!Shape_Length! * 0.000621371) / 3.1) * 60", expression_type="PYTHON_9.3")
if __name__ == "__main__":
# execute only if run as a script
main()