I am working with polylines with hundreds of thousands of features, and would like to write a script that returns the OIDs of all lines adjacent (intersecting with) each line. I have been experimenting with the Geometry object and the shp.touches() method, but it seems as though a cursor with a nested cursor on the same feature is the only way to use it, and this takes much too long.
The main goal is to perform an "Eliminate" task on a polyline, where short lines are merged to adjacent longer lines that share some unique ID. Collecting information in a dictionary has always been my technique of choice because of its speed, but dealing with geometries complicates this significantly. Unfortunately, Eliminate only works on polygons, and is quite slow itself.
I have already tried to record shape geometries in a dictionary (dict[row.OBJECTID] = [row.Shape_Length, row.Shape, row.uniqueID]
) and attempted a nested iteration, but the geometry objects don't seem to be interacting in the same way they do within a cursor iteration (shp.touches() doesn't work). Has anyone come across any techniques I could use for this problem?
ArcPy – Getting List of Adjacent Lines per Line
arcpygeometry
Best Answer
I try to avoid answering my own questions, but I came up with an arcpy solution. Kudos to kenbuja, who provided a good ArcObjects solution, but the question asked for an arcpy solution. To address PolyGeo, this particular solution does not require creating a topology, but simply accessing the Shape object. A topology-based solution may also work, but I've had trouble automating the corrections within the topology framework. I would love to see a topology solution though. Here's my cleanLineGeom function, which assumes that adjacent lines share a startPoint / endPoint combination.
This function was written for stream networks, hence the params "streamID" and "segID", but can be used for any polyline. "StreamID" refers to the line ID, while "segID" refers to the ID for smaller lines that share a line ID. The function will only merge short (length < lineClusterTolerance) line segments to longer (length > lineClusterTolerance) line segments that share a "streamID". Lastly, the output is a new feature class, so the input is not altered.
Notice -- there will be some short lines left untouched in the process. These are lines that had no longer lines adjacent. These lines are exceptions, and can simply be dissolved normally after the function is run.