1

I have a line layer and point layer on my ArcGIS project. The points are on the lines. I want to create vertex on lines at this point coordinates.

import arcpy

point_rows = arcpy.da.SearchCursor("D:\Test.gdb\MyPoints", ['OID@', 'SHAPE'])

rows = arcpy.UpdateCursor("D:\Test.gdb\MyLines")

for row in rows:
    geom = row.SHAPE
    for part in geom.getPart():
        for pnt in point_rows:
                row.X = pnt.X
                row.Y = pnt.Y
                rows.updateRow(row)

I could not add vertex on points, if point is on the line. How can I do this using arcpy?

  • Related 1: gis.stackexchange.com/questions/250263/… – Mr. Che Aug 2 '18 at 9:24
  • Related 2: gis.stackexchange.com/questions/81777/… – Mr. Che Aug 2 '18 at 9:25
  • 1
    Your code does not attempt to perform the task. – Vince Aug 2 '18 at 11:16
  • Code updated in post. – barteloma Aug 2 '18 at 11:56
  • Can you clarify the what your data really consists of? You say The points are on the lines. Are you saying you have multiple points on a single line or each line has a corresponding single point? If they are single points, do their row order correspond to the row order of the polyline? Do these points ever occur at the ends? Are these polylines joined at their ends such as in a road network? Do they overlap? Looking at the suggested code below people are making assumptions (not unreasonable) about the row order relationship. You need to describe your data if you want a robust solution. – Hornbydd Aug 3 '18 at 14:30
1

Below is some python code that will take an un-ordered set of polylines with zero or more intersecting points and insert a vertex into the polyline at the point position.

Sample data

Sample data

This code is designed to be dropped into the Python console in ArcMap, simply change lineLayer and pointLayer.

import arcpy

# Layers in MXD
lineLayer = "fcLine"
pointLayer = "fcPoint"

with arcpy.da.UpdateCursor(lineLayer,['SHAPE@']) as lineCursor:
    for row in lineCursor:
        geom = row[0]

        # Get selected points along line, this could be zero, 1 or more
        arcpy.SelectLayerByLocation_management(pointLayer,"INTERSECT",geom,"#","NEW_SELECTION")
        res = arcpy.GetCount_management(pointLayer)
        n = int(res.getOutput(0))
        if n > 0:
            # We have at least 1 point intersecting line
            # Store selected point(s) in list for further processing
            pointList = []
            with arcpy.da.SearchCursor(pointLayer,['SHAPE@']) as pointCursor:
                for pointRow in pointCursor:
                    pointList.append(pointRow[0])
            print(str(len(pointList)) + " intersect current line.")

            # Convert polyline to points
            # Assumes line is simple geometry, i,e a single part
            lineArr = geom.getPart(0) # Returns an array
            for p in lineArr:
                pointList.append(arcpy.PointGeometry(p))

            # PointList is a list of PointGeometries composed of points on the line and points from the line itself
            # Now need to work out position of points along the line
            posDict = {}
            for p in pointList:
                pos = geom.measureOnLine(p,True)
                posDict[pos] = p

            # Reconstruct polyline by using sorted keys in posDict
            newArray = arcpy.Array()
            for key in sorted(posDict.iterkeys()):
                newArray.add(posDict[key].centroid) # Array takes points not PointGeometry, hence using centroid property
            newLine = arcpy.Polyline(newArray)

            # Insert updated geometry line back into dataset
            row[0] = newLine
            lineCursor.updateRow(row)
  • 1
    Thanks, your script worked as expected. Is there anyway to improve performance? It took about 5 minutes to add a point to 1100 lines. – GreyHippo Nov 29 '18 at 16:43
  • @GreyHippo Don't think so, it's already using the faster cursor type and the logic excludes lines that do not have any intersecting points. You could try moving the layers into an IN_MEMORY workspace to see if performance is improved or if your source datasets are shapefiles make sure they have a spatial index. – Hornbydd Nov 29 '18 at 16:57
  • Also after I run the command it takes a long time to save the MXD. Would your script cause something like that – GreyHippo Nov 29 '18 at 18:11
  • If you perform this script on a 10 lines the MXD saves normally but if I perform the script on 200 lines then it takes a few minutes to save the MXD. – GreyHippo Nov 29 '18 at 18:35
  • I just checked the MXD filesize and it is 64 mb after doing the script on 200 lines – GreyHippo Nov 29 '18 at 18:36
0

I think I have a solution! I ve checked the following code and it works.

1) This example creates a Point Feature of the Vertices of your line with the help of Numpy Arrays (Numpy Needs to be installed)

2) Then it merges These Vertices as Points together with your 'points' on the line -> Theres one drawback: On the Output Pointfile of this merge you Need to create a new field and sort the Points in the right order (1-9 in this example) Otherwise the final line would look like a 'grinding by numbers' (but Ive found also examples to automate this too..

3) Finally a new line is created including the original line and the Points on the line

Feel free to ask me, in case you've got questions or some parts of the code dont work on your system

import arcpy, numpy, os

sr = arcpy.SpatialReference(25832)


### The Input: Your Points on the line (PointsLTW) // The line feature itself (InFcLine)

PointsLTW = r"C:\lineVerts\PointsLTW.shp"
InFcLine  = r"C:\\lineVerts\LineLTW.shp" # input feature class

OutFcLine = r"C:\lineVerts\LineLTW_out2.shp" # output feature class


print "Inputs accepted.."

# Creates a Point Array of your Line

arrayLine = arcpy.da.FeatureClassToNumPyArray(InFcLine,["SHAPE@XY"], "", sr, explode_to_points=True)

print "Numpy Array created.."

# ..in case no Array was created

if arrayLine.size == 0:
    arcpy.AddError(InFcLine + " contains no features!")

# From Array to Point Feature of your Input Line
else:
    arcpy.da.NumPyArrayToFeatureClass(arrayLine, OutFcLine, ['SHAPE@XY'], sr)
    print "New Multipoint Feature (LineToVertPoints) from Numpy Array.."

# Now you just merge your original PointsLTW with your original Line, now written as a Point Feature out of the lines Vertices

arcpy.Merge_management(inputs="PointsLTW;LineLTW_out2",output="C:/lineVerts/FinalPointsxx.shp",field_mappings="""Id "Id" true true false 6 Long 0 6 ,First,#,PointsLTW,Id,-1,-1,LineLTW_out2,Id,-1,-1""")

# Finally you create a line out of the merged points, the only drawback is that you need the Points to be sorted after the line Direction (From East to West or VV), I did this with a new field sorting the points by hand

arcpy.PointsToLine_management(r"C:/lineVerts/FinalPointsxx.shp" , r"D:\FinalLinexx.shp", "","sortedLTW")

enter image description here

-1

As the easiest way (not too much coding, but questionable performance) you might try to do this (ArcGIS Desktop Advanced license required):

  1. Use Split Line at Point tool to split the lines.
  2. Use Unsplit Line tool to merge the lines back.

As described in the description of the tool:

If Search Radius (search_radius in Python) is unspecified, the nearest point will be used to split the line feature. If a Search Radius is specified, all points within the search radius are used to split the line.

So by default Split Line at Point only works for ONE point per line. Other points on the line are ignored. But if you set huge Search Radius all points will split the line.

________Before_____________________ Splitted_____________________ UNsplitted

before_________ splitted_________ UNsplitted

This code should do the job (not tested):

import arcpy

points = r"D:\Test.gdb\MyPoints"
lines = r"D:\Test.gdb\MyLines"
splitted = r"D:\Test.gdb\MySplittedLines"
unsplitted = r"D:\Test.gdb\MyUnSplittedLines"
searchRadius = "9999999999999999999 Meters"

arcpy.SplitLineAtPoint_management(lines, points, splitted, searchRadius)
arcpy.UnsplitLine_management(splitted, unsplitted)
  • But Split and Unsplit does not create verticies on line. – barteloma Aug 2 '18 at 10:58
  • aplit and unsplid operations recreates objects and changes the objectid's – barteloma Aug 2 '18 at 14:16
  • @barteloma You can copy ID's to a new field before the operation. – Mr. Che Aug 3 '18 at 4:09
  • I have an error: 'The tool is not licensed. Failed to execute' So I need using update. – barteloma Aug 3 '18 at 5:41
-1

I think you had your geometry token for your points wrong. It should have come as "Shape@".

The code can be written as :

    Import arcpy 
    # Setting path 
    arcpy.env.workspace = "path" 
    # This line of code returns x, and y as tuple. 
    with arcpy.da.searchCursor("Feature/Table",['OID@','Shape@']) as /
    point_cursor
    for row in point_cursor: 
       pnt.X,pnt.Y = row[1]
       print('{},{}'.format(pnt.X,pnt.Y)) 
       ## The first code reads the x,y of the point layer 
       ### The next code is to write the point x,y on the line 
       with arcpy.InsertCursor('Feature/Table',"Shape@") as line_cursor 
         array = arcpy.array([pnt.X,pnt.Y]) 
         Line_ = arcpy.polyline(array) 
         line_cursor.insertRow([Line_])
  • This code appears not to insert the point into the line, in fact as I read it, it INSERTS not UPDATES a polyline and actually fails by inserting a line consisting of 1 vertex which makes no sense. – Hornbydd Aug 3 '18 at 15:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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