PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ 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: