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

◆ ptarray_simplify_in_place()

void ptarray_simplify_in_place ( POINTARRAY pa,
double  tolerance,
uint32_t  minpts 
)
Parameters
minptsminimum number of points to retain, if possible.

Definition at line 1595 of file ptarray.c.

1596{
1597 /* Do not try to simplify really short things */
1598 if (pa->npoints < 3 || pa->npoints <= minpts)
1599 return;
1600
1601 /* We use this array to keep track of the points we are keeping, so
1602 * we store just TRUE / FALSE in their position */
1603 uint8_t *kept_points = lwalloc(sizeof(uint8_t) * pa->npoints);
1604 memset(kept_points, LW_FALSE, sizeof(uint8_t) * pa->npoints);
1605 kept_points[0] = LW_TRUE;
1606 kept_points[pa->npoints - 1] = LW_TRUE;
1607 uint32_t keptn = 2;
1608
1609 /* We use this array as a stack to store the iterators that we are going to need
1610 * in the following steps.
1611 * This is ~10% faster than iterating over @kept_points looking for them
1612 */
1613 uint32_t *iterator_stack = lwalloc(sizeof(uint32_t) * pa->npoints);
1614 iterator_stack[0] = 0;
1615 uint32_t iterator_stack_size = 1;
1616
1617 uint32_t it_first = 0;
1618 uint32_t it_last = pa->npoints - 1;
1619
1620 const double tolerance_sqr = tolerance * tolerance;
1621 /* For the first @minpts points we ignore the tolerance */
1622 double it_tol = keptn >= minpts ? tolerance_sqr : -1.0;
1623
1624 while (iterator_stack_size)
1625 {
1626 uint32_t split = ptarray_dp_findsplit_in_place(pa, it_first, it_last, it_tol);
1627 if (split == it_first)
1628 {
1629 it_first = it_last;
1630 it_last = iterator_stack[--iterator_stack_size];
1631 }
1632 else
1633 {
1634 kept_points[split] = LW_TRUE;
1635 keptn++;
1636
1637 iterator_stack[iterator_stack_size++] = it_last;
1638 it_last = split;
1639 it_tol = keptn >= minpts ? tolerance_sqr : -1.0;
1640 }
1641 }
1642
1643 const size_t pt_size = ptarray_point_size(pa);
1644 /* The first point is already in place, so we don't need to copy it */
1645 size_t kept_it = 1;
1646 if (keptn == 2)
1647 {
1648 /* If there are 2 points remaining, it has to be first and last as
1649 * we added those at the start */
1650 memcpy(pa->serialized_pointlist + pt_size * kept_it,
1651 pa->serialized_pointlist + pt_size * (pa->npoints - 1),
1652 pt_size);
1653 }
1654 else
1655 {
1656 for (uint32_t i = 1; i < pa->npoints; i++)
1657 {
1658 if (kept_points[i])
1659 {
1660 memcpy(pa->serialized_pointlist + pt_size * kept_it,
1661 pa->serialized_pointlist + pt_size * i,
1662 pt_size);
1663 kept_it++;
1664 }
1665 }
1666 }
1667 pa->npoints = keptn;
1668
1669 lwfree(kept_points);
1670 lwfree(iterator_stack);
1671}
#define LW_FALSE
Definition liblwgeom.h:108
void * lwalloc(size_t size)
Definition lwutil.c:227
void lwfree(void *mem)
Definition lwutil.c:242
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:107
static size_t ptarray_point_size(const POINTARRAY *pa)
Definition lwinline.h:48
static uint32_t ptarray_dp_findsplit_in_place(const POINTARRAY *pts, uint32_t it_first, uint32_t it_last, double max_distance_sqr)
Definition ptarray.c:1531
uint32_t npoints
Definition liblwgeom.h:413
uint8_t * serialized_pointlist
Definition liblwgeom.h:420

References LW_FALSE, LW_TRUE, lwalloc(), lwfree(), POINTARRAY::npoints, ptarray_dp_findsplit_in_place(), ptarray_point_size(), and POINTARRAY::serialized_pointlist.

Referenced by lwgeom_simplify_in_place().

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