5

I am looking to erase an area in one shapefile by the area of another shapefile. After looking for as many resources as I can on this, I cannot get things to work.

def erase_shapes(self, to_erase, eraser, out_file):
    driver = ogr.GetDriverByName('ESRI Shapefile')
    feat1 = driver.Open(to_erase, 0)
    feat2 = driver.Open(eraser, 1)
    feat1Layer = feat1.GetLayer()
    feat2Layer = feat2.GetLayer()
    outDataSource = driver.CreateDataSource(out_file)

    out_ds = feat1Layer.Erase(feat1Layer, feat2Layer, outDataSource )
    out_ds = None

I am getting the following error:

ERROR 6: Only one feature iterator can be active at a time

Using:

numberVar = feat1Layer.GetFeatureCount()
numberVar = feat2Layer.GetFeatureCount()

it is confirmed that there is only 1 feature in each dataset.

When I try to add an iterator:

for feat in feat2Layer:
    out_ds = feat1Layer.Erase(feat1Layer, feat, outDataSource)
    out_ds = None

I get:

TypeError: in method 'Layer_Erase', argument 3 of type 'OGRLayerShadow *'

There is a lot of confusing information out there on how to get this to work. Any suggestions?

1
  • 1
    When posting code, don't just cut a method out of a class. Make it a complete and as runnable (as possible) example, including module imports and opening/setting of input data/variables etc.
    – user2856
    Jan 6, 2021 at 21:30

1 Answer 1

5

The Erase method signature is Erase(Layer self, Layer method_layer, Layer result_layer, optional args...)

You're doing two things incorrectly:

  1. Passing the input layer in twice, first implicitly (basic python, self is always passed to object methods, you don't explicitly pass it), then explicitly as the 1st argument;

  2. Passing a Dataset not a Layer as the result_layer argument.

Working example:

from osgeo import ogr
ogr.UseExceptions()


def erase_shapes(to_erase, eraser, out_file):
    feat1 = ogr.Open(to_erase)
    feat2 = ogr.Open(eraser)
    feat1Layer = feat1.GetLayer()
    feat2Layer = feat2.GetLayer()

    driver = ogr.GetDriverByName('ESRI Shapefile')
    outDataSource = driver.CreateDataSource(out_file)
    srs = feat1Layer.GetSpatialRef()
    outLayer = outDataSource.CreateLayer('', srs, ogr.wkbPolygon)

    out_ds = feat1Layer.Erase(feat2Layer, outLayer)
    out_ds = None

to_erase = "test1.shp"
eraser = "test2.shp"
out_file = "test3.shp"

erase_shapes(to_erase, eraser, out_file)

enter image description here

enter image description here

2
  • beauty. Thank you very much. If my eraser has multiple features, will I have to do a for loop?
    – D_C
    Jan 6, 2021 at 22:04
  • 1
    Yes the method_layer argument is a layer, not a feature so will use all features
    – user2856
    Jan 6, 2021 at 22:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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