PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ lw_dist3d_seg_seg()

int lw_dist3d_seg_seg ( POINT3DZ s1p1,
POINT3DZ s1p2,
POINT3DZ s2p1,
POINT3DZ s2p2,
DISTPTS3D dl 
)

Finds the two closest points on two linesegments.

Definition at line 1136 of file measures3d.c.

1137 {
1138  VECTOR3D v1, v2, vl;
1139  double s1k, s2k; /*two variables representing where on Line 1 (s1k) and where on Line 2 (s2k) a connecting line
1140  between the two lines is perpendicular to both lines*/
1141  POINT3DZ p1, p2;
1142  double a, b, c, d, e, D;
1143 
1144  /*s1p1 and s1p2 are the same point */
1145  if ((s1p1->x == s1p2->x) && (s1p1->y == s1p2->y) && (s1p1->z == s1p2->z))
1146  {
1147  return lw_dist3d_pt_seg(s1p1, s2p1, s2p2, dl);
1148  }
1149  /*s2p1 and s2p2 are the same point */
1150  if ((s2p1->x == s2p2->x) && (s2p1->y == s2p2->y) && (s2p1->z == s2p2->z))
1151  {
1152  dl->twisted = ((dl->twisted) * (-1));
1153  return lw_dist3d_pt_seg(s2p1, s1p1, s1p2, dl);
1154  }
1155 
1156  /*
1157  Here we use algorithm from softsurfer.com
1158  that can be found here
1159  http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
1160  */
1161 
1162  if (!get_3dvector_from_points(s1p1, s1p2, &v1))
1163  return LW_FALSE;
1164 
1165  if (!get_3dvector_from_points(s2p1, s2p2, &v2))
1166  return LW_FALSE;
1167 
1168  if (!get_3dvector_from_points(s2p1, s1p1, &vl))
1169  return LW_FALSE;
1170 
1171  a = DOT(v1, v1);
1172  b = DOT(v1, v2);
1173  c = DOT(v2, v2);
1174  d = DOT(v1, vl);
1175  e = DOT(v2, vl);
1176  D = a * c - b * b;
1177 
1178  if (D < 0.000000001)
1179  { /* the lines are almost parallel*/
1180  s1k =
1181  0.0; /*If the lines are parallel we try by using the startpoint of first segment. If that gives a
1182  projected point on the second line outside segment 2 it wil be found that s2k is >1 or <0.*/
1183  if (b > c) /* use the largest denominator*/
1184  s2k = d / b;
1185  else
1186  s2k = e / c;
1187  }
1188  else
1189  {
1190  s1k = (b * e - c * d) / D;
1191  s2k = (a * e - b * d) / D;
1192  }
1193 
1194  /* Now we check if the projected closest point on the infinite lines is outside our segments. If so the
1195  * combinations with start and end points will be tested*/
1196 
1197  if (s1k <= 0.0 || s1k >= 1.0 || s2k <= 0.0 || s2k >= 1.0)
1198  {
1199  if (s1k <= 0.0)
1200  {
1201  if (!lw_dist3d_pt_seg(s1p1, s2p1, s2p2, dl))
1202  return LW_FALSE;
1203  }
1204  if (s1k >= 1.0)
1205  {
1206  if (!lw_dist3d_pt_seg(s1p2, s2p1, s2p2, dl))
1207  return LW_FALSE;
1208  }
1209  if (s2k <= 0.0)
1210  {
1211  dl->twisted = ((dl->twisted) * (-1));
1212  if (!lw_dist3d_pt_seg(s2p1, s1p1, s1p2, dl))
1213  return LW_FALSE;
1214  }
1215  if (s2k >= 1.0)
1216  {
1217  dl->twisted = ((dl->twisted) * (-1));
1218  if (!lw_dist3d_pt_seg(s2p2, s1p1, s1p2, dl))
1219  return LW_FALSE;
1220  }
1221  }
1222  else
1223  { /*Find the closest point on the edges of both segments*/
1224  p1.x = s1p1->x + s1k * (s1p2->x - s1p1->x);
1225  p1.y = s1p1->y + s1k * (s1p2->y - s1p1->y);
1226  p1.z = s1p1->z + s1k * (s1p2->z - s1p1->z);
1227 
1228  p2.x = s2p1->x + s2k * (s2p2->x - s2p1->x);
1229  p2.y = s2p1->y + s2k * (s2p2->y - s2p1->y);
1230  p2.z = s2p1->z + s2k * (s2p2->z - s2p1->z);
1231 
1232  if (!lw_dist3d_pt_pt(&p1, &p2, dl)) /* Send the closest points to point-point calculation*/
1233  {
1234  return LW_FALSE;
1235  }
1236  }
1237  return LW_TRUE;
1238 }
#define LW_FALSE
Definition: liblwgeom.h:94
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:93
static int get_3dvector_from_points(POINT3DZ *p1, POINT3DZ *p2, VECTOR3D *v)
Definition: measures3d.c:34
int lw_dist3d_pt_pt(POINT3DZ *thep1, POINT3DZ *thep2, DISTPTS3D *dl)
Compares incoming points and stores the points closest to each other or most far away from each other...
Definition: measures3d.c:1045
int lw_dist3d_pt_seg(POINT3DZ *p, POINT3DZ *A, POINT3DZ *B, DISTPTS3D *dl)
If searching for min distance, this one finds the closest point on segment A-B from p.
Definition: measures3d.c:989
#define DOT(u, v)
Definition: measures3d.h:31
int twisted
Definition: measures3d.h:45
double z
Definition: liblwgeom.h:396
double x
Definition: liblwgeom.h:396
double y
Definition: liblwgeom.h:396

References DOT, get_3dvector_from_points(), lw_dist3d_pt_pt(), lw_dist3d_pt_seg(), LW_FALSE, LW_TRUE, DISTPTS3D::twisted, POINT3DZ::x, POINT3DZ::y, and POINT3DZ::z.

Referenced by lw_dist3d_ptarray_ptarray().

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