This is a follow-up question to Having two input feature layers and derived output feature layer in ArcGIS Python Toolbox tool?.
The following Python Toolbox tool accepts one or more points from the user and calculates the station, offset, and orientation of the point(s) based on a single polyline (an 'alignment'). It works fine as a geoprocessing tool in ArcMap with all the layers in the local Tennessee State Plane NAD83 coordinate system. However, I'd like this to also work correctly from within the Geoprocessing Widget in Web AppBuilder. When the user goes to digitize the point(s) in WAB, they are of course in the Web Mercator (auxiliary sphere) coordinate system. For the geoprocessing service to work correctly, I need to somehow project those points from Web Mercator back to TN State Plane so that the queryPointAndDistance method correctly calculates the station, offset, and orientation. What is the best (or easiest) method for accomplishing this?
import arcpy
class Toolbox(object):
def __init__(self):
self.label = "Station Offset toolbox"
self.alias = "StationOffset"
# List of tool classes associated with this toolbox
self.tools = [CalculateStationOffset]
class CalculateStationOffset(object):
def __init__(self):
self.label = "Calculate Station Offset"
self.description = "Calculate Station Offset"
def getParameterInfo(self):
#Define parameter definitions
# Input Features parameter
in_features = arcpy.Parameter(
displayName="Input Features",
name="in_features",
datatype="GPFeatureLayer",
parameterType="Required",
direction="Input")
in_features.filter.list = ["Point"]
# Alignment parameter
in_alignment = arcpy.Parameter(
displayName="Alignment",
name="in_alignment",
datatype="GPFeatureLayer",
parameterType="Required",
direction="Input")
in_alignment.filter.list = ["Polyline"]
# Derived Output Features parameter
out_features = arcpy.Parameter(
displayName="Output Features",
name="out_features",
datatype="GPFeatureLayer",
parameterType="Derived",
direction="Output")
out_features.parameterDependencies = [in_features.name]
out_features.schema.clone = True
parameters = [in_features, in_alignment, out_features]
return parameters
def isLicensed(self):
return True
def updateParameters(self, parameters):
if parameters[0].altered:
parameters[1].value = arcpy.ValidateFieldName(parameters[1].value, parameters[0].value)
return
def updateMessages(self, parameters):
return
def execute(self, parameters, messages):
fc_pnt = parameters[0].valueAsText
fc_line = parameters[1].valueAsText
# Fields
fields = ['SHAPE@', 'MEAS', 'Distance', 'NEAR_X', 'NEAR_Y', 'Orient', 'POINT_X', 'POINT_Y', 'NEAR_ANGLE']
# Get line geometry - assumes only one feature in feature class
polyline = arcpy.da.SearchCursor(fc_line, "SHAPE@").next()[0]
# Loop over the point feature class
with arcpy.da.UpdateCursor(fc_pnt, fields) as cursor:
for row in cursor:
dist=polyline.queryPointAndDistance(row[0], False)
row[1] = dist[1]
row[2] = dist[2]
row[3] = dist[0].centroid.X
row[4] = dist[0].centroid.Y
if dist[3] == 0:
row[5]="Left"
else:
row[5]="Right"
row[6] = row[0].centroid.X
row[7] = row[0].centroid.Y
print(dist)
cursor.updateRow(row)
Answer
It may not be pretty, but was able to get this to work using the following code:
# Loop over the point feature class
with arcpy.da.UpdateCursor(fc_pnt, fields) as cursor:
for row in cursor:
projPt = arcpy.PointGeometry(arcpy.Point(row[0].centroid.X,row[0].centroid.Y),arcpy.SpatialReference(102100)).projectAs(arcpy.SpatialReference(102736))
dist = polyline.queryPointAndDistance(projPt, False)
No comments:
Post a Comment