The "operation attempted on empty geometry" error message may not have anything to do with the SDE network dataset. It could be that you have run out of some computer resource (memory or disk space).
In ArcGIS Pro, Closest Facility computes the shortest route and then generates the route geometry to write to the output Routes feature class and also generates the driving directions and writes them to the output directions feature class. It is will generate a lot of data for 2.5 million routes.
Also, for a 2.5 million to 1 case, it will be solving 2.5 million routes. At a minimum, you could flip these so that you have a 1 to 2.5 million case and switch the default "Towards Facility" to "Away from Facilities" to get the same answer but the solver will only need to do ONE route solve.
So let me ask, do you need the output route geometry and directions? Or do you simply need the shortest time/distance between these locations? If you do not need the actual route geometry, then use the Origin-Destination Cost Matrix solver. It will be much quicker with less overhead.
Hi Jay, Very helpful. Based on this I'm thinking it's a memory issue. I'll switch the solve direction in the 1st instance as the geometry and directions would be helpful for quality assurance more than anything. But if this proves inpractical - the Cost Matrix will also be suitable for us so I will give that a go next. Many Thanks, I'll report back with anything of note.
Thanks for you replies.
I tried to get the distances for 36 shipping routes (36 origin ports and 36 destinations), I get a reasonable map, but only get one route solved, from port 1 to port 72. Do you know why?
Also, can CF or OD matrix do the same thing for every port pair? instead of the closest one/all the combinations between those ports, but to the designated port within each port pair?
CF and OD return routes to locations within the specified distance cutoff or number specified. They do not honor "pairs". To find routes between pairs of locations, you can either solve each pair independently OR better way is to load them into a single route but set a common ID as the ROUTENAME property. That way you can load in 72 stops as 36 route pairs and solve in one route solver. More details here:
I tried Newroute, and set common ID for origin ports and destination ports, but the routes solved to be only 1, not 36, do you know the possible reason?
And there is an error:
Warning: The output geometry for "Location 1 - Location 86" in "Routes" has no M values because the maximum M value is larger than the largest M value that can be supported by the M domain.
I could use some help on the python above. I am being asked to run 2000 routes from an input file and record info about each trip. The above appears to be exactly what I need....but.....the script fails around:
rows = arcpy.SearchCursor(lyrName + "\\Routes")
I think this occurs this "lyrName" is actually set at "layer1" further up in the script. But when I make such an adjustment it still fails. Seems the field "row.Total_TravelTime" does not exists in the array.
BTW, when I step through this script, I can load stops and solve the route. I just can't figure out how to get the results back out so I can write out.
Any help offered to get this to work, and run a batch of routes would be greatly appreciated!
First, I encourage you to use arcpy.da.SearchCursor instead of the old arcpy.SearchCursor, which is deprecated and slow.
With arcpy.da.SearchCursor, you specify explicitly which fields you want to retrieve from the data.
for row in arcpy.da.SearchCursor(<your layer>, [python list of field names]): print(row)
The field name to retrieve depends on your network dataset and the output you care about. In the example script you're looking at, I guess the impedance attribute being used for the analysis was called "TravelTime", so the output field in the output routes sublayer was "Total_TravelTime". Basically you need to retrieve a field called "Total_[name of impedance attribute]".
Let's say you solved using an impedance attribute called TravelTime. Then do this:
for row in arcpy.da.SearchCursor(<your layer>, ["Total_TravelTime"]): print(row)
Let's say you additionally accumulated a field called "Miles". Then you can also do this:
for row in arcpy.da.SearchCursor(<your layer>, ["Total_TravelTime", "Total_Miles"]): travel_time = row travel_distance = row
An explanation of all input and output fields for a Route analysis is here: Route analysis—Help | Documentation
Thank you! This is exactly what I needed. Now I can get the routes' total miles and total minutes into variables and write to an output file. Whoot!
layer1 = "MyRouteLayer" #an open in-memory layer
for row in arcpy.da.SearchCursor(layer1 + "\\Routes", ["Total_Minutes", "Total_Miles"]):
travel_minutes = row
travel_miles = row