Sequencing and indexing bus stops based on network spatial weights

3636
15
Jump to solution
03-03-2014 04:25 PM
SuiTao
by
New Contributor II
Hello guys,

I have a problem that might be less straightforward, but please bear with me.

I have a polyline shapefile that contains all the bus routes (each bus route has an id, like 111, 120), and a point shape file that contains all the bus stops (each stop has an id, like 30102, 5061, and lat and long for each point).

Based on these two files, my goal is to generate a table that sequence stops (marked as 1, 2, 3...) for all the bus routes based on the sequence the stops are passed through. The attached file gives an example of such a table.

I have a logic to do this:
(1) Find the stops for all the bus routes based on spatial relationship (for example, intersecting);
(2) Calculate the network spatial weights for the stops on each route (it is a gis tool called 'generate spatial network weights', the resulting spatial weights are between 0-1, the larger the value the closer the two points are and vice versa);
(3) Identify the first stop (origin) for each route and mark them as 1st stop;
(4) Re-sequence the stops based on the spatial weight (for example, find the next stop closest to the first stop and mark it 2nd stop, and continue this process till there's no more stops left).

I can do the first three steps using the tools of gis. The problem is the final step: I cannot do it manually since there are over 10,000 bus stops and over 900 bus routes. So my question is that is there any scripts or any other tools to automate this process to generate the table I want? Of course you don't have to follow my logic. The sole direction is to generate the attached table for all the routes.

I'm very desparate to find a solution so please don't hesitate with any suggestions.

Many thanks!
Sui Tao
0 Kudos
15 Replies
SuiTao
by
New Contributor II
Hi Melinda,
Sorry for this heavy replying. I did more change to the script and the measureOnLine finally works. Here's the script:

>>> import arcpy

# import stop feature class and create geometry objects
>>> fcStop = 'C:/shapefile/bus_stops.shp'
>>> cursorStop = arcpy.da.SearchCursor(fcStop,['STOP_ID','SHAPE@'])
>>> stopGeom = cursorStop.next()
>>> stopGeom = stopGeom[0]

# import route feature class and create geometry objects
>>> fcRoute = 'C:/shapefile/routes.shp'
>>> cursorRoute = arcpy.da.SearchCursor(fcRoute,['SHAPE@'])
>>> routeGeom = cursorRoute.next()
>>> routeGeom = routeGeom[0]

#measure distance on route
>>> dist_along_route = routeGeom.measureOnLine(stopGeom,FALSE)

#print results
>>> print dist_along_route
The above script generates a value of 26983.41708113748.

I think it calculates the distance of the first stop to the first route. I checked the stop and the route, turned out the stop is not on the route. So two more questions:
1) How to interpret the meaning of this 'distance'? Is it euclidean distance?
2) For each route, how to calculate the distances of stops that only falls on this route? Should I generate separate point shpfiles for each route?

Again, sorry for all the troubles, and many thanks.
Sui
0 Kudos
MelindaMorang
Esri Regular Contributor
Glad you figured it out.  Yes, the SearchCursor returns items in a tuple.  You could have chosen to return more than one field (in addition to SHAPE@), and it would have returned something like (SHAPE@, Field, Field), so it makes sense that you have to use a [0] to get the first item in the tuple (even if there is only one item in it).

The distance is, I believe, the distance along the route in the units of the coordinate system used by the route.  If it's in a geographic coordinate system, you should probably project it into something appropriate for the area you're studying.

Do your stops have a route ID associated with them?  If so, you can use a loop to loop through the routes. For each route, you can use MakeFeatureLayer on the stops to select only the stops associated with the route ID, and then do the SearchCursor on the feature layer and loop through those stops to calculate the distance along the line.

Something like this (which I didn't test, so it might not be perfect):

cursorRoute = arcpy.da.SearchCursor(fcRoute,['SHAPE@', 'RouteID'])
for route in cursorRoute:
    RouteID = route[1]
    routeGeom = route[0]
    where = '"RouteID" = %s' % str(RouteID)
    arcpy.management.MakeFeatureLayer(fcStop, "Stops", where)
    cursorStop = arcpy.da.SearchCursor(fcStop,['STOP_ID','SHAPE@'])
    for stop in cursorStop:
        stopGeom = stopGeom[1] # Looks like the geometry is the second item in your tuple here
        dist_along_route = routeGeom.measureOnLine(stopGeom,FALSE)
0 Kudos
SuiTao
by
New Contributor II
Glad you figured it out.  Yes, the SearchCursor returns items in a tuple.  You could have chosen to return more than one field (in addition to SHAPE@), and it would have returned something like (SHAPE@, Field, Field), so it makes sense that you have to use a [0] to get the first item in the tuple (even if there is only one item in it).

The distance is, I believe, the distance along the route in the units of the coordinate system used by the route.  If it's in a geographic coordinate system, you should probably project it into something appropriate for the area you're studying.

Do your stops have a route ID associated with them?  If so, you can use a loop to loop through the routes. For each route, you can use MakeFeatureLayer on the stops to select only the stops associated with the route ID, and then do the SearchCursor on the feature layer and loop through those stops to calculate the distance along the line.

Something like this (which I didn't test, so it might not be perfect):

cursorRoute = arcpy.da.SearchCursor(fcRoute,['SHAPE@', 'RouteID'])
for route in cursorRoute:
    RouteID = route[1]
    routeGeom = route[0]
    where = '"RouteID" = %s' % str(RouteID)
    arcpy.management.MakeFeatureLayer(fcStop, "Stops", where)
    cursorStop = arcpy.da.SearchCursor(fcStop,['STOP_ID','SHAPE@'])
    for stop in cursorStop:
        stopGeom = stopGeom[1] # Looks like the geometry is the second item in your tuple here
        dist_along_route = routeGeom.measureOnLine(stopGeom,FALSE)


Thanks Melinda. Looks much closer to what I want. Trying this right away.
0 Kudos
SuiTao
by
New Contributor II
Another issue: for one certain route, if the stops (points) are not actually on this route (polyline). Is it still OK to use measureOnLine to calculate distance?
0 Kudos
SuiTao
by
New Contributor II
Sorry, a second issue: I'm still confused about how the calculation is defined of measureOnLine. In arcGIS resource it says 'A point (PointGeometry or Point) that is used to measure from the start point of the polyline.' So how does it identify start point? Does it automatically find the first point when the polyline is created?
0 Kudos
SuiTao
by
New Contributor II
Hi Melinda,
I tested the method on one route, and the resulting sequence of stops (they are not even on the route/polyline but only within a certain distance to the route) based on the calculated online distance is correct, which is amazing! I did not define the start nor end point of the route, but it seems this method automatically found the start point. I'm still curious about the calculation method. But it seems working out. Will test them on all the routes and stops to reassure.
Many thanks!
Sui
0 Kudos