PostGIS  2.1.10dev-r@@SVN_REVISION@@
int edge_intersects ( const POINT3D A1,
const POINT3D A2,
const POINT3D B1,
const POINT3D B2 
)

Returns non-zero if edges A and B interact.

The type of interaction is given in the return value with the bitmask elements defined above.

Definition at line 3096 of file lwgeodetic.c.

References dot_product(), dot_product_side(), FP_EQUALS, PIR_A_TOUCH_LEFT, PIR_A_TOUCH_RIGHT, PIR_B_TOUCH_LEFT, PIR_B_TOUCH_RIGHT, PIR_COLINEAR, PIR_INTERSECTS, PIR_NO_INTERACT, point_in_cone(), unit_normal(), and vector_scale().

Referenced by circ_tree_contains_point(), circ_tree_distance_tree_internal(), ptarray_contains_point_sphere(), ptarray_distance_spheroid(), and test_edge_intersects().

3097 {
3098  POINT3D AN, BN, VN; /* Normals to plane A and plane B */
3099  double ab_dot;
3100  int a1_side, a2_side, b1_side, b2_side;
3101  int rv = PIR_NO_INTERACT;
3102 
3103  /* Normals to the A-plane and B-plane */
3104  unit_normal(A1, A2, &AN);
3105  unit_normal(B1, B2, &BN);
3106 
3107  /* Are A-plane and B-plane basically the same? */
3108  ab_dot = dot_product(&AN, &BN);
3109  if ( FP_EQUALS(fabs(ab_dot), 1.0) )
3110  {
3111  /* Co-linear case */
3112  if ( point_in_cone(A1, A2, B1) || point_in_cone(A1, A2, B2) ||
3113  point_in_cone(B1, B2, A1) || point_in_cone(B1, B2, A2) )
3114  {
3115  rv |= PIR_INTERSECTS;
3116  rv |= PIR_COLINEAR;
3117  }
3118  return rv;
3119  }
3120 
3121  /* What side of plane-A and plane-B do the end points */
3122  /* of A and B fall? */
3123  a1_side = dot_product_side(&BN, A1);
3124  a2_side = dot_product_side(&BN, A2);
3125  b1_side = dot_product_side(&AN, B1);
3126  b2_side = dot_product_side(&AN, B2);
3127 
3128  /* Both ends of A on the same side of plane B. */
3129  if ( a1_side == a2_side && a1_side != 0 )
3130  {
3131  /* No intersection. */
3132  return PIR_NO_INTERACT;
3133  }
3134 
3135  /* Both ends of B on the same side of plane A. */
3136  if ( b1_side == b2_side && b1_side != 0 )
3137  {
3138  /* No intersection. */
3139  return PIR_NO_INTERACT;
3140  }
3141 
3142  /* A straddles B and B straddles A, so... */
3143  if ( a1_side != a2_side && (a1_side + a2_side) == 0 &&
3144  b1_side != b2_side && (b1_side + b2_side) == 0 )
3145  {
3146  /* Have to check if intersection point is inside both arcs */
3147  unit_normal(&AN, &BN, &VN);
3148  if ( point_in_cone(A1, A2, &VN) && point_in_cone(B1, B2, &VN) )
3149  {
3150  return PIR_INTERSECTS;
3151  }
3152 
3153  /* Have to check if intersection point is inside both arcs */
3154  vector_scale(&VN, -1);
3155  if ( point_in_cone(A1, A2, &VN) && point_in_cone(B1, B2, &VN) )
3156  {
3157  return PIR_INTERSECTS;
3158  }
3159 
3160  return PIR_NO_INTERACT;
3161  }
3162 
3163  /* The rest are all intersects variants... */
3164  rv |= PIR_INTERSECTS;
3165 
3166  /* A touches B */
3167  if ( a1_side == 0 )
3168  {
3169  /* Touches at A1, A2 is on what side? */
3170  rv |= (a2_side < 0 ? PIR_A_TOUCH_RIGHT : PIR_A_TOUCH_LEFT);
3171  }
3172  else if ( a2_side == 0 )
3173  {
3174  /* Touches at A2, A1 is on what side? */
3175  rv |= (a1_side < 0 ? PIR_A_TOUCH_RIGHT : PIR_A_TOUCH_LEFT);
3176  }
3177 
3178  /* B touches A */
3179  if ( b1_side == 0 )
3180  {
3181  /* Touches at B1, B2 is on what side? */
3182  rv |= (b2_side < 0 ? PIR_B_TOUCH_RIGHT : PIR_B_TOUCH_LEFT);
3183  }
3184  else if ( b2_side == 0 )
3185  {
3186  /* Touches at B2, B1 is on what side? */
3187  rv |= (b1_side < 0 ? PIR_B_TOUCH_RIGHT : PIR_B_TOUCH_LEFT);
3188  }
3189 
3190  return rv;
3191 }
#define PIR_B_TOUCH_RIGHT
Definition: lwgeodetic.h:77
#define PIR_A_TOUCH_RIGHT
Definition: lwgeodetic.h:75
static int dot_product_side(const POINT3D *p, const POINT3D *q)
Utility function for edge_intersects(), signum with a tolerance in determining if the value is zero...
Definition: lwgeodetic.c:3081
static void vector_scale(POINT3D *n, double scale)
Scale a vector out by a factor.
Definition: lwgeodetic.c:438
#define PIR_A_TOUCH_LEFT
Definition: lwgeodetic.h:76
void unit_normal(const POINT3D *P1, const POINT3D *P2, POINT3D *normal)
Calculates the unit normal to two vectors, trying to avoid problems with over-narrow or over-wide cas...
Definition: lwgeodetic.c:490
static double dot_product(const POINT3D *p1, const POINT3D *p2)
Convert cartesion coordinates on unit sphere to lon/lat coordinates static void cart2ll(const POINT3D...
Definition: lwgeodetic.c:397
static int point_in_cone(const POINT3D *A1, const POINT3D *A2, const POINT3D *P)
Utility function for checking if P is within the cone defined by A1/A2.
Definition: lwgeodetic.c:3043
#define FP_EQUALS(A, B)
#define PIR_NO_INTERACT
Bitmask elements for edge_intersects() return value.
Definition: lwgeodetic.h:72
#define PIR_B_TOUCH_LEFT
Definition: lwgeodetic.h:78
#define PIR_COLINEAR
Definition: lwgeodetic.h:74
#define PIR_INTERSECTS
Definition: lwgeodetic.h:73

Here is the call graph for this function:

Here is the caller graph for this function: