Sequencing and indexing bus stops based on network spatial weights

2408
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
1 Solution

Accepted Solutions
MelindaMorang
Esri Regular Contributor
Hello, Sui Tao.

I will try to help you out with this.  What version of ArcGIS are you running?

There's a new python method in ArcGIS 10.2.1 that would be perfect for what you're trying to do.  It allows you to quickly find the distance along a line that a point falls.  You could find the distance that each stop falls along the route they're assigned to and sort by that distance to determine the order.  You have to create a Polyline geometry object for your route line and a Point geometry object for each stop.  Then use the measureOnLine() method.  You would end up with something like:
dist_along_route = lineGeom.measureOnLine(ptGeom)

See http://resources.arcgis.com/en/help/main/10.2/index.html#//018z00000070000000.
Unfortunately, this simple method isn't available in ArcGIS versions prior to 10.2.1.

If you don't have 10.2.1 yet, you could accomplish the same thing using the linear referencing tools.  See http://resources.arcgis.com/en/help/main/10.2/index.html#//003m00000002000000.  You would first use the Create Routes tool on your polyline routes.  This just generates measures along those route lines so you can return the distance along the lines later.  Then, you would use Locate Features Along Routes to determine the distance along each route that each stop falls.  You could then extract the distance from the resulting table and sort it to determine your stop sequence.  You would want to run the tool separately for each route in your system.  If you have a lot of routes, this will likely be time consuming, as the linear referencing tools tend to run a bit slowly.  The 10.2.1 Geometry method I mentioned above is much faster.

Let me know if this doesn't answer your question or if I can provide any further assistance.

View solution in original post

0 Kudos
15 Replies
MelindaMorang
Esri Regular Contributor
Hello, Sui Tao.

I will try to help you out with this.  What version of ArcGIS are you running?

There's a new python method in ArcGIS 10.2.1 that would be perfect for what you're trying to do.  It allows you to quickly find the distance along a line that a point falls.  You could find the distance that each stop falls along the route they're assigned to and sort by that distance to determine the order.  You have to create a Polyline geometry object for your route line and a Point geometry object for each stop.  Then use the measureOnLine() method.  You would end up with something like:
dist_along_route = lineGeom.measureOnLine(ptGeom)

See http://resources.arcgis.com/en/help/main/10.2/index.html#//018z00000070000000.
Unfortunately, this simple method isn't available in ArcGIS versions prior to 10.2.1.

If you don't have 10.2.1 yet, you could accomplish the same thing using the linear referencing tools.  See http://resources.arcgis.com/en/help/main/10.2/index.html#//003m00000002000000.  You would first use the Create Routes tool on your polyline routes.  This just generates measures along those route lines so you can return the distance along the lines later.  Then, you would use Locate Features Along Routes to determine the distance along each route that each stop falls.  You could then extract the distance from the resulting table and sort it to determine your stop sequence.  You would want to run the tool separately for each route in your system.  If you have a lot of routes, this will likely be time consuming, as the linear referencing tools tend to run a bit slowly.  The 10.2.1 Geometry method I mentioned above is much faster.

Let me know if this doesn't answer your question or if I can provide any further assistance.
0 Kudos
SuiTao
by
New Contributor II
Hello, Sui Tao.

I will try to help you out with this.  What version of ArcGIS are you running?

There's a new python method in ArcGIS 10.2.1 that would be perfect for what you're trying to do.  It allows you to quickly find the distance along a line that a point falls.  You could find the distance that each stop falls along the route they're assigned to and sort by that distance to determine the order.  You have to create a Polyline geometry object for your route line and a Point geometry object for each stop.  Then use the measureOnLine() method.  You would end up with something like:
dist_along_route = lineGeom.measureOnLine(ptGeom)

See http://resources.arcgis.com/en/help/main/10.2/index.html#//018z00000070000000.
Unfortunately, this simple method isn't available in ArcGIS versions prior to 10.2.1.

If you don't have 10.2.1 yet, you could accomplish the same thing using the linear referencing tools.  See http://resources.arcgis.com/en/help/main/10.2/index.html#//003m00000002000000.  You would first use the Create Routes tool on your polyline routes.  This just generates measures along those route lines so you can return the distance along the lines later.  Then, you would use Locate Features Along Routes to determine the distance along each route that each stop falls.  You could then extract the distance from the resulting table and sort it to determine your stop sequence.  You would want to run the tool separately for each route in your system.  If you have a lot of routes, this will likely be time consuming, as the linear referencing tools tend to run a bit slowly.  The 10.2.1 Geometry method I mentioned above is much faster.

Let me know if this doesn't answer your question or if I can provide any further assistance.


Hi Melinda,

Thank you for the quick reply.

I'm using arcGIS 10.1, but I can update to 10.2. If not, I will try to use the second method of linear referencing tools.

The measureOnLine code you provided seems pretty tempting. I will try that first and let you know the results asap.

Sui
0 Kudos
MelindaMorang
Esri Regular Contributor
Great.  Just to clarify, the measureOnLine() function isn't available in 10.2, only in 10.2.1, which is a separate product.  If you're going to upgrade, make sure you can upgrade all the way to 10.2.1 and not just 10.2.
0 Kudos
SuiTao
by
New Contributor II
Alright. Will keep that in mind. Many thanks!
0 Kudos
SuiTao
by
New Contributor II
Hi Melinda,
Just got GIS 10.2.1.
Sorry, but I have another possibly stupid question (I'm a newbie to arcpy...). So I alreay have the shapefile feature classes of the bus routes and points, how do I convert them into geometry objects? Or do I just run the measureOnLine script using these feature classes?
Cheers,
Sui
0 Kudos
MelindaMorang
Esri Regular Contributor
Not a stupid question at all!  You need to read in your shapefile or feature class using a search cursor (arcpy.da.SearchCursor).  You can read in the shape geometry using the SHAPE@ keyword, and that should give you a point or a line geometry object.  You then feed the point and line geometry objects to the measureOnLine method.  There are some SearchCursor examples here: http://resources.arcgis.com/en/help/main/10.2/index.html#//018w00000011000000
0 Kudos
SuiTao
by
New Contributor II
Not a stupid question at all!  You need to read in your shapefile or feature class using a search cursor (arcpy.da.SearchCursor).  You can read in the shape geometry using the SHAPE@ keyword, and that should give you a point or a line geometry object.  You then feed the point and line geometry objects to the measureOnLine method.  There are some SearchCursor examples here: http://resources.arcgis.com/en/help/main/10.2/index.html#//018w00000011000000


Many thanks! Trying that now.
0 Kudos
SuiTao
by
New Contributor II
Hi Melinda,
Just tried the acrpy.da.SearchCursor coupled with measureOnLine. Not surprisingly it did not work since I probably coded in a wrong way (but logicall in the right direction I hope). So could you please have a look at the codes and comment on them?

>>> import arcpy

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

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

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

#the results were
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
AttributeError: 'da.SearchCursor' object has no attribute 'measureOnLine'

I also tried another code 'arcpy.CopyFeatures_management' to create geometry objects, the results were the same.

Many thanks!
Sui
0 Kudos
SuiTao
by
New Contributor II
Hi Melinda,
I did a bit more searching and changed the script as follows:

>>> import arcpy

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

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

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

This returned the result:
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'measureOnLine'

Does that mean the script measureOnLine not exist? BTW, I use gis 10.2.1 and pythonwin 2.7.5

Many thanks,
Sui
0 Kudos