PostGIS  2.1.10dev-r@@SVN_REVISION@@
Datum geos_intersects ( PG_FUNCTION_ARGS  )

Definition at line 2571 of file postgis/lwgeom_geos.c.

References PrepGeomCache::argnum, error_if_srid_mismatch(), errorIfGeometryCollection(), FALSE, gbox_overlaps_2d(), GetPrepGeomCache(), GetRtreeCache(), gserialized_get_gbox_p(), gserialized_get_srid(), gserialized_get_type(), gserialized_is_empty(), LW_FALSE, lwerror(), lwgeom_as_lwpoint(), lwgeom_free(), lwgeom_from_gserialized(), lwgeom_geos_errmsg, lwgeom_geos_error(), lwnotice(), lwpoint_free(), MULTIPOLYGONTYPE, point_in_multipolygon(), point_in_multipolygon_rtree(), point_in_polygon(), POINTTYPE, RTREE_POLY_CACHE::polyCount, POLYGONTYPE, POSTGIS2GEOS(), PrepGeomCache::prepared_geom, result, RTREE_POLY_CACHE::ringCounts, RTREE_POLY_CACHE::ringIndices, and TRUE.

2572 {
2573  GSERIALIZED *geom1;
2574  GSERIALIZED *geom2;
2575  GSERIALIZED *serialized_poly;
2576  int result;
2577  GBOX box1, box2;
2578  int type1, type2, polytype;
2579  LWPOINT *point;
2580  LWGEOM *lwgeom;
2581  RTREE_POLY_CACHE *poly_cache;
2582  PrepGeomCache *prep_cache;
2583 
2584  geom1 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
2585  geom2 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
2586 
2587  errorIfGeometryCollection(geom1,geom2);
2589 
2590  /* A.Intersects(Empty) == FALSE */
2591  if ( gserialized_is_empty(geom1) || gserialized_is_empty(geom2) )
2592  PG_RETURN_BOOL(false);
2593 
2594  /*
2595  * short-circuit 1: if geom2 bounding box does not overlap
2596  * geom1 bounding box we can prematurely return FALSE.
2597  * Do the test IFF BOUNDING BOX AVAILABLE.
2598  */
2599  if ( gserialized_get_gbox_p(geom1, &box1) &&
2600  gserialized_get_gbox_p(geom2, &box2) )
2601  {
2602  if ( gbox_overlaps_2d(&box1, &box2) == LW_FALSE )
2603  {
2604  PG_RETURN_BOOL(FALSE);
2605  }
2606  }
2607 
2608  /*
2609  * short-circuit 2: if the geoms are a point and a polygon,
2610  * call the point_outside_polygon function.
2611  */
2612  type1 = gserialized_get_type(geom1);
2613  type2 = gserialized_get_type(geom2);
2614  if ( (type1 == POINTTYPE && (type2 == POLYGONTYPE || type2 == MULTIPOLYGONTYPE)) ||
2615  (type2 == POINTTYPE && (type1 == POLYGONTYPE || type1 == MULTIPOLYGONTYPE)))
2616  {
2617  POSTGIS_DEBUG(3, "Point in Polygon test requested...short-circuiting.");
2618 
2619  if ( type1 == POINTTYPE )
2620  {
2622  lwgeom = lwgeom_from_gserialized(geom2);
2623  serialized_poly = geom2;
2624  polytype = type2;
2625  }
2626  else
2627  {
2629  lwgeom = lwgeom_from_gserialized(geom1);
2630  serialized_poly = geom1;
2631  polytype = type1;
2632  }
2633 
2634  poly_cache = GetRtreeCache(fcinfo, serialized_poly);
2635 
2636  if ( poly_cache && poly_cache->ringIndices )
2637  {
2638  result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCounts, point);
2639  }
2640  else if ( polytype == POLYGONTYPE )
2641  {
2642  result = point_in_polygon((LWPOLY*)lwgeom, point);
2643  }
2644  else if ( polytype == MULTIPOLYGONTYPE )
2645  {
2646  result = point_in_multipolygon((LWMPOLY*)lwgeom, point);
2647  }
2648  else
2649  {
2650  /* Gulp! Should not be here... */
2651  elog(ERROR,"Type isn't poly or multipoly!");
2652  PG_RETURN_NULL();
2653  }
2654 
2655  lwgeom_free(lwgeom);
2656  lwpoint_free(point);
2657  PG_FREE_IF_COPY(geom1, 0);
2658  PG_FREE_IF_COPY(geom2, 1);
2659  if ( result != -1 ) /* not outside */
2660  {
2661  PG_RETURN_BOOL(TRUE);
2662  }
2663  else
2664  {
2665  PG_RETURN_BOOL(FALSE);
2666  }
2667  }
2668 
2669  initGEOS(lwnotice, lwgeom_geos_error);
2670  prep_cache = GetPrepGeomCache( fcinfo, geom1, geom2 );
2671 
2672  if ( prep_cache && prep_cache->prepared_geom )
2673  {
2674  if ( prep_cache->argnum == 1 )
2675  {
2676  GEOSGeometry *g = (GEOSGeometry *)POSTGIS2GEOS(geom2);
2677  if ( 0 == g ) /* exception thrown at construction */
2678  {
2679  lwerror("Geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
2680  PG_RETURN_NULL();
2681  }
2682  result = GEOSPreparedIntersects( prep_cache->prepared_geom, g);
2683  GEOSGeom_destroy(g);
2684  }
2685  else
2686  {
2687  GEOSGeometry *g = (GEOSGeometry *)POSTGIS2GEOS(geom1);
2688  if ( 0 == g ) /* exception thrown at construction */
2689  {
2690  lwerror("Geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
2691  PG_RETURN_NULL();
2692  }
2693  result = GEOSPreparedIntersects( prep_cache->prepared_geom, g);
2694  GEOSGeom_destroy(g);
2695  }
2696  }
2697  else
2698  {
2699  GEOSGeometry *g1;
2700  GEOSGeometry *g2;
2701  g1 = (GEOSGeometry *)POSTGIS2GEOS(geom1);
2702  if ( 0 == g1 ) /* exception thrown at construction */
2703  {
2704  lwerror("First argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
2705  PG_RETURN_NULL();
2706  }
2707  g2 = (GEOSGeometry *)POSTGIS2GEOS(geom2);
2708  if ( 0 == g2 ) /* exception thrown at construction */
2709  {
2710  lwerror("Second argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
2711  GEOSGeom_destroy(g1);
2712  PG_RETURN_NULL();
2713  }
2714  result = GEOSIntersects( g1, g2);
2715  GEOSGeom_destroy(g1);
2716  GEOSGeom_destroy(g2);
2717  }
2718 
2719  if (result == 2)
2720  {
2721  lwerror("GEOSIntersects: %s", lwgeom_geos_errmsg);
2722  PG_RETURN_NULL(); /* never get here */
2723  }
2724 
2725  PG_FREE_IF_COPY(geom1, 0);
2726  PG_FREE_IF_COPY(geom2, 1);
2727 
2728  PG_RETURN_BOOL(result);
2729 }
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *box)
Read the bounding box off a serialization and calculate one if it is not already there.
Definition: g_serialized.c:373
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area...
Definition: g_serialized.c:56
const GEOSPreparedGeometry * prepared_geom
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
void error_if_srid_mismatch(int srid1, int srid2)
Definition: lwutil.c:317
#define POLYGONTYPE
Definition: liblwgeom.h:62
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:180
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1006
The tree structure used for fast P-i-P tests by point_in_multipolygon_rtree()
Definition: lwgeom_rtree.h:33
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
int point_in_multipolygon_rtree(RTREE_NODE **root, int polyCount, int *ringCounts, LWPOINT *point)
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition: lwgeom.c:80
int point_in_multipolygon(LWMPOLY *mpolygon, LWPOINT *point)
char ** result
Definition: liblwgeom.h:218
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: g_serialized.c:140
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:54
void lwgeom_geos_error(const char *fmt,...)
#define LW_FALSE
Definition: liblwgeom.h:52
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:65
int point_in_polygon(LWPOLY *polygon, LWPOINT *point)
int gbox_overlaps_2d(const GBOX *g1, const GBOX *g2)
Return LW_TRUE if the GBOX overlaps on the 2d plane, LW_FALSE otherwise.
Definition: g_box.c:281
#define FALSE
Definition: dbfopen.c:169
GEOSGeometry * POSTGIS2GEOS(GSERIALIZED *pglwgeom)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
PrepGeomCache * GetPrepGeomCache(FunctionCallInfoData *fcinfo, GSERIALIZED *g1, GSERIALIZED *g2)
Given a couple potential geometries and a function call context, return a prepared structure for one ...
RTREE_NODE ** ringIndices
Definition: lwgeom_rtree.h:35
RTREE_POLY_CACHE * GetRtreeCache(FunctionCallInfoData *fcinfo, GSERIALIZED *g1)
Checks for a cache hit against the provided geometry and returns a pre-built index structure (RTREE_P...
Definition: lwgeom_rtree.c:418
#define TRUE
Definition: dbfopen.c:170
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: g_serialized.c:70
void errorIfGeometryCollection(GSERIALIZED *g1, GSERIALIZED *g2)
Throws an ereport ERROR if either geometry is a COLLECTIONTYPE.

Here is the call graph for this function: