1488 double area, bbox_area, bbox_width, bbox_height;
1491 uint32_t sample_npoints, sample_sqrt, sample_width, sample_height;
1492 double sample_cell_size;
1498 const GEOSPreparedGeometry* gprep;
1500 GEOSCoordSequence* gseq;
1505 const size_t size = 2 *
sizeof(int);
1506 char tmp[2 *
sizeof(int)];
1507 const size_t stride = 2 *
sizeof(int);
1511 lwerror(
"%s: only polygons supported", __func__);
1520 bbox = *(lwpoly->bbox);
1523 bbox_width = bbox.
xmax - bbox.
xmin;
1524 bbox_height = bbox.
ymax - bbox.
ymin;
1525 bbox_area = bbox_width * bbox_height;
1527 if (
area == 0.0 || bbox_area == 0.0)
1529 lwerror(
"%s: zero area input polygon, TBD", __func__);
1534 sample_npoints = npoints * bbox_area /
area;
1539 sample_sqrt = lround(sqrt(sample_npoints));
1540 if (sample_sqrt == 0) sample_sqrt = 1;
1543 if (bbox_width > bbox_height)
1545 sample_width = sample_sqrt;
1546 sample_height = ceil((
double)sample_npoints / (
double)sample_width);
1547 sample_cell_size = bbox_width / sample_width;
1551 sample_height = sample_sqrt;
1552 sample_width = ceil((
double)sample_npoints / (
double)sample_height);
1553 sample_cell_size = bbox_height / sample_height;
1564 gprep = GEOSPrepare(g);
1575 cells =
lwalloc(2 *
sizeof(
int) * sample_height * sample_width);
1576 for (i = 0; i < sample_width; i++)
1578 for (j = 0; j < sample_height; j++)
1580 cells[2 * (i * sample_height + j)] = i;
1581 cells[2 * (i * sample_height + j) + 1] = j;
1586 n = sample_height * sample_width;
1589 for (i = 0; i < n - 1; ++i)
1591 size_t rnd = (size_t)rand();
1592 size_t j = i + rnd / (RAND_MAX / (n - i) + 1);
1594 memcpy(tmp, (
char *)cells + j * stride, size);
1595 memcpy((
char *)cells + j * stride, (
char *)cells + i * stride, size);
1596 memcpy((
char *)cells + i * stride, tmp, size);
1601 while (npoints_generated < npoints)
1604 for (i = 0; i < sample_width * sample_height; i++)
1607 double y = bbox.
ymin + cells[2 * i] * sample_cell_size;
1608 double x = bbox.
xmin + cells[2 * i + 1] * sample_cell_size;
1609 x += rand() * sample_cell_size / RAND_MAX;
1610 y += rand() * sample_cell_size / RAND_MAX;
1611 if (
x >= bbox.
xmax ||
y >= bbox.
ymax)
continue;
1613 gseq = GEOSCoordSeq_create(1, 2);
1614 #if POSTGIS_GEOS_VERSION < 38
1615 GEOSCoordSeq_setX(gseq, 0,
x);
1616 GEOSCoordSeq_setY(gseq, 0,
y);
1618 GEOSCoordSeq_setXY(gseq, 0,
x,
y);
1620 gpt = GEOSGeom_createPoint(gseq);
1622 contains = GEOSPreparedIntersects(gprep, gpt);
1624 GEOSGeom_destroy(gpt);
1628 GEOSPreparedGeom_destroy(gprep);
1629 GEOSGeom_destroy(g);
1635 npoints_generated++;
1637 if (npoints_generated == npoints)
1646 if (npoints_tested % 10000 == 0)
1647 LW_ON_INTERRUPT(GEOSPreparedGeom_destroy(gprep); GEOSGeom_destroy(g);
return NULL);
1651 if (done || iterations > 100)
break;
1654 GEOSPreparedGeom_destroy(gprep);
1655 GEOSGeom_destroy(g);
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
void lwgeom_geos_error(const char *fmt,...)
LWPOINT * lwpoint_make2d(int srid, double x, double y)
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
LWMPOINT * lwmpoint_add_lwpoint(LWMPOINT *mobj, const LWPOINT *obj)
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
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...
LWMPOINT * lwmpoint_construct_empty(int srid, char hasz, char hasm)
void * lwalloc(size_t size)
#define LW_ON_INTERRUPT(x)
double lwpoly_area(const LWPOLY *poly)
Find the area of the outer ring - sum (area of inner rings).
Datum area(PG_FUNCTION_ARGS)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Datum contains(PG_FUNCTION_ARGS)