My question involves handling data types, particularly of strings, points and tuples. I start with a single object (I think I can say feature object as it has geometry on top of other attributes) selected by location in a feature layer. I then try to access a point geometry from that object using the SHAPE@TRUECENTROID token within a arcpy.da.SearchCurser() method and set that Point Geometry equal to a variable. I then call that variable within the queryPointAndDistance() function as my input Point or PointGeometry, but Arcpy gives me the following at the end of the error message error.
File "<expression>", line 1, in <module> File "<string>", line 22, in Strike ValueError: (612744.9906049052, 3417217.9973794315)
It appear that it does not recognize my function as either a Point or PointGeometry. Where does the output from the curser function become something different (a different type perhaps)?
This post python - ArcPy QueryPointAndDistance: Incorrect Lengths? - Stack Overflow suggested to me that by setting a variable equal to a SearchCurser, that variable would equal the geometry object specified. Is there any difference between the logic used there when the he gets the line geometry and what I am doing that I did not catch?
The problematic part of the code is as follows:
If it helps answer the question, this script is within a def in the codeblock of a CalculateField_management() method so 'shape' = the geometry of the record being calculated, and PairedCheck6 is my feature layer with one selected record.
codeblock = """def Strike(shape, seed, fid):
# PairedCheck6 = feature layer with single selection
cursorResult = arcpy.da.SearchCursor('PairedCheck6','SHAPE@TRUECENTROID').next()[0]
centroid = None
if len(cursorResult) > 0:
centroid = cursorResult
else:
return '5000'
(pointGeometry, distance, minDistance, isCentroidRight) = shape.queryPointAndDistance( centroid, False)"""
I can show more of the code if requested, but I did not want to ask anyone to look through more than is required.
Solved! Go to Solution.
This is a datatype issue. According to SearchCursor—Help | ArcGIS Desktop :
SHAPE@TRUECENTROID —A tuple of the feature's true centroid x,y coordinates.
The token you are using with the Search Cursor isn't returning a geometry, it is returning a Python tuple. You will need to turn that Python tuple of coordinates into a PointGeometry—Help | ArcGIS Desktop . Something along the lines of:
SR = # arcpy spatial reference object
ptg = PointGeometry(arcpy.Point(*centroid), SR)
This is a datatype issue. According to SearchCursor—Help | ArcGIS Desktop :
SHAPE@TRUECENTROID —A tuple of the feature's true centroid x,y coordinates.
The token you are using with the Search Cursor isn't returning a geometry, it is returning a Python tuple. You will need to turn that Python tuple of coordinates into a PointGeometry—Help | ArcGIS Desktop . Something along the lines of:
SR = # arcpy spatial reference object
ptg = PointGeometry(arcpy.Point(*centroid), SR)
simple point* geometries can also be more readily obtained using
SHAPE@XY etc http://desktop.arcgis.com/en/arcmap/latest/analyze/python/writing-geometries.htm
or even SHAPE@X and ...@Y as well. For point objects, obviously it shouldn't matter which you use, but what is returned depends depends on how you call it
flds = ['OBJECTID', 'SHAPE@TRUECENTROID']
args = [in_fc, flds, None, None, False, (None, None)]
cur = arcpy.da.SearchCursor(*args)
a = cur._as_narray()
a[0]
(1, [340005.73319999967, 5024293.363399999])
flds = ['OBJECTID', 'SHAPE@X', 'SHAPE@Y']
args = [in_fc, flds, None, None, False, (None, None)]
cur = arcpy.da.SearchCursor(*args)
a = cur._as_narray()
a[0]
(1, 340005.73319999967, 5024293.363399999)
I thought that I might have fixed it for a moment. You can put either a point or a PointGeometry into into the queryPointAndDistance(in_point) according to PointGeometry—ArcPy Classes | ArcGIS Desktop. However, when I create either one, it gives the ValueError message for my point/PointGeometry.
cursorResult = arcpy.da.SearchCursor('PairedCheck6','SHAPE@TRUECENTROID').next()[0]
centroid = None
if len(cursorResult) > 0:
centroid = cursorResult
ptg = arcpy.Point(*centroid)
else:
return '5000'
(pointGeometry, distance, minDistance, isCentroidRight) = shape.queryPointAndDistance( ptg, False)
Traceback (most recent call last): File "<expression>", line 1, in <module> File "<string>", line 23, in Strike ValueError: <Point (612744.990605, 3417217.99738, #, #)> Failed to execute (CalculateField).
This is the entire error code, although I think that the above is the important part.
Runtime error Traceback (most recent call last): File "<string>", line 49, in <module> File "c:\program files (x86)\arcgis\desktop10.4\arcpy\arcpy\management.py", line 3360, in CalculateField raise e ExecuteError: ERROR 000539: Error running expression: Strike( GPVARIANTOBJECT0, 124, 1 ) Traceback (most recent call last): File "<expression>", line 1, in <module> File "<string>", line 23, in Strike ValueError: <Point (612744.990605, 3417217.99738, #, #)> Failed to execute (CalculateField).
cursorResult = arcpy.da.SearchCursor('PairedCheck6','SHAPE@TRUECENTROID').next()[0]
centroid = None
if len(cursorResult) > 0:
centroid = cursorResult
inTable = # My shapefile
spatialRef = arcpy.Describe(inTable).spatialReference
ptg = arcpy.PointGeometry(arcpy.Point(*centroid), spatialRef)
else:
return '5000'
(pointGeometry, distance, minDistance, isCentroidRight) = shape.queryPointAndDistance( ptg, False)
Traceback (most recent call last): File "<expression>", line 1, in <module> File "<string>", line 26, in Strike ValueError: <PointGeometry object at 0xedb99b0[0xedb9140]> Failed to execute (CalculateField).
I am wondering if there is something wrong with the original spatial reference of my data, as when I had originally found the reference by describing my feature class.
inTable = #my shapefile
spatialRef = arcpy.Describe(inTable).spatialReference
# Print the spatial reference name
print spatialRef.name
# returns: unnamed
However, this might be getting beyond the scope of my original question as it is no longer about how to make my input a Point, but why my input point does not work.
you should always define the coordinate system before working with geometries. If you know what it is, use the define project tool then retry. Unknown is not the same as None. If you don't use a defined SR, then geometry values will be in error... minor, but there is no record of the geoprocessing engine having been fixed (unless someone wants to point me to the official documentation)
Turns out it was the shape in the
shape.queryPointAndDistance(ptg, False)
that was wrong. I had to make a new geometry object by selecting the record and putting it into a FeatureLayer ( MakeFeatureLayer_management() ), then copy that record as a geomentry object using ( CopyFeatures_management() ). I then had to select that one object to take it out of the array (I think) so that I ended up with shapeG as my polyline geometry.
codeblock = """def Strike(shape, seed, fid):
arcpy.MakeFeatureLayer_management("my shapefile", 'shapelyr', '"FID" ='+str(fid))
g = arcpy.Geometry()
geometryList = arcpy.CopyFeatures_management('shapelyr', g)
shapeG = geometryList[0]
cursorResult = arcpy.da.SearchCursor('PairedCheck6','SHAPE@TRUECENTROID').next()[0]
centroid = None
if len(cursorResult) > 0:
centroid = cursorResult
ptg = arcpy.Point(*centroid)
else:
return '5000'
(pointGeometry, distance, minDistance, isCentroidRight) = shapeG.queryPointAndDistance( ptg, False)
Not sure whose answer I should mark as correct now.