PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ edge_intersection()

int edge_intersection ( const GEOGRAPHIC_EDGE e1,
const GEOGRAPHIC_EDGE e2,
GEOGRAPHIC_POINT g 
)

Returns true if an intersection can be calculated, and places it in *g.

Returns false otherwise.

Definition at line 1123 of file lwgeodetic.c.

References dot_product(), edge_contains_point(), GEOGRAPHIC_EDGE::end, FP_EQUALS, geographic_point_equals(), GEOGRAPHIC_POINT::lat, GEOGRAPHIC_POINT::lon, LW_FALSE, LW_TRUE, LWDEBUG, LWDEBUGF, normalize(), rad2deg, robust_cross_product(), GEOGRAPHIC_EDGE::start, unit_normal(), POINT3D::x, POINT3D::y, and POINT3D::z.

Referenced by circ_tree_distance_tree_internal(), and test_edge_intersection().

1124 {
1125  POINT3D ea, eb, v;
1126  LWDEBUGF(4, "e1 start(%.20g %.20g) end(%.20g %.20g)", e1->start.lat, e1->start.lon, e1->end.lat, e1->end.lon);
1127  LWDEBUGF(4, "e2 start(%.20g %.20g) end(%.20g %.20g)", e2->start.lat, e2->start.lon, e2->end.lat, e2->end.lon);
1128 
1129  LWDEBUGF(4, "e1 start(%.20g %.20g) end(%.20g %.20g)", rad2deg(e1->start.lon), rad2deg(e1->start.lat), rad2deg(e1->end.lon), rad2deg(e1->end.lat));
1130  LWDEBUGF(4, "e2 start(%.20g %.20g) end(%.20g %.20g)", rad2deg(e2->start.lon), rad2deg(e2->start.lat), rad2deg(e2->end.lon), rad2deg(e2->end.lat));
1131 
1132  if ( geographic_point_equals(&(e1->start), &(e2->start)) )
1133  {
1134  *g = e1->start;
1135  return LW_TRUE;
1136  }
1137  if ( geographic_point_equals(&(e1->end), &(e2->end)) )
1138  {
1139  *g = e1->end;
1140  return LW_TRUE;
1141  }
1142  if ( geographic_point_equals(&(e1->end), &(e2->start)) )
1143  {
1144  *g = e1->end;
1145  return LW_TRUE;
1146  }
1147  if ( geographic_point_equals(&(e1->start), &(e2->end)) )
1148  {
1149  *g = e1->start;
1150  return LW_TRUE;
1151  }
1152 
1153  robust_cross_product(&(e1->start), &(e1->end), &ea);
1154  normalize(&ea);
1155  robust_cross_product(&(e2->start), &(e2->end), &eb);
1156  normalize(&eb);
1157  LWDEBUGF(4, "e1 cross product == POINT(%.12g %.12g %.12g)", ea.x, ea.y, ea.z);
1158  LWDEBUGF(4, "e2 cross product == POINT(%.12g %.12g %.12g)", eb.x, eb.y, eb.z);
1159  LWDEBUGF(4, "fabs(dot_product(ea, eb)) == %.14g", fabs(dot_product(&ea, &eb)));
1160  if ( FP_EQUALS(fabs(dot_product(&ea, &eb)), 1.0) )
1161  {
1162  LWDEBUGF(4, "parallel edges found! dot_product = %.12g", dot_product(&ea, &eb));
1163  /* Parallel (maybe equal) edges! */
1164  /* Hack alert, only returning ONE end of the edge right now, most do better later. */
1165  /* Hack alart #2, returning a value of 2 to indicate a co-linear crossing event. */
1166  if ( edge_contains_point(e1, &(e2->start)) )
1167  {
1168  *g = e2->start;
1169  return 2;
1170  }
1171  if ( edge_contains_point(e1, &(e2->end)) )
1172  {
1173  *g = e2->end;
1174  return 2;
1175  }
1176  if ( edge_contains_point(e2, &(e1->start)) )
1177  {
1178  *g = e1->start;
1179  return 2;
1180  }
1181  if ( edge_contains_point(e2, &(e1->end)) )
1182  {
1183  *g = e1->end;
1184  return 2;
1185  }
1186  }
1187  unit_normal(&ea, &eb, &v);
1188  LWDEBUGF(4, "v == POINT(%.12g %.12g %.12g)", v.x, v.y, v.z);
1189  g->lat = atan2(v.z, sqrt(v.x * v.x + v.y * v.y));
1190  g->lon = atan2(v.y, v.x);
1191  LWDEBUGF(4, "g == GPOINT(%.12g %.12g)", g->lat, g->lon);
1192  LWDEBUGF(4, "g == POINT(%.12g %.12g)", rad2deg(g->lon), rad2deg(g->lat));
1193  if ( edge_contains_point(e1, g) && edge_contains_point(e2, g) )
1194  {
1195  return LW_TRUE;
1196  }
1197  else
1198  {
1199  LWDEBUG(4, "flipping point to other side of sphere");
1200  g->lat = -1.0 * g->lat;
1201  g->lon = g->lon + M_PI;
1202  if ( g->lon > M_PI )
1203  {
1204  g->lon = -1.0 * (2.0 * M_PI - g->lon);
1205  }
1206  if ( edge_contains_point(e1, g) && edge_contains_point(e2, g) )
1207  {
1208  return LW_TRUE;
1209  }
1210  }
1211  return LW_FALSE;
1212 }
void robust_cross_product(const GEOGRAPHIC_POINT *p, const GEOGRAPHIC_POINT *q, POINT3D *a)
Computes the cross product of two vectors using their lat, lng representations.
Definition: lwgeodetic.c:630
void normalize(POINT3D *p)
Normalize to a unit vector.
Definition: lwgeodetic.c:611
int edge_contains_point(const GEOGRAPHIC_EDGE *e, const GEOGRAPHIC_POINT *p)
Returns true if the point p is on the minor edge defined by the end points of e.
Definition: lwgeodetic.c:1030
double y
Definition: liblwgeom.h:340
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
double x
Definition: liblwgeom.h:340
double z
Definition: liblwgeom.h:340
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:537
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:442
#define LW_FALSE
Definition: liblwgeom.h:77
#define rad2deg(r)
Definition: lwgeodetic.h:80
GEOGRAPHIC_POINT start
Definition: lwgeodetic.h:63
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:76
GEOGRAPHIC_POINT end
Definition: lwgeodetic.h:64
int geographic_point_equals(const GEOGRAPHIC_POINT *g1, const GEOGRAPHIC_POINT *g2)
Definition: lwgeodetic.c:170
#define FP_EQUALS(A, B)
#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: