PostGIS  3.1.6dev-r@@SVN_REVISION@@

◆ mvt_safe_clip_polygon_by_box()

static LWGEOM* mvt_safe_clip_polygon_by_box ( LWGEOM lwg_in,
GBOX clip_box 
)
static

Clips an input geometry using GEOSIntersection It used to try to use GEOSClipByRect (as mvt_unsafe_clip_by_box) but since that produces invalid output when an invalid geometry is given and detecting it resulted to be impossible, we use intersection instead and, upon error, force validation of the input and retry.

Might return NULL

Definition at line 847 of file mvt.c.

848 {
849  LWGEOM *geom_clipped, *envelope;
850  GBOX geom_box;
851  GEOSGeometry *geos_input, *geos_box, *geos_result;
852 
853  gbox_init(&geom_box);
854  FLAGS_SET_GEODETIC(geom_box.flags, 0);
855  lwgeom_calculate_gbox(lwg_in, &geom_box);
856 
857  if (!gbox_overlaps_2d(&geom_box, clip_box))
858  {
859  POSTGIS_DEBUG(3, "mvt_geom: geometry outside clip box");
860  return NULL;
861  }
862 
863  if (gbox_contains_2d(clip_box, &geom_box))
864  {
865  POSTGIS_DEBUG(3, "mvt_geom: geometry contained fully inside the box");
866  return lwg_in;
867  }
868 
869  initGEOS(lwnotice, lwgeom_geos_error);
870  if (!(geos_input = LWGEOM2GEOS(lwg_in, 1)))
871  return NULL;
872 
873  envelope = (LWGEOM *)lwpoly_construct_envelope(
874  lwg_in->srid, clip_box->xmin, clip_box->ymin, clip_box->xmax, clip_box->ymax);
875  geos_box = LWGEOM2GEOS(envelope, 1);
876  lwgeom_free(envelope);
877  if (!geos_box)
878  {
879  GEOSGeom_destroy(geos_input);
880  return NULL;
881  }
882 
883  geos_result = GEOSIntersection(geos_input, geos_box);
884  if (!geos_result)
885  {
886  POSTGIS_DEBUG(3, "mvt_geom: no geometry after intersection. Retrying after validation");
887  GEOSGeom_destroy(geos_input);
888  lwg_in = lwgeom_make_valid(lwg_in);
889  if (!(geos_input = LWGEOM2GEOS(lwg_in, 1)))
890  {
891  GEOSGeom_destroy(geos_box);
892  return NULL;
893  }
894  geos_result = GEOSIntersection(geos_input, geos_box);
895  if (!geos_result)
896  {
897  GEOSGeom_destroy(geos_box);
898  GEOSGeom_destroy(geos_input);
899  return NULL;
900  }
901  }
902 
903  GEOSSetSRID(geos_result, lwg_in->srid);
904  geom_clipped = GEOS2LWGEOM(geos_result, 0);
905 
906  GEOSGeom_destroy(geos_box);
907  GEOSGeom_destroy(geos_input);
908  GEOSGeom_destroy(geos_result);
909 
910  if (!geom_clipped || lwgeom_is_empty(geom_clipped))
911  {
912  POSTGIS_DEBUG(3, "mvt_geom: no geometry after clipping");
913  return NULL;
914  }
915 
916  return geom_clipped;
917 }
int gbox_overlaps_2d(const GBOX *g1, const GBOX *g2)
Return LW_TRUE if the GBOX overlaps on the 2d plane, LW_FALSE otherwise.
Definition: gbox.c:323
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
Definition: gbox.c:40
int gbox_contains_2d(const GBOX *g1, const GBOX *g2)
Return LW_TRUE if the first GBOX contains the second on the 2d plane, LW_FALSE otherwise.
Definition: gbox.c:339
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, uint8_t want3d)
void lwgeom_geos_error(const char *fmt,...)
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1138
LWPOLY * lwpoly_construct_envelope(int32_t srid, double x1, double y1, double x2, double y2)
Definition: lwpoly.c:98
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...
Definition: lwgeom.c:738
#define FLAGS_SET_GEODETIC(flags, value)
Definition: liblwgeom.h:189
LWGEOM * lwgeom_make_valid(LWGEOM *geom)
Attempts to make an invalid geometries valid w/out losing points.
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
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
double ymax
Definition: liblwgeom.h:371
double xmax
Definition: liblwgeom.h:369
double ymin
Definition: liblwgeom.h:370
double xmin
Definition: liblwgeom.h:368
lwflags_t flags
Definition: liblwgeom.h:367
int32_t srid
Definition: liblwgeom.h:474

References GBOX::flags, FLAGS_SET_GEODETIC, gbox_contains_2d(), gbox_init(), gbox_overlaps_2d(), GEOS2LWGEOM(), LWGEOM2GEOS(), lwgeom_calculate_gbox(), lwgeom_free(), lwgeom_geos_error(), lwgeom_is_empty(), lwgeom_make_valid(), lwnotice(), lwpoly_construct_envelope(), LWGEOM::srid, GBOX::xmax, GBOX::xmin, GBOX::ymax, and GBOX::ymin.

Referenced by mvt_iterate_clip_by_box_geos().

Here is the call graph for this function:
Here is the caller graph for this function: