PostGIS  3.2.2dev-r@@SVN_REVISION@@

◆ 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 1980 of file ptarray.c.

1981 {
1982  /* Do not try to simplify really short things */
1983  if (pa->npoints < 3 || pa->npoints <= minpts)
1984  return;
1985 
1986  if (tolerance == 0 && minpts <= 2)
1987  {
1989  return;
1990  }
1991 
1992  /* We use this array to keep track of the points we are keeping, so
1993  * we store just TRUE / FALSE in their position */
1994  uint8_t *kept_points = lwalloc(sizeof(uint8_t) * pa->npoints);
1995  memset(kept_points, LW_FALSE, sizeof(uint8_t) * pa->npoints);
1996  kept_points[0] = LW_TRUE;
1997  kept_points[pa->npoints - 1] = LW_TRUE;
1998  uint32_t keptn = 2;
1999 
2000  /* We use this array as a stack to store the iterators that we are going to need
2001  * in the following steps.
2002  * This is ~10% faster than iterating over @kept_points looking for them
2003  */
2004  uint32_t *iterator_stack = lwalloc(sizeof(uint32_t) * pa->npoints);
2005  iterator_stack[0] = 0;
2006  uint32_t iterator_stack_size = 1;
2007 
2008  uint32_t it_first = 0;
2009  uint32_t it_last = pa->npoints - 1;
2010 
2011  const double tolerance_sqr = tolerance * tolerance;
2012  /* For the first @minpts points we ignore the tolerance */
2013  double it_tol = keptn >= minpts ? tolerance_sqr : -1.0;
2014 
2015  while (iterator_stack_size)
2016  {
2017  uint32_t split = ptarray_dp_findsplit_in_place(pa, it_first, it_last, it_tol);
2018  if (split == it_first)
2019  {
2020  it_first = it_last;
2021  it_last = iterator_stack[--iterator_stack_size];
2022  }
2023  else
2024  {
2025  kept_points[split] = LW_TRUE;
2026  keptn++;
2027 
2028  iterator_stack[iterator_stack_size++] = it_last;
2029  it_last = split;
2030  it_tol = keptn >= minpts ? tolerance_sqr : -1.0;
2031  }
2032  }
2033 
2034  const size_t pt_size = ptarray_point_size(pa);
2035  /* The first point is already in place, so we don't need to copy it */
2036  size_t kept_it = 1;
2037  if (keptn == 2)
2038  {
2039  /* If there are 2 points remaining, it has to be first and last as
2040  * we added those at the start */
2041  memcpy(pa->serialized_pointlist + pt_size * kept_it,
2042  pa->serialized_pointlist + pt_size * (pa->npoints - 1),
2043  pt_size);
2044  }
2045  else if (pa->npoints != keptn) /* We don't need to move any points if we are keeping them all */
2046  {
2047  for (uint32_t i = 1; i < pa->npoints; i++)
2048  {
2049  if (kept_points[i])
2050  {
2051  memcpy(pa->serialized_pointlist + pt_size * kept_it,
2052  pa->serialized_pointlist + pt_size * i,
2053  pt_size);
2054  kept_it++;
2055  }
2056  }
2057  }
2058  pa->npoints = keptn;
2059 
2060  lwfree(kept_points);
2061  lwfree(iterator_stack);
2062 }
#define LW_FALSE
Definition: liblwgeom.h:108
void lwfree(void *mem)
Definition: lwutil.c:242
void * lwalloc(size_t size)
Definition: lwutil.c:227
#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:58
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:1873
static void ptarray_simplify_in_place_tolerance0(POINTARRAY *pa)
Definition: ptarray.c:1938
uint32_t npoints
Definition: liblwgeom.h:441
uint8_t * serialized_pointlist
Definition: liblwgeom.h:448

References LW_FALSE, LW_TRUE, lwalloc(), lwfree(), POINTARRAY::npoints, ptarray_dp_findsplit_in_place(), ptarray_point_size(), ptarray_simplify_in_place_tolerance0(), 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: