I've found the following forum post https://community.esri.com/thread/102954 where the geometry method measureOnLine was used. I'm trying to determine how to use the same method for calculating the chainage (accumulated distance) along a cross-section polyline. I need to extract the profile of each cross-section into a point feature class based on the position of the vertices within each cross-section polyline. I would like to end up with a point feature class with the following fields:
The chainage will be the accumulative distance (i.e. XS point 1 = 0 ; XS point 2 = 20m ; XS point 3 = 35m etc)
I would like to use the polyline Z Feature Class to generate a pointGeometry Object and iterate through each point that will be used as the point for the measureOnLine method against the original Polyline Feature Class. The determined length (Chainage) will be inserted (i.e. InsertCursor) with the Point Object ; ID (Cross Section Field) and Chainage into a newly generated feature class.
I'm still very new to ArcPy and Python and battling to figure out how to iterate through the PointGeometry from the Polyline to use the measureOnline method and then insert the Point Geometry ; ID ; Chainage into a new Feature Class.
Any help in getting going will trully be appreciated.
Regards
Peter Wilson
Solved! Go to Solution.
Hi Peter,
Since you are interested in Python, let's throw in some Python code. I haven't tested the code, since the measureOnLine method was introduced at 10.2.1 and I have a lower version here. The rest of the code seems to work though.
Have a look at the code below:
Hope it works for you, good luck, Xander
import arcpy, os
arcpy.env.overwriteOutput = True
# featureclasses
fc_in = r"D:\Xander\GeoNet\3Dlines2Points\test.gdb\my3Dlines"
fc_out = r"D:\Xander\GeoNet\3Dlines2Points\test.gdb\myPoints"
# fields
fld_ID = "ID" # ID of Cross-Section in line featureclass
fld_Number = "Number" # just to add a number to the points
fld_Z = "Z" # Elevation
fld_Chainage = "Chainage" # Distance m from start of polyline
# fields for search cursor on input lines
flds_in = ("SHAPE@", fld_ID)
# get some input data to create the output
sr = arcpy.Describe(fc_in).spatialReference
ofld_ID = arcpy.ListFields(fc_in, fld_ID)[0]
# create the output featureclass
geometry_type = "POINT"
template = ""
has_m = "DISABLED" # you could enable M values...
has_z = "ENABLED"
ws_path, fc_out_name = os.path.split(fc_out)
arcpy.CreateFeatureclass_management(ws_path, fc_out_name,
geometry_type, template, has_m, has_z, sr)
# add the fields to the point featureclass
arcpy.AddField_management(fc_out, fld_ID, ofld_ID.type)
arcpy.AddField_management(fc_out, fld_Number, "LONG")
arcpy.AddField_management(fc_out, fld_Z, "DOUBLE")
arcpy.AddField_management(fc_out, fld_Chainage, "DOUBLE" )
# fields for insert cursor on output points
flds_out = ("SHAPE@", fld_ID, fld_Number, fld_Z, fld_Chainage)
# start insert cursor for output points
with arcpy.da.InsertCursor(fc_out, flds_out) as curs_out:
# start search cursor on lines
with arcpy.da.SearchCursor(fc_in, flds_in) as curs:
for row in curs:
number = 0
polyline = row[0]
line_ID = row[1]
for part in polyline:
for pnt in part:
number += 1
if pnt:
ptGeom = arcpy.PointGeometry(pnt, sr)
chainage = polyline.measureOnLine(ptGeom)
elevation = pnt.Z
curs_out.insertRow((ptGeom, line_ID, number, elevation, chainage))
Alternatively:
Hi Peter,
Since you are interested in Python, let's throw in some Python code. I haven't tested the code, since the measureOnLine method was introduced at 10.2.1 and I have a lower version here. The rest of the code seems to work though.
Have a look at the code below:
Hope it works for you, good luck, Xander
import arcpy, os
arcpy.env.overwriteOutput = True
# featureclasses
fc_in = r"D:\Xander\GeoNet\3Dlines2Points\test.gdb\my3Dlines"
fc_out = r"D:\Xander\GeoNet\3Dlines2Points\test.gdb\myPoints"
# fields
fld_ID = "ID" # ID of Cross-Section in line featureclass
fld_Number = "Number" # just to add a number to the points
fld_Z = "Z" # Elevation
fld_Chainage = "Chainage" # Distance m from start of polyline
# fields for search cursor on input lines
flds_in = ("SHAPE@", fld_ID)
# get some input data to create the output
sr = arcpy.Describe(fc_in).spatialReference
ofld_ID = arcpy.ListFields(fc_in, fld_ID)[0]
# create the output featureclass
geometry_type = "POINT"
template = ""
has_m = "DISABLED" # you could enable M values...
has_z = "ENABLED"
ws_path, fc_out_name = os.path.split(fc_out)
arcpy.CreateFeatureclass_management(ws_path, fc_out_name,
geometry_type, template, has_m, has_z, sr)
# add the fields to the point featureclass
arcpy.AddField_management(fc_out, fld_ID, ofld_ID.type)
arcpy.AddField_management(fc_out, fld_Number, "LONG")
arcpy.AddField_management(fc_out, fld_Z, "DOUBLE")
arcpy.AddField_management(fc_out, fld_Chainage, "DOUBLE" )
# fields for insert cursor on output points
flds_out = ("SHAPE@", fld_ID, fld_Number, fld_Z, fld_Chainage)
# start insert cursor for output points
with arcpy.da.InsertCursor(fc_out, flds_out) as curs_out:
# start search cursor on lines
with arcpy.da.SearchCursor(fc_in, flds_in) as curs:
for row in curs:
number = 0
polyline = row[0]
line_ID = row[1]
for part in polyline:
for pnt in part:
number += 1
if pnt:
ptGeom = arcpy.PointGeometry(pnt, sr)
chainage = polyline.measureOnLine(ptGeom)
elevation = pnt.Z
curs_out.insertRow((ptGeom, line_ID, number, elevation, chainage))
I was just thinking, I don't need the 10.2.1 functionality to do this. It is also possible to something like this:
# start insert cursor for output points
with arcpy.da.InsertCursor(fc_out, flds_out) as curs_out:
# start search cursor on lines
with arcpy.da.SearchCursor(fc_in, flds_in) as curs:
for row in curs:
number = 0
polyline = row[0]
line_ID = row[1]
chainage = 0
for part in polyline:
for pnt in part:
number += 1
if pnt:
ptGeom = arcpy.PointGeometry(pnt, sr)
if number > 1:
chainage += ptGeom.distanceTo(prev_pnt)
# chainage = polyline.measureOnLine(ptGeom)
elevation = pnt.Z
curs_out.insertRow((ptGeom, line_ID, number, elevation, chainage))
prev_pnt = ptGeom
It uses the distanceTo on the point geometry to sum the traveled distance on the line...
Kind regards, Xander