Trying to write a python scrip to find and dissolve pseudo nodes for a large dataset.
Anyone have any code to perform such a task?
For example, I have a road line with several end/start nodes (pseudo nodes) created by the cartographers.
Easy enough to run a topology but I have upwards of 4,000,000 +/- pseudo node to get rid of.
Software: ArcGIS 10.2.2 Python 2.7
-
Not in network?FelixIP– FelixIP2015年02月11日 02:34:14 +00:00Commented Feb 11, 2015 at 2:34
-
1Hi Jeff, welcome to GIS.SE. Can you please indicate what GIS software you're writing the script for; a brief description of what you believe a 'pseudo node' to be would also be great as ideas on this point can differ.Michael Stimson– Michael Stimson2015年02月11日 02:34:19 +00:00Commented Feb 11, 2015 at 2:34
-
1I have some code that might help but in my case a true pseudo node is an endpoint connecting to only one other line and sharing the same (important) attributes, but it's written in Arc 9.3 or earlier. Have you got any code so far to share?Michael Stimson– Michael Stimson2015年02月11日 02:46:09 +00:00Commented Feb 11, 2015 at 2:46
-
Yes - same concept (Psuedo Node) or a node connecting only two edges with similar (same) attributesJeff– Jeff2015年02月11日 02:51:26 +00:00Commented Feb 11, 2015 at 2:51
-
1Is this question about just finding (flagging/displaying) pseudo nodes or their automatic removal? Either way I think the inclusion of a graphic will help nail down what is being asked. Have you reviewed the Online Help on Checking for unnecessary pseudo nodes which seems to require a Data Reviewer license? If so, then what prevents you using that as a solution would be useful to include in your question.PolyGeo– PolyGeo ♦2015年02月11日 02:54:23 +00:00Commented Feb 11, 2015 at 2:54
1 Answer 1
The simplest way is to use FeatureVerticesToPoints to create an end points feature class, dissolve with your key fields to a temporary feature class, create end points from that then compare the original points to the dissolved end points using Near, any that don't match between the original and dissolved end points are worth looking at.
Of course in a 3 (or more) way intersection the dissolve tool will dissolve the line with the matching attributes regardless of connection which makes this method unsuitable except as a very rough guide. To get around this I created a script (in 9.3) that I've quickly converted to v10.1 to take advantage of the new cursor objects:
import os, sys, arcpy
InLayer = sys.argv[1]
MatchFields = sys.argv[2]
SearchTol = "1 Meter" # How far between endpoints before they're considered to be the same
fRange = range(len(MatchFields))
desc = arcpy.Describe(InLayer)
OIDfieldName = desc.OIDFieldName
# check it's a polyline feature class
if desc.shapeType != "Polyline":
arcpy.AddError("This script only works on lines")
sys.exit(0)
SR = desc.spatialReference
# check that the units are suitable
if SR.linearUnitName != "Meter":
arcpy.AddError("This tool only works in projected coordinates")
Scratch = os.environ.get("TEMP") # Windows TEMP directory
Points = os.path.join(Scratch,"POINTS.shp")
Buffers = os.path.join(Scratch,"BUFFERS.shp")
BuffEx = os.path.join(Scratch,"EXPLODED_BUFFERS.shp")
JPoints = os.path.join(Scratch,"JOINED_POINTS.shp")
SumTab = os.path.join(Scratch,"SUMMARY_TABLE.dbf")
# clean up
if arcpy.Exists(Points):
arcpy.Delete_management(Points)
if arcpy.Exists(Buffers):
arcpy.Delete_management(Buffers)
if arcpy.Exists(BuffEx):
arcpy.Delete_management(BuffEx)
if arcpy.Exists(JPoints):
arcpy.Delete_management(JPoints)
if arcpy.Exists(SumTab):
arcpy.Delete_management(SumTab)
# you can use Make Events but the coordinates need to match
# exactly... instead I use a buffer and count.
arcpy.FeatureVerticesToPoints_management(InLayer,Points,"BOTH_ENDS")
arcpy.AddField_management(Points,"PointID","LONG")
arcpy.CalculateField_management(Points,"PointID","!FID!","PYTHON_9.3")
arcpy.Buffer_analysis(Points,Buffers,SearchTol,dissolve_option="ALL")
arcpy.MultipartToSinglepart_management(Buffers,BuffEx)
arcpy.AddField_management(BuffEx,"EndID","LONG")
arcpy.CalculateField_management(BuffEx,"EndID","!FID!","PYTHON_9.3")
arcpy.SpatialJoin_analysis(Points,BuffEx,JPoints)
# count the points for each polygon
arcpy.Statistics_analysis(JPoints,SumTab,[["PointID","COUNT"]],"EndID")
# go through all the count=2 rows
with arcpy.da.SearchCursor(SumTab,"EndID","COUNT_Poin = 2") as SumCur:
for SumRow in SumCur:
SelectIDs = list() # start with an empty list
with arcpy.da.SearchCursor(JPoints,"ORIG_FID","EndID = " + str(SumRow[0])) as JCur:
for JRow in JCur:
SelectIDs.append(JRow[0]) # add this ID to the list
MatchValues = list()
FirstFeature = True
AllFieldsMatch = True
# get the matching lines using the ORIG_FID field added by the
# feature verticestopoints tool
with arcpy.da.SearchCursor(InLayer,MatchFields,OIDfieldName + " in (" + str(SelectIDs[0]) + "," + str(SelectIDs[0]) + ")") as LCur:
# read the first features values into memory
# then compare against the second feature
for LRow in LCur:
if FirstFeature:
FirstFeature = False
# put all the values into a list
for fIdx in fRange:
MatchValues.append(str(LRow[fIdx]))
else:
for fIdx in fRange:
if MatchValues[fIdx] != str(LRow[fIdx]):
AllFieldsMatch = False # if one fails they all fail
break # no point checking any more
if AllFieldsMatch:
# then it's a true pseudo node, insert something here
pass
This script uses Feature Vertices to Points which requires an advanced license, if you don't have access to this there are other ways to make points from line end points in python which you can search and replace - I think this script is already too long.
-
Thanks I'll take a look. I did figure out not to verify the topology first but rather use the Topology tool "Validate Topology in a Specified Area" and I was able to remove upwards of 14,000 pseudo notes in ~ 1 hour.Jeff– Jeff2015年02月11日 22:53:47 +00:00Commented Feb 11, 2015 at 22:53
Explore related questions
See similar questions with these tags.