Skip to content

Basics

arcpie is designed to be an easy drop in alongside arcpy proper that aligns interaction with geospatial objects closer to the Python model.

Here's a simple example of summing up the total length of road in a city:

from arcpy import Polyline, Polygon
from arcpie import FeatureClass

roads = FeatureClass[Polyline]('Roads')
cities = FeatureClass[Polygon]('Cities')

for city_name, city_boundary in cities[('Name', 'SHAPE@')]:
    with roads.spatial_filter(city_boundary): # Apply a spatial filter
        road_length = sum(
            road.intersect(city, 2).length # Clip road to city limits
            for road in roads.shapes # Iterate the road shapes
        )
    print(f'{city_name} has {road_length} {roads.units} of road')

Here we accomplish quite a bit with a single simple comprehension and a flat feature iterator! Here's that same code written using base arcpy:

from arcpy.da import SearchCursor

with SearchCursor('Cities', ['Name', 'SHAPE@']) as city_cur:
    for city_name, city_boundary in city_cur: # Iterate cities
        road_length = 0.0 # Initialize road length
        road_units = None
        with SearchCursor('Roads', ['SHAPE@'], spatial_filter=city_boundary) as road_cur: # Iterate Roads
            for road, in road_cur:
                if road_units is None:
                    road_units = road.spatialReference.linearUnitName
                road_length += road.intersect(city_boundary, 2).length # Clip and add

        print(f'{city_name} has {road_length} {road_units} of road')

Lets see what else we can do with that FeatureClass object:

from arcpie import FeatureClass, RowRecord, FilterFunc, count

# Create a dynamic filter function that counts the number of
# lines in a text field
def line_count(field: str, line_count: int):
    def _inner(func: FilterFunc) -> bool:
        return len(row[field].splitlines()) == lines
    return _inner

notes = FeatureClass('FieldNotes')

print(count(notes[line_count('COMMENTS', 5)]))
# prints 50

print(count(notes[line_count('COMMENTS', 2)]))
# prints 245

Here we used a function index that allows you to define a condition for row iteration. The arcpie.count() function is just an alias for sum(1 for _ in Iterator) since all FeatureClass indexes are iterators and do not have a known length until they are exhausted.