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

◆ ptarray_locate_point()

double ptarray_locate_point ( const POINTARRAY pa,
const POINT4D pt,
double *  dist,
POINT4D p_located 
)
extern

Definition at line 1518 of file ptarray.c.

1519{
1520 double mindist=DBL_MAX;
1521 double tlen, plen;
1522 uint32_t t, seg=0;
1523 POINT4D start4d, end4d, projtmp;
1524 POINT2D proj, p;
1525 const POINT2D *start = NULL, *end = NULL;
1526
1527 /* Initialize our 2D copy of the input parameter */
1528 p.x = p4d->x;
1529 p.y = p4d->y;
1530
1531 if ( ! proj4d ) proj4d = &projtmp;
1532
1533 /* Check for special cases (length 0 and 1) */
1534 if ( pa->npoints <= 1 )
1535 {
1536 if ( pa->npoints == 1 )
1537 {
1538 getPoint4d_p(pa, 0, proj4d);
1539 if ( mindistout )
1540 *mindistout = distance2d_pt_pt(&p, getPoint2d_cp(pa, 0));
1541 }
1542 return 0.0;
1543 }
1544
1545 start = getPoint2d_cp(pa, 0);
1546 /* Loop through pointarray looking for nearest segment */
1547 for (t=1; t<pa->npoints; t++)
1548 {
1549 double dist_sqr;
1550 end = getPoint2d_cp(pa, t);
1551 dist_sqr = distance2d_sqr_pt_seg(&p, start, end);
1552
1553 if (dist_sqr < mindist)
1554 {
1555 mindist = dist_sqr;
1556 seg=t-1;
1557 if ( mindist == 0 )
1558 {
1559 LWDEBUG(3, "Breaking on mindist=0");
1560 break;
1561 }
1562 }
1563
1564 start = end;
1565 }
1566 mindist = sqrt(mindist);
1567
1568 if ( mindistout ) *mindistout = mindist;
1569
1570 LWDEBUGF(3, "Closest segment: %d", seg);
1571 LWDEBUGF(3, "mindist: %g", mindist);
1572
1573 /*
1574 * We need to project the
1575 * point on the closest segment.
1576 */
1577 getPoint4d_p(pa, seg, &start4d);
1578 getPoint4d_p(pa, seg+1, &end4d);
1579 closest_point_on_segment(p4d, &start4d, &end4d, proj4d);
1580
1581 /* Copy 4D values into 2D holder */
1582 proj.x = proj4d->x;
1583 proj.y = proj4d->y;
1584
1585 LWDEBUGF(3, "Closest segment:%d, npoints:%d", seg, pa->npoints);
1586
1587 /* For robustness, force 1 when closest point == endpoint */
1588 if ( (seg >= (pa->npoints-2)) && p2d_same(&proj, end) )
1589 {
1590 return 1.0;
1591 }
1592
1593 LWDEBUGF(3, "Closest point on segment: %g,%g", proj.x, proj.y);
1594
1595 tlen = ptarray_length_2d(pa);
1596
1597 LWDEBUGF(3, "tlen %g", tlen);
1598
1599 /* Location of any point on a zero-length line is 0 */
1600 /* See http://trac.osgeo.org/postgis/ticket/1772#comment:2 */
1601 if ( tlen == 0 ) return 0;
1602
1603 plen=0;
1604 start = getPoint2d_cp(pa, 0);
1605 for (t=0; t<seg; t++, start=end)
1606 {
1607 end = getPoint2d_cp(pa, t+1);
1608 plen += distance2d_pt_pt(start, end);
1609
1610 LWDEBUGF(4, "Segment %d made plen %g", t, plen);
1611 }
1612
1613 plen+=distance2d_pt_pt(&proj, start);
1614
1615 LWDEBUGF(3, "plen %g, tlen %g", plen, tlen);
1616
1617 /* Floating point arithmetic is not reliable, make sure we return values [0,1] */
1618 double result = plen / tlen;
1619 if ( result < 0.0 ) {
1620 result = 0.0;
1621 } else if ( result > 1.0 ) {
1622 result = 1.0;
1623 }
1624 return result;
1625}
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition cu_print.c:267
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition measures.c:2344
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:2354
int p2d_same(const POINT2D *p1, const POINT2D *p2)
Definition lwalgorithm.c:57
#define LWDEBUG(level, msg)
Definition lwgeom_log.h:101
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
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:97
void closest_point_on_segment(const POINT4D *p, const POINT4D *A, const POINT4D *B, POINT4D *ret)
Definition ptarray.c:1408
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition ptarray.c:1975
double y
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:390
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(), result, 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: