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

Definition at line 2569 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(), HANDLE_GEOS_ERROR, LW_FALSE, lwgeom_as_lwpoint(), lwgeom_free(), lwgeom_from_gserialized(), lwgeom_geos_error(), lwpoint_free(), MULTIPOLYGONTYPE, point_in_multipolygon(), point_in_multipolygon_rtree(), point_in_polygon(), POINTTYPE, RTREE_POLY_CACHE::polyCount, POLYGONTYPE, POSTGIS2GEOS(), PrepGeomCache::prepared_geom, RTREE_POLY_CACHE::ringCounts, RTREE_POLY_CACHE::ringIndices, and TRUE.

2570 {
2571  GSERIALIZED *geom1;
2572  GSERIALIZED *geom2;
2573  GSERIALIZED *serialized_poly;
2574  int result;
2575  GBOX box1, box2;
2576  int type1, type2, polytype;
2577  LWPOINT *point;
2578  LWGEOM *lwgeom;
2579  RTREE_POLY_CACHE *poly_cache;
2580  PrepGeomCache *prep_cache;
2581 
2582  geom1 = PG_GETARG_GSERIALIZED_P(0);
2583  geom2 = PG_GETARG_GSERIALIZED_P(1);
2584 
2585  errorIfGeometryCollection(geom1,geom2);
2587 
2588  /* A.Intersects(Empty) == FALSE */
2589  if ( gserialized_is_empty(geom1) || gserialized_is_empty(geom2) )
2590  PG_RETURN_BOOL(false);
2591 
2592  /*
2593  * short-circuit 1: if geom2 bounding box does not overlap
2594  * geom1 bounding box we can prematurely return FALSE.
2595  * Do the test IFF BOUNDING BOX AVAILABLE.
2596  */
2597  if ( gserialized_get_gbox_p(geom1, &box1) &&
2598  gserialized_get_gbox_p(geom2, &box2) )
2599  {
2600  if ( gbox_overlaps_2d(&box1, &box2) == LW_FALSE )
2601  {
2602  PG_RETURN_BOOL(FALSE);
2603  }
2604  }
2605 
2606  /*
2607  * short-circuit 2: if the geoms are a point and a polygon,
2608  * call the point_outside_polygon function.
2609  */
2610  type1 = gserialized_get_type(geom1);
2611  type2 = gserialized_get_type(geom2);
2612  if ( (type1 == POINTTYPE && (type2 == POLYGONTYPE || type2 == MULTIPOLYGONTYPE)) ||
2613  (type2 == POINTTYPE && (type1 == POLYGONTYPE || type1 == MULTIPOLYGONTYPE)))
2614  {
2615  POSTGIS_DEBUG(3, "Point in Polygon test requested...short-circuiting.");
2616 
2617  if ( type1 == POINTTYPE )
2618  {
2620  lwgeom = lwgeom_from_gserialized(geom2);
2621  serialized_poly = geom2;
2622  polytype = type2;
2623  }
2624  else
2625  {
2627  lwgeom = lwgeom_from_gserialized(geom1);
2628  serialized_poly = geom1;
2629  polytype = type1;
2630  }
2631 
2632  poly_cache = GetRtreeCache(fcinfo, serialized_poly);
2633 
2634  if ( poly_cache && poly_cache->ringIndices )
2635  {
2636  result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCounts, point);
2637  }
2638  else if ( polytype == POLYGONTYPE )
2639  {
2640  result = point_in_polygon((LWPOLY*)lwgeom, point);
2641  }
2642  else if ( polytype == MULTIPOLYGONTYPE )
2643  {
2644  result = point_in_multipolygon((LWMPOLY*)lwgeom, point);
2645  }
2646  else
2647  {
2648  /* Gulp! Should not be here... */
2649  elog(ERROR,"Type isn't poly or multipoly!");
2650  PG_RETURN_NULL();
2651  }
2652 
2653  lwgeom_free(lwgeom);
2654  lwpoint_free(point);
2655  PG_FREE_IF_COPY(geom1, 0);
2656  PG_FREE_IF_COPY(geom2, 1);
2657  if ( result != -1 ) /* not outside */
2658  {
2659  PG_RETURN_BOOL(TRUE);
2660  }
2661  else
2662  {
2663  PG_RETURN_BOOL(FALSE);
2664  }
2665  }
2666 
2667  initGEOS(lwpgnotice, lwgeom_geos_error);
2668  prep_cache = GetPrepGeomCache( fcinfo, geom1, geom2 );
2669 
2670  if ( prep_cache && prep_cache->prepared_geom )
2671  {
2672  if ( prep_cache->argnum == 1 )
2673  {
2674  GEOSGeometry *g = (GEOSGeometry *)POSTGIS2GEOS(geom2);
2675  if ( 0 == g ) /* exception thrown at construction */
2676  {
2677  HANDLE_GEOS_ERROR("Geometry could not be converted to GEOS");
2678  PG_RETURN_NULL();
2679  }
2680  result = GEOSPreparedIntersects( prep_cache->prepared_geom, g);
2681  GEOSGeom_destroy(g);
2682  }
2683  else
2684  {
2685  GEOSGeometry *g = (GEOSGeometry *)POSTGIS2GEOS(geom1);
2686  if ( 0 == g ) /* exception thrown at construction */
2687  {
2688  HANDLE_GEOS_ERROR("Geometry could not be converted to GEOS");
2689  PG_RETURN_NULL();
2690  }
2691  result = GEOSPreparedIntersects( prep_cache->prepared_geom, g);
2692  GEOSGeom_destroy(g);
2693  }
2694  }
2695  else
2696  {
2697  GEOSGeometry *g1;
2698  GEOSGeometry *g2;
2699  g1 = (GEOSGeometry *)POSTGIS2GEOS(geom1);
2700  if ( 0 == g1 ) /* exception thrown at construction */
2701  {
2702  HANDLE_GEOS_ERROR("First argument geometry could not be converted to GEOS");
2703  PG_RETURN_NULL();
2704  }
2705  g2 = (GEOSGeometry *)POSTGIS2GEOS(geom2);
2706  if ( 0 == g2 ) /* exception thrown at construction */
2707  {
2708  HANDLE_GEOS_ERROR("Second argument geometry could not be converted to GEOS");
2709  GEOSGeom_destroy(g1);
2710  PG_RETURN_NULL();
2711  }
2712  result = GEOSIntersects( g1, g2);
2713  GEOSGeom_destroy(g1);
2714  GEOSGeom_destroy(g2);
2715  }
2716 
2717  if (result == 2)
2718  {
2719  HANDLE_GEOS_ERROR("GEOSIntersects");
2720  PG_RETURN_NULL(); /* never get here */
2721  }
2722 
2723  PG_FREE_IF_COPY(geom1, 0);
2724  PG_FREE_IF_COPY(geom2, 1);
2725 
2726  PG_RETURN_BOOL(result);
2727 }
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:371
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:55
const GEOSPreparedGeometry * prepared_geom
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
#define POLYGONTYPE
Definition: liblwgeom.h:72
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:182
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1050
The tree structure used for fast P-i-P tests by point_in_multipolygon_rtree()
Definition: lwgeom_rtree.h:33
int point_in_multipolygon_rtree(RTREE_NODE **root, int polyCount, int *ringCounts, LWPOINT *point)
void error_if_srid_mismatch(int srid1, int srid2)
Definition: lwutil.c:341
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition: lwgeom.c:80
int point_in_multipolygon(LWMPOLY *mpolygon, LWPOINT *point)
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: g_serialized.c:139
void lwgeom_geos_error(const char *fmt,...)
#define LW_FALSE
Definition: liblwgeom.h:62
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:75
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:300
#define FALSE
Definition: dbfopen.c:168
GEOSGeometry * POSTGIS2GEOS(GSERIALIZED *pglwgeom)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:70
PrepGeomCache * GetPrepGeomCache(FunctionCallInfoData *fcinfo, GSERIALIZED *g1, GSERIALIZED *g2)
Given a couple potential geometries and a function call context, return a prepared structure for one ...
#define HANDLE_GEOS_ERROR(label)
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:169
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:69
void errorIfGeometryCollection(GSERIALIZED *g1, GSERIALIZED *g2)
Throws an ereport ERROR if either geometry is a COLLECTIONTYPE.

Here is the call graph for this function: