0

I am learning to work with the geometry objects included in ArcPy. I'm really interested in using them since I don't want to create files at all since most of the data I'm going to use is just mere intermediaries. Reading the documentation I was able to discover that according to them they say an ArcPy Geometry object can be used together with the geoprocessing tools. I have tried this and it is really very interesting to be able to use these objects instead of writing files, the main problem is that not all the tools work (or at least I can't make them work). More specifically the FeatureClassToNumpyArray() function, which when passing Polyline ArcPy object returns me the following error: 'in_table' is not a table or a featureclass. I get the same error when I try to use searchCursor(), and I would like to know if it is possible to use some of the previous two functions (or if there is another efficient way) to obtain a numpy array of points through a Polyline () object.

2
  • You could try creating an in-memory dataset with mem_fc = arcpy.CopyFeatures_management([polyline0, polyline1], 'in_memory/test') then feeding that in. However since you won't have any attributes anyway, you could also just loop over the vertices of the geometry objects themselves to manually construct your numpy array
    – mikewatt
    Jun 17 '21 at 17:46
  • @mikewatt really what I want to store is the output of "contourLists" (which by the way, it would be great if it accepted a tin as input, since I have to previously convert the tin to raster, maybe it is not the best approach), the first thing I tried as you Well it indicates it was to use the "in_memory" space, however, when I stored the contour list there, the generated contours do not have the "Shape_Lenght" field and it is precisely one of the fields that I need to extract when I pass it to "contourList". For this reason I got rid of that idea. Jun 18 '21 at 10:52
1

You can see the official docs for how to extract Point() objects from geometries. Using that to create numpy arrays would look something like this:

polylines = arcpy.CopyFeatures_management('polyline_fc', arcpy.Geometry())

for geom in polylines:
    coords = []
    for point in geom.getPart(0):
        coords.append((point.X, point.Y))
    array = np.array(coords)
    print(array)

For giggles lets try another approach that parses the well-known binary representation:

import numpy as np

polylines = arcpy.CopyFeatures_management('polyline_fc', arcpy.Geometry())

for geom in polylines:
    buff = geom.WKB

    dtype_struct = np.dtype([('byteOrder', np.byte), ('wkbType', np.uint32), ('numPoints', np.uint32)])
    array_struct = np.frombuffer(buff[:dtype_struct.itemsize], dtype_struct)

    assert array_struct['byteOrder'] == 1
    assert array_struct['wkbType'] == 2

    array_points = np.frombuffer(buff[dtype_struct.itemsize:], np.float64).reshape((-1, 2))

    print(array_points)

If you do away with the validation it boils down to:

for geom in polylines:
    array = np.frombuffer(geom.WKB[9:], np.float64).reshape((-1, 2))

WKB reference: https://www.ibm.com/docs/en/ias?topic=formats-well-known-binary-wkb-representation

6
  • Thank you very much for the demonstration. I knew that I could extract the coordinates one by one, however, I don't know if by having to construct the coordinates one by one I lose the speed improvement that I gained by storing the output of "contourList" in a python object instead of in a file . I really don't understand how they don't provide an easier way to pass geometry objects to numpy and I would like to know why it's not possible to use "FeatureClassToNumpyArray" since I can use other tools, which is a shame. Thanks again for answering me Jun 18 '21 at 11:05
  • No problem. I think only the ESRI devs can answer that one, but perhaps because FeatureClassToNumpyArray is geared towards converting tabular data into numpy format they didn't bother to accept straight geometry objects. However my 2nd example shows how to bypass the one-by-one point unpacking if that's your goal
    – mikewatt
    Jun 18 '21 at 16:32
  • There's also no way to store the coordinates from multiple polyline geometries in a single numpy array, because they likely have different numbers of vertices. And in numpy arrays all of the fields must be the same size. So there's no avoiding having to unpack each polyline into an individual numpy array
    – mikewatt
    Jun 18 '21 at 16:37
  • I have been testing your suggestions and they work really well, however I am facing the following problem: Since the output of contourLists () is a collection of polylines that I must filter, until now what I did was group the lines based on the "Contour" field that is generated by default when using this tool and then keep only the polyline that present the longest length for each group and then I pass them to points. Jun 20 '21 at 13:31
  • The problem is that while the "Shape_Length" field can be easily obtained using geom.length, the "Contour" field that is generated when I write the output of contourList () in a file is not generated (or at least not I know how to access it) when I use arcpy objects. Is there a way to maintain that field? If you think it is the reason for a new question, please say so without problems. Thanks, as always. @mikewatt Jun 20 '21 at 13:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.