PostGIS  3.2.2dev-r@@SVN_REVISION@@

◆ lwgeom_remove_repeated_points_in_place()

int lwgeom_remove_repeated_points_in_place ( LWGEOM in,
double  tolerance 
)

Definition at line 1587 of file lwgeom.c.

1588 {
1589  int geometry_modified = LW_FALSE;
1590  switch (geom->type)
1591  {
1592  /* No-op! Cannot remove points */
1593  case POINTTYPE:
1594  case TRIANGLETYPE:
1595  return geometry_modified;
1596  case LINETYPE: {
1597  LWLINE *g = (LWLINE *)(geom);
1598  POINTARRAY *pa = g->points;
1599  uint32_t npoints = pa->npoints;
1600  ptarray_remove_repeated_points_in_place(pa, tolerance, 2);
1601  geometry_modified = npoints != pa->npoints;
1602  /* Invalid input, discard the collapsed line */
1603  if (pa->npoints < 2)
1604  {
1605  pa->npoints = 0;
1606  geometry_modified = LW_TRUE;
1607  }
1608  break;
1609  }
1610  case POLYGONTYPE: {
1611  uint32_t j = 0;
1612  LWPOLY *g = (LWPOLY *)(geom);
1613  for (uint32_t i = 0; i < g->nrings; i++)
1614  {
1615  POINTARRAY *pa = g->rings[i];
1616  uint32_t npoints = pa->npoints;
1617  ptarray_remove_repeated_points_in_place(pa, tolerance, 4);
1618  geometry_modified |= npoints != pa->npoints;
1619  /* Drop collapsed rings */
1620  if (pa->npoints < 4)
1621  {
1622  geometry_modified = LW_TRUE;
1623  ptarray_free(pa);
1624  continue;
1625  }
1626  g->rings[j++] = pa;
1627  }
1628  /* Update ring count */
1629  g->nrings = j;
1630  break;
1631  }
1632  case MULTIPOINTTYPE: {
1633  double tolsq = tolerance * tolerance;
1634  LWMPOINT *mpt = (LWMPOINT *)geom;
1635 
1636  for (uint8_t dim = 0; dim < 2; dim++)
1637  {
1638  /* sort by y, then by x - this way the result is sorted by x */
1639  qsort(mpt->geoms, mpt->ngeoms, sizeof(LWPOINT *), dim ? cmp_point_x : cmp_point_y);
1640  for (uint32_t i = 0; i < mpt->ngeoms; i++)
1641  {
1642  if (!mpt->geoms[i])
1643  continue;
1644 
1645  const POINT2D *pti = getPoint2d_cp(mpt->geoms[i]->point, 0);
1646  if (!pti) continue;
1647 
1648  /* check upcoming points if they're within tolerance of current one */
1649  for (uint32_t j = i + 1; j < mpt->ngeoms; j++)
1650  {
1651  if (!mpt->geoms[j])
1652  continue;
1653 
1654  const POINT2D *ptj = getPoint2d_cp(mpt->geoms[j]->point, 0);
1655  if (!ptj) continue;
1656 
1657  /* check that the point is in the strip of tolerance around the point */
1658  if ((dim ? ptj->x - pti->x : ptj->y - pti->y) > tolerance)
1659  break;
1660 
1661  /* remove any upcoming point that is within tolerance circle */
1662  if (distance2d_sqr_pt_pt(pti, ptj) <= tolsq)
1663  {
1664  lwpoint_free(mpt->geoms[j]);
1665  mpt->geoms[j] = NULL;
1666  geometry_modified = LW_TRUE;
1667  }
1668  }
1669  }
1670 
1671  /* null out empties */
1672  for (uint32_t j = 0; j < mpt->ngeoms; j++)
1673  {
1674  if (mpt->geoms[j] && lwpoint_is_empty(mpt->geoms[j]))
1675  {
1676  lwpoint_free(mpt->geoms[j]);
1677  mpt->geoms[j] = NULL;
1678  geometry_modified = LW_TRUE;
1679  }
1680  }
1681 
1682  /* compactify array of points */
1683  uint32_t i = 0;
1684  for (uint32_t j = 0; j < mpt->ngeoms; j++)
1685  if (mpt->geoms[j])
1686  mpt->geoms[i++] = mpt->geoms[j];
1687  mpt->ngeoms = i;
1688  }
1689 
1690  break;
1691  }
1692 
1693  case CIRCSTRINGTYPE:
1694  /* Dunno how to handle these, will return untouched */
1695  return geometry_modified;
1696 
1697  /* Can process most multi* types as generic collection */
1698  case MULTILINETYPE:
1699  case MULTIPOLYGONTYPE:
1700  case TINTYPE:
1701  case COLLECTIONTYPE:
1702  /* Curve types we mostly ignore, but allow the linear */
1703  /* portions to be processed by recursing into them */
1704  case MULTICURVETYPE:
1705  case CURVEPOLYTYPE:
1706  case MULTISURFACETYPE:
1707  case COMPOUNDTYPE: {
1708  uint32_t i, j = 0;
1709  LWCOLLECTION *col = (LWCOLLECTION *)(geom);
1710  for (i = 0; i < col->ngeoms; i++)
1711  {
1712  LWGEOM *g = col->geoms[i];
1713  if (!g)
1714  continue;
1715  geometry_modified |= lwgeom_remove_repeated_points_in_place(g, tolerance);
1716  /* Drop zero'ed out geometries */
1717  if (lwgeom_is_empty(g))
1718  {
1719  lwgeom_free(g);
1720  continue;
1721  }
1722  col->geoms[j++] = g;
1723  }
1724  /* Update geometry count */
1725  col->ngeoms = j;
1726  break;
1727  }
1728  default: {
1729  lwerror("%s: unsupported geometry type: %s", __func__, lwtype_name(geom->type));
1730  break;
1731  }
1732  }
1733 
1734  if (geometry_modified)
1735  lwgeom_drop_bbox(geom);
1736  return geometry_modified;
1737 }
#define LW_FALSE
Definition: liblwgeom.h:108
#define COLLECTIONTYPE
Definition: liblwgeom.h:122
#define COMPOUNDTYPE
Definition: liblwgeom.h:124
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:213
#define CURVEPOLYTYPE
Definition: liblwgeom.h:125
#define MULTILINETYPE
Definition: liblwgeom.h:120
#define MULTISURFACETYPE
Definition: liblwgeom.h:127
#define LINETYPE
Definition: liblwgeom.h:117
#define MULTIPOINTTYPE
Definition: liblwgeom.h:119
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:116
#define TINTYPE
Definition: liblwgeom.h:130
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:121
#define POLYGONTYPE
Definition: liblwgeom.h:118
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:123
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:126
#define TRIANGLETYPE
Definition: liblwgeom.h:129
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:107
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:1553
int lwgeom_remove_repeated_points_in_place(LWGEOM *geom, double tolerance)
Definition: lwgeom.c:1587
void lwgeom_drop_bbox(LWGEOM *lwgeom)
Call this function to drop BBOX and SRID from LWGEOM.
Definition: lwgeom.c:665
static int cmp_point_y(const void *pa, const void *pb)
Definition: lwgeom.c:1570
void lwgeom_free(LWGEOM *lwgeom)
Definition: lwgeom.c:1138
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:594
LWGEOM ** geoms
Definition: liblwgeom.h:589
POINTARRAY * points
Definition: liblwgeom.h:497
uint32_t ngeoms
Definition: liblwgeom.h:552
LWPOINT ** geoms
Definition: liblwgeom.h:547
POINTARRAY * point
Definition: liblwgeom.h:485
POINTARRAY ** rings
Definition: liblwgeom.h:533
uint32_t nrings
Definition: liblwgeom.h:538
double y
Definition: liblwgeom.h:404
double x
Definition: liblwgeom.h:404
uint32_t npoints
Definition: liblwgeom.h:441

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: