Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

Is it possible to create a network dataset with ArcPy to be used with the network assistant?

In the documentation I found the Build Network and Dissolve Network functions, but it looks like both require an already existing network dataset as input parameter.

In this thread people say it is not possible with Python but with .NET. In this thread, somebody says it is possible to create geometric networks with arcpy in 10.1. Is it possible to use a geometric network with the network assistant?

In the documentation it says: Only point and line feature classes are supported as input. The feature classes cannot participate in another geometric network or other advanced geodatabase dataset such as a topology, network dataset, terrain, or fabric.

share|improve this question
    
Which ArcGIS version and license level are you using? Your link says 10.1 and Standard or Advanced is needed. –  PolyGeo May 6 '13 at 10:29
add comment

2 Answers 2

up vote 4 down vote accepted

You cannot create a network dataset with arcpy at this time. Your option is to use ArcObjects. There is a Street Data Processing toolbox that is built on .NET by Esri (the source code is provided), which you might modify to meet your business workflows. A GP tool which is part of the toolbox creates a network dataset with certain user-defined parameters, so this should work fine for you too.

Geometric networks and network datasets are not the same thing and you cannot create a network dataset from a geometric network in ArcGIS. The only option is to use ArcObjects at this time.

share|improve this answer
    
thanks for your answer. I go for now with the custom approach, but as soon as I can benefit more from the network analyst features I will try it. It's a pitty that it is not possible to create network datasets directly from Python. –  brumgabrasch May 13 '13 at 13:33
add comment

As I currently only need all shortest paths between two set of points, I ended up by calculating the shortest paths on my own with the Python binding of the igraph library. What I have is an input data set with points and a dataset with the street network as set of polylines with start node, end node and length. What I do is first find for each data point the nearest point on the road network. Then I create the graph from the road network. For each data point, I add two new edges to the graph. This is actually the biggest part of the code. Maybe there are more elegant and shorter versions. I know for each data point the id of the polyline nearest to it. For each such polyline I iterate over the segments and check if the nearest point of the data point is on the segment or the points between.

'''
Created on 13.05.2013

Create graph from road network dataset and find shortest path  

'''

import arcpy
import igraph
from collections import defaultdict


poi_layer = 1  # Layer with points of interests.
street_layer = 2  # Layer with streets as polylines. Start and end vertex ids in fields

# Find for every poi closest point on road entwork
arcpy.analysis.Near(poi_layer, street_layer, location="LOCATION")

# Set of ids of all polylines containing a nearest point
intersect_points = defaultdict(set)

with arcpy.da.SearchCursor(poi_layer, ("SHAPE@", "NEAR_FID", "NEAR_DIST", "NEAR_X", "NEAR_Y", "OBJECTID")) as cursor:
    for row in cursor:
        near_fid = row[1]
        near_dist = row[2]
        near_x = row[3]
        near_y = row[4]
        objectId = row[5]
        id = str(objectId)
        intersect_points[near_fid].add(
            (near_x,
             near_y,
             near_dist,
             id,
             objectId))
del row
del cursor

# Create Road Network
vertices = set()
edges, weights = [], []

fields = ["FNODE_", "TNODE_", "SHAPE@", "LENGTH", "OBJECTID_1"]
with arcpy.da.SearchCursor(street_layer, fields) as cursor:
    for row in cursor:
        s = str(int(row[0]))  # Start node id
        t = str(int(row[1]))  # End node id
        line = row[2]  # Polyline object of road
        length = row[3]  # Road length
        lineid = row[4]  # Road id

        vertices.add(s)
        vertices.add(t)

        # Check if road near to some data points
        if lineid in intersect_points:

            # For each intersection point
            for ip in intersect_points[lineid]:

                ip_near_distance = ip[2]
                ip_source_id = ip[3]

                intersect_point = arcpy.Point(ip[0], ip[1])
                last_point = None
                found = False
                length_from = 0.0
                length_to = 0.0

                # Check for each line segment if it intersects
                for part in line:

                    for current_point in part:

                        current_point_pg = arcpy.PointGeometry(current_point)

                        # Check if intersection point is on line point
                        if current_point_pg.contains(intersect_point):
                            found = True
                            length_from += ip_near_distance
                            length_to = ip_near_distance

                        if last_point is not None:

                            # Create line segment
                            array = arcpy.Array()
                            array.add(last_point)
                            array.add(current_point)
                            last_point_pg = arcpy.PointGeometry(last_point)
                            segment = arcpy.Polyline(array)

                            # Check if intersection point is on line segment
                            if not found and segment.contains(intersect_point):
                                found = True
                                length_from += ip_near_distance + \
                                    last_point_pg.distanceTo(intersect_point)
                                length_to = ip_near_distance + \
                                    current_point_pg.distanceTo(
                                        intersect_point)
                                last_point = current_point
                                continue

                            if found:
                                length_to += segment.length
                            else:
                                length_from += segment.length

                        last_point = current_point
                if not found:
                    print "Int point not found!"

                # If interection point found road, add new node to
                # network
                else:

                    vertices.add(ip_source_id)

                    # Add edge from start node to data point
                    edges.append((s, ip_source_id))
                    weights.append(length_from)

                    # Add edge from data point to end node
                    edges.append((ip_source_id, t))
                    weights.append(length_to)

        # Add road to network
        e = (s, t)
        w = length

        edges.append(e)
        weights.append(w)

del row
del cursor

# Create road network graph
g = igraph.Graph()
for v in vertices:
    g.add_vertex(v)
for e in edges:
    g.add_edge(e[0], e[1])
g.es["weight"] = weights

# Find location points
sources =  # List of vertices ids
targets =  # List of vertices ids

# Find shortest paths
shortest_paths = g.shortest_paths(
    sources,
    targets,
    weights="weight",
    mode="ALL")
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.