PostGIS  3.3.9dev-r@@SVN_REVISION@@

◆ lwgeom_remove_repeated_points_in_place()

int lwgeom_remove_repeated_points_in_place ( LWGEOM in,
double  tolerance 
)

Definition at line 1604 of file lwgeom.c.

1605 {
1606  int geometry_modified = LW_FALSE;
1607  switch (geom->type)
1608  {
1609  /* No-op! Cannot remove points */
1610  case POINTTYPE:
1611  case TRIANGLETYPE:
1612  return geometry_modified;
1613  case LINETYPE: {
1614  LWLINE *g = (LWLINE *)(geom);
1615  POINTARRAY *pa = g->points;
1616  uint32_t npoints = pa->npoints;
1617  ptarray_remove_repeated_points_in_place(pa, tolerance, 2);
1618  geometry_modified = npoints != pa->npoints;
1619  /* Invalid input, discard the collapsed line */
1620  if (pa->npoints < 2)
1621  {
1622  pa->npoints = 0;
1623  geometry_modified = LW_TRUE;
1624  }
1625  break;
1626  }
1627  case POLYGONTYPE: {
1628  uint32_t j = 0;
1629  LWPOLY *g = (LWPOLY *)(geom);
1630  for (uint32_t i = 0; i < g->nrings; i++)
1631  {
1632  POINTARRAY *pa = g->rings[i];
1633  uint32_t npoints = pa->npoints;
1634  ptarray_remove_repeated_points_in_place(pa, tolerance, 4);
1635  geometry_modified |= npoints != pa->npoints;
1636  /* Drop collapsed rings */
1637  if (pa->npoints < 4)
1638  {
1639  geometry_modified = LW_TRUE;
1640  ptarray_free(pa);
1641  continue;
1642  }
1643  g->rings[j++] = pa;
1644  }
1645  /* Update ring count */
1646  g->nrings = j;
1647  break;
1648  }
1649  case MULTIPOINTTYPE: {
1650  double tolsq = tolerance * tolerance;
1651  LWMPOINT *mpt = (LWMPOINT *)geom;
1652 
1653  for (uint8_t dim = 0; dim < 2; dim++)
1654  {
1655  /* sort by y, then by x - this way the result is sorted by x */
1656  qsort(mpt->geoms, mpt->ngeoms, sizeof(LWPOINT *), dim ? cmp_point_x : cmp_point_y);
1657  for (uint32_t i = 0; i < mpt->ngeoms; i++)
1658  {
1659  if (!mpt->geoms[i])
1660  continue;
1661 
1662  const POINT2D *pti = getPoint2d_cp(mpt->geoms[i]->point, 0);
1663  if (!pti) continue;
1664 
1665  /* check upcoming points if they're within tolerance of current one */
1666  for (uint32_t j = i + 1; j < mpt->ngeoms; j++)
1667  {
1668  if (!mpt->geoms[j])
1669  continue;
1670 
1671  const POINT2D *ptj = getPoint2d_cp(mpt->geoms[j]->point, 0);
1672  if (!ptj) continue;
1673 
1674  /* check that the point is in the strip of tolerance around the point */
1675  if ((dim ? ptj->x - pti->x : ptj->y - pti->y) > tolerance)
1676  break;
1677 
1678  /* remove any upcoming point that is within tolerance circle */
1679  if (distance2d_sqr_pt_pt(pti, ptj) <= tolsq)
1680  {
1681  lwpoint_free(mpt->geoms[j]);
1682  mpt->geoms[j] = NULL;
1683  geometry_modified = LW_TRUE;
1684  }
1685  }
1686  }
1687 
1688  /* null out empties */
1689  for (uint32_t j = 0; j < mpt->ngeoms; j++)
1690  {
1691  if (mpt->geoms[j] && lwpoint_is_empty(mpt->geoms[j]))
1692  {
1693  lwpoint_free(mpt->geoms[j]);
1694  mpt->geoms[j] = NULL;
1695  geometry_modified = LW_TRUE;
1696  }
1697  }
1698 
1699  /* compactify array of points */
1700  uint32_t i = 0;
1701  for (uint32_t j = 0; j < mpt->ngeoms; j++)
1702  if (mpt->geoms[j])
1703  mpt->geoms[i++] = mpt->geoms[j];
1704  mpt->ngeoms = i;
1705  }
1706 
1707  break;
1708  }
1709 
1710  case CIRCSTRINGTYPE:
1711  /* Dunno how to handle these, will return untouched */
1712  return geometry_modified;
1713 
1714  /* Can process most multi* types as generic collection */
1715  case MULTILINETYPE:
1716  case MULTIPOLYGONTYPE:
1717  case TINTYPE:
1718  case COLLECTIONTYPE:
1719  /* Curve types we mostly ignore, but allow the linear */
1720  /* portions to be processed by recursing into them */
1721  case MULTICURVETYPE:
1722  case CURVEPOLYTYPE:
1723  case MULTISURFACETYPE:
1724  case COMPOUNDTYPE: {
1725  uint32_t i, j = 0;
1726  LWCOLLECTION *col = (LWCOLLECTION *)(geom);
1727  for (i = 0; i < col->ngeoms; i++)
1728  {
1729  LWGEOM *g = col->geoms[i];
1730  if (!g)
1731  continue;
1732  geometry_modified |= lwgeom_remove_repeated_points_in_place(g, tolerance);
1733  /* Drop zero'ed out geometries */
1734  if (lwgeom_is_empty(g))
1735  {
1736  lwgeom_free(g);
1737  continue;
1738  }
1739  col->geoms[j++] = g;
1740  }
1741  /* Update geometry count */
1742  col->ngeoms = j;
1743  break;
1744  }
1745  default: {
1746  lwerror("%s: unsupported geometry type: %s", __func__, lwtype_name(geom->type));
1747  break;
1748  }
1749  }
1750 
1751  if (geometry_modified)
1752  lwgeom_drop_bbox(geom);
1753  return geometry_modified;
1754 }
#define LW_FALSE
Definition: liblwgeom.h:109
#define COLLECTIONTYPE
Definition: liblwgeom.h:123
#define COMPOUNDTYPE
Definition: liblwgeom.h:125
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:213
#define CURVEPOLYTYPE
Definition: liblwgeom.h:126
#define MULTILINETYPE
Definition: liblwgeom.h:121
#define MULTISURFACETYPE
Definition: liblwgeom.h:128
#define LINETYPE
Definition: liblwgeom.h:118
#define MULTIPOINTTYPE
Definition: liblwgeom.h:120
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:117
#define TINTYPE
Definition: liblwgeom.h:131
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:122
#define POLYGONTYPE
Definition: liblwgeom.h:119
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:124
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:216
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:327
#define MULTICURVETYPE
Definition: liblwgeom.h:127
#define TRIANGLETYPE
Definition: liblwgeom.h:130
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:108
void ptarray_remove_repeated_points_in_place(POINTARRAY *pa, double tolerance, uint32_t min_points)
Definition: ptarray.c:1522
int lwpoint_is_empty(const LWPOINT *point)
static int cmp_point_x(const void *pa, const void *pb)
Definition: lwgeom.c:1570
int lwgeom_remove_repeated_points_in_place(LWGEOM *geom, double tolerance)
Definition: lwgeom.c:1604
void lwgeom_drop_bbox(LWGEOM *lwgeom)
Call this function to drop BBOX and SRID from LWGEOM.
Definition: lwgeom.c:682
static int cmp_point_y(const void *pa, const void *pb)
Definition: lwgeom.c:1587
void lwgeom_free(LWGEOM *lwgeom)
Definition: lwgeom.c:1155
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
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
static double distance2d_sqr_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition: lwinline.h:35
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwinline.h:203
uint32_t ngeoms
Definition: liblwgeom.h:595
LWGEOM ** geoms
Definition: liblwgeom.h:590
POINTARRAY * points
Definition: liblwgeom.h:498
uint32_t ngeoms
Definition: liblwgeom.h:553
LWPOINT ** geoms
Definition: liblwgeom.h:548
POINTARRAY * point
Definition: liblwgeom.h:486
POINTARRAY ** rings
Definition: liblwgeom.h:534
uint32_t nrings
Definition: liblwgeom.h:539
double y
Definition: liblwgeom.h:405
double x
Definition: liblwgeom.h:405
uint32_t npoints
Definition: liblwgeom.h:442

References CIRCSTRINGTYPE, cmp_point_x(), cmp_point_y(), COLLECTIONTYPE, COMPOUNDTYPE, CURVEPOLYTYPE, distance2d_sqr_pt_pt(), LWMPOINT::geoms, LWCOLLECTION::geoms, getPoint2d_cp(), LINETYPE, LW_FALSE, LW_TRUE, lwerror(), lwgeom_drop_bbox(), lwgeom_free(), lwgeom_is_empty(), lwgeom_remove_repeated_points_in_place(), lwpoint_free(), lwpoint_is_empty(), lwtype_name(), MULTICURVETYPE, MULTILINETYPE, MULTIPOINTTYPE, MULTIPOLYGONTYPE, MULTISURFACETYPE, LWMPOINT::ngeoms, LWCOLLECTION::ngeoms, POINTARRAY::npoints, LWPOLY::nrings, LWPOINT::point, LWLINE::points, POINTTYPE, POLYGONTYPE, ptarray_free(), ptarray_remove_repeated_points_in_place(), LWPOLY::rings, TINTYPE, TRIANGLETYPE, LWGEOM::type, POINT2D::x, and POINT2D::y.

Referenced by lwgeom_remove_repeated_points(), lwgeom_remove_repeated_points_in_place(), mvt_geom(), ST_RemoveRepeatedPoints(), and test_lwgeom_remove_repeated_points().

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