1682 double area, bbox_area, bbox_width, bbox_height;
1685 int sample_npoints, sample_sqrt, sample_width, sample_height;
1686 double sample_cell_size;
1689 int npoints_generated = 0;
1690 int npoints_tested = 0;
1692 const GEOSPreparedGeometry *gprep;
1694 GEOSCoordSequence *gseq;
1699 const size_t size = 2*
sizeof(int);
1700 char tmp[2*
sizeof(int)];
1701 const size_t stride = 2*
sizeof(int);
1706 lwerror(
"%s: only polygons supported", __func__);
1722 bbox = *(lwpoly->bbox);
1725 bbox_width = bbox.
xmax - bbox.
xmin;
1726 bbox_height = bbox.
ymax - bbox.
ymin;
1727 bbox_area = bbox_width * bbox_height;
1729 if (area == 0.0 || bbox_area == 0.0)
1731 lwerror(
"%s: zero area input polygon, TBD", __func__);
1737 sample_npoints = npoints * bbox_area /
area;
1743 sample_sqrt = lround(sqrt(sample_npoints));
1744 if (sample_sqrt == 0)
1748 if (bbox_width > bbox_height)
1750 sample_width = sample_sqrt;
1751 sample_height = ceil((
double)sample_npoints / (
double)sample_width);
1752 sample_cell_size = bbox_width / sample_width;
1756 sample_height = sample_sqrt;
1757 sample_width = ceil((
double)sample_npoints / (
double)sample_height);
1758 sample_cell_size = bbox_height / sample_height;
1769 gprep = GEOSPrepare(g);
1780 cells =
lwalloc(2*
sizeof(
int)*sample_height*sample_width);
1781 for (i = 0; i < sample_width; i++)
1783 for (j = 0; j < sample_height; j++)
1785 cells[2*(i*sample_height+j)] = i;
1786 cells[2*(i*sample_height+j)+1] = j;
1792 n = sample_height*sample_width;
1794 for (i = 0; i < n - 1; ++i) {
1795 size_t rnd = (size_t) rand();
1796 size_t j = i + rnd / (RAND_MAX / (n - i) + 1);
1798 memcpy(tmp, (
char *)cells + j * stride, size);
1799 memcpy((
char *)cells + j * stride, (
char *)cells + i * stride, size);
1800 memcpy((
char *)cells + i * stride, tmp, size);
1807 while (npoints_generated < npoints)
1810 for (i = 0; i < sample_width*sample_height; i++)
1813 double y = bbox.
ymin + cells[2*i] * sample_cell_size;
1814 double x = bbox.
xmin + cells[2*i+1] * sample_cell_size;
1815 x += rand() * sample_cell_size / RAND_MAX;
1816 y += rand() * sample_cell_size / RAND_MAX;
1817 if (x >= bbox.
xmax || y >= bbox.
ymax)
1820 gseq = GEOSCoordSeq_create(1, 2);
1821 GEOSCoordSeq_setX(gseq, 0, x);
1822 GEOSCoordSeq_setY(gseq, 0, y);
1823 gpt = GEOSGeom_createPoint(gseq);
1825 contains = GEOSPreparedIntersects(gprep, gpt);
1827 GEOSGeom_destroy(gpt);
1831 GEOSPreparedGeom_destroy(gprep);
1832 GEOSGeom_destroy(g);
1838 npoints_generated++;
1840 if (npoints_generated == npoints)
1849 if (npoints_tested % 10000 == 0)
1851 LW_ON_INTERRUPT(GEOSPreparedGeom_destroy(gprep); GEOSGeom_destroy(g);
return NULL);
1856 if (done || iterations > 100)
break;
1859 GEOSPreparedGeom_destroy(gprep);
1860 GEOSGeom_destroy(g);
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
LWPOINT * lwpoint_make2d(int srid, double x, double y)
Datum area(PG_FUNCTION_ARGS)
Datum contains(PG_FUNCTION_ARGS)
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
#define LW_ON_INTERRUPT(x)
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
Calculate bounding box of a geometry, automatically taking into account whether it is cartesian or ge...
void lwgeom_geos_error(const char *fmt,...)
double lwpoly_area(const LWPOLY *poly)
Find the area of the outer ring - sum (area of inner rings).
LWMPOINT * lwmpoint_construct_empty(int srid, char hasz, char hasm)
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, int autofix)
LWMPOINT * lwmpoint_add_lwpoint(LWMPOINT *mobj, const LWPOINT *obj)
void * lwalloc(size_t size)
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
void lwerror(const char *fmt,...)
Write a notice out to the error handler.