Select to view content in your preferred language

Aligning random Address Points to a straight line.

721
1
07-19-2023 11:42 AM
NeilSexton
New Contributor

I have a bunch of address points that all over the place and not in a line.    I want to be able to clean these up and put them in a straight line.     I want to be able to highlight the address points I want to straighten and snap them to a line or just put them in a straight line. 

 

Things I have tried -

I have snaping them to a street line then moving them.  But that will not keep them evenly separated.   

I have tried using the Disperse tool, but some address points are to far out of the search area when setting minimum spacing.   

I have tried the Align Features tool, but that doesn't seem to work. 

 

Suggestions?

Thanks in advance 

 

1 Reply
JohannesLindner
MVP Frequent Contributor

Here's one way to do it:

  • Copy/paste the script into your ArcGIS Pro Python Window and execute. This will define a function 'straighten_points'.
import numpy

def straighten_points(layer, fit_degree=1):
    """Snaps all (selected) points in a layer to a regression line. This edits the input layer!
    
    layer: layer name (str) or layer object (arcpy.mp.Layer)
    fit_degree (int): degree of the polynomal fit, defaults to 1 (linear regression)
    """ 
    sr = arcpy.Describe(layer).spatialReference
    # extract point coordinates
    points = [r[0].firstPoint for r in arcpy.da.SearchCursor(layer, ["SHAPE@"])]
    x = [p.X for p in points]
    y = [p.Y for p in points]
    # polynomial fit
    coef = numpy.polyfit(x, y, fit_degree)
    polynom = numpy.poly1d(coef)
    # construct fit line geometry
    fit_xy = [
        [x_, polynom(x_)]
         for x_ in numpy.linspace(min(x) - 1000, max(x) + 1000, 100)
    ]
    fit_points = [arcpy.Point(fx, fy) for fx, fy in fit_xy]
    line = arcpy.Polyline(arcpy.Array(fit_points), spatial_reference=sr)
    # snap points to regression line geometry and update layer
    with arcpy.da.UpdateCursor(layer, ["SHAPE@"]) as cursor:
        for  p, in cursor:
            new_p = line.snapToLine(p)
            cursor.updateRow([new_p])

 

  • Select the points you want to straighten

 

  • Run the function. Using 1 does a linear regression, which should be fine for straight road segments. For curves, you could try 2 or higher degrees, but remember that using this function will edit the layer, so make a backup.
straighten_points("NameOfYourLayer", 1)

 

 

Before:

JohannesLindner_0-1689805777072.png

 

 

After (northern road: fit_degree = 1, southern road: fit_degree = 2:

JohannesLindner_1-1689805838236.png

 


Have a great day!
Johannes