[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