PostGIS  2.3.7dev-r@@SVN_REVISION@@
int circ_tree_contains_point ( const CIRC_NODE node,
const POINT2D pt,
const POINT2D pt_outside,
int *  on_boundary 
)

Walk the tree and count intersections between the stab line and the edges.

odd => containment, even => no containment. KNOWN PROBLEM: Grazings (think of a sharp point, just touching the stabline) will be counted for one, which will throw off the count.

Definition at line 480 of file lwgeodetic_tree.c.

References circ_node::center, circ_node_is_leaf(), circ_tree_contains_point(), edge_distance_to_point(), edge_intersects(), circ_node::edge_num, GEOGRAPHIC_EDGE::end, FP_LTEQ, geog2cart(), geographic_point_init(), GEOGRAPHIC_POINT::lat, GEOGRAPHIC_POINT::lon, LWDEBUG, LWDEBUGF, circ_node::nodes, circ_node::num_nodes, circ_node::p1, circ_node::p2, PIR_B_TOUCH_RIGHT, PIR_COLINEAR, PIR_INTERSECTS, rad2deg, circ_node::radius, GEOGRAPHIC_EDGE::start, POINT2D::x, and POINT2D::y.

Referenced by circ_tree_contains_point(), circ_tree_distance_tree_internal(), CircTreePIP(), test_tree_circ_pip(), and test_tree_circ_pip2().

481 {
482  GEOGRAPHIC_POINT closest;
483  GEOGRAPHIC_EDGE stab_edge, edge;
484  POINT3D S1, S2, E1, E2;
485  double d;
486  int i, c;
487 
488  /* Construct a stabline edge from our "inside" to our known outside point */
489  geographic_point_init(pt->x, pt->y, &(stab_edge.start));
490  geographic_point_init(pt_outside->x, pt_outside->y, &(stab_edge.end));
491  geog2cart(&(stab_edge.start), &S1);
492  geog2cart(&(stab_edge.end), &S2);
493 
494  LWDEBUG(3, "entered");
495 
496  /*
497  * If the stabline doesn't cross within the radius of a node, there's no
498  * way it can cross.
499  */
500 
501  LWDEBUGF(3, "working on node %p, edge_num %d, radius %g, center POINT(%g %g)", node, node->edge_num, node->radius, rad2deg(node->center.lon), rad2deg(node->center.lat));
502  d = edge_distance_to_point(&stab_edge, &(node->center), &closest);
503  LWDEBUGF(3, "edge_distance_to_point=%g, node_radius=%g", d, node->radius);
504  if ( FP_LTEQ(d, node->radius) )
505  {
506  LWDEBUGF(3,"entering this branch (%p)", node);
507 
508  /* Return the crossing number of this leaf */
509  if ( circ_node_is_leaf(node) )
510  {
511  int inter;
512  LWDEBUGF(3, "leaf node calculation (edge %d)", node->edge_num);
513  geographic_point_init(node->p1->x, node->p1->y, &(edge.start));
514  geographic_point_init(node->p2->x, node->p2->y, &(edge.end));
515  geog2cart(&(edge.start), &E1);
516  geog2cart(&(edge.end), &E2);
517 
518  inter = edge_intersects(&S1, &S2, &E1, &E2);
519 
520  if ( inter & PIR_INTERSECTS )
521  {
522  LWDEBUG(3," got stab line edge_intersection with this edge!");
523  /* To avoid double counting crossings-at-a-vertex, */
524  /* always ignore crossings at "lower" ends of edges*/
525 
526  if ( inter & PIR_B_TOUCH_RIGHT || inter & PIR_COLINEAR )
527  {
528  LWDEBUG(3," rejecting stab line grazing by left-side edge");
529  return 0;
530  }
531  else
532  {
533  LWDEBUG(3," accepting stab line intersection");
534  return 1;
535  }
536  }
537  }
538  /* Or, add up the crossing numbers of all children of this node. */
539  else
540  {
541  c = 0;
542  for ( i = 0; i < node->num_nodes; i++ )
543  {
544  LWDEBUG(3,"internal node calculation");
545  LWDEBUGF(3," calling circ_tree_contains_point on child %d!", i);
546  c += circ_tree_contains_point(node->nodes[i], pt, pt_outside, on_boundary);
547  }
548  return c % 2;
549  }
550  }
551  else
552  {
553  LWDEBUGF(3,"skipping this branch (%p)", node);
554  }
555 
556  return 0;
557 }
Two-point great circle segment from a to b.
Definition: lwgeodetic.h:56
#define PIR_B_TOUCH_RIGHT
Definition: lwgeodetic.h:86
GEOGRAPHIC_POINT center
POINT2D * p2
POINT2D * p1
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
#define FP_LTEQ(A, B)
Point in spherical coordinates on the world.
Definition: lwgeodetic.h:47
double x
Definition: liblwgeom.h:327
static int circ_node_is_leaf(const CIRC_NODE *node)
Internal nodes have their point references set to NULL.
#define rad2deg(r)
Definition: lwgeodetic.h:75
GEOGRAPHIC_POINT start
Definition: lwgeodetic.h:58
double edge_distance_to_point(const GEOGRAPHIC_EDGE *e, const GEOGRAPHIC_POINT *gp, GEOGRAPHIC_POINT *closest)
Definition: lwgeodetic.c:1183
int circ_tree_contains_point(const CIRC_NODE *node, const POINT2D *pt, const POINT2D *pt_outside, int *on_boundary)
Walk the tree and count intersections between the stab line and the edges.
GEOGRAPHIC_POINT end
Definition: lwgeodetic.h:59
double y
Definition: liblwgeom.h:327
void geog2cart(const GEOGRAPHIC_POINT *g, POINT3D *p)
Convert spherical coordinates to cartesion coordinates on unit sphere.
Definition: lwgeodetic.c:369
int edge_intersects(const POINT3D *A1, const POINT3D *A2, const POINT3D *B1, const POINT3D *B2)
Returns non-zero if edges A and B interact.
Definition: lwgeodetic.c:3110
void geographic_point_init(double lon, double lat, GEOGRAPHIC_POINT *g)
Initialize a geographic point.
Definition: lwgeodetic.c:171
double radius
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
#define PIR_COLINEAR
Definition: lwgeodetic.h:83
struct circ_node ** nodes
#define PIR_INTERSECTS
Definition: lwgeodetic.h:82

Here is the call graph for this function:

Here is the caller graph for this function: