[geos-devel] Exception Issues
David Blasby
dblasby at refractions.net
Tue May 27 16:27:24 EDT 2003
Norman,
You've got some good ideas here, I thought I'd try to summarize what
I've done so far so you dont re-invent the wheel.
<spew mode>
================================
Here's a test C++ program. It tries to relate "LINESTRING(0 0,0 0)" to
itself. This is an invalid geometry and causes an exception which is
caught. It catches an 'anonymous - "catch (...)"' exception. The
output is:
in try block
about to cause an exception
anonymous exeception
NOTE: this program is linked to both libc and libc++.
int main(int argC, char* argV[])
{
WKTReader *r = new WKTReader();
GeometryFactory *geomFactory;
Geometry *g1, *g2,*g3, *g4 ;
geomFactory= new GeometryFactory( new PrecisionModel(), -1);
try{
cout << "in try block " <<endl;
g1 = r->read("LINESTRING(0 0,0 0)");
g2 = r->read("LINESTRING(0 0,0 0)");
cout << "about to cause an exception" << endl;
IntersectionMatrix *im = g1->relate(g2);
cout << "finished relate"<< endl;
}
catch (exception e)
{
cout << "caught exception"<<endl;
cout << e.what() << endl;
}
catch (char *s)
{
cout << "caught string exception:"<<s<<endl;
}
catch (...)
{
cout << "anonymous exeception"<< endl;
}
}
=========================================
I thought that I might be able to catch exceptions if I modified the
GEOS source code. I did an experiment like this:
Added a function to the GEOS geometry.cpp like this:
void throwError()
{
cout << "about to throw an error" << endl;
try {
throw "weee an error\n";
}
catch (...)
{
cout <<"caught an error"<<endl;
}
}
Amazingly, when I call this GEOS frunction from postgis, IT CATCHES THE
ERROR!!
I was very happy with this and wrote GeometryCAPI (see attached) that
would wrap all the important GEOS functions. Unfortunately, this didnt
work. The throwError() function doesnt actually involve a
stack-unwinding, so the exceptionhandling works. If you add these 2
functions to GEOS Geometry.cpp:
void throwError2()
{
cout << "in throwError2() - about to call throwError3()" << endl;
try {
throwError3();
}
catch (...)
{
cout <<"throwError2():caught an error"<<endl;
}
}
void throwError3()
{
throw "throwError3 error";
}
This doesnt work - when you call throwError2(), a stack unwinding takes
place and a SIGABRT is caused. Double-plus-ungood.
===================================
Next we tried compiling postgresql and postgis with the -fexceptions
option. This didnt have any any effect - SIBABRT is still sent during a
stack-unwind.
===================================
My current working version (NOT commited to CVS) uses the GeometryCAPI
method of calling GEOS.
To use my version:
1. Get the most recent GEOS - if it has util/GeometryCAPI.cpp great! If
not, you'll have to add it (attached).
2. replace the postgis_geos.c and postgis_geos_wrapper.cpp in your
postgis installation.
Basically, when postgis want to do a relate, it calls
postgis_geos_wrapper.cpp::GEOSrelate(Geometry *g1, Geometry*g2). This
calls GeometryCAPI::relate(Geometry *g1, Geometry*g2). This calls the
actual GEOS relate function. All exception should be caught in the GEOS
c++ code before it gets near postgis or postgresql.
The postgis_geos_wrapper.cpp::GEOSrelate(Geometry *g1, Geometry*g2) is
very simple. NOTE: this should never encounter an exception from
GeometryCAPI - the try block here is just redunant.
char *GEOSrelate(Geometry *g1, Geometry*g2)
{
try {
char *result = geometryCAPI->relate(g1,g2);
return result;
}
catch (...)
{
return NULL;
}
}
GeometryCAPI::relate(Geometry *g1, Geometry*g2) is also simple - it
tries to catch errors thrown by GEOS. It also prints out a little bit
of debugging.
//callers responsiblity to free the char* this returns
char *GeometryCAPI::relate(Geometry *g1, Geometry*g2)
{
try {
cout << "In GeometryCAPI::relate and about to g1->relate(g2) " << endl;
IntersectionMatrix *im = g1->relate(g2);
cout << "past relate" << endl;
string s;
char *result;
if (im == NULL)
return NULL;
s= im->toString();
result = (char*) malloc( s.length() + 1);
strcpy(result, s.c_str() );
return result;
}
catch (...)
{
cout << "caught error in GeometryCAPI::relate" << endl;
return NULL;
}
}
The actual postgis function is a little more complex - but its mostly
just debugging code. It never gets past the "GEOSrelate(g1, g2);" line.
PG_FUNCTION_INFO_V1(relate_full);
Datum relate_full(PG_FUNCTION_ARGS)
{
GEOMETRY *geom1 = (GEOMETRY *)
PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
GEOMETRY *geom2 = (GEOMETRY *)
PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
Geometry *g1,*g2;
char *relate_str;
int len;
char *result;
elog(NOTICE,"in relate_full()");
errorIfGeometryCollection(geom1,geom2);
initGEOS(MAXIMUM_ALIGNOF);
elog(NOTICE,"GEOS init()");
g1 = POSTGIS2GEOS(geom1 );
g2 = POSTGIS2GEOS(geom2 );
elog(NOTICE,"constructed geometries ");
if ((g1==NULL) || (g2 == NULL))
elog(NOTICE,"g1 or g2 are null");
elog(NOTICE,GEOSasText(g1));
elog(NOTICE,GEOSasText(g2));
elog(NOTICE,"valid g1 = %i", GEOSisvalid(g1));
elog(NOTICE,"valid g2 = %i",GEOSisvalid(g2));
elog(NOTICE,"about to relate()");
relate_str = GEOSrelate(g1, g2);
elog(NOTICE,"finished relate()");
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g2);
if (relate_str == NULL)
{
//free(relate_str);
elog(ERROR,"GEOS relate() threw an error!");
PG_RETURN_NULL(); //never get here
}
len = strlen(relate_str) + 4;
result= palloc(len);
*((int *) result) = len;
memcpy(result +4, relate_str, len-4);
free(relate_str);
PG_RETURN_POINTER(result);
}
If look at the postgresql console while executing a simple query like:
select relate('LINESTRING(0 0,0 0)'::geometry,'LINESTRING(0 0,0
0)'::geometry);
You'll see something like:
[postgres at hydra init.d]$ /opt/pgsql73/bin/postmaster -i -D
/raid/pgdata/pgsql_devel_73
LOG: database system was shut down at 2003-05-27 13:12:41 PDT
LOG: checkpoint record is at 0/E955D68
LOG: redo record is at 0/E955D68; undo record is at 0/0; shutdown TRUE
LOG: next transaction id: 6708; next oid: 577113
LOG: database system is ready
NOTICE: in relate_full()
NOTICE: GEOS init()
NOTICE: constructed geometries
NOTICE: LINESTRING (0.0000000000000000 0.0000000000000000,
0.0000000000000000 0.0000000000000000)
NOTICE: LINESTRING (0.0000000000000000 0.0000000000000000,
0.0000000000000000 0.0000000000000000)
NOTICE: valid g1 = 0
NOTICE: valid g2 = 0
NOTICE: about to relate()
In GeometryCAPI::relate and about to g1->relate(g2)
LOG: server process (pid 11062) was terminated by signal 6
Signal 6 is SIGABRT.
===================================
</spew>
attached: GeometryCAPI.h (inside GEOS)
GeometryCAPI.cpp (inside GEOS)
postgis_geos_wrapper.cpp (inside postgis)
postgis_geos.c (inside postgis)
What we havent tried:
1. linking postgresql to libc++. This should work, but we dont want to
have a special 'postgis' version of postgresql hanging around.
2. removing exceptions from GEOS. This could be quite a bit of work
3. Try a newer compiler/libc
4. see if this problem occurs on other platforms.
-------------------------------------------------------
nhv at cape.com wrote:
> Our problem is that we were AFAICT never trying to catch any
> exceptions other then those defined by GEOS hence when a
> standard exception was thrown it was never caught and therefore
> the underlying C++ standard terminate() handler was called when
> a standard exception was raised.
Yes - we are trying to catch all exceptions using the "catch (...)"
symantic. I think the real problem is that the default exception
handler is supposed to pop the exception up the call stack, but the
exception handler that is in libc doesnt know how to do that and will
immediately SIGABRT.
> At a minimum this would consist of
> 1) A common PostGIS data set
> 2) The PostGIS GEOS enabled SQL query that causes the behaviour
> on this data set
select relate('LINESTRING(0 0,0 0)'::geometry,'LINESTRING(0 0,0
0)'::geometry);
If you can catch this, we should be off to the races.
Any thoughts?
dave
-------------- next part --------------
#include "geom.h"
#include "stdio.h"
#include "GeometryCAPI.h"
//---------------------------------------------------------------------------
// constructors
GeometryCAPI::GeometryCAPI(void)
{
factory = new GeometryFactory( new PrecisionModel(), -1); // NOTE: SRID will have to be changed after geometry creation
SRID = -1;
}
GeometryCAPI::GeometryCAPI(PrecisionModel *pm)
{
factory = new GeometryFactory( pm, -1); // NOTE: SRID will have to be changed after geometry creation
SRID = -1;
}
GeometryCAPI::GeometryCAPI(PrecisionModel *pm,int srid)
{
factory = new GeometryFactory( pm, SRID); // NOTE: SRID will have to be changed after geometry creation
SRID = srid;
}
//---------------------------------------------------------------------------
// geometryFactory functions
void GeometryCAPI::setSRID(Geometry *g, int srid)
{
try{
g->setSRID(srid);
}
catch (...)
{
//do nothing
}
}
Geometry *GeometryCAPI::makeBox(Envelope* envelope)
{
try{
Geometry *result =factory->toGeometry(envelope, factory->getPrecisionModel() , SRID );
return result;
}
catch (...)
{
return NULL;
}
}
Geometry *GeometryCAPI::buildGeometry(vector<Geometry *> *subGeos)
{
try{
Geometry *result =factory->buildGeometry(subGeos);
return result;
}
catch (...)
{
return NULL;
}
}
Geometry *GeometryCAPI::createPoint(Coordinate *c)
{
try{
Geometry *result =factory->createPoint(*c);
return result;
}
catch (...)
{
return NULL;
}
}
Geometry *GeometryCAPI::createMultiPolygon(vector<Geometry *> *polys)
{
try{
Geometry *result =factory->createMultiPolygon(polys);
return result;
}
catch (...)
{
return NULL;
}
}
Geometry *GeometryCAPI::createMultiLineString(vector<Geometry *> *lines)
{
try{
Geometry *result =factory->createMultiLineString(lines);
return result;
}
catch (...)
{
return NULL;
}
}
Geometry *GeometryCAPI::createMultiPoint(vector<Geometry *> *points)
{
try{
Geometry *result =factory->createMultiPoint(points);
return result;
}
catch (...)
{
return NULL;
}
}
Geometry *GeometryCAPI::createLinearRing(BasicCoordinateList *pts)
{
try{
Geometry *result =factory->createLinearRing(pts);
return result;
}
catch (...)
{
return NULL;
}
}
Geometry *GeometryCAPI::createPolygon(LinearRing *outer, vector<Geometry *> *innerRings)
{
try{
Geometry *result =factory->createPolygon(outer,innerRings);
return result;
}
catch (...)
{
return NULL;
}
}
Geometry *GeometryCAPI::createLineString(BasicCoordinateList *pts)
{
try{
Geometry *result =factory->createLineString(pts);
return result;
}
catch (...)
{
return NULL;
}
}
//---------------------------------------------------------------------------
// relate-type functions
//-----------------------------------------------------------
// relate()-related functions
// return 0 = false, 1 = true, 2 = error occured
//-----------------------------------------------------------
char GeometryCAPI::disjoint(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = g1->disjoint(g2);
if (result)
return 1;
else
return 0;
}
catch (...)
{
return 2;
}
}
char GeometryCAPI::touches(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = g1->touches(g2);
if (result)
return 1;
else
return 0;
}
catch (...)
{
return 2;
}
}
char GeometryCAPI::intersects(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = g1->intersects(g2);
if (result)
return 1;
else
return 0;
}
catch (...)
{
return 2;
}
}
char GeometryCAPI::crosses(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = g1->crosses(g2);
if (result)
return 1;
else
return 0;
}
catch (...)
{
return 2;
}
}
char GeometryCAPI::within(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = g1->within(g2);
if (result)
return 1;
else
return 0;
}
catch (...)
{
return 2;
}
}
// call g1->contains(g2)
// returns 0 = false
// 1 = true
// 2 = error was trapped
char GeometryCAPI::contains(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = g1->contains(g2);
if (result)
return 1;
else
return 0;
}
catch (...)
{
return 2;
}
}
char GeometryCAPI::overlaps(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = g1->overlaps(g2);
if (result)
return 1;
else
return 0;
}
catch (...)
{
return 2;
}
}
//-------------------------------------------------------------------
// low-level relate functions
//------------------------------------------------------------------
char GeometryCAPI::relatePattern(Geometry *g1, Geometry*g2,char *pat)
{
try {
bool result;
string s = pat;
result = g1->relate(g2,pat);
if (result)
return 1;
else
return 0;
}
catch (...)
{
return 2;
}
}
//callers responsiblity to free the char* this returns
char *GeometryCAPI::relate(Geometry *g1, Geometry*g2)
{
try {
cout << "In GeometryCAPI::relate and about to g1->relate(g2) " << endl;
IntersectionMatrix *im = g1->relate(g2);
cout << "past relate" << endl;
string s;
char *result;
if (im == NULL)
return NULL;
s= im->toString();
result = (char*) malloc( s.length() + 1);
strcpy(result, s.c_str() );
return result;
}
catch (...)
{
cout << "caught error in GeometryCAPI::relate" << endl;
return NULL;
}
}
//-----------------------------------------------------------------
// isValid
//-----------------------------------------------------------------
char GeometryCAPI::isValid(Geometry *g1)
{
try {
bool result;
result =g1->isValid();
if (result)
return 1;
else
return 0;
}
catch (...)
{
return 2;
}
}
//-----------------------------------------------------------------
// general purpose
//-----------------------------------------------------------------
//callers responsibility to free the char* result.
char *GeometryCAPI::asText(Geometry *g1)
{
try
{
string s = g1->toString();
char *result;
result = (char*) malloc( s.length() + 1);
strcpy(result, s.c_str() );
return result;
}
catch (...)
{
return NULL;
}
}
//-------------------------------------------------------------------
// memory management functions
//------------------------------------------------------------------
//BUG:: this leaks memory, but delete kills the PrecisionModel for ALL the geometries
void GeometryCAPI::deleteGeometry(Geometry *a)
{
try{
// delete a;
}
catch(...)
{
// do nothing!
}
}
void GeometryCAPI::deleteChar(char *a)
{
try{
free(a);
}
catch(...)
{
// do nothing!
}
}
-------------- next part --------------
// This is just a simple wrapper for basic geometry functions. See the
// Geometry type documentation for exact definition for these functions.
//
//
// Because some C programs might have trouble calling C++ (most notably
// postgresql, PERL, PYTHON, JAVA, etc...) when there is triple indirect
// access (postgresql -> libpostgis -> libgeos).
// A more technical discussion of this bug is at http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=37933
// Basically, if libc is loaded before libc++ exception handling might be comprimised.
//
// This class solves this problem. It basically wraps try..catch blocks around the obvious
// calls to GEOS functions.
//
// For functions that return a boolean (ie. g->isValid() or g1->disjoint(g2)), these functions
// return:
// 0 -- FALSE
// 1 -- TRUE
// 2 -- ERROR OCCURRED * usually due to invalid geometry or robustness failure
//
//
// For functions that return objects (ie. g->asText(), g1->relate(g2)), these functions
// return either the appropriate object or NULL if an error occurred.
//
//
// Usage:
// if you want to do
// g1->relate(g2);
//
// then you do:
// GeometryCAPI *capi = new GeometryCAPI();
// char result = capi->relate(g1,g2);
// if (result ==2)
// {
// //handle error
// }
//
//
// GeometryCAPI also handles geometry construction. When you create a GeometryCAPI,
// you also make a new GeometryFactory (see GeometryCAPI constructors vis-a-vis GeometryFactory).
class GeometryCAPI
{
public:
//relate() related functions - 0=false, 1=true, 2=error
char disjoint(Geometry *g1, Geometry*g2);
char touches(Geometry *g1, Geometry*g2);
char intersects(Geometry *g1, Geometry*g2);
char crosses(Geometry *g1, Geometry*g2);
char within(Geometry *g1, Geometry*g2);
char contains(Geometry *g1, Geometry*g2);
char overlaps(Geometry *g1, Geometry*g2);
char relatePattern(Geometry *g1, Geometry*g2,char *pat);
char isValid(Geometry *g1);
char *asText(Geometry *g1);
char *relate(Geometry *g1, Geometry*g2);
//memory management ERROR = no action
void deleteGeometry(Geometry *a);
void deleteChar(char *a);
//constructors
GeometryCAPI(); //make GeometryFactory( new PrecisionModel(), -1)
GeometryCAPI(PrecisionModel*); //make GeometryFactory(<PrecisionModel>, -1)
GeometryCAPI(PrecisionModel*,int); //make GeometryFactory(<PrecisionModel>, #)
// geometryFactory-type methods (c.f. GeometryFactory for what these functions do)
// returns NULL = ERROR occured
Geometry *makeBox(Envelope*); // make a polygon representing the envelope
Geometry *buildGeometry(vector<Geometry *>*); // make a geometrycollection (or multi*)
Geometry *createPoint(Coordinate *);
Geometry *createMultiPolygon(vector<Geometry *>*);
Geometry *createMultiLineString(vector<Geometry *>*);
Geometry *createMultiPoint(vector<Geometry *>*);
Geometry *createLinearRing(BasicCoordinateList*);
Geometry *createPolygon(LinearRing*, vector<Geometry *>*);
Geometry *createLineString(BasicCoordinateList*);
void setSRID(Geometry *g1, int SRID); // ERROR = no action
private:
GeometryFactory *factory;
int SRID;
};
-------------- next part --------------
// g++ postgis_GEOSwrapper.cpp -c -I/usr/local/include -I/usr/local/include/geos -I/usr/local/src/postgresql-7.2.3//src/include
#include <stdio.h>
#include <string>
#include <iostream>
#include <fstream>
//#include "geom.h"
//#include "util.h"
//#include "graph.h"
#include "io.h"
#include "GeometryCAPI.h"
//#include "opRelate.h"
//WARNING THIS *MUST* BE SET CORRECTLY.
int MAXIMUM_ALIGNOF = -999999; // to be set during initialization - this will be either 4 (intel) or 8 (sparc)
//for getting things to align properly double are on 8byte align on solaris machines, and 4bytes on intel
#define TYPEALIGN(ALIGNVAL,LEN) (((long)(LEN) + (ALIGNVAL-1)) & ~(ALIGNVAL-1))
#define MAXALIGN(LEN) TYPEALIGN(MAXIMUM_ALIGNOF, (LEN))
typedef int int32;
typedef struct
{
double x,y,z; //for lat/long x=long, y=lat
} POINT3D;
typedef struct
{
POINT3D LLB,URT; /* corner POINT3Ds on long diagonal */
} BOX3D;
typedef struct
{
int32 npoints; // how many points in the line
int32 junk; // double-word alignment
POINT3D points[1]; // array of actual points
} LINE3D;
typedef struct
{
int32 nrings; // how many rings in this polygon
int32 npoints[1]; //how many points in each ring
/* could be 4 byes of filler here to make sure points[] is
double-word aligned*/
POINT3D points[1]; // array of actual points
} POLYGON3D;
//###########################################################
extern "C" char *GEOSrelate(Geometry *g1, Geometry*g2);
extern "C" void initGEOS(int maxalign);
extern "C" void GEOSdeleteChar(char *a);
extern "C" void GEOSdeleteGeometry(Geometry *a);
extern "C" char GEOSrelatePattern(Geometry *g1, Geometry*g2,char *pat);
extern "C" char GEOSrelateDisjoint(Geometry *g1, Geometry*g2);
extern "C" char GEOSrelateTouches(Geometry *g1, Geometry*g2);
extern "C" char GEOSrelateIntersects(Geometry *g1, Geometry*g2);
extern "C" char GEOSrelateCrosses(Geometry *g1, Geometry*g2);
extern "C" char GEOSrelateWithin(Geometry *g1, Geometry*g2);
extern "C" char GEOSrelateContains(Geometry *g1, Geometry*g2);
extern "C" char GEOSrelateOverlaps(Geometry *g1, Geometry*g2);
extern "C" Geometry *PostGIS2GEOS_point(POINT3D *point,int SRID, bool is3d);
extern "C" Geometry *PostGIS2GEOS_linestring(LINE3D *line,int SRID, bool is3d);
extern "C" Geometry *PostGIS2GEOS_polygon(POLYGON3D *polygon,int SRID, bool is3d);
extern "C" Geometry *PostGIS2GEOS_multipolygon(POLYGON3D **polygons,int npolys, int SRID, bool is3d);
extern "C" Geometry *PostGIS2GEOS_multilinestring(LINE3D **lines,int nlines, int SRID, bool is3d);
extern "C" Geometry *PostGIS2GEOS_multipoint(POINT3D **points,int npoints, int SRID, bool is3d);
extern "C" Geometry *PostGIS2GEOS_box3d(BOX3D *box, int SRID);
extern "C" Geometry *PostGIS2GEOS_collection(Geometry **geoms, int ngeoms,int SRID, bool is3d);
extern "C" char GEOSisvalid(Geometry *g1);
extern "C" char *GEOSasText(Geometry *g1);
extern "C" char *throw_exception(Geometry *g);
//###########################################################
GeometryCAPI *geometryCAPI = NULL;
void initGEOS (int maxalign)
{
if (geometryCAPI == NULL)
{
geometryCAPI = new GeometryCAPI( new PrecisionModel(), -1); // NOTE: SRID will have to be changed after geometry creation
MAXIMUM_ALIGNOF = maxalign;
}
}
// ------------------------------------------------------------------------------
// geometry constuctors - return NULL if there was an error
//-------------------------------------------------------------------------------
//note: you lose the 3d from this!
Geometry *PostGIS2GEOS_box3d(BOX3D *box, int SRID)
{
try {
Geometry *g;
Envelope *envelope = new Envelope(box->LLB.x,box->URT.x ,box->LLB.y,box->URT.y);
g = geometryCAPI->makeBox(envelope);
if (g==NULL)
return NULL;
geometryCAPI->setSRID(g,SRID);
delete envelope;
return g;
}
catch (...)
{
return NULL;
}
}
Geometry *PostGIS2GEOS_collection(Geometry **geoms, int ngeoms,int SRID, bool is3d)
{
try
{
Geometry *g;
int t;
vector<Geometry *> *subGeos=new vector<Geometry *>;
for (t =0; t< ngeoms; t++)
{
subGeos->push_back(geoms[t]);
}
g = geometryCAPI->buildGeometry(subGeos);
if (g==NULL)
return NULL;
g->setSRID(SRID);
return g;
}
catch (...)
{
return NULL;
}
}
Geometry *PostGIS2GEOS_point(POINT3D *point,int SRID, bool is3d)
{
try
{
Coordinate *c;
if (is3d)
c = new Coordinate(point->x, point->y);
else
c = new Coordinate(point->x, point->y, point->z);
Geometry *g = geometryCAPI->createPoint(c);
if (g==NULL)
return NULL;
g->setSRID(SRID);
return g;
}
catch (...)
{
return NULL;
}
}
Geometry *PostGIS2GEOS_linestring(LINE3D *line,int SRID, bool is3d)
{
try{
int t;
Coordinate c;
//build coordinatelist & pre-allocate space
BasicCoordinateList *coords = new BasicCoordinateList(line->npoints);
if (is3d)
{
for (t=0;t<line->npoints;t++)
{
c.x = line->points[t].x;
c.y = line->points[t].y;
c.z = line->points[t].z;
coords->setAt( c ,t);
}
}
else //make 2d points
{
for (t=0;t<line->npoints;t++)
{
c.x = line->points[t].x;
c.y = line->points[t].y;
c.z = DoubleNotANumber;
coords->setAt( c ,t);
}
}
Geometry *g = geometryCAPI->createLineString(coords);
if (g==NULL)
return NULL;
g->setSRID(SRID);
return g;
}
catch (...)
{
return NULL;
}
}
//polygons is an array of pointers to polygons
Geometry *PostGIS2GEOS_multipolygon(POLYGON3D **polygons,int npolys, int SRID, bool is3d)
{
try
{
int t;
vector<Geometry *> *subPolys=new vector<Geometry *>;
Geometry *g;
for (t =0; t< npolys; t++)
{
subPolys->push_back(PostGIS2GEOS_polygon(polygons[t], SRID,is3d ));
}
g = geometryCAPI->createMultiPolygon(subPolys);
if (g== NULL)
return NULL;
g->setSRID(SRID);
return g;
}
catch (...)
{
return NULL;
}
}
//lines is an array of pointers to line3d
Geometry *PostGIS2GEOS_multilinestring(LINE3D **lines,int nlines, int SRID, bool is3d)
{
try
{
int t;
vector<Geometry *> *subLines =new vector<Geometry *>;
Geometry *g;
for (t =0; t< nlines; t++)
{
subLines->push_back(PostGIS2GEOS_linestring(lines[t], SRID,is3d ));
}
g = geometryCAPI->createMultiLineString(subLines);
if (g==NULL)
return NULL;
g->setSRID(SRID);
return g;
}
catch (...)
{
return NULL;
}
}
Geometry *PostGIS2GEOS_multipoint(POINT3D **points,int npoints, int SRID, bool is3d)
{
try
{
int t;
vector<Geometry *> *subPoints =new vector<Geometry *>;
Geometry *g;
for (t =0; t< npoints; t++)
{
subPoints->push_back(PostGIS2GEOS_point(points[t], SRID,is3d ));
}
g = geometryCAPI->createMultiPoint(subPoints);
if (g==NULL)
return NULL;
g->setSRID(SRID);
return g;
}
catch (...)
{
return NULL;
}
}
Geometry *PostGIS2GEOS_polygon(POLYGON3D *polygon,int SRID, bool is3d)
{
try
{
POINT3D *pts;
Coordinate c;
int ring,t;
Geometry *g;
LinearRing *outerRing;
LinearRing *innerRing;
BasicCoordinateList *cl;
int pointOffset =0; // first point that we're looking at. a POLYGON3D has all its points smooshed together
vector<Geometry *> *innerRings=new vector<Geometry *>;
pts = (POINT3D *) ( (char *)&(polygon->npoints[polygon->nrings] ) );
pts = (POINT3D *) MAXALIGN(pts);
// make outerRing
cl = new BasicCoordinateList(polygon->npoints[0]);
if (is3d)
{
for(t=0;t<polygon->npoints[0];t++)
{
c.x = pts[t].x;
c.y = pts[t].y;
c.z = pts[t].z;
cl->setAt( c ,t);
}
}
else
{
for(t=0;t<polygon->npoints[0];t++)
{
c.x = pts[t].x;
c.y = pts[t].y;
c.z = DoubleNotANumber;
cl->setAt( c ,t);
}
}
outerRing = (LinearRing*) geometryCAPI->createLinearRing(cl);
if (outerRing == NULL)
return NULL;
outerRing->setSRID(SRID);
pointOffset = polygon->npoints[0];
for(ring =1; ring< polygon->nrings; ring++)
{
cl = new BasicCoordinateList(polygon->npoints[ring]);
if (is3d)
{
for(t=0;t<polygon->npoints[ring];t++)
{
c.x = pts[t+pointOffset].x;
c.y = pts[t+pointOffset].y;
c.z = pts[t+pointOffset].z;
cl->setAt( c ,t);
}
}
else
{
for(t=0;t<polygon->npoints[ring];t++)
{
c.x = pts[t+pointOffset].x;
c.y = pts[t+pointOffset].y;
c.z = DoubleNotANumber;
cl->setAt( c ,t);
}
}
innerRing = (LinearRing *) geometryCAPI->createLinearRing(cl);
if (innerRing == NULL)
return NULL;
innerRing->setSRID(SRID);
innerRings->push_back(innerRing);
pointOffset += polygon->npoints[ring];
}
g = geometryCAPI->createPolygon(outerRing, innerRings);
if (g==NULL)
return NULL;
g->setSRID(SRID);
return g;
}
catch (...)
{
return NULL;
}
}
//-----------------------------------------------------------
// relate()-related functions
// return 0 = false, 1 = true, 2 = error occured
//-----------------------------------------------------------
char GEOSrelateDisjoint(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = geometryCAPI->disjoint(g1,g2);
return result;
}
catch (...)
{
return 2;
}
}
char GEOSrelateTouches(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = geometryCAPI->touches(g1,g2);
return result;
}
catch (...)
{
return 2;
}
}
char GEOSrelateIntersects(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = geometryCAPI->intersects(g1,g2);
return result;
}
catch (...)
{
return 2;
}
}
char GEOSrelateCrosses(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = geometryCAPI->crosses(g1,g2);
return result;
}
catch (...)
{
return 2;
}
}
char GEOSrelateWithin(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = geometryCAPI->within(g1,g2);
return result;
}
catch (...)
{
return 2;
}
}
// call g1->contains(g2)
// returns 0 = false
// 1 = true
// 2 = error was trapped
char GEOSrelateContains(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = geometryCAPI->contains(g1,g2);
return result;
}
catch (...)
{
return 2;
}
}
char GEOSrelateOverlaps(Geometry *g1, Geometry*g2)
{
try {
bool result;
result = geometryCAPI->overlaps(g1,g2);
return result;
}
catch (...)
{
return 2;
}
}
//-------------------------------------------------------------------
// low-level relate functions
//------------------------------------------------------------------
char GEOSrelatePattern(Geometry *g1, Geometry*g2,char *pat)
{
try {
bool result;
string s = pat;
result = geometryCAPI->relatePattern(g1,g2,pat);
return result;
}
catch (...)
{
return 2;
}
}
char *GEOSrelate(Geometry *g1, Geometry*g2)
{
try {
char *result = geometryCAPI->relate(g1,g2);
return result;
}
catch (...)
{
return NULL;
}
}
//-----------------------------------------------------------------
// isValid
//-----------------------------------------------------------------
char GEOSisvalid(Geometry *g1)
{
try {
bool result;
result =geometryCAPI->isValid(g1);
return result;
}
catch (...)
{
return 2;
}
}
//-----------------------------------------------------------------
// general purpose
//-----------------------------------------------------------------
char *GEOSasText(Geometry *g1)
{
try
{
char * result = geometryCAPI->asText(g1);
return result;
}
catch (...)
{
return NULL;
}
}
//-------------------------------------------------------------------
// memory management functions
//------------------------------------------------------------------
//BUG:: this leaks memory, but delete kills the PrecisionModel for ALL the geometries
void GEOSdeleteGeometry(Geometry *a)
{
try{
geometryCAPI->deleteGeometry(a);
}
catch(...)
{
// do nothing!
}
}
void GEOSdeleteChar(char *a)
{
try{
geometryCAPI->deleteChar(a);
}
catch(...)
{
// do nothing!
}
}
-------------- next part --------------
//--------------------------------------------------------------------------
//
#ifdef USE_GEOS
#include "postgres.h"
#include <math.h>
#include <float.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "fmgr.h"
#include "postgis.h"
#include "utils/elog.h"
#include "access/gist.h"
#include "access/itup.h"
#include "access/rtree.h"
#include "utils/builtins.h"
typedef struct Geometry Geometry;
extern const char * createGEOSPoint(POINT3D *pt);
extern void initGEOS(int maxalign);
extern char *GEOSrelate(Geometry *g1, Geometry*g2);
extern char GEOSrelatePattern(Geometry *g1, Geometry*g2,char *pat);
extern char GEOSrelateDisjoint(Geometry *g1, Geometry*g2);
extern char GEOSrelateTouches(Geometry *g1, Geometry*g2);
extern char GEOSrelateIntersects(Geometry *g1, Geometry*g2);
extern char GEOSrelateCrosses(Geometry *g1, Geometry*g2);
extern char GEOSrelateWithin(Geometry *g1, Geometry*g2);
extern char GEOSrelateContains(Geometry *g1, Geometry*g2);
extern char GEOSrelateOverlaps(Geometry *g1, Geometry*g2);
extern char *GEOSasText(Geometry *g1);
extern void GEOSdeleteChar(char *a);
extern void GEOSdeleteGeometry(Geometry *a);
extern Geometry *PostGIS2GEOS_point(POINT3D *point,int SRID, bool is3d);
extern Geometry *PostGIS2GEOS_linestring(LINE3D *line,int SRID, bool is3d);
extern Geometry *PostGIS2GEOS_polygon(POLYGON3D *polygon,int SRID, bool is3d);
extern Geometry *PostGIS2GEOS_multipolygon(POLYGON3D **polygons,int npolys, int SRID, bool is3d);
extern Geometry *PostGIS2GEOS_multilinestring(LINE3D **lines,int nlines, int SRID, bool is3d);
extern Geometry *PostGIS2GEOS_multipoint(POINT3D **points,int npoints, int SRID, bool is3d);
extern Geometry *PostGIS2GEOS_box3d(BOX3D *box, int SRID);
extern Geometry *PostGIS2GEOS_collection(Geometry **geoms, int ngeoms,int SRID, bool is3d);
extern char GEOSisvalid(Geometry *g1);
extern char *throw_exception(Geometry *g);
Datum relate_full(PG_FUNCTION_ARGS);
Datum relate_pattern(PG_FUNCTION_ARGS);
Datum disjoint(PG_FUNCTION_ARGS);
Datum touches(PG_FUNCTION_ARGS);
Datum intersects(PG_FUNCTION_ARGS);
Datum crosses(PG_FUNCTION_ARGS);
Datum within(PG_FUNCTION_ARGS);
Datum contains(PG_FUNCTION_ARGS);
Datum overlaps(PG_FUNCTION_ARGS);
Datum isvalid(PG_FUNCTION_ARGS);
Geometry *POSTGIS2GEOS(GEOMETRY *g);
void errorIfGeometryCollection(GEOMETRY *g1, GEOMETRY *g2);
// return a GEOS Geometry from a POSTGIS GEOMETRY
void errorIfGeometryCollection(GEOMETRY *g1, GEOMETRY *g2)
{
if ( (g1->type == COLLECTIONTYPE) || (g2->type == COLLECTIONTYPE) )
elog(ERROR,"Relate Operation called with a GEOMETRYCOLLECTION type. This is unsupported");
}
PG_FUNCTION_INFO_V1(isvalid);
Datum isvalid(PG_FUNCTION_ARGS)
{
GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
bool result;
Geometry *g1;
initGEOS(MAXIMUM_ALIGNOF);
g1 = POSTGIS2GEOS(geom1 );
result = GEOSisvalid(g1);
GEOSdeleteGeometry(g1);
if (result == 2)
{
elog(ERROR,"GEOS isvalid() threw an error!");
PG_RETURN_NULL(); //never get here
}
PG_RETURN_BOOL(result);
}
// overlaps(GEOMETRY g1,GEOMETRY g2)
// returns if GEOS::g1->overlaps(g2) returns true
// throws an error (elog(ERROR,...)) if GEOS throws an error
PG_FUNCTION_INFO_V1(overlaps);
Datum overlaps(PG_FUNCTION_ARGS)
{
GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
GEOMETRY *geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
Geometry *g1,*g2;
bool result;
errorIfGeometryCollection(geom1,geom2);
initGEOS(MAXIMUM_ALIGNOF);
g1 = POSTGIS2GEOS(geom1 );
g2 = POSTGIS2GEOS(geom2 );
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g2);
result = GEOSrelateOverlaps(g1,g2);
if (result == 2)
{
elog(ERROR,"GEOS overlaps() threw an error!");
PG_RETURN_NULL(); //never get here
}
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(contains);
Datum contains(PG_FUNCTION_ARGS)
{
GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
GEOMETRY *geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
Geometry *g1,*g2;
bool result;
errorIfGeometryCollection(geom1,geom2);
initGEOS(MAXIMUM_ALIGNOF);
g1 = POSTGIS2GEOS(geom1 );
g2 = POSTGIS2GEOS(geom2 );
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g2);
result = GEOSrelateContains(g1,g2);
if (result == 2)
{
elog(ERROR,"GEOS contains() threw an error!");
PG_RETURN_NULL(); //never get here
}
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(within);
Datum within(PG_FUNCTION_ARGS)
{
GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
GEOMETRY *geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
Geometry *g1,*g2;
bool result;
errorIfGeometryCollection(geom1,geom2);
initGEOS(MAXIMUM_ALIGNOF);
g1 = POSTGIS2GEOS(geom1 );
g2 = POSTGIS2GEOS(geom2 );
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g2);
result = GEOSrelateWithin(g1,g2);
if (result == 2)
{
elog(ERROR,"GEOS within() threw an error!");
PG_RETURN_NULL(); //never get here
}
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(crosses);
Datum crosses(PG_FUNCTION_ARGS)
{
GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
GEOMETRY *geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
Geometry *g1,*g2;
bool result;
errorIfGeometryCollection(geom1,geom2);
initGEOS(MAXIMUM_ALIGNOF);
g1 = POSTGIS2GEOS(geom1 );
g2 = POSTGIS2GEOS(geom2 );
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g2);
result = GEOSrelateCrosses(g1,g2);
if (result == 2)
{
elog(ERROR,"GEOS crosses() threw an error!");
PG_RETURN_NULL(); //never get here
}
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(intersects);
Datum intersects(PG_FUNCTION_ARGS)
{
GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
GEOMETRY *geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
Geometry *g1,*g2;
bool result;
errorIfGeometryCollection(geom1,geom2);
initGEOS(MAXIMUM_ALIGNOF);
g1 = POSTGIS2GEOS(geom1 );
g2 = POSTGIS2GEOS(geom2 );
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g2);
result = GEOSrelateIntersects(g1,g2);
if (result == 2)
{
elog(ERROR,"GEOS intersects() threw an error!");
PG_RETURN_NULL(); //never get here
}
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(touches);
Datum touches(PG_FUNCTION_ARGS)
{
GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
GEOMETRY *geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
Geometry *g1,*g2;
bool result;
errorIfGeometryCollection(geom1,geom2);
initGEOS(MAXIMUM_ALIGNOF);
g1 = POSTGIS2GEOS(geom1 );
g2 = POSTGIS2GEOS(geom2 );
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g2);
result = GEOSrelateTouches(g1,g2);
if (result == 2)
{
elog(ERROR,"GEOS touches() threw an error!");
PG_RETURN_NULL(); //never get here
}
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(disjoint);
Datum disjoint(PG_FUNCTION_ARGS)
{
GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
GEOMETRY *geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
Geometry *g1,*g2;
bool result;
errorIfGeometryCollection(geom1,geom2);
initGEOS(MAXIMUM_ALIGNOF);
g1 = POSTGIS2GEOS(geom1 );
g2 = POSTGIS2GEOS(geom2 );
result = GEOSrelateDisjoint(g1,g2);
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g2);
if (result == 2)
{
elog(ERROR,"GEOS disjoin() threw an error!");
PG_RETURN_NULL(); //never get here
}
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(relate_pattern);
Datum relate_pattern(PG_FUNCTION_ARGS)
{
GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
GEOMETRY *geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
char *patt;
bool result;
Geometry *g1,*g2;
errorIfGeometryCollection(geom1,geom2);
initGEOS(MAXIMUM_ALIGNOF);
g1 = POSTGIS2GEOS(geom1 );
g2 = POSTGIS2GEOS(geom2 );
patt = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(PG_GETARG_DATUM(2))));
result = GEOSrelatePattern(g1,g2,patt);
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g2);
pfree(patt);
if (result == 2)
{
elog(ERROR,"GEOS relate_pattern() threw an error!");
PG_RETURN_NULL(); //never get here
}
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(relate_full);
Datum relate_full(PG_FUNCTION_ARGS)
{
GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
GEOMETRY *geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
Geometry *g1,*g2;
char *relate_str;
int len;
char *result;
elog(NOTICE,"in relate_full()");
errorIfGeometryCollection(geom1,geom2);
initGEOS(MAXIMUM_ALIGNOF);
elog(NOTICE,"GEOS init()");
g1 = POSTGIS2GEOS(geom1 );
g2 = POSTGIS2GEOS(geom2 );
elog(NOTICE,"constructed geometries ");
if ((g1==NULL) || (g2 == NULL))
elog(NOTICE,"g1 or g2 are null");
elog(NOTICE,GEOSasText(g1));
elog(NOTICE,GEOSasText(g2));
elog(NOTICE,"valid g1 = %i", GEOSisvalid(g1));
elog(NOTICE,"valid g2 = %i",GEOSisvalid(g2));
elog(NOTICE,"about to relate()");
relate_str = GEOSrelate(g1, g2);
elog(NOTICE,"finished relate()");
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g2);
if (relate_str == NULL)
{
//free(relate_str);
elog(ERROR,"GEOS relate() threw an error!");
PG_RETURN_NULL(); //never get here
}
len = strlen(relate_str) + 4;
result= palloc(len);
*((int *) result) = len;
memcpy(result +4, relate_str, len-4);
free(relate_str);
PG_RETURN_POINTER(result);
}
//BBOXONLYTYPE -> returns as a 2d polygon
Geometry *POSTGIS2GEOS(GEOMETRY *g)
{
POINT3D *pt;
LINE3D *line;
POLYGON3D *poly;
POLYGON3D **polys;
LINE3D **lines;
POINT3D **points;
Geometry **geoms;
Geometry *geos;
char *obj;
int obj_type;
int t;
Geometry *result;
int32 *offsets1 = (int32 *) ( ((char *) &(g->objType[0] ))+ sizeof(int32) * g->nobjs ) ;
switch(g->type)
{
case POINTTYPE:
pt = (POINT3D*) ((char *) g +offsets1[0]) ;
result = PostGIS2GEOS_point(pt,g->SRID,g->is3d);
if (result == NULL)
{
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
}
return result;
break;
case LINETYPE:
line = (LINE3D*) ((char *) g +offsets1[0]) ;
result = PostGIS2GEOS_linestring(line,g->SRID,g->is3d);
if (result == NULL)
{
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
}
return result;
break;
case POLYGONTYPE:
poly = (POLYGON3D*) ((char *) g +offsets1[0]) ;
result = PostGIS2GEOS_polygon(poly,g->SRID,g->is3d);
if (result == NULL)
{
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
}
return result;
break;
case MULTIPOLYGONTYPE:
//make an array of POLYGON3Ds
polys = (POLYGON3D**) palloc(sizeof (POLYGON3D*) * g->nobjs);
for (t=0;t<g->nobjs;t++)
{
polys[t] = (POLYGON3D*) ((char *) g +offsets1[t]) ;
}
geos= PostGIS2GEOS_multipolygon(polys, g->nobjs, g->SRID,g->is3d);
pfree(polys);
if (geos == NULL)
{
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
}
return geos;
break;
case MULTILINETYPE:
//make an array of POLYGON3Ds
lines = (LINE3D**) palloc(sizeof (LINE3D*) * g->nobjs);
for (t=0;t<g->nobjs;t++)
{
lines[t] = (LINE3D*) ((char *) g +offsets1[t]) ;
}
geos= PostGIS2GEOS_multilinestring(lines, g->nobjs, g->SRID,g->is3d);
pfree(lines);
if (geos == NULL)
{
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
}
return geos;
break;
case MULTIPOINTTYPE:
//make an array of POINT3Ds
points = (POINT3D**) palloc(sizeof (POINT3D*) * g->nobjs);
for (t=0;t<g->nobjs;t++)
{
points[t] = (POINT3D*) ((char *) g +offsets1[t]) ;
}
geos= PostGIS2GEOS_multipoint(points, g->nobjs,g->SRID,g->is3d);
pfree(points);
if (geos == NULL)
{
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
}
return geos;
break;
case BBOXONLYTYPE:
result = PostGIS2GEOS_box3d(&g->bvol, g->SRID);
if (result == NULL)
{
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
}
return result;
break;
case COLLECTIONTYPE:
//make an array of GEOS Geometrys
geoms = (Geometry**) palloc(sizeof (Geometry*) * g->nobjs);
for (t=0;t<g->nobjs;t++)
{
obj = ((char *) g +offsets1[t]);
obj_type = g->objType[t];
switch (obj_type)
{
case POINTTYPE:
pt = (POINT3D*) obj ;
geoms[t] = PostGIS2GEOS_point(pt,g->SRID,g->is3d);
if (geoms[t] == NULL)
{
pfree(geoms);
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
return NULL;
}
break;
case LINETYPE:
line = (LINE3D*) obj ;
geoms[t] = PostGIS2GEOS_linestring(line,g->SRID,g->is3d);
if (geoms[t] == NULL)
{
pfree(geoms);
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
return NULL;
}
break;
case POLYGONTYPE:
poly = (POLYGON3D*) obj ;
geoms[t] = PostGIS2GEOS_polygon(poly,g->SRID,g->is3d);
if (geoms[t] == NULL)
{
pfree(geoms);
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
return NULL;
}
break;
}
}
geos= PostGIS2GEOS_collection(geoms,g->nobjs,g->SRID,g->is3d);
pfree(geoms);
if (geos == NULL)
{
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
}
return geos;
break;
}
return NULL;
}
//----------------------------------------------------------------------------
// NULL implementation here
// ---------------------------------------------------------------------------
#else
#include "postgres.h"
#include <math.h>
#include <float.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "fmgr.h"
Datum relate_full(PG_FUNCTION_ARGS);
Datum relate_pattern(PG_FUNCTION_ARGS);
Datum disjoint(PG_FUNCTION_ARGS);
Datum touches(PG_FUNCTION_ARGS);
Datum intersects(PG_FUNCTION_ARGS);
Datum crosses(PG_FUNCTION_ARGS);
Datum within(PG_FUNCTION_ARGS);
Datum contains(PG_FUNCTION_ARGS);
Datum overlaps(PG_FUNCTION_ARGS);
Datum isvalid(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(relate_full);
Datum relate_full(PG_FUNCTION_ARGS)
{
elog(ERROR,"relate_full:: operation not implemented - compile PostGIS with GEOS support");
PG_RETURN_NULL(); // never get here
}
PG_FUNCTION_INFO_V1(relate_pattern);
Datum relate_pattern(PG_FUNCTION_ARGS)
{
elog(ERROR,"relate_pattern:: operation not implemented - compile PostGIS with GEOS support");
PG_RETURN_NULL(); // never get here
}
PG_FUNCTION_INFO_V1(disjoint);
Datum disjoint(PG_FUNCTION_ARGS)
{
elog(ERROR,"disjoint:: operation not implemented - compile PostGIS with GEOS support");
PG_RETURN_NULL(); // never get here
}
PG_FUNCTION_INFO_V1(intersects);
Datum intersects(PG_FUNCTION_ARGS)
{
elog(ERROR,"intersects:: operation not implemented - compile PostGIS with GEOS support");
PG_RETURN_NULL(); // never get here
}
PG_FUNCTION_INFO_V1(touches);
Datum touches(PG_FUNCTION_ARGS)
{
elog(ERROR,"touches:: operation not implemented - compile PostGIS with GEOS support");
PG_RETURN_NULL(); // never get here
}
PG_FUNCTION_INFO_V1(crosses);
Datum crosses(PG_FUNCTION_ARGS)
{
elog(ERROR,"crosses:: operation not implemented - compile PostGIS with GEOS support");
PG_RETURN_NULL(); // never get here
}
PG_FUNCTION_INFO_V1(within);
Datum within(PG_FUNCTION_ARGS)
{
elog(ERROR,"within:: operation not implemented - compile PostGIS with GEOS support");
PG_RETURN_NULL(); // never get here
}
PG_FUNCTION_INFO_V1(contains);
Datum contains(PG_FUNCTION_ARGS)
{
elog(ERROR,"contains:: operation not implemented - compile PostGIS with GEOS support");
PG_RETURN_NULL(); // never get here
}
PG_FUNCTION_INFO_V1(overlaps);
Datum overlaps(PG_FUNCTION_ARGS)
{
elog(ERROR,"overlaps:: operation not implemented - compile PostGIS with GEOS support");
PG_RETURN_NULL(); // never get here
}
PG_FUNCTION_INFO_V1(isvalid);
Datum isvalid(PG_FUNCTION_ARGS)
{
elog(ERROR,"isvalid:: operation not implemented - compile PostGIS with GEOS support");
PG_RETURN_NULL(); // never get here
}
#endif
More information about the geos-devel
mailing list