PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ circ_tree_contains_point()

int circ_tree_contains_point ( const CIRC_NODE node,
const POINT2D pt,
const POINT2D pt_outside,
int  level,
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 494 of file lwgeodetic_tree.c.

495{
496 GEOGRAPHIC_POINT closest;
497 GEOGRAPHIC_EDGE stab_edge, edge;
498 POINT3D S1, S2, E1, E2;
499 double d;
500 uint32_t i, c;
501
502 /* Construct a stabline edge from our "inside" to our known outside point */
503 geographic_point_init(pt->x, pt->y, &(stab_edge.start));
504 geographic_point_init(pt_outside->x, pt_outside->y, &(stab_edge.end));
505 geog2cart(&(stab_edge.start), &S1);
506 geog2cart(&(stab_edge.end), &S2);
507
508 LWDEBUGF(3, "%*s entered", level, "");
509
510 /*
511 * If the stabline doesn't cross within the radius of a node, there's no
512 * way it can cross.
513 */
514
515 LWDEBUGF(3, "%*s :working on node %p, edge_num %d, radius %g, center POINT(%.12g %.12g)", level, "", node, node->edge_num, node->radius, rad2deg(node->center.lon), rad2deg(node->center.lat));
516 d = edge_distance_to_point(&stab_edge, &(node->center), &closest);
517 LWDEBUGF(3, "%*s :edge_distance_to_point=%g, node_radius=%g", level, "", d, node->radius);
518 if ( FP_LTEQ(d, node->radius) )
519 {
520 LWDEBUGF(3,"%*s :entering this branch (%p)", level, "", node);
521
522 /* Return the crossing number of this leaf */
523 if ( circ_node_is_leaf(node) )
524 {
525 int inter;
526 LWDEBUGF(3, "%*s :leaf node calculation (edge %d)", level, "", node->edge_num);
527 geographic_point_init(node->p1->x, node->p1->y, &(edge.start));
528 geographic_point_init(node->p2->x, node->p2->y, &(edge.end));
529 geog2cart(&(edge.start), &E1);
530 geog2cart(&(edge.end), &E2);
531
532 inter = edge_intersects(&S1, &S2, &E1, &E2);
533 LWDEBUGF(3, "%*s :inter = %d", level, "", inter);
534
535 if ( inter & PIR_INTERSECTS )
536 {
537 LWDEBUGF(3,"%*s ::got stab line edge_intersection with this edge!", level, "");
538 /* To avoid double counting crossings-at-a-vertex, */
539 /* always ignore crossings at "lower" ends of edges*/
540 GEOGRAPHIC_POINT e1, e2;
541 cart2geog(&E1,&e1); cart2geog(&E2,&e2);
542
543 LWDEBUGF(3,"%*s LINESTRING(%.15g %.15g,%.15g %.15g)", level, "",
544 pt->x, pt->y,
545 pt_outside->x, pt_outside->y
546 );
547
548 LWDEBUGF(3,"%*s LINESTRING(%.15g %.15g,%.15g %.15g)", level, "",
549 rad2deg(e1.lon), rad2deg(e1.lat),
550 rad2deg(e2.lon), rad2deg(e2.lat)
551 );
552
553 if ( inter & PIR_B_TOUCH_RIGHT || inter & PIR_COLINEAR )
554 {
555 LWDEBUGF(3,"%*s ::rejecting stab line grazing by left-side edge", level, "");
556 return 0;
557 }
558 else
559 {
560 LWDEBUGF(3,"%*s ::accepting stab line intersection", level, "");
561 return 1;
562 }
563 }
564 else
565 {
566 LWDEBUGF(3,"%*s edge does not intersect", level, "");
567 }
568 }
569 /* Or, add up the crossing numbers of all children of this node. */
570 else
571 {
572 c = 0;
573 for ( i = 0; i < node->num_nodes; i++ )
574 {
575 LWDEBUGF(3,"%*s calling circ_tree_contains_point on child %d!", level, "", i);
576 c += circ_tree_contains_point(node->nodes[i], pt, pt_outside, level + 1, on_boundary);
577 }
578 return c % 2;
579 }
580 }
581 else
582 {
583 LWDEBUGF(3,"%*s skipping this branch (%p)", level, "", node);
584 }
585 return 0;
586}
#define FP_LTEQ(A, B)
void cart2geog(const POINT3D *p, GEOGRAPHIC_POINT *g)
Convert cartesian coordinates on unit sphere to spherical coordinates.
Definition lwgeodetic.c:414
void geographic_point_init(double lon, double lat, GEOGRAPHIC_POINT *g)
Initialize a geographic point.
Definition lwgeodetic.c:180
uint32_t edge_intersects(const POINT3D *A1, const POINT3D *A2, const POINT3D *B1, const POINT3D *B2)
Returns non-zero if edges A and B interact.
double edge_distance_to_point(const GEOGRAPHIC_EDGE *e, const GEOGRAPHIC_POINT *gp, GEOGRAPHIC_POINT *closest)
void geog2cart(const GEOGRAPHIC_POINT *g, POINT3D *p)
Convert spherical coordinates to cartesian coordinates on unit sphere.
Definition lwgeodetic.c:404
#define rad2deg(r)
Definition lwgeodetic.h:81
#define PIR_COLINEAR
Definition lwgeodetic.h:89
#define PIR_INTERSECTS
Definition lwgeodetic.h:88
#define PIR_B_TOUCH_RIGHT
Definition lwgeodetic.h:92
static int circ_node_is_leaf(const CIRC_NODE *node)
Internal nodes have their point references set to NULL.
int circ_tree_contains_point(const CIRC_NODE *node, const POINT2D *pt, const POINT2D *pt_outside, int level, int *on_boundary)
Walk the tree and count intersections between the stab line and the edges.
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
GEOGRAPHIC_POINT start
Definition lwgeodetic.h:64
GEOGRAPHIC_POINT end
Definition lwgeodetic.h:65
Two-point great circle segment from a to b.
Definition lwgeodetic.h:63
Point in spherical coordinates on the world.
Definition lwgeodetic.h:54
double y
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:390
uint32_t num_nodes
POINT2D * p2
struct circ_node ** nodes
POINT2D * p1
GEOGRAPHIC_POINT center

References cart2geog(), 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, 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().

Here is the call graph for this function:
Here is the caller graph for this function: