New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed line draws as edge of no length; breaks graph.py at add_edges_from() #2423
Comments
Or to allow the user to choose: +def read_shp(path, simplify=True, geom_attrs=True, ignore_rings=True):
-def read_shp(path, simplify=True, geom_attrs=True):
print(simplify)
"""Generates a networkx.DiGraph from shapefiles. Point geometries are
translated into nodes, lines into edges. Coordinate tuples are used as
keys. Attributes are preserved, line geometries are simplified into start
and end coordinates. Accepts a single shapefile or directory of many
shapefiles.
"The Esri Shapefile or simply a shapefile is a popular geospatial vector
data format for geographic information systems software [1]_."
Parameters
----------
path : file or string
File, directory, or filename to read.
simplify: bool
If True, simplify line geometries to start and end coordinates.
If False, and line feature geometry has multiple segments, the
non-geometric attributes for that feature will be repeated for each
edge comprising that feature.
geom_attrs: bool
If True, include the Wkb, Wkt and Json geometry attributes with
each edge.
NOTE: if these attributes are available, write_shp will use them
to write the geometry. If nodes store the underlying coordinates for
the edge geometry as well (as they do when they are read via
this method) and they change, your geomety will be out of sync.
+ ignore_rings: bool
+ If True, ignores non-intersecting rings that would create an edge of no length
Returns
-------
G : NetworkX graph
Examples
--------
>>> G=nx.read_shp('test.shp') # doctest: +SKIP
References
----------
.. [1] http://en.wikipedia.org/wiki/Shapefile
"""
try:
from osgeo import ogr
except ImportError:
raise ImportError("read_shp requires OGR: http://www.gdal.org/")
if not isinstance(path, str):
return
net = nx.DiGraph()
shp = ogr.Open(path)
for lyr in shp:
fields = [x.GetName() for x in lyr.schema]
for f in lyr:
flddata = [f.GetField(f.GetFieldIndex(x)) for x in fields]
g = f.geometry()
attributes = dict(zip(fields, flddata))
attributes["ShpName"] = lyr.GetName()
# Note: Using layer level geometry type
if g.GetGeometryType() == ogr.wkbPoint:
net.add_node((g.GetPoint_2D(0)), attributes)
elif g.GetGeometryType() in (ogr.wkbLineString,
ogr.wkbMultiLineString):
for edge in edges_from_line(g, attributes, simplify,
geom_attrs):
e1, e2, attr = edge
+ if e1 != e2 and ignore_rings == True:
+ net.add_edge(e1, e2)
+ net[e1][e2].update(attr)
+ else:
+ net.add_edge(e1, e2)
+ net[e1][e2].update(attr)
- net.add_edge(e1, e2)
- net[e1][e2].update(attr)
else:
raise ImportError("GeometryType {} not supported".
format(g.GetGeometryType()))
return net |
Perhaps a better option would be to add in functionality to handle this without removing the rings? In if geom.GetGeometryType() == ogr.wkbLineString:
if simplify:
edge_attrs = attrs.copy()
+ sp = geom.GetPoint_2D(0)
last = geom.GetPointCount() - 1
+ ep = geom.GetPoint_2D(last)
if geom_attrs:
edge_attrs["Wkb"] = geom.ExportToWkb()
edge_attrs["Wkt"] = geom.ExportToWkt()
edge_attrs["Json"] = geom.ExportToJson()
+ if sp == ep:
+ middleish = int(geom.GetPointCount() / 2)
+ mp = geom.GetPoint_2D(middleish)
+ yield (sp, mp, edge_attr)
+ yield (mp, ep, edge_attr)
+ else:
+ yield (sp, ep, edge_attrs)
- yield (geom.GetPoint_2D(0), geom.GetPoint_2D(last), edge_attrs) Thoughts? |
I like adding the rings as in your last example. |
One problem with the last option of adding the rings is that it obliterates the ring shape and creates two edges that are essentially the same in reverse. Would it be better to convert the ring into a node or into a triangle? EDIT: Or even for that matter, just add the edge once with |
I'm not familiar with the use of these data as graphs. Which do you think is the best (or least surprising) solution? |
Thanks for explaining this in detail. You are far more expert me and probably most others here. So let's fix it the way you think makes the most sense. |
I'd love to see this turned into a PR so we could include the improvements. |
The original posted error is casued by turning an edge into a set. The solution is to leave the edge as a tuple. The second issue discussed here is more related to drawing self-loops in networkx. I'm going to close this issue. |
Attempted to read a shapefile of OSM road data with the following code:
This resulted in the following error:
Some error tracing revealed that closed lines have the same start point and end point, resulting in a 1-tuple in
G.edges()
:1-tuple is created in
read_shp()
at line 94:Perhaps the following change to ignore these rings?
The text was updated successfully, but these errors were encountered: