PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ ptarray_locate_point()

double ptarray_locate_point ( const POINTARRAY pa,
const POINT4D p4d,
double *  mindistout,
POINT4D proj4d 
)

Definition at line 1386 of file ptarray.c.

1387 {
1388  double mindist=DBL_MAX;
1389  double tlen, plen;
1390  uint32_t t, seg=0;
1391  POINT4D start4d, end4d, projtmp;
1392  POINT2D proj, p;
1393  const POINT2D *start = NULL, *end = NULL;
1394 
1395  /* Initialize our 2D copy of the input parameter */
1396  p.x = p4d->x;
1397  p.y = p4d->y;
1398 
1399  if ( ! proj4d ) proj4d = &projtmp;
1400 
1401  /* Check for special cases (length 0 and 1) */
1402  if ( pa->npoints <= 1 )
1403  {
1404  if ( pa->npoints == 1 )
1405  {
1406  getPoint4d_p(pa, 0, proj4d);
1407  if ( mindistout )
1408  *mindistout = distance2d_pt_pt(&p, getPoint2d_cp(pa, 0));
1409  }
1410  return 0.0;
1411  }
1412 
1413  start = getPoint2d_cp(pa, 0);
1414  /* Loop through pointarray looking for nearest segment */
1415  for (t=1; t<pa->npoints; t++)
1416  {
1417  double dist_sqr;
1418  end = getPoint2d_cp(pa, t);
1419  dist_sqr = distance2d_sqr_pt_seg(&p, start, end);
1420 
1421  if (dist_sqr < mindist)
1422  {
1423  mindist = dist_sqr;
1424  seg=t-1;
1425  if ( mindist == 0 )
1426  {
1427  LWDEBUG(3, "Breaking on mindist=0");
1428  break;
1429  }
1430  }
1431 
1432  start = end;
1433  }
1434  mindist = sqrt(mindist);
1435 
1436  if ( mindistout ) *mindistout = mindist;
1437 
1438  LWDEBUGF(3, "Closest segment: %d", seg);
1439  LWDEBUGF(3, "mindist: %g", mindist);
1440 
1441  /*
1442  * We need to project the
1443  * point on the closest segment.
1444  */
1445  getPoint4d_p(pa, seg, &start4d);
1446  getPoint4d_p(pa, seg+1, &end4d);
1447  closest_point_on_segment(p4d, &start4d, &end4d, proj4d);
1448 
1449  /* Copy 4D values into 2D holder */
1450  proj.x = proj4d->x;
1451  proj.y = proj4d->y;
1452 
1453  LWDEBUGF(3, "Closest segment:%d, npoints:%d", seg, pa->npoints);
1454 
1455  /* For robustness, force 1 when closest point == endpoint */
1456  if ( (seg >= (pa->npoints-2)) && p2d_same(&proj, end) )
1457  {
1458  return 1.0;
1459  }
1460 
1461  LWDEBUGF(3, "Closest point on segment: %g,%g", proj.x, proj.y);
1462 
1463  tlen = ptarray_length_2d(pa);
1464 
1465  LWDEBUGF(3, "tlen %g", tlen);
1466 
1467  /* Location of any point on a zero-length line is 0 */
1468  /* See http://trac.osgeo.org/postgis/ticket/1772#comment:2 */
1469  if ( tlen == 0 ) return 0;
1470 
1471  plen=0;
1472  start = getPoint2d_cp(pa, 0);
1473  for (t=0; t<seg; t++, start=end)
1474  {
1475  end = getPoint2d_cp(pa, t+1);
1476  plen += distance2d_pt_pt(start, end);
1477 
1478  LWDEBUGF(4, "Segment %d made plen %g", t, plen);
1479  }
1480 
1481  plen+=distance2d_pt_pt(&proj, start);
1482 
1483  LWDEBUGF(3, "plen %g, tlen %g", plen, tlen);
1484 
1485  return plen/tlen;
1486 }
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition: measures.c:2398
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:125
double distance2d_sqr_pt_seg(const POINT2D *p, const POINT2D *A, const POINT2D *B)
Definition: measures.c:2408
int p2d_same(const POINT2D *p1, const POINT2D *p2)
Definition: lwalgorithm.c:49
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition: lwinline.h:101
void closest_point_on_segment(const POINT4D *p, const POINT4D *A, const POINT4D *B, POINT4D *ret)
Definition: ptarray.c:1276
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition: ptarray.c:1832
double y
Definition: liblwgeom.h:390
double x
Definition: liblwgeom.h:390
double x
Definition: liblwgeom.h:414
double y
Definition: liblwgeom.h:414
uint32_t npoints
Definition: liblwgeom.h:427

References closest_point_on_segment(), distance2d_pt_pt(), distance2d_sqr_pt_seg(), getPoint2d_cp(), getPoint4d_p(), LWDEBUG, LWDEBUGF, POINTARRAY::npoints, p2d_same(), ptarray_length_2d(), POINT2D::x, POINT4D::x, POINT2D::y, and POINT4D::y.

Referenced by lwgeom_interpolate_point(), LWGEOM_line_locate_point(), and test_ptarray_locate_point().

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