PostGIS  3.0.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 883 of file mvt.c.

884 {
885  LWGEOM *geom_clipped, *envelope;
886  GBOX geom_box;
887  GEOSGeometry *geos_input, *geos_box, *geos_result;
888 
889  gbox_init(&geom_box);
890  FLAGS_SET_GEODETIC(geom_box.flags, 0);
891  lwgeom_calculate_gbox(lwg_in, &geom_box);
892 
893  if (!gbox_overlaps_2d(&geom_box, clip_box))
894  {
895  POSTGIS_DEBUG(3, "mvt_geom: geometry outside clip box");
896  return NULL;
897  }
898 
899  if (gbox_contains_2d(clip_box, &geom_box))
900  {
901  POSTGIS_DEBUG(3, "mvt_geom: geometry contained fully inside the box");
902  return lwg_in;
903  }
904 
905  initGEOS(lwnotice, lwgeom_geos_error);
906  if (!(geos_input = LWGEOM2GEOS(lwg_in, 1)))
907  return NULL;
908 
909  envelope = (LWGEOM *)lwpoly_construct_envelope(
910  lwg_in->srid, clip_box->xmin, clip_box->ymin, clip_box->xmax, clip_box->ymax);
911  geos_box = LWGEOM2GEOS(envelope, 1);
912  lwgeom_free(envelope);
913  if (!geos_box)
914  {
915  GEOSGeom_destroy(geos_input);
916  return NULL;
917  }
918 
919  geos_result = GEOSIntersection(geos_input, geos_box);
920  if (!geos_result)
921  {
922  POSTGIS_DEBUG(3, "mvt_geom: no geometry after intersection. Retrying after validation");
923  GEOSGeom_destroy(geos_input);
924  lwg_in = lwgeom_make_valid(lwg_in);
925  if (!(geos_input = LWGEOM2GEOS(lwg_in, 1)))
926  {
927  GEOSGeom_destroy(geos_box);
928  return NULL;
929  }
930  geos_result = GEOSIntersection(geos_input, geos_box);
931  if (!geos_result)
932  {
933  GEOSGeom_destroy(geos_box);
934  GEOSGeom_destroy(geos_input);
935  return NULL;
936  }
937  }
938 
939  GEOSSetSRID(geos_result, lwg_in->srid);
940  geom_clipped = GEOS2LWGEOM(geos_result, 0);
941 
942  GEOSGeom_destroy(geos_box);
943  GEOSGeom_destroy(geos_input);
944  GEOSGeom_destroy(geos_result);
945 
946  if (!geom_clipped || lwgeom_is_empty(geom_clipped))
947  {
948  POSTGIS_DEBUG(3, "mvt_geom: no geometry after clipping");
949  return NULL;
950  }
951 
952  return geom_clipped;
953 }
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:737
#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:193
double ymax
Definition: liblwgeom.h:343
double xmax
Definition: liblwgeom.h:341
double ymin
Definition: liblwgeom.h:342
double xmin
Definition: liblwgeom.h:340
lwflags_t flags
Definition: liblwgeom.h:339
int32_t srid
Definition: liblwgeom.h:446

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: