Creating chainage points with distance from start point included

3638
10
04-10-2022 03:31 PM
Status: Implemented
Labels (1)
JordanFuhrmann
New Contributor III

The ability to add distance from start point to individual chainage points would be greatly beneficial. Whilst using "arcpy.GeneratePointsAlongLines_management" allows you to add chainage points at your required intervals, once you start dealing with longer lines and multiple unique lines with many points it becomes very difficult to know the distance of a given chainage point from the start point. Ideally, a new field would be created in the output table that shows an individual points distance from the start point of a unique line.

10 Comments
DuncanHornby

This is a good idea and I'm surprised the tool does not write that information out. Why create a series of points and not want to know their position relative to the line they were just created from?

The tool itself is a script tool so you have access to its source code. It would only take a few extra lines of code to give you what you want, that's it you feel brave enough to script in python? But we shouldn't be needing to edit system tools so lets hope ESRI listens?

JordanFuhrmann

Cheers @DuncanHornby .

Have you any suggestions on how to do this?

I'm relatively inexperienced with the use of Python, so any guidance at all would be greatly appreciated!

 

 

 

DuncanHornby

How much experience have you with writing python? The script behind the tool is located here:

c:\program files\arcgis\pro\Resources\ArcToolbox\scripts\generatepointsfromlines.py

Before you do anything I would strong suggest you make a copy of it as a back up in case you mess it up and destroy a system tool. You will need Admin privileges to overwrite this file.

Open the above script in your preferred IDE, spyder works well with ArcPro if you have installed it through ArcPro. I wrote a short blog here.

You need only replace the two functions in the code (create_feature_class and create_points_from_line) with the updated code below. Any lines I have added you will see a DDH comment to identify them.

 

def create_points_from_lines(input_fc, output_fc, spatial_ref, percent=False,
                             dist=True, add_end_points=False):
    """Convert line features to feature class of points

    :param input_fc: Input line features
    :param output_fc: Output point feature class
    :param spatial_ref: The spatial reference of the input
    :param percent: If creating points by percentage (or distance)
    :param dist: The distance used to create points (if percentage == False).
    The distance should be in units of the input (see convert_units)
    :param add_end_points: If True, an extra point will be added from start
    and end point of each line feature
    :return: None
    """

    if percent:
        is_percentage = True
    else:
        is_percentage = False

    create_feature_class(input_fc, output_fc, spatial_ref)

    # Add a field to transfer FID from input
    fid_name = 'ORIG_FID'
    arcpy.AddField_management(output_fc, fid_name, 'LONG')

    # Create new points based on input lines
    in_fields = ['SHAPE@', 'OID@']
    out_fields = ['SHAPE@', fid_name, "Distance"] # Add Distance field - Added by DDH on 12/4/22

    with arcpy.da.SearchCursor(input_fc, in_fields) as search_cursor:
        with arcpy.da.InsertCursor(output_fc, out_fields) as insert_cursor:
            for row in search_cursor:
                line = row[0]

                if line:  # if null geometry--skip
                    if line.type == 'polygon':
                        line = line.boundary()
                        
                    if add_end_points:
                        insert_cursor.insertRow([line.firstPoint, row[1], 0]) # Added 0 - Added by DDH on 12/4/22

                    increment = (percent or dist)
                    cur_length = increment

                    if is_percentage:
                        max_position = 1.0
                    else:
                        max_position = line.length

                    while cur_length < max_position:
                        new_point = line.positionAlongLine(cur_length,is_percentage)
                        insert_cursor.insertRow([new_point, row[1], cur_length]) # Added cur_length - Added by DDH on 12/4/22
                        cur_length += increment

                    if add_end_points:
                        end_point = line.positionAlongLine(1, True)
                        if is_percentage:
                            insert_cursor.insertRow([end_point, row[1], 1])  # Added 1 - Added by DDH on 12/4/22
                        else:
                            insert_cursor.insertRow([end_point, row[1], line.length])  # Added length - Added by DDH on 12/4/22

        try:
            oid_name = get_OID_name(input_fc)
            arcpy.JoinField_management(out_fc, fid_name, input_fc, oid_name)
        except arcpy.ExecuteError:
            # In unlikely event that JoinField fails, proceed regardless,
            # as spatial and join field are already complete
            pass

    return


def create_feature_class(input_fc, output_fc, spatial_ref):
    """Create the initial feature class

    :param input_fc: Input line features
    :param output_fc: Output point feature class
    :param spatial_ref: The spatial reference of the input
    """

    desc = arcpy.Describe(input_fc)

    # Take flag environment over Describe property unless set to default
    support_m = arcpy.env.outputMFlag.upper() if arcpy.env.outputMFlag in ['Enabled', 'Disabled'] \
        else "ENABLED" if desc.hasM else "DISABLED"
    support_z = arcpy.env.outputZFlag.upper() if arcpy.env.outputZFlag in ['Enabled', 'Disabled'] \
        else "ENABLED" if desc.hasZ else "DISABLED"

    # Create output feature class
    arcpy.CreateFeatureclass_management(
        os.path.dirname(output_fc),
        os.path.basename(output_fc),
        geometry_type="POINT",
        has_m=support_m,
        has_z=support_z,
        spatial_reference=spatial_ref)

    # Add Distance field - Added by DDH on 12/4/22
    arcpy.AddField_management(out_fc,"Distance","Double",None,None,None,"Distance along line",True,False,None)
    return

 

 

An example of the output is below:

DuncanHornby_0-1649771193804.png

Ideally ESRI would add this functionality to their core release

Scott_Harris
Status changed to: Needs Clarification

@JordanFuhrmann 

If you can clarify the goal a bit more, perhaps there is existing functionality that will do what you need?

Just going by the information you've provided, here are some suggestions:

Create Points Along Line and Offset are Editing tools that can create points along a line but they also do not write out a distance attribute for the point. What they will do is store interpolated measure values on m-enabled points if the source line also has its m-values populated. There are few ways to populate m-values on m-enabled lines.

https://pro.arcgis.com/en/pro-app/latest/help/editing/edit-vertex-m-values.htm

https://pro.arcgis.com/en/pro-app/latest/help/editing/create-a-route-from-line-features.htm

If the goal is just to display distance values on a line, perhaps you don't even need the points and you can just use measured hatch symbols to get the desired result.

If the goal is something else completely, feel free to fill in the blanks 🙂

-Scott

KoryKramer
Status changed to: Open
 
JordanFuhrmann

Thankyou @DuncanHornby, I'll see how I go with it. @scool the goal is as follows.

- I have a line (say its 1000m long). I want to create a point every 100m along this line, with the distance from the start point included in the output (e.g. point 1 = 100m, point 2 =200m ....). 

I need to be able to do this to many unique lines at the same time. 

Cheers.

DrewFlater
Status changed to: In Product Plan

The enhancement will be integrated to the Generate Points Along Lines tool in ArcGIS Pro in the near term. 

JordanFuhrmann

Hi @DrewFlater,

Any idea of a possible time line for when this may become available?

 

Cheers,

Jordan

DrewFlater

@JordanFuhrmann  it is currently in our Pro 3.1 release plan, though these plans are subject to change. I'm comfortable to say Near Term. 

AmeliaBradshaw
Status changed to: Implemented

This Idea has been implemented in ArcGIS Pro 3.1. Please see the What's New documentation for more new features in Pro 3.1.

The Ideas in ArcGIS Pro 3.1 blog will be wrapped up soon, highlighting all Ideas implemented in this release, including this one. Once complete, I will add the link to this comment.