PostGIS  2.1.10dev-r@@SVN_REVISION@@
lwgeom_backend_api.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * Wrapper around external librairies functions (GEOS/CGAL...)
7  *
8  * Copyright 2012-2013 Oslandia <infos@oslandia.com>
9  *
10  * This is free software; you can redistribute and/or modify it under
11  * the terms of the GNU General Public Licence. See the COPYING file.
12  *
13  **********************************************************************/
14 
15 #include "postgres.h"
16 #include "fmgr.h"
17 #include "../liblwgeom/liblwgeom.h"
18 
19 /* for custom variables */
20 #include "utils/guc.h"
21 
22 #include "../postgis_config.h"
23 #include "lwgeom_backend_api.h"
24 #include "lwgeom_geos.h"
25 #if HAVE_SFCGAL
26 #include "lwgeom_sfcgal.h"
27 #endif
28 
29 Datum intersects(PG_FUNCTION_ARGS);
30 Datum intersects3d(PG_FUNCTION_ARGS);
31 Datum intersection(PG_FUNCTION_ARGS);
32 Datum area(PG_FUNCTION_ARGS);
33 Datum distance(PG_FUNCTION_ARGS);
34 Datum distance3d(PG_FUNCTION_ARGS);
35 
36 Datum intersects3d_dwithin(PG_FUNCTION_ARGS);
37 
38 
40 {
41  const char* name;
42  Datum (*intersects_fn) (PG_FUNCTION_ARGS);
43  Datum (*intersects3d_fn) (PG_FUNCTION_ARGS);
44  Datum (*intersection_fn) (PG_FUNCTION_ARGS);
45  Datum (*area_fn) (PG_FUNCTION_ARGS);
46  Datum (*distance_fn) (PG_FUNCTION_ARGS);
47  Datum (*distance3d_fn) (PG_FUNCTION_ARGS);
48 };
49 
50 #if HAVE_SFCGAL
51 #define LWGEOM_NUM_BACKENDS 2
52 #else
53 #define LWGEOM_NUM_BACKENDS 1
54 #endif
55 
57  { .name = "geos",
58  .intersects_fn = geos_intersects,
59  .intersects3d_fn = intersects3d_dwithin,
60  .intersection_fn = geos_intersection,
61  .area_fn = LWGEOM_area_polygon,
62  .distance_fn = LWGEOM_mindistance2d,
63  .distance3d_fn = LWGEOM_mindistance3d
64  },
65 #if HAVE_SFCGAL
66  { .name = "sfcgal",
67  .intersects_fn = sfcgal_intersects,
68  .intersects3d_fn = sfcgal_intersects3D,
69  .intersection_fn = sfcgal_intersection,
70  .area_fn = sfcgal_area,
71  .distance_fn = sfcgal_distance,
72  .distance3d_fn = sfcgal_distance3D
73  }
74 #endif
75 };
76 
77 
78 /* Geometry Backend */
80 struct lwgeom_backend_definition* lwgeom_backend = &lwgeom_backends[0];
81 
82 #if POSTGIS_PGSQL_VERSION >= 91
83 static void lwgeom_backend_switch( const char* newvalue, void* extra )
84 {
85  int i;
86 
87  if (!newvalue) { return; }
88 
89  for ( i = 0; i < LWGEOM_NUM_BACKENDS; ++i ) {
90  if ( !strcmp(lwgeom_backends[i].name, newvalue) ) {
91  lwgeom_backend = &lwgeom_backends[i];
92  return;
93  }
94  }
95  lwerror("Can't find %s geometry backend", newvalue );
96 }
97 #else
98 static const char * lwgeom_backend_switch( const char* newvalue, bool doit, GucSource source )
99 {
100  int i;
101 
102  if (!newvalue)
103  return NULL;
104 
105  for (i = 0; i < LWGEOM_NUM_BACKENDS; ++i)
106  {
107  if (!strcmp(lwgeom_backends[i].name, newvalue))
108  {
109  lwgeom_backend = &lwgeom_backends[i];
110  return newvalue;
111  }
112  }
113  lwerror("Can't find %s geometry backend", newvalue );
114  return NULL;
115 }
116 #endif
117 
119 {
120  DefineCustomStringVariable( "postgis.backend", /* name */
121  "Sets the PostGIS Geometry Backend.", /* short_desc */
122  "Sets the PostGIS Geometry Backend (allowed values are 'geos' or 'sfcgal')", /* long_desc */
123  &lwgeom_backend_name, /* valueAddr */
124  (char *)lwgeom_backends[0].name, /* bootValue */
125  PGC_USERSET, /* GucContext context */
126  0, /* int flags */
127 #if POSTGIS_PGSQL_VERSION >= 91
128  NULL, /* GucStringCheckHook check_hook */
129 #endif
130  lwgeom_backend_switch, /* GucStringAssignHook assign_hook */
131  NULL /* GucShowHook show_hook */
132  );
133 }
134 
136 Datum intersects(PG_FUNCTION_ARGS)
137 {
138  return (*lwgeom_backend->intersects_fn)( fcinfo );
139 }
140 
142 Datum intersection(PG_FUNCTION_ARGS)
143 {
144  return (*lwgeom_backend->intersection_fn)( fcinfo );
145 }
146 
148 Datum area(PG_FUNCTION_ARGS)
149 {
150  return (*lwgeom_backend->area_fn)( fcinfo );
151 }
152 
154 Datum distance(PG_FUNCTION_ARGS)
155 {
156  return (*lwgeom_backend->distance_fn)( fcinfo );
157 }
158 
160 Datum distance3d(PG_FUNCTION_ARGS)
161 {
162  return (*lwgeom_backend->distance3d_fn)( fcinfo );
163 }
164 
166 Datum intersects3d(PG_FUNCTION_ARGS)
167 {
168  return (*lwgeom_backend->intersects3d_fn)( fcinfo );
169 }
170 
171 
172 
173 /* intersects3d through dwithin
174  * used by the 'geos' backend
175  */
177 Datum intersects3d_dwithin(PG_FUNCTION_ARGS)
178 {
179  double mindist;
180  GSERIALIZED *geom1 = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
181  GSERIALIZED *geom2 = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
182  LWGEOM *lwgeom1 = lwgeom_from_gserialized(geom1);
183  LWGEOM *lwgeom2 = lwgeom_from_gserialized(geom2);
184 
185  if (lwgeom1->srid != lwgeom2->srid)
186  {
187  elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
188  PG_RETURN_NULL();
189  }
190 
191  mindist = lwgeom_mindistance3d_tolerance(lwgeom1,lwgeom2,0.0);
192 
193  PG_FREE_IF_COPY(geom1, 0);
194  PG_FREE_IF_COPY(geom2, 1);
195  /*empty geometries cases should be right handled since return from underlying
196  functions should be MAXFLOAT which causes false as answer*/
197  PG_RETURN_BOOL(0.0 == mindist);
198 }
Datum(* distance_fn)(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(intersects)
Datum distance3d(PG_FUNCTION_ARGS)
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Datum area(PG_FUNCTION_ARGS)
Datum intersects3d_dwithin(PG_FUNCTION_ARGS)
Datum LWGEOM_mindistance3d(PG_FUNCTION_ARGS)
char * lwgeom_backend_name
Datum sfcgal_distance3D(PG_FUNCTION_ARGS)
Datum intersection(PG_FUNCTION_ARGS)
int32_t srid
Definition: liblwgeom.h:355
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
void lwgeom_init_backend()
Datum(* distance3d_fn)(PG_FUNCTION_ARGS)
Datum intersects(PG_FUNCTION_ARGS)
Datum sfcgal_intersects3D(PG_FUNCTION_ARGS)
#define POSTGIS_PGSQL_VERSION
Definition: sqldefines.h:9
Datum(* intersects3d_fn)(PG_FUNCTION_ARGS)
struct lwgeom_backend_definition * lwgeom_backend
Datum intersects3d(PG_FUNCTION_ARGS)
Datum(* area_fn)(PG_FUNCTION_ARGS)
Datum distance(PG_FUNCTION_ARGS)
Datum sfcgal_intersects(PG_FUNCTION_ARGS)
Datum LWGEOM_area_polygon(PG_FUNCTION_ARGS)
#define LWGEOM_NUM_BACKENDS
Datum geos_intersects(PG_FUNCTION_ARGS)
static void lwgeom_backend_switch(const char *newvalue, void *extra)
Datum LWGEOM_mindistance2d(PG_FUNCTION_ARGS)
Datum sfcgal_distance(PG_FUNCTION_ARGS)
Datum sfcgal_intersection(PG_FUNCTION_ARGS)
Datum sfcgal_area(PG_FUNCTION_ARGS)
Datum(* intersection_fn)(PG_FUNCTION_ARGS)
Datum(* intersects_fn)(PG_FUNCTION_ARGS)
double lwgeom_mindistance3d_tolerance(LWGEOM *lw1, LWGEOM *lw2, double tolerance)
Function handling 3d min distance calculations and dwithin calculations.
Definition: measures3d.c:164
Datum geos_intersection(PG_FUNCTION_ARGS)
struct lwgeom_backend_definition lwgeom_backends[LWGEOM_NUM_BACKENDS]