PostGIS  2.5.0dev-r@@SVN_REVISION@@
int lwpoly_covers_point2d ( const LWPOLY poly,
const POINT2D pt_to_test 
)

Given a polygon (lon/lat decimal degrees) and point (lon/lat decimal degrees) and a guaranteed outside point (lon/lat decimal degrees) (calculate with gbox_pt_outside()) return LW_TRUE if point is inside or on edge of polygon.

Definition at line 2427 of file lwgeodetic.c.

References LWPOLY::bbox, GBOX::flags, gbox_contains_point3d(), gbox_pt_outside(), gbox_to_string(), geog2cart(), geographic_point_init(), LW_FALSE, LW_TRUE, LWDEBUG, LWDEBUGF, lwgeom_calculate_gbox_geodetic(), lwgeom_is_empty(), lwgeom_to_ewkt(), LWPOLY::nrings, ptarray_contains_point_sphere(), LWPOLY::rings, POINT2D::x, and POINT2D::y.

Referenced by lwgeom_covers_lwgeom_sphere(), lwgeom_distance_spheroid(), lwpoly_covers_pointarray(), test_lwpoly_covers_point2d(), and test_tree_circ_pip2().

2428 {
2429  uint32_t i;
2430  int in_hole_count = 0;
2431  POINT3D p;
2432  GEOGRAPHIC_POINT gpt_to_test;
2433  POINT2D pt_outside;
2434  GBOX gbox;
2435  gbox.flags = 0;
2436 
2437  /* Nulls and empties don't contain anything! */
2438  if ( ! poly || lwgeom_is_empty((LWGEOM*)poly) )
2439  {
2440  LWDEBUG(4,"returning false, geometry is empty or null");
2441  return LW_FALSE;
2442  }
2443 
2444  /* Make sure we have boxes */
2445  if ( poly->bbox )
2446  gbox = *(poly->bbox);
2447  else
2448  lwgeom_calculate_gbox_geodetic((LWGEOM*)poly, &gbox);
2449 
2450  /* Point not in box? Done! */
2451  geographic_point_init(pt_to_test->x, pt_to_test->y, &gpt_to_test);
2452  geog2cart(&gpt_to_test, &p);
2453  if ( ! gbox_contains_point3d(&gbox, &p) )
2454  {
2455  LWDEBUG(4, "the point is not in the box!");
2456  return LW_FALSE;
2457  }
2458 
2459  /* Calculate our outside point from the gbox */
2460  gbox_pt_outside(&gbox, &pt_outside);
2461 
2462  LWDEBUGF(4, "pt_outside POINT(%.18g %.18g)", pt_outside.x, pt_outside.y);
2463  LWDEBUGF(4, "pt_to_test POINT(%.18g %.18g)", pt_to_test->x, pt_to_test->y);
2464  LWDEBUGF(4, "polygon %s", lwgeom_to_ewkt((LWGEOM*)poly));
2465  LWDEBUGF(4, "gbox %s", gbox_to_string(&gbox));
2466 
2467  /* Not in outer ring? We're done! */
2468  if ( ! ptarray_contains_point_sphere(poly->rings[0], &pt_outside, pt_to_test) )
2469  {
2470  LWDEBUG(4,"returning false, point is outside ring");
2471  return LW_FALSE;
2472  }
2473 
2474  LWDEBUGF(4, "testing %d rings", poly->nrings);
2475 
2476  /* But maybe point is in a hole... */
2477  for ( i = 1; i < poly->nrings; i++ )
2478  {
2479  LWDEBUGF(4, "ring test loop %d", i);
2480  /* Count up hole containment. Odd => outside boundary. */
2481  if ( ptarray_contains_point_sphere(poly->rings[i], &pt_outside, pt_to_test) )
2482  in_hole_count++;
2483  }
2484 
2485  LWDEBUGF(4, "in_hole_count == %d", in_hole_count);
2486 
2487  if ( in_hole_count % 2 )
2488  {
2489  LWDEBUG(4,"returning false, inner ring containment count is odd");
2490  return LW_FALSE;
2491  }
2492 
2493  LWDEBUG(4,"returning true, inner ring containment count is even");
2494  return LW_TRUE;
2495 }
char * gbox_to_string(const GBOX *gbox)
Allocate a string representation of the GBOX, based on dimensionality of flags.
Definition: g_box.c:399
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
Definition: lwgeom.c:549
int gbox_contains_point3d(const GBOX *gbox, const POINT3D *pt)
Return true if the point is inside the gbox.
Definition: g_box.c:254
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
GBOX * bbox
Definition: liblwgeom.h:452
Point in spherical coordinates on the world.
Definition: lwgeodetic.h:47
uint32_t nrings
Definition: liblwgeom.h:454
unsigned int uint32_t
Definition: uthash.h:78
double x
Definition: liblwgeom.h:327
int ptarray_contains_point_sphere(const POINTARRAY *pa, const POINT2D *pt_outside, const POINT2D *pt_to_test)
This routine returns LW_TRUE if the stabline joining the pt_outside and pt_to_test crosses the ring a...
Definition: lwgeodetic.c:3516
#define LW_FALSE
Definition: liblwgeom.h:76
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:75
int lwgeom_calculate_gbox_geodetic(const LWGEOM *geom, GBOX *gbox)
Calculate the geodetic bounding box for an LWGEOM.
Definition: lwgeodetic.c:2927
POINTARRAY ** rings
Definition: liblwgeom.h:456
double y
Definition: liblwgeom.h:327
uint8_t flags
Definition: liblwgeom.h:290
void geog2cart(const GEOGRAPHIC_POINT *g, POINT3D *p)
Convert spherical coordinates to cartesion coordinates on unit sphere.
Definition: lwgeodetic.c:369
void gbox_pt_outside(const GBOX *gbox, POINT2D *pt_outside)
Given a unit geocentric gbox, return a lon/lat (degrees) coordinate point point that is guaranteed to...
Definition: lwgeodetic.c:1461
void geographic_point_init(double lon, double lat, GEOGRAPHIC_POINT *g)
Initialize a geographic point.
Definition: lwgeodetic.c:171
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Definition: lwgeom.c:1386
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88

Here is the call graph for this function:

Here is the caller graph for this function: