I have a tool/script that performed exceptionally well in ArcMap both as a tool/script and as an Add-in. However, I've been attempting to convert it to ArcGIS Pro without success. This tool/script in ArcMap allowed users to calculate the distance between two points with just two clicks, essentially creating a polyline that conveyed the length for further calculations. It also generated a point and updated a field based on this calculation. Although I've attempted to replicate the parameters from ArcMap in Pro, the tool fails to function as expected. It doesn't allow me to click on the map or initiate any actions. How can I go about ensuring this script works in ArcGIS Pro?
The noticeable difference that I see in the parameters section is that script in pro doesn't have Schema.
ArcMap parameters:
Input - Feature Set-
Type - Required
Direction - Input
MultiValue - no
Schema - points to the Point layer
Script,
import arcpy
from arcpy import env
import pythonaddins
import os
fc = "Points"
arcpy.env.workspace = r"C:\Temp\PointsTest.mdb"
pointLayer = arcpy.env.workspace + os.sep + "Points" #target point feature class
if arcpy.Exists ("line_test"):
arcpy.Delete_management ("line_test")
# Start an edit session. Must provide the worksapce.
edit = arcpy.da.Editor(arcpy.env.workspace)
# Edit session is started without an undo/redo stack for versioned data
# (for second argument, use False for unversioned data)
edit.startEditing(True)
# Start an edit operation
edit.startOperation()
input = arcpy.GetParameterAsText(0)
Range = float(arcpy.GetParameterAsText(1))
# Create empty Point and Array objects
point = arcpy.Point()
array = arcpy.Array()
# A list that will hold each the Polyline object
featureList = []
rows = arcpy.SearchCursor(input)
for row in rows:
geom = row.Shape
point.X = geom.centroid.X
point.Y = geom.centroid.Y
# Add each point to the array
array.add(point)
# Create the polyline
polyline = arcpy.Polyline(array)
# Clear the array for future use
array.removeAll()
featureList.append(polyline)
del row, rows
# Copy the polyline to file geodatabase to create a Shape_Length field
arcpy.CopyFeatures_management(featureList, "line_test")
with arcpy.da.SearchCursor("line_test", ["SHAPE@","SHAPE@LENGTH"]) as cursor:
for row in cursor:
X = row[0].lastPoint.X
Y = row[0].lastPoint.Y
length = row[1] / 5.28
print("Length:", length)
row_value = (length, (X, Y))
cursor = arcpy.da.InsertCursor(pointLayer, ("SiteNum", "SHAPE@XY"))
cursor.insertRow(row_value)
Add-in,
import arcpy
import pythonaddins
class PointTool(object):
"""Implementation for Point_addin.PointTool (Tool)"""
def __init__(self):
self.enabled = True
self.cursor=3
self.shape = "Line" # Can set to "Line", "Circle" or "Rectangle" for interactive shape drawing and to activate the onLine/Polygon/Circle event sinks.
def onLine(self, line_geometry):
fc = "Points"
arcpy.env.workspace = r"C:\Temp\PointsTest.mdb"
pointLayer = arcpy.env.workspace + os.sep + "Points" #target point feature class
if arcpy.Exists ("line_test"):
arcpy.Delete_management ("line_test")
# Start an edit session. Must provide the worksapce.
edit = arcpy.da.Editor(arcpy.env.workspace)
# Edit session is started without an undo/redo stack for versioned data
# (for second argument, use False for unversioned data)
edit.startEditing(True)
# Start an edit operation
edit.startOperation()
input = arcpy.GetParameterAsText(0)
Range = float(arcpy.GetParameterAsText(1))
# Create empty Point and Array objects
point = arcpy.Point()
array = arcpy.Array()
# A list that will hold each the Polyline object
featureList = []
rows = arcpy.SearchCursor(input)
for row in rows:
geom = row.Shape
point.X = geom.centroid.X
point.Y = geom.centroid.Y
# Add each point to the array
array.add(point)
# Create the polyline
polyline = arcpy.Polyline(array)
# Clear the array for future use
array.removeAll()
featureList.append(polyline)
del row, rows
# Copy the polyline to file geodatabase to create a Shape_Length field
arcpy.CopyFeatures_management(featureList, "line_test")
with arcpy.da.SearchCursor("line_test", ["SHAPE@","SHAPE@LENGTH"]) as cursor:
for row in cursor:
X = row[0].lastPoint.X
Y = row[0].lastPoint.Y
length = row[1] / 5.28
print("Length:", length)
row_value = (length, (X, Y))
cursor = arcpy.da.InsertCursor(pointLayer, ("SiteNum", "SHAPE@XY"))
cursor.insertRow(row_value)
Solved! Go to Solution.
Try the attached tool. First, update the gdb variable by right-clicking on the toolbox > Properties > Execution:
Next, double-click the Script tool. Click the dropdown next the pencil and select Points. Create two points and execute the tool.
Full disclosure, I'm not sure any of the below points are the issue, except maybe #2 (Line 49). That said, a few things that jump out at me in no particular order:
with arcpy.da.SearchCursor('line_test', 'SHAPE@') as cursor:
for row in cursor:
x = row[0].lastPoint.X
y = row[0].lastPoint.Y
length = row[0].length / 5.28
print(f'Length: {length}')
My bad, I had different variations going on.
Hi @TonyAlmeida,
You could use something like below to create the line feature class:
import os
import arcpy
# Variables
input = arcpy.GetParameterAsText(0)
gdb = r"C:\temp\python\test.gdb"
wkid = 2272
# Environment Variables
arcpy.env.overwriteOutput = True
arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(2272)
arcpy.env.workspace = gdb
array = arcpy.Array()
with arcpy.da.SearchCursor(input, ["SHAPE@X", "SHAPE@Y"]) as cursor:
for row in cursor:
pt = arcpy.Point(row[0], row[1])
array.add(pt)
del cursor
polyline = arcpy.Polyline(array)
arcpy.CopyFeatures_management(polyline, "line_test")
Is there a tool in Pro that I need to use to initiate me to allow me to click on the map? It currently doesn't allow me to do that with the following parameters.
Currently using legacy toolbox script.
I have set up the parameters, like so.
Input:
Label - Input
Name - Input
Data type - Feature Set
Type - Required
Direction - Input
Default - points to .lyr file
Rang:
Label - Input
Name - Input
Data Type - Double
Type - Required
Direction - Input
Current code,
import arcpy
import os
# Set up your environment
fc = "Points"
arcpy.env.workspace = r"C:\Temp\PointsTest.gdb"
pointLayer = os.path.join(arcpy.env.workspace, "Points") # target point feature class
# Check if "line_test" exists and delete it if it does
if arcpy.Exists("line_test"):
arcpy.Delete_management("line_test")
# Start an edit session. Must provide the workspace.
edit = arcpy.da.Editor(arcpy.env.workspace)
# Edit session is started without an undo/redo stack for versioned data
# (for the second argument, use False for unversioned data)
edit.startEditing(True)
# Variables
input = arcpy.GetParameterAsText(0)
gdb = r"C:\Temp\PointsTest.gdb"
wkid = 2272
# Set environment variables
arcpy.env.overwriteOutput = True
arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(2272)
arcpy.env.workspace = gdb
array = arcpy.Array()
# Iterate over the features in the input and create a polyline
with arcpy.da.SearchCursor(input, ["SHAPE@X", "SHAPE@Y"]) as cursor:
for row in cursor:
pt = arcpy.Point(row[0], row[1])
array.add(pt)
# Create a polyline from the array
polyline = arcpy.Polyline(array)
# Save the polyline to "line_test" feature class
arcpy.CopyFeatures_management(polyline, "line_test")
# Retrieve the last point of the polyline and calculate its attributes
with arcpy.da.SearchCursor("line_test", "SHAPE@") as cursor:
for row in cursor:
X = row[0].lastPoint.X
Y = row[0].lastPoint.Y
length = row[0].length / 5.28
print("Length:", length)
# Prepare the row value tuple
row_value = (length, (X, Y))
# Use arcpy.da.InsertCursor with a context manager to insert rows into the point layer
with arcpy.da.InsertCursor(fc, ["SiteNum", "SHAPE@XY"]) as cursor:
cursor.insertRow(row_value)
In the input parameters dependency I had it pointing to a .lyr file and gave me totally something different. After removing that .lyr and starting a edit session I am able to see what you see. After clicking on points, it appears that a point layer is created based on the name of the script, for mine it was PointTestScript input(Points), temp layer?, I get options to use point or point at the end of line, I've tried both. The point doesn't do anything other then just create points in the temp layer? If I use the point at the end of line I get error, line 45, in <module>
X = row[0].lastPoint.X
AttributeError: 'NoneType' object has no attribute 'lastPoint'
Inside the database there is layers being created that correspond with the temp point layers, "Points_1", "Points_2", etc. with field names Name, Text, IntegerValue, DoubleValue and DateTime, but they are empty.
Also, I appreciate your help and patience.
Can you post the updated code your using?
Of course.
From what I can tell, the "polyline" doesn't get created inside the database, which is why I am getting the error. I just see "points" with the fields I mention before.
import arcpy
import os
# Set the workspace and target point feature class
workspace = r"C:\Temp\PointsTest.gdb"
arcpy.env.workspace = workspace
fc = "Points"
pointLayer = os.path.join(workspace, "CCAP") # Corrected quotation marks here
# Variables
input = arcpy.GetParameterAsText(0) # Changed variable name to follow Python conventions
Range = float(arcpy.GetParameterAsText(1))
wkid = 26770 # Corrected wkid to match the spatial reference
# Environment Variables
arcpy.env.overwriteOutput = True
arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(wkid) # Corrected the spatial reference wkid
# Delete line_test if exists
if arcpy.Exists("line_test"):
arcpy.Delete_management("line_test")
# Create an array to hold the point geometries
array = arcpy.Array()
# Iterate through the input features to create the polyline
with arcpy.da.SearchCursor(input, ["SHAPE@X", "SHAPE@Y"]) as cursor:
for row in cursor:
pt = arcpy.Point(row[0], row[1])
array.add(pt)
del cursor
# Create the polyline from the array of points
polyline = arcpy.Polyline(array)
# Save the polyline to a file
arcpy.CopyFeatures_management(polyline, "line_test")
# Retrieve the last point's coordinates and calculate length
with arcpy.da.SearchCursor("line_test", "SHAPE@") as cursor:
for row in cursor:
last_point = row[0].lastPoint
X = last_point.X
Y = last_point.Y
length = row[0].length / 5.28
print("Length:", length)
# Prepare values to insert into the point layer
row_value = (length, (X, Y))
# Use arcpy.da.InsertCursor with a context manager to insert rows into the point layer
with arcpy.da.InsertCursor(pointLayer, ["SiteNum", "SHAPE@XY"]) as cursor:
cursor.insertRow(row_value)
Make sure your map is in coordinate system (26770), then try the following:
import os
import arcpy
# Variables
input = arcpy.GetParameterAsText(0)
gdb = r"C:\temp\PointsTest.gdb"
wkid = 26770
# Environment Variables
arcpy.env.overwriteOutput = True
arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(wkid)
arcpy.env.workspace = gdb
array = arcpy.Array()
with arcpy.da.SearchCursor(input, ["SHAPE@X", "SHAPE@Y"]) as cursor:
for row in cursor:
pt = arcpy.Point(row[0], row[1])
array.add(pt)
del cursor
polyline = arcpy.Polyline(array)
arcpy.AddMessage("Copying line features")
arcpy.CopyFeatures_management(polyline, "line_test")
# Retrieve the last point's coordinates and calculate length
with arcpy.da.SearchCursor("line_test", "SHAPE@") as cursor:
for row in cursor:
last_point = row[0].lastPoint
X = last_point.X
Y = last_point.Y
length = row[0].length / 5.28
arcpy.AddMessage(f"Length: {length}")
# Prepare values to insert into the point layer
row_value = (length, (X, Y))
# Use arcpy.da.InsertCursor with a context manager to insert rows into the point layer
arcpy.AddMessage("Inserting values into point layer")
with arcpy.da.InsertCursor("CCAP", ["SiteNum", "SHAPE@XY"]) as cursor:
cursor.insertRow(row_value)
del cursor