28 #include "../postgis_config.h"
33 #include "utils/array.h"
34 #include "utils/builtins.h"
35 #include "utils/lsyscache.h"
36 #include "utils/numeric.h"
37 #include "access/htup_details.h"
52 Datum
touches(PG_FUNCTION_ARGS);
54 Datum
crosses(PG_FUNCTION_ARGS);
56 Datum
within(PG_FUNCTION_ARGS);
58 Datum
covers(PG_FUNCTION_ARGS);
93 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
94 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
95 const GSERIALIZED *geom1 = shared_gserialized_get(shared_geom1);
96 const GSERIALIZED *geom2 = shared_gserialized_get(shared_geom2);
105 PG_RETURN_BOOL(
false);
115 PG_RETURN_BOOL(
false);
125 SHARED_GSERIALIZED *shared_gpoly =
is_poly(geom1) ? shared_geom1 : shared_geom2;
126 SHARED_GSERIALIZED *shared_gpoint =
is_point(geom1) ? shared_geom1 : shared_geom2;
127 const GSERIALIZED *gpoint = shared_gserialized_get(shared_gpoint);
140 GEOSGeometry *g = prep_cache->
gcache.argnum == 1
149 GEOSGeometry *g1, *g2;
151 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
155 GEOSGeom_destroy(g1);
158 result = GEOSIntersects(g1, g2);
159 GEOSGeom_destroy(g1);
160 GEOSGeom_destroy(g2);
172 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
173 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
174 const GSERIALIZED *geom1 = shared_gserialized_get(shared_geom1);
175 const GSERIALIZED *geom2 = shared_gserialized_get(shared_geom2);
178 GEOSGeometry *g1, *g2;
184 PG_RETURN_BOOL(
true);
195 PG_RETURN_BOOL(
false);
203 if (VARSIZE(geom1) == VARSIZE(geom2) && !memcmp(geom1, geom2, VARSIZE(geom1))) {
204 PG_RETURN_BOOL(
true);
210 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
214 GEOSGeom_destroy(g1);
217 result = GEOSEquals(g1, g2);
218 GEOSGeom_destroy(g1);
219 GEOSGeom_destroy(g2);
231 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
232 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
233 const GSERIALIZED *geom1 = shared_gserialized_get(shared_geom1);
234 const GSERIALIZED *geom2 = shared_gserialized_get(shared_geom2);
243 PG_RETURN_BOOL(
false);
254 PG_RETURN_BOOL(
false);
263 GEOSGeometry *g = prep_cache->
gcache.argnum == 1
272 GEOSGeometry *g1, *g2;
274 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
278 GEOSGeom_destroy(g1);
281 result = GEOSTouches(g1, g2);
282 GEOSGeom_destroy(g1);
283 GEOSGeom_destroy(g2);
295 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
296 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
297 const GSERIALIZED *geom1 = shared_gserialized_get(shared_geom1);
298 const GSERIALIZED *geom2 = shared_gserialized_get(shared_geom2);
307 PG_RETURN_BOOL(
true);
318 PG_RETURN_BOOL(
true);
327 GEOSGeometry *g = prep_cache->
gcache.argnum == 1
336 GEOSGeometry *g1, *g2;
338 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
342 GEOSGeom_destroy(g1);
345 result = GEOSDisjoint(g1, g2);
346 GEOSGeom_destroy(g1);
347 GEOSGeom_destroy(g2);
363 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
364 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
365 const GSERIALIZED *geom1 = shared_gserialized_get(shared_geom1);
366 const GSERIALIZED *geom2 = shared_gserialized_get(shared_geom2);
375 PG_RETURN_BOOL(
false);
386 PG_RETURN_BOOL(
false);
395 GEOSGeometry *g = prep_cache->
gcache.argnum == 1
404 GEOSGeometry *g1, *g2;
406 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
410 GEOSGeom_destroy(g1);
413 result = GEOSOverlaps(g1, g2);
414 GEOSGeom_destroy(g1);
415 GEOSGeom_destroy(g2);
430 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
431 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
432 const GSERIALIZED *geom1 = shared_gserialized_get(shared_geom1);
433 const GSERIALIZED *geom2 = shared_gserialized_get(shared_geom2);
442 PG_RETURN_BOOL(
false);
453 PG_RETURN_BOOL(
false);
462 GEOSGeometry *g = prep_cache->
gcache.argnum == 1
471 GEOSGeometry *g1, *g2;
473 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
477 GEOSGeom_destroy(g1);
480 result = GEOSCrosses(g1, g2);
481 GEOSGeom_destroy(g1);
482 GEOSGeom_destroy(g2);
498 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
499 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
500 const GSERIALIZED *geom1 = shared_gserialized_get(shared_geom1);
501 const GSERIALIZED *geom2 = shared_gserialized_get(shared_geom2);
503 GEOSGeometry *g1, *g2;
511 PG_RETURN_BOOL(
false);
523 PG_RETURN_BOOL(
false);
532 const GSERIALIZED *gpoint = shared_gserialized_get(shared_geom2);
550 GEOSGeom_destroy(g1);
555 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
560 GEOSGeom_destroy(g1);
562 result = GEOSContains( g1, g2);
563 GEOSGeom_destroy(g1);
564 GEOSGeom_destroy(g2);
569 PG_RETURN_BOOL(
result > 0);
579 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
580 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
581 const GSERIALIZED *geom1 = shared_gserialized_get(shared_geom1);
582 const GSERIALIZED *geom2 = shared_gserialized_get(shared_geom2);
584 GEOSGeometry *g1, *g2;
592 PG_RETURN_BOOL(
false);
604 PG_RETURN_BOOL(
false);
613 const GSERIALIZED *gpoint = shared_gserialized_get(shared_geom1);
631 GEOSGeom_destroy(g1);
636 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
641 GEOSGeom_destroy(g1);
643 result = GEOSWithin(g1, g2);
644 GEOSGeom_destroy(g1);
645 GEOSGeom_destroy(g2);
650 PG_RETURN_BOOL(
result > 0);
659 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
660 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
661 const GSERIALIZED *geom1 = shared_gserialized_get(shared_geom1);
662 const GSERIALIZED *geom2 = shared_gserialized_get(shared_geom2);
671 PG_RETURN_BOOL(
false);
681 PG_RETURN_BOOL(
false);
690 if (!g)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
696 GEOSGeometry *g1, *g2;
698 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
702 GEOSGeom_destroy(g1);
705 result = GEOSRelatePattern(g1, g2,
"T**FF*FF*");
706 GEOSGeom_destroy(g1);
707 GEOSGeom_destroy(g2);
724 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
725 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
726 const GSERIALIZED *geom1 = shared_gserialized_get(shared_geom1);
727 const GSERIALIZED *geom2 = shared_gserialized_get(shared_geom2);
736 PG_RETURN_BOOL(
false);
749 PG_RETURN_BOOL(
false);
758 const GSERIALIZED *gpoint = shared_gserialized_get(shared_geom2);
772 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
774 GEOSGeom_destroy(g1);
778 GEOSGeometry *g1, *g2;
781 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
785 GEOSGeom_destroy(g1);
788 result = GEOSRelatePattern( g1, g2,
"******FF*" );
789 GEOSGeom_destroy(g1);
790 GEOSGeom_destroy(g2);
808 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
809 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
810 const GSERIALIZED *geom1 = shared_gserialized_get(shared_geom1);
811 const GSERIALIZED *geom2 = shared_gserialized_get(shared_geom2);
822 PG_RETURN_BOOL(
false);
833 PG_RETURN_BOOL(
false);
842 const GSERIALIZED *gpoint = shared_gserialized_get(shared_geom1);
856 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
858 GEOSGeom_destroy(g1);
862 GEOSGeometry *g1, *g2;
864 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
869 GEOSGeom_destroy(g1);
873 result = GEOSCoveredBy(g1, g2);
874 GEOSGeom_destroy(g1);
875 GEOSGeom_destroy(g2);
883 #if POSTGIS_GEOS_VERSION >= 31300
893 t = im[1]; im[1] = im[3]; im[3] = t;
894 t = im[2]; im[2] = im[6]; im[6] = t;
895 t = im[5]; im[5] = im[7]; im[7] = t;
902 SHARED_GSERIALIZED *shared_geom1 = ToastCacheGetGeometry(fcinfo, 0);
903 SHARED_GSERIALIZED *shared_geom2 = ToastCacheGetGeometry(fcinfo, 1);
904 const GSERIALIZED *geom1 = shared_gserialized_get(shared_geom1);
905 const GSERIALIZED *geom2 = shared_gserialized_get(shared_geom2);
908 text *imPtr = DatumGetTextP(DirectFunctionCall2(text_left,
909 PG_GETARG_DATUM(2), Int32GetDatum(9)));
910 char *im = text_to_cstring(imPtr);
913 #if POSTGIS_GEOS_VERSION >= 31300
922 for (i = 0; i < strlen(im); i++)
923 im[i] = toupper(im[i]);
927 #if POSTGIS_GEOS_VERSION >= 31300
931 GEOSGeometry *g = NULL;
932 if (prep_cache->
gcache.argnum == 1)
949 GEOSGeometry *g1, *g2;
951 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
956 GEOSGeom_destroy(g1);
958 result = GEOSRelatePattern(g1, g2, im);
959 GEOSGeom_destroy(g1);
960 GEOSGeom_destroy(g2);
975 GEOSGeometry *g1, *g2;
978 int bnr = GEOSRELATE_BNR_OGC;
983 if ( PG_NARGS() > 2 )
984 bnr = PG_GETARG_INT32(2);
994 GEOSGeom_destroy(g1);
998 POSTGIS_DEBUG(3,
"constructed geometries ");
1000 POSTGIS_DEBUGF(3,
"%s", GEOSGeomToWKT(g1));
1001 POSTGIS_DEBUGF(3,
"%s", GEOSGeomToWKT(g2));
1003 relate_str = GEOSRelateBoundaryNodeRule(g1, g2, bnr);
1005 GEOSGeom_destroy(g1);
1006 GEOSGeom_destroy(g2);
1009 result = cstring_to_text(relate_str);
1010 GEOSFree(relate_str);
1011 GEOSGeom_destroy(g1);
1012 GEOSGeom_destroy(g2);
1014 PG_FREE_IF_COPY(geom1, 0);
1015 PG_FREE_IF_COPY(geom2, 1);
1017 PG_RETURN_TEXT_P(
result);
char result[OUT_DOUBLE_BUFFER_SIZE]
int gbox_overlaps_2d(const GBOX *g1, const GBOX *g2)
Return LW_TRUE if the GBOX overlaps on the 2d plane, LW_FALSE otherwise.
int gbox_within_2d(const GBOX *g1, const GBOX *g2)
Return LW_TRUE if the first GBOX is within the second on the 2d plane, LW_FALSE otherwise.
int gbox_same_2d_float(const GBOX *g1, const GBOX *g2)
Check if two given GBOX are the same in x and y, or would round to the same GBOX in x and if serializ...
int gbox_contains_2d(const GBOX *g1, const GBOX *g2)
Return LW_TRUE if the first GBOX contains the second on the 2d plane, LW_FALSE otherwise.
void gserialized_error_if_srid_mismatch(const GSERIALIZED *g1, const GSERIALIZED *g2, const char *funcname)
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
void lwgeom_geos_error(const char *fmt,...)
void lwgeom_free(LWGEOM *geom)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
This library is the generic geometry handling section of PostGIS.
Datum contains(PG_FUNCTION_ARGS)
Datum coveredby(PG_FUNCTION_ARGS)
static char is_point(const GSERIALIZED *g)
Datum covers(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(ST_Intersects)
Datum touches(PG_FUNCTION_ARGS)
Datum disjoint(PG_FUNCTION_ARGS)
Datum ST_Intersects(PG_FUNCTION_ARGS)
Datum crosses(PG_FUNCTION_ARGS)
Datum relate_full(PG_FUNCTION_ARGS)
Datum relate_pattern(PG_FUNCTION_ARGS)
static char is_poly(const GSERIALIZED *g)
Datum overlaps(PG_FUNCTION_ARGS)
Datum ST_Equals(PG_FUNCTION_ARGS)
Datum within(PG_FUNCTION_ARGS)
Datum containsproperly(PG_FUNCTION_ARGS)
PrepGeomCache * GetPrepGeomCache(FunctionCallInfo fcinfo, SHARED_GSERIALIZED *g1, SHARED_GSERIALIZED *g2)
Given a couple potential geometries and a function call context, return a prepared structure for one ...
bool itree_pip_intersects(const IntervalTree *itree, const LWGEOM *lwpoints)
IntervalTree * GetIntervalTree(FunctionCallInfo fcinfo, SHARED_GSERIALIZED *g1)
Checks for a cache hit against the provided geometry and returns a pre-built index structure (RTREE_P...
bool itree_pip_covers(const IntervalTree *itree, const LWGEOM *lwpoints)
bool itree_pip_contains(const IntervalTree *itree, const LWGEOM *lwpoints)
GEOSGeometry * POSTGIS2GEOS(const GSERIALIZED *pglwgeom)
#define HANDLE_GEOS_ERROR(label)
const GEOSPreparedGeometry * prepared_geom