PostGIS  2.5.7dev-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 831 of file mvt.c.

832 {
833  LWGEOM *geom_clipped, *envelope;
834  GBOX geom_box;
835  GEOSGeometry *geos_input, *geos_box, *geos_result;
836 
837  gbox_init(&geom_box);
838  FLAGS_SET_GEODETIC(geom_box.flags, 0);
839  lwgeom_calculate_gbox(lwg_in, &geom_box);
840 
841  if (!gbox_overlaps_2d(&geom_box, clip_box))
842  {
843  POSTGIS_DEBUG(3, "mvt_geom: geometry outside clip box");
844  return NULL;
845  }
846 
847  if (gbox_contains_2d(clip_box, &geom_box))
848  {
849  POSTGIS_DEBUG(3, "mvt_geom: geometry contained fully inside the box");
850  return lwg_in;
851  }
852 
853  initGEOS(lwnotice, lwgeom_geos_error);
854  if (!(geos_input = LWGEOM2GEOS(lwg_in, 1)))
855  return NULL;
856 
857  envelope = (LWGEOM *)lwpoly_construct_envelope(
858  lwg_in->srid, clip_box->xmin, clip_box->ymin, clip_box->xmax, clip_box->ymax);
859  geos_box = LWGEOM2GEOS(envelope, 1);
860  lwgeom_free(envelope);
861  if (!geos_box)
862  {
863  GEOSGeom_destroy(geos_input);
864  return NULL;
865  }
866 
867  geos_result = GEOSIntersection(geos_input, geos_box);
868  if (!geos_result)
869  {
870  POSTGIS_DEBUG(3, "mvt_geom: no geometry after intersection. Retrying after validation");
871  GEOSGeom_destroy(geos_input);
872  lwg_in = lwgeom_make_valid(lwg_in);
873  if (!(geos_input = LWGEOM2GEOS(lwg_in, 1)))
874  {
875  GEOSGeom_destroy(geos_box);
876  return NULL;
877  }
878  geos_result = GEOSIntersection(geos_input, geos_box);
879  if (!geos_result)
880  {
881  GEOSGeom_destroy(geos_box);
882  GEOSGeom_destroy(geos_input);
883  return NULL;
884  }
885  }
886 
887  GEOSSetSRID(geos_result, lwg_in->srid);
888  geom_clipped = GEOS2LWGEOM(geos_result, 0);
889 
890  GEOSGeom_destroy(geos_box);
891  GEOSGeom_destroy(geos_input);
892  GEOSGeom_destroy(geos_result);
893 
894  if (!geom_clipped || lwgeom_is_empty(geom_clipped))
895  {
896  POSTGIS_DEBUG(3, "mvt_geom: no geometry after clipping");
897  return NULL;
898  }
899 
900  return geom_clipped;
901 }
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: g_box.c:330
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
Definition: g_box.c:47
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: g_box.c:346
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:1144
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwgeom.c:1393
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:746
#define FLAGS_SET_GEODETIC(flags, value)
Definition: liblwgeom.h:149
LWPOLY * lwpoly_construct_envelope(int srid, double x1, double y1, double x2, double y2)
Definition: lwpoly.c:98
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
double ymax
Definition: liblwgeom.h:298
double xmax
Definition: liblwgeom.h:296
double ymin
Definition: liblwgeom.h:297
double xmin
Definition: liblwgeom.h:295
uint8_t flags
Definition: liblwgeom.h:294
int32_t srid
Definition: liblwgeom.h:402

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: