[gdal-dev] Fwd: Changed API for exportToGEOS

Even Rouault even.rouault at mines-paris.org
Fri Nov 8 11:04:49 PST 2013


Le vendredi 08 novembre 2013 14:52:17, Paul Meems a écrit :
> Hi all,
> 
> Sorry to bother you all again.
> We're still struggling with upgrading to GDAL and GEOS.
> When I use GDALv1.9 with GEOSv3.3.5 with our C++ application (MapWinGIS), I
> have no problems.
> The GEOS methods are still working. I've made a test to buffer a geometry.
> 
> When I upgrade to GDAL trunk (v1.11) and GEOSv3.4.2 I can't compile my
> project because of API changes.
> As mentioned before the function createFromGEOS() has now a different
> signature.
> 
> First of all why was this method changed instead of creating a new one?

Because we don't offer stability of the C++ API between major versions, that it 
wasn't thought as being used outside of GDAL code, and, due to the GEOS API, 
there's no way of implementing both methods in an elegant way (you would need 
to have the same code copied & pasted, a version with non reentrant GEOS 
symbols, and the one one with the _r symbols)

> There is a buffer and a buffer_r method.
> If the new method would have been called createFromGEOS_r() we would not
> have so much trouble.
> 
> Secondly I added GEOSContextHandle_t hGEOSCtxt =
> OGRGeometry::createGEOSContext(); before calling the changed
> createFromGEOS().
> I can compile now but GEOSBuffer() is always returning NULL.

The issue must be that you provide here a different GEOS context (the one 
you've created) than the one that was attached to your GEOS geometry when it 
was created (the global thread unsfafe GEOS context). I'm not surprised that 
GEOS doesn't appreciate that a lot.

One idea to avoid migrating your application to the _r calls would have been 
to use the global GEOS context, but unfortunatelly I've just skimmed through 
GEOS code and that context remains hidden, so I think you have no other choice 
than migrating to the _r API if you still want to use the C++ methods of GDAL 
that expose the GEOS side of things.

> 
> If the original situation cannot be restored be keeping createFromGEOS and
> creating createFromGEOS_r I need to know how I should change the rest of my
> code to make the GEOS functions work again.

If you badly need the old createFromGEOS, just incorporate its code into your 
application. Its implementation uses public GEOS API + 
OGRGeometryFactory::createFromWkb()

See 
http://trac.osgeo.org/gdal/browser/branches/1.10/gdal/ogr/ogrgeometryfactory.cpp#L1486

I wouldn't like OGR code to keep such a left-over of the past with its thread-
safety issues.

> I can try to use buffer_r and
> use the context created before. But that means I need to change a lot of
> code. Before I do that I need to know if that is solving my issue.

General methodological advice : experiment on a small test program to validate 
your ideas before changing everything blindly.

> 
> Our BufferByDistance function is now not working and probably needs to be
> changed. The source code is here:
> https://mapwingis.svn.codeplex.com/svn/MapWinGIS/trunk/COM%20classes/Shapef
> ile_Geoprocessing.cpp Our Shape2GEOSGeom() function is now calling
> createGEOSContext() and Shape2GEOSGeom is called by our BufferByDistance
> function. The code is here:
> https://mapwingis.svn.codeplex.com/svn/MapWinGIS/trunk/Processing/Geometry
> Converter.cpp
> 
> I think I need to create the context in our BufferByDistance function and
> pass it as an argument to our Shape2GEOSGeom() function. Next I should
> switch to GEOSBuffer_r and use the same context. Am I right? Is that the
> correct approach? If so I need to change the signature of our
> Shape2GEOSGeom() function which is use in a lot places. That is OK, as long
> as I know it is the solution.

The root of the issue must be with the constant switch between the global GEOS 
context and the temporary GEOS context you use for OGRGeometry::exportToGEOS() 
and OGRGeometryFactory::createFromGEOS_r().

So if you create a GEOS context with OGRGeometry::createGEOSContext(), use it 
during the whole life time of objects that will be instanciated with it and 
destroys it afterwards it should work. Basically it could have the lifetime of 
your application.

Slighlty out-of-topic : I've skimmed very quickly through your code, and I'm 
wondering why you do so many conversions : OGRGeometry -> GEOSGeometry -> 
GEOSBuffer -> GEOSGeometry -> OGRGeometry. You could just use the 
OGRGeometry::Buffer() operation instead of going through GEOS by yourself. 
OGRGeometry::Buffer() does that for you.


Hum, actually, after having written this email, I now believe that your issue 
might be more simple than that. Do you call initGEOS() at all in your 
application code ? If you don't, then the global GEOS context will not be 
initialized at all, and when reviewing GEOS code, I can see that all non _r 
methods will fail silently. You could confirm with a debug build of GEOS and 
stepping into methods. Mixing of global vs local GEOS context might perhaps 
cause issues, but more likely in more advanced situations than just 
GEOSBuffer(). So calling initGEOS() in your code might be a (not recommanded) 
trick to quick fix your immediate issues, but it could perhaps lead to subtle 
problems.

Even

-- 
Geospatial professional services
http://even.rouault.free.fr/services.html


More information about the gdal-dev mailing list