3

I want to copy a geometry with Python OGR within a loop:

I tried the following, but I get ERROR 1: Empty geometries cannot be constructed

import ogr
import copy

d = ogr.Open('sampleData.geojson')
l = d.GetLayer()

for f in l: 
     gCurrent = f.GetGeometryRef()
     gPrevious = copy.copy(gCurrent)

I know I can't just assign gPrevious = gCurrent since it only references the geometry. But why is it trying to construct an empty geometry?

2
  • why you want to use the module copy ?
    – gene
    Commented Dec 11, 2014 at 21:23
  • No particular reason. What would you use?
    – ustroetz
    Commented Dec 11, 2014 at 21:58

3 Answers 3

3

Don't expect OGR to be Pythonic. In fact, there is a large list of gotchas documented to describe these. Essentially, all of the variables are references to objects described in C++, so they often don't make sense with workflows in Python. Modules like copy only work on Python objects, which is why your example doesn't work as expected. You need to keep references to the features and the geometries alive, not just the geometry, otherwise it will crash.

For example, here is something that will calculate the union of current and previous features, showing the area of all three geometries:

l = d.GetLayer()

fPrevious = None
for fid in range(l.GetFeatureCount()):
    fCurrent = l.GetFeature(fid)
    if fPrevious:
        gCurrent = fCurrent.GetGeometryRef()
        gPrevious = fPrevious.GetGeometryRef()
        # Do something with the two geometries
        gNew = gCurrent.Union(gPrevious)
        print("Areas: %d vs %d vs %d" % (gPrevious.GetArea(), gCurrent.GetArea(), gNew.GetArea()))
    fPrevious = fCurrent

But if, for example, outside the loop did gNew = gCurrent.Union(gPrevious) it will crash since the references to the features have changed.

1

@Mike T's post tells you about some of the caveats of using OGR, but it doesn't actually answer your main question: how can you generate a copy of an OGR geometry?

I'm not sure if this is the best way to do so, but here's a simple and generic solution:

gPrevious = ogr.CreateGeometryFromWkb(gCurrent.ExportToIsoWkb())

Now you don't have two references that just point to the same geometry in memory. Instead, you actually have two separate geometries.

1

Clone() method seems to work properly:

gPrevious = gCurrent.Clone()

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.