Back when I was doing a lot of GIS work for civil and electrical asset management, a common task I had was to ensure that all civil structures represented as a polyline (reticulation and bulk pipelines, eletrical feeder cables, road surfaces etc) were split at the physical road intersections as seen on the latest available aerial imagery, as well as where they crossed each other.
This task wasn’t too much trouble if the lines were already drawn across each other, as more often than not, the lines crossed at the road intersections. The result was usually achieved by using the Planarize option on the Advanced Editing toolbar. However, it became a problem for new areas which had to be digitised by hand (no CAD drawings or shapefiles received), or lines which had to be corrected.
I would have to visually check on the imagery where the road intersections were, and then manually split each polyline. I ran through some ideas, including digitising all road intersections as points (which would be good data to have anyway), and then splitting all the lines at the closest intersection by using the Split Line at Point tool.
I did however want to create a method of splitting the line multiple times on the fly, instead of just splitting it once (which is the option provided by the Split button on the Editor toolbar). I wanted to be able to select a line, click as many points along the line as I wanted, and then split the line into those points.
|@author Cindy Williams|
|Uses an arcpy FeatureSet to allow the user to interactively create|
|points on a line which will be used to split that line into parts,|
|while retaining all attributes.|
|– Works as a script tool. Add to a toolbox.|
|– Can only work on a single line for now. Select the line, right|
|click the layer and "Create layer from selected features". Use|
|this selection layer as input to the tool.|
|– Digitise points snapped to the selected line. Tool will fail if not|
|– Digitise points left to right along the line.|
|Future versions will include:|
|– split multiple lines at same time|
|– snap points automatically/error that points should be snapped|
|– points will be sorted after digitising to ensure correct order|
|Built on an idea here http://gis.stackexchange.com/questions/154708/standalone-python-script-to-split-a-polyline-with-a-point-layer|
|inset = arcpy.GetParameter(0) # FeatureSet of interactive points from ArcMap|
|inline = arcpy.GetParameterAsText(1) # Input polyline feature layer|
|# Get all field names excluding dynamic fields|
|fields = ["SHAPE@"]|
|fields.extend([field.name for field in arcpy.ListFields(inline) if field.name not in ["OBJECTID", "Shape_Length", "Shape"]])|
|# Open an insert cursor for inserting the cut lines|
|cursor_ins = arcpy.da.InsertCursor(inline, fields)|
|# Get the spatial reference from the polyline|
|sr = arcpy.Describe(inline).spatialReference|
|# Get the polyline and delete the original record|
|with arcpy.da.UpdateCursor(inline, fields) as cursor:|
|for row in cursor:|
|polyline = row|
|# Iterate over the points|
|with arcpy.da.SearchCursor(inset, "SHAPE@") as cursor:|
|for row in cursor:|
|point = row.firstPoint|
|# Build a temporary diagonal line from the point|
|diag = arcpy.Polyline(arcpy.Array([arcpy.Point(point.X + 10.0, point.Y + 10.0), arcpy.Point(point.X–10.0, point.Y–10.0)]), sr)|
|# Cut the original polyline|
|geom = polyline.cut(diag)|
|# Create a new line with the right side of the geom i.e. finished with this side|
|newline = [geom]|
|# Insert the line into the feature layer|
|# Set the left side of the cut line as the new line for cutting|
|polyline = [geom]|
|# Insert the last portion of the line|
The tool iterates over all the points created by the user in the FeatureSet. For each point, a temporary diagonal is created to cut the original polyline. This new part is saved in a list and the tool runs again on the original polyline (minus the new part). Once all the points have been processed, the original polyline is removed from the feature class, and the new parts are inserted. All feature attributes are maintained.
My intention with this tool was to expand it with more features, fix the bugs (it would randomly not work) and upload it as a toolbox. However, the need to do that fell away. I also realised I was starting to get into a space where I was forcing as much code as I could into my work in order to get through the day.