Python – Select Rows Without Creating New Field or Table

arcgis-10.7arcpyenterprise-geodatabaseselect-by-attributetrue-curves

ArcMap 10.7.1 — Oracle 18c SDE.ST_GEOMETRY — Polyline FC


Occasionally, we come across scenarios where we want to select rows in a FC in the attribute table, but there isn't a way to run the query using Select by Attributes — due to limitations in Oracle SQL or SDE.ST_GEOEMTRY functions.

For example:

Select features that have true curves.


While it's not possible to make that selection via SQL, it's relatively easy to find the records via ArcPy:

  • ArcMap 10.7.1:
def has_curves(geom):
    geom_orig = geom
    geom_densified = geom.densify("ANGLE", 10000, 0.174533)
    if geom_orig.pointCount != geom_densified.pointCount:
        return "Y"
    else:
        return None

In order to use Python to find features with curves, I think I would need to create a new HAS_CURVES field in the FC. Or create a parallel table to store the flag field, related to the master table via an ID.

That would work, but there are scenarios where we'd rather just select the rows in the attribute table. Instead of creating temporary data.


Is there a way to select rows using Python? (without creating new a new field or table to store a static flag)

Best Answer

Below is the code you need, you could run it in the python console, notebook, scripting tool or even from within modelbuilder in ArcGIS Pro. This will select the features with a curve, you just need to change layername.

import arcpy
layername = "cables"
oidList = list()
with arcpy.da.SearchCursor(layername,["OID@", "SHAPE@"]) as cursor:
    for row in cursor:        
        oid = row[0]
        geom = row[1]
        if geom.hasCurves:
            # Geometry has a curve so add it's objectID to the list
            oidList.append(oid)
   
if len(oidList) == 0:
    print("No curves")
else:
    # Update Selection Set on the layer object with the list of oid's 
    aprx = arcpy.mp.ArcGISProject("CURRENT")
    firstMap = aprx.listMaps()[0]
    layer = firstMap.listLayers(layername)[0]    
    layer.setSelectionSet(oidList,"NEW")

This code works as it is directly modifying the selectionset of the layer.