PostGIS  3.1.6dev-r@@SVN_REVISION@@

◆ lwgeom_remove_repeated_points_in_place()

int lwgeom_remove_repeated_points_in_place ( LWGEOM in,
double  tolerance 
)

Definition at line 1554 of file lwgeom.c.

1555 {
1556  int geometry_modified = LW_FALSE;
1557  switch (geom->type)
1558  {
1559  /* No-op! Cannot remote points */
1560  case POINTTYPE:
1561  case TRIANGLETYPE:
1562  return geometry_modified;
1563  case LINETYPE:
1564  {
1565  LWLINE *g = (LWLINE*)(geom);
1566  POINTARRAY *pa = g->points;
1567  uint32_t npoints = pa->npoints;
1568  ptarray_remove_repeated_points_in_place(pa, tolerance, 2);
1569  geometry_modified = npoints != pa->npoints;
1570  /* Invalid output */
1571  if (pa->npoints == 1 && pa->maxpoints > 1)
1572  {
1573  /* Use first point as last point */
1574  pa->npoints = 2;
1575  ptarray_copy_point(pa, 0, 1);
1576  }
1577  break;
1578  }
1579  case POLYGONTYPE:
1580  {
1581  uint32_t i, j = 0;
1582  LWPOLY *g = (LWPOLY*)(geom);
1583  for (i = 0; i < g->nrings; i++)
1584  {
1585  POINTARRAY *pa = g->rings[i];
1586  int minpoints = 4;
1587  uint32_t npoints = 0;
1588  /* Skip zero'ed out rings */
1589  if(!pa)
1590  continue;
1591  npoints = pa->npoints;
1592  ptarray_remove_repeated_points_in_place(pa, tolerance, minpoints);
1593  geometry_modified |= npoints != pa->npoints;
1594  /* Drop collapsed rings */
1595  if(pa->npoints < 4)
1596  {
1597  geometry_modified = LW_TRUE;
1598  ptarray_free(pa);
1599  continue;
1600  }
1601  g->rings[j++] = pa;
1602  }
1603  /* Update ring count */
1604  g->nrings = j;
1605  break;
1606  }
1607  case MULTIPOINTTYPE:
1608  {
1609  double tolsq = tolerance*tolerance;
1610  uint32_t i, j, n = 0;
1611  LWMPOINT *mpt = (LWMPOINT *)(geom);
1612  LWPOINT **out;
1613  LWPOINT *out_stack[out_stack_size];
1614  int use_heap = (mpt->ngeoms > out_stack_size);
1615 
1616  /* No-op on empty */
1617  if (mpt->ngeoms < 2)
1618  return geometry_modified;
1619 
1620  /* We cannot write directly back to the multipoint */
1621  /* geoms array because we're reading out of it still */
1622  /* so we use a side array */
1623  if (use_heap)
1624  out = lwalloc(sizeof(LWMPOINT *) * mpt->ngeoms);
1625  else
1626  out = out_stack;
1627 
1628  /* Inefficient O(n^2) implementation */
1629  for (i = 0; i < mpt->ngeoms; i++)
1630  {
1631  int seen = 0;
1632  LWPOINT *p1 = mpt->geoms[i];
1633  const POINT2D *pt1 = getPoint2d_cp(p1->point, 0);
1634  for (j = 0; j < n; j++)
1635  {
1636  LWPOINT *p2 = out[j];
1637  const POINT2D *pt2 = getPoint2d_cp(p2->point, 0);
1638  if (distance2d_sqr_pt_pt(pt1, pt2) <= tolsq)
1639  {
1640  seen = 1;
1641  break;
1642  }
1643  }
1644  if (seen)
1645  {
1646  lwpoint_free(p1);
1647  continue;
1648  }
1649  out[n++] = p1;
1650  }
1651 
1652  /* Copy remaining points back into the input */
1653  /* array */
1654  memcpy(mpt->geoms, out, sizeof(LWPOINT *) * n);
1655  geometry_modified = mpt->ngeoms != n;
1656  mpt->ngeoms = n;
1657  if (use_heap) lwfree(out);
1658  break;
1659  }
1660 
1661  case CIRCSTRINGTYPE:
1662  /* Dunno how to handle these, will return untouched */
1663  return geometry_modified;
1664 
1665  /* Can process most multi* types as generic collection */
1666  case MULTILINETYPE:
1667  case MULTIPOLYGONTYPE:
1668  case TINTYPE:
1669  case COLLECTIONTYPE:
1670  /* Curve types we mostly ignore, but allow the linear */
1671  /* portions to be processed by recursing into them */
1672  case MULTICURVETYPE:
1673  case CURVEPOLYTYPE:
1674  case MULTISURFACETYPE:
1675  case COMPOUNDTYPE:
1676  {
1677  uint32_t i, j = 0;
1678  LWCOLLECTION *col = (LWCOLLECTION*)(geom);
1679  for (i = 0; i < col->ngeoms; i++)
1680  {
1681  LWGEOM *g = col->geoms[i];
1682  if (!g) continue;
1683  geometry_modified |= lwgeom_remove_repeated_points_in_place(g, tolerance);
1684  /* Drop zero'ed out geometries */
1685  if(lwgeom_is_empty(g))
1686  {
1687  lwgeom_free(g);
1688  continue;
1689  }
1690  col->geoms[j++] = g;
1691  }
1692  /* Update geometry count */
1693  col->ngeoms = j;
1694  break;
1695  }
1696  default:
1697  {
1698  lwerror("%s: unsupported geometry type: %s", __func__, lwtype_name(geom->type));
1699  break;
1700  }
1701  }
1702 
1703  if (geometry_modified)
1704  {
1705  lwgeom_drop_bbox(geom);
1706  }
1707  return geometry_modified;
1708 }
#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
void lwfree(void *mem)
Definition: lwutil.c:242
#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
void * lwalloc(size_t size)
Definition: lwutil.c:227
#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:1460
void ptarray_copy_point(POINTARRAY *pa, uint32_t from, uint32_t to)
Definition: lwgeom_api.c:395
int lwgeom_remove_repeated_points_in_place(LWGEOM *geom, double tolerance)
Definition: lwgeom.c:1554
void lwgeom_drop_bbox(LWGEOM *lwgeom)
Call this function to drop BBOX and SRID from LWGEOM.
Definition: lwgeom.c:665
void lwgeom_free(LWGEOM *lwgeom)
Definition: lwgeom.c:1138
#define out_stack_size
Definition: lwgeom.c:34
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
uint32_t maxpoints
Definition: liblwgeom.h:442
uint32_t npoints
Definition: liblwgeom.h:441

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

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: