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

◆ lwgeom_remove_repeated_points_in_place()

int lwgeom_remove_repeated_points_in_place ( LWGEOM geom,
double  tolerance 
)

Definition at line 1695 of file lwgeom.c.

1696{
1697 int geometry_modified = LW_FALSE;
1698 switch (geom->type)
1699 {
1700 /* No-op! Cannot remove points */
1701 case POINTTYPE:
1702 case TRIANGLETYPE:
1703 return geometry_modified;
1704 case LINETYPE: {
1705 LWLINE *g = (LWLINE *)(geom);
1706 POINTARRAY *pa = g->points;
1707 uint32_t npoints = pa->npoints;
1709 geometry_modified = npoints != pa->npoints;
1710 /* Invalid input, discard the collapsed line */
1711 if (pa->npoints < 2)
1712 {
1713 pa->npoints = 0;
1714 geometry_modified = LW_TRUE;
1715 }
1716 break;
1717 }
1718 case POLYGONTYPE: {
1719 uint32_t j = 0;
1720 LWPOLY *g = (LWPOLY *)(geom);
1721 for (uint32_t i = 0; i < g->nrings; i++)
1722 {
1723 POINTARRAY *pa = g->rings[i];
1724 uint32_t npoints = pa->npoints;
1726 geometry_modified |= npoints != pa->npoints;
1727 /* Drop collapsed rings */
1728 if (pa->npoints < 4)
1729 {
1730 geometry_modified = LW_TRUE;
1731 ptarray_free(pa);
1732 continue;
1733 }
1734 g->rings[j++] = pa;
1735 }
1736 /* Update ring count */
1737 g->nrings = j;
1738 break;
1739 }
1740 case MULTIPOINTTYPE: {
1741 double tolsq = tolerance * tolerance;
1742 LWMPOINT *mpt = (LWMPOINT *)geom;
1743
1744 for (uint8_t dim = 0; dim < 2; dim++)
1745 {
1746 /* sort by y, then by x - this way the result is sorted by x */
1747 qsort(mpt->geoms, mpt->ngeoms, sizeof(LWPOINT *), dim ? cmp_point_x : cmp_point_y);
1748 for (uint32_t i = 0; i < mpt->ngeoms; i++)
1749 {
1750 if (!mpt->geoms[i])
1751 continue;
1752
1753 const POINT2D *pti = getPoint2d_cp(mpt->geoms[i]->point, 0);
1754 if (!pti) continue;
1755
1756 /* check upcoming points if they're within tolerance of current one */
1757 for (uint32_t j = i + 1; j < mpt->ngeoms; j++)
1758 {
1759 if (!mpt->geoms[j])
1760 continue;
1761
1762 const POINT2D *ptj = getPoint2d_cp(mpt->geoms[j]->point, 0);
1763 if (!ptj) continue;
1764
1765 /* check that the point is in the strip of tolerance around the point */
1766 if ((dim ? ptj->x - pti->x : ptj->y - pti->y) > tolerance)
1767 break;
1768
1769 /* remove any upcoming point that is within tolerance circle */
1770 if (distance2d_sqr_pt_pt(pti, ptj) <= tolsq)
1771 {
1772 lwpoint_free(mpt->geoms[j]);
1773 mpt->geoms[j] = NULL;
1774 geometry_modified = LW_TRUE;
1775 }
1776 }
1777 }
1778
1779 /* null out empties */
1780 for (uint32_t j = 0; j < mpt->ngeoms; j++)
1781 {
1782 if (mpt->geoms[j] && lwpoint_is_empty(mpt->geoms[j]))
1783 {
1784 lwpoint_free(mpt->geoms[j]);
1785 mpt->geoms[j] = NULL;
1786 geometry_modified = LW_TRUE;
1787 }
1788 }
1789
1790 /* compactify array of points */
1791 uint32_t i = 0;
1792 for (uint32_t j = 0; j < mpt->ngeoms; j++)
1793 if (mpt->geoms[j])
1794 mpt->geoms[i++] = mpt->geoms[j];
1795 mpt->ngeoms = i;
1796 }
1797
1798 break;
1799 }
1800
1801 case CIRCSTRINGTYPE:
1802 /* Dunno how to handle these, will return untouched */
1803 return geometry_modified;
1804
1805 /* Can process most multi* types as generic collection */
1806 case MULTILINETYPE:
1807 case MULTIPOLYGONTYPE:
1808 case TINTYPE:
1809 case COLLECTIONTYPE:
1810 /* Curve types we mostly ignore, but allow the linear */
1811 /* portions to be processed by recursing into them */
1812 case MULTICURVETYPE:
1813 case CURVEPOLYTYPE:
1814 case MULTISURFACETYPE:
1815 case COMPOUNDTYPE: {
1816 uint32_t i, j = 0;
1817 LWCOLLECTION *col = (LWCOLLECTION *)(geom);
1818 for (i = 0; i < col->ngeoms; i++)
1819 {
1820 LWGEOM *g = col->geoms[i];
1821 if (!g)
1822 continue;
1823 geometry_modified |= lwgeom_remove_repeated_points_in_place(g, tolerance);
1824 /* Drop zero'ed out geometries */
1825 if (lwgeom_is_empty(g))
1826 {
1827 lwgeom_free(g);
1828 continue;
1829 }
1830 col->geoms[j++] = g;
1831 }
1832 /* Update geometry count */
1833 col->ngeoms = j;
1834 break;
1835 }
1836 default: {
1837 lwerror("%s: unsupported geometry type: %s", __func__, lwtype_name(geom->type));
1838 break;
1839 }
1840 }
1841
1842 if (geometry_modified)
1843 lwgeom_drop_bbox(geom);
1844 return geometry_modified;
1845}
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
#define LW_FALSE
Definition liblwgeom.h:94
#define COLLECTIONTYPE
Definition liblwgeom.h:108
#define COMPOUNDTYPE
Definition liblwgeom.h:110
void lwpoint_free(LWPOINT *pt)
Definition lwpoint.c:213
#define CURVEPOLYTYPE
Definition liblwgeom.h:111
#define MULTILINETYPE
Definition liblwgeom.h:106
#define MULTISURFACETYPE
Definition liblwgeom.h:113
#define LINETYPE
Definition liblwgeom.h:103
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
#define TINTYPE
Definition liblwgeom.h:116
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:107
#define POLYGONTYPE
Definition liblwgeom.h:104
#define CIRCSTRINGTYPE
Definition liblwgeom.h:109
void ptarray_free(POINTARRAY *pa)
Definition ptarray.c:327
#define MULTICURVETYPE
Definition liblwgeom.h:112
#define TRIANGLETYPE
Definition liblwgeom.h:115
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:93
void ptarray_remove_repeated_points_in_place(POINTARRAY *pa, double tolerance, uint32_t min_points)
Definition ptarray.c:1674
int lwpoint_is_empty(const LWPOINT *point)
static int cmp_point_x(const void *pa, const void *pb)
Definition lwgeom.c:1661
int lwgeom_remove_repeated_points_in_place(LWGEOM *geom, double tolerance)
Definition lwgeom.c:1695
void lwgeom_drop_bbox(LWGEOM *lwgeom)
Call this function to drop BBOX and SRID from LWGEOM.
Definition lwgeom.c:710
static int cmp_point_y(const void *pa, const void *pb)
Definition lwgeom.c:1678
void lwgeom_free(LWGEOM *lwgeom)
Definition lwgeom.c:1246
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
static double distance2d_sqr_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition lwinline.h:33
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:199
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:97
uint32_t ngeoms
Definition liblwgeom.h:580
LWGEOM ** geoms
Definition liblwgeom.h:575
uint8_t type
Definition liblwgeom.h:462
POINTARRAY * points
Definition liblwgeom.h:483
uint32_t ngeoms
Definition liblwgeom.h:538
LWPOINT ** geoms
Definition liblwgeom.h:533
POINTARRAY * point
Definition liblwgeom.h:471
POINTARRAY ** rings
Definition liblwgeom.h:519
uint32_t nrings
Definition liblwgeom.h:524
double x
Definition liblwgeom.h:390
uint32_t npoints
Definition liblwgeom.h:427

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: