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

◆ lw_dist3d_seg_seg()

int lw_dist3d_seg_seg ( const POINT3DZ A,
const POINT3DZ B,
const POINT3DZ C,
const POINT3DZ D,
DISTPTS3D dl 
)

Finds the two closest points on two linesegments.

Definition at line 1173 of file measures3d.c.

1174{
1175 VECTOR3D v1, v2, vl;
1176 double s1k, s2k; /*two variables representing where on Line 1 (s1k) and where on Line 2 (s2k) a connecting line
1177 between the two lines is perpendicular to both lines*/
1178 POINT3DZ p1, p2;
1179 double a, b, c, d, e, D;
1180
1181 /*s1p1 and s1p2 are the same point */
1182 if (p3dz_same(s1p1, s1p2))
1183 {
1184 return lw_dist3d_pt_seg(s1p1, s2p1, s2p2, dl);
1185 }
1186 /*s2p1 and s2p2 are the same point */
1187 if (p3dz_same(s2p1, s2p2))
1188 {
1189 dl->twisted = ((dl->twisted) * (-1));
1190 return lw_dist3d_pt_seg(s2p1, s1p1, s1p2, dl);
1191 }
1192 /*s2p1 and s1p1 are the same point */
1193 if (p3dz_same(s2p1, s1p1))
1194 {
1195 dl->distance = 0.0;
1196 dl->p1 = dl->p2 = *s2p1;
1197 return LW_TRUE;
1198 }
1199 /*
1200 Here we use algorithm from softsurfer.com
1201 that can be found here
1202 http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
1203 */
1204
1205 if (!get_3dvector_from_points(s1p1, s1p2, &v1))
1206 return LW_FALSE;
1207
1208 if (!get_3dvector_from_points(s2p1, s2p2, &v2))
1209 return LW_FALSE;
1210
1211 if (!get_3dvector_from_points(s2p1, s1p1, &vl))
1212 return LW_FALSE;
1213
1214 a = DOT(v1, v1);
1215 b = DOT(v1, v2);
1216 c = DOT(v2, v2);
1217 d = DOT(v1, vl);
1218 e = DOT(v2, vl);
1219 D = a * c - b * b;
1220
1221 if (D < 0.000000001)
1222 { /* the lines are almost parallel*/
1223 s1k =
1224 0.0; /*If the lines are parallel we try by using the startpoint of first segment. If that gives a
1225 projected point on the second line outside segment 2 it will be found that s2k is >1 or <0.*/
1226 if (b > c) /* use the largest denominator*/
1227 s2k = d / b;
1228 else
1229 s2k = e / c;
1230 }
1231 else
1232 {
1233 s1k = (b * e - c * d) / D;
1234 s2k = (a * e - b * d) / D;
1235 }
1236
1237 /* Now we check if the projected closest point on the infinite lines is outside our segments. If so the
1238 * combinations with start and end points will be tested*/
1239
1240 if (s1k <= 0.0 || s1k >= 1.0 || s2k <= 0.0 || s2k >= 1.0)
1241 {
1242 if (s1k <= 0.0)
1243 {
1244 if (!lw_dist3d_pt_seg(s1p1, s2p1, s2p2, dl))
1245 return LW_FALSE;
1246 }
1247 if (s1k >= 1.0)
1248 {
1249 if (!lw_dist3d_pt_seg(s1p2, s2p1, s2p2, dl))
1250 return LW_FALSE;
1251 }
1252 if (s2k <= 0.0)
1253 {
1254 dl->twisted = ((dl->twisted) * (-1));
1255 if (!lw_dist3d_pt_seg(s2p1, s1p1, s1p2, dl))
1256 return LW_FALSE;
1257 }
1258 if (s2k >= 1.0)
1259 {
1260 dl->twisted = ((dl->twisted) * (-1));
1261 if (!lw_dist3d_pt_seg(s2p2, s1p1, s1p2, dl))
1262 return LW_FALSE;
1263 }
1264 }
1265 else
1266 { /*Find the closest point on the edges of both segments*/
1267 p1.x = s1p1->x + s1k * (s1p2->x - s1p1->x);
1268 p1.y = s1p1->y + s1k * (s1p2->y - s1p1->y);
1269 p1.z = s1p1->z + s1k * (s1p2->z - s1p1->z);
1270
1271 p2.x = s2p1->x + s2k * (s2p2->x - s2p1->x);
1272 p2.y = s2p1->y + s2k * (s2p2->y - s2p1->y);
1273 p2.z = s2p1->z + s2k * (s2p2->z - s2p1->z);
1274
1275 if (!lw_dist3d_pt_pt(&p1, &p2, dl)) /* Send the closest points to point-point calculation*/
1276 {
1277 return LW_FALSE;
1278 }
1279 }
1280 return LW_TRUE;
1281}
#define LW_FALSE
Definition liblwgeom.h:94
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:93
int p3dz_same(const POINT3DZ *p1, const POINT3DZ *p2)
Definition lwalgorithm.c:49
int lw_dist3d_pt_pt(const POINT3DZ *thep1, const POINT3DZ *thep2, DISTPTS3D *dl)
Compares incoming points and stores the points closest to each other or most far away from each other...
static int get_3dvector_from_points(const POINT3DZ *p1, const POINT3DZ *p2, VECTOR3D *v)
Definition measures3d.c:34
int lw_dist3d_pt_seg(const POINT3DZ *p, const POINT3DZ *A, const POINT3DZ *B, DISTPTS3D *dl)
If searching for min distance, this one finds the closest point on segment A-B from p.
#define DOT(u, v)
Definition measures3d.h:31
POINT3DZ p2
Definition measures3d.h:42
int twisted
Definition measures3d.h:45
POINT3DZ p1
Definition measures3d.h:41
double distance
Definition measures3d.h:40
double z
Definition liblwgeom.h:396
double x
Definition liblwgeom.h:396
double y
Definition liblwgeom.h:396

References DISTPTS3D::distance, DOT, get_3dvector_from_points(), lw_dist3d_pt_pt(), lw_dist3d_pt_seg(), LW_FALSE, LW_TRUE, DISTPTS3D::p1, DISTPTS3D::p2, p3dz_same(), 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: