1

I am trying to modify some lines in ArcGIS Pro, shifting the Start vertex to coordinates in a pair of fields in the layer attributes. My arcpy script works... almost.

import arcpy

aprx = arcpy.mp.ArcGISProject("CURRENT")
mapx = aprx.activeMap
layer_name = "tempfc"
layer = mapx.listLayers(layer_name)[0]

# Create an update cursor to modify feature geometry
with arcpy.da.UpdateCursor(layer, ["SHAPE@", "xcoord", "ycoord"]) as cursor:
    for row in cursor:
        # Unpack the current feature's geometry and the target x, y coordinates
        geom, x_coord, y_coord = row
        
        # Create a new point geometry for the start point
        new_start_point = arcpy.Point(x_coord, y_coord)
        
        # Get the array of points from the current geometry (line)
        # We need to ensure we use an arcpy Array to handle points
        old_points = geom.getPart(0)
        new_points = arcpy.Array([new_start_point] + [old_points.getObject(i) for i in range(1, old_points.count)])
        
        # Create a new polyline using the updated array of points
        new_line = arcpy.Polyline(new_points, geom.spatialReference)
        
        # Update the row with the new geometry
        cursor.updateRow([new_line, x_coord, y_coord])
print("Start points of lines have been updated.")

The problem is, some of my lines contain curves (or curve segments), and in my Update Cursor when I rebuild the shape it simply draws straight lines between each of the existing vertices

This is my line in red enter image description here

And after running my script, this is what the line looks like (with the original shown in blue for reference). The shift of the first vertex to the new start point is good, exactly what I want, and the last segment is fine too. But the curve has gone and become a straight line.
enter image description here

How can I modify my line shape but keep existing curve segments in place? If the first segment is a curve, I still want it to become a straight segment (this is to avoid nasty curves appearing because I shifted it), but the rest I would like to remain as-is.

0

2 Answers 2

2

Thanks to the various comments and links to similar questions (namely Determining if polyline has true curve using ArcPy with ArcMap), I was able to come up with an acceptable solution.

Update Cursors do not handle curves well, so modifying the geometry with the cursor will end up removing the curves. So the solution for me was to check if curves exist on the line, and if so then densify that line first. I did this by adding this into the start of the cursor before it attempts to shift my start vertex (from the question above).

    for row in cursor:
        polyline = row[0]
        if polyline.hasCurves:
            polyline = polyline.densify('ANGLE',10, 0.174533)
            row[0] = polyline

This is the end result, in which you can barely make out that the curve has now been densified into multiple straight segments and additional vertices (an acceptable variation in my case).

enter image description here

And the complete cursor:

# Create an update cursor to modify feature geometry
with arcpy.da.UpdateCursor(layer, ["SHAPE@", "xcoord", "ycoord"]) as cursor:
    for row in cursor:
        # Unpack the current feature's geometry and the target x, y coordinates
        polyline, x_coord, y_coord = row
        
        # Check if line contains curves, and densify if needed
        if polyline.hasCurves:
            polyline = polyline.densify('ANGLE', 10, 0.174533)  # In Radians to preserve curve shape

        # Create a new point geometry for the start point
        new_start_point = arcpy.Point(x_coord, y_coord)

        # Get the array of points from the current geometry (line)
        # We need to ensure we use an arcpy Array to handle points
        old_points = polyline.getPart(0)
        new_points = arcpy.Array([new_start_point] + [old_points.getObject(i) for i in range(1, old_points.count)])

        # Create a new polyline using the updated array of points
        new_line = arcpy.Polyline(new_points, polyline.spatialReference)

        # Update the row with the new geometry
        cursor.updateRow([new_line, x_coord, y_coord])
print("Start points of lines have been updated.")
1

This question is mistitled, it should read "Keeping curves intact with ArcPy Geometry constructors." There is no limitation to working with true curves and UpdateCursor - ArcGIS Pro | Documentation. The limitation being encountered here is that ArcPy Geometry - ArcGIS Pro | Documentation constructors do not support constructing geometries with true curves. When given a geometry with a true curve, the UpdateCursor will correctly insert it back into the feature data set.

Regarding the question of maintaining true curves with ArcPy Geometry constructors, the answer is you can't. As already covered in another answer to this question, one can work with densified curves and ArcPy Geometry constructors, but that obviously gives up working with true curves.

So if UpdateCursor - ArcGIS Pro | Documentation supports true curves but ArcPy Geometry - ArcGIS Pro | Documentation constructors don't, how does someone modify true curves? The answer is to work with the Esri JSON represenation of Geometry objects | ArcGIS REST APIs | ArcGIS Developers

import arcpy
import json

aprx = arcpy.mp.ArcGISProject("CURRENT")
mapx = aprx.activeMap
layer_name = "tempfc"
layer = mapx.listLayers(layer_name)[0]

# Create an update cursor to modify feature geometry
with arcpy.da.UpdateCursor(layer, ["SHAPE@JSON", "xcoord", "ycoord"]) as cursor:
   for esri_json, x_coord, y_coord in cursor:
       # Convert Esri JSON to Python dict
       geom_dict = json.loads(esri_json)
       
       # Get 'Paths' key name 
       paths_key = {"Paths", "curvePaths"}.intersection(geom_dict.keys()).pop()
       
       # Update first coordinate of first part of geometry
       geom_dict[paths_key][0][0] = [x_coord, y_coord]
       
       # Update the row with new geometry
       cursor.updateRow([json.dumps(geom_dict), x_coord, y_coord])

print("Start points of lines have been updated.")

Using Esri JSON allows a true curve like

Esri Polyline with true curve

to be modified to

Esri Polyline with true curve modified using Esri JSON

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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