PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ lwgeom_subdivide_recursive()

static int lwgeom_subdivide_recursive ( const LWGEOM geom,
int  maxvertices,
int  depth,
LWCOLLECTION col,
const GBOX clip 
)
static

Definition at line 1943 of file lwgeom.c.

References FP_TOLERANCE, LWCOLLECTION::geoms, lwcollection_add_lwgeom(), lwerror(), lwgeom_clip_by_rect(), lwgeom_clone_deep(), lwgeom_count_vertices(), lwgeom_free(), lwgeom_is_collection(), lwtype_name(), MULTIPOINTTYPE, LWCOLLECTION::ngeoms, POINTTYPE, POLYHEDRALSURFACETYPE, TINTYPE, LWGEOM::type, GBOX::xmax, GBOX::xmin, GBOX::ymax, and GBOX::ymin.

Referenced by lwgeom_grid(), and lwgeom_subdivide().

1944 {
1945  const int maxdepth = 50;
1946  int nvertices = 0;
1947  int i, n = 0;
1948  double width = clip->xmax - clip->xmin;
1949  double height = clip->ymax - clip->ymin;
1950  GBOX subbox1, subbox2;
1951  LWGEOM *clipped1, *clipped2;
1952 
1953  if ( geom->type == POLYHEDRALSURFACETYPE || geom->type == TINTYPE )
1954  {
1955  lwerror("%s: unsupported geometry type '%s'", __func__, lwtype_name(geom->type));
1956  }
1957 
1958  if ( width == 0.0 && height == 0.0 )
1959  {
1960  if ( geom->type == POINTTYPE )
1961  {
1963  return 1;
1964  }
1965  else
1966  {
1967  return 0;
1968  }
1969  }
1970 
1971  /* Always just recurse into collections */
1972  if ( lwgeom_is_collection(geom) && geom->type != MULTIPOINTTYPE )
1973  {
1974  LWCOLLECTION *incol = (LWCOLLECTION*)geom;
1975  int n = 0;
1976  for ( i = 0; i < incol->ngeoms; i++ )
1977  {
1978  /* Don't increment depth yet, since we aren't actually subdividing geomtries yet */
1979  n += lwgeom_subdivide_recursive(incol->geoms[i], maxvertices, depth, col, clip);
1980  }
1981  return n;
1982  }
1983 
1984  /* But don't go too far. 2^50 ~= 10^15, that's enough subdivision */
1985  /* Just add what's left */
1986  if ( depth > maxdepth )
1987  {
1989  return 1;
1990  }
1991 
1992  nvertices = lwgeom_count_vertices(geom);
1993  /* Skip empties entirely */
1994  if ( nvertices == 0 )
1995  {
1996  return 0;
1997  }
1998 
1999  /* If it is under the vertex tolerance, just add it, we're done */
2000  if ( nvertices < maxvertices )
2001  {
2003  return 1;
2004  }
2005 
2006  subbox1 = subbox2 = *clip;
2007  if ( width > height )
2008  {
2009  subbox1.xmax = subbox2.xmin = (clip->xmin + clip->xmax)/2;
2010  }
2011  else
2012  {
2013  subbox1.ymax = subbox2.ymin = (clip->ymin + clip->ymax)/2;
2014  }
2015 
2016  if ( height == 0 )
2017  {
2018  subbox1.ymax += FP_TOLERANCE;
2019  subbox2.ymax += FP_TOLERANCE;
2020  subbox1.ymin -= FP_TOLERANCE;
2021  subbox2.ymin -= FP_TOLERANCE;
2022  }
2023 
2024  if ( width == 0 )
2025  {
2026  subbox1.xmax += FP_TOLERANCE;
2027  subbox2.xmax += FP_TOLERANCE;
2028  subbox1.xmin -= FP_TOLERANCE;
2029  subbox2.xmin -= FP_TOLERANCE;
2030  }
2031 
2032  clipped1 = lwgeom_clip_by_rect(geom, subbox1.xmin, subbox1.ymin, subbox1.xmax, subbox1.ymax);
2033  clipped2 = lwgeom_clip_by_rect(geom, subbox2.xmin, subbox2.ymin, subbox2.xmax, subbox2.ymax);
2034 
2035  ++depth;
2036 
2037  if ( clipped1 )
2038  {
2039  n += lwgeom_subdivide_recursive(clipped1, maxvertices, depth, col, &subbox1);
2040  lwgeom_free(clipped1);
2041  }
2042 
2043  if ( clipped2 )
2044  {
2045  n += lwgeom_subdivide_recursive(clipped2, maxvertices, depth, col, &subbox2);
2046  lwgeom_free(clipped2);
2047  }
2048 
2049  return n;
2050 
2051 }
double xmax
Definition: liblwgeom.h:293
LWGEOM * lwgeom_clip_by_rect(const LWGEOM *geom1, double x0, double y0, double x1, double y1)
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:97
int lwgeom_count_vertices(const LWGEOM *geom)
Count points in an LWGEOM.
Definition: lwgeom.c:1189
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep-clone an LWGEOM object.
Definition: lwgeom.c:482
double ymin
Definition: liblwgeom.h:294
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
double xmin
Definition: liblwgeom.h:292
LWGEOM ** geoms
Definition: liblwgeom.h:509
#define TINTYPE
Definition: liblwgeom.h:99
#define FP_TOLERANCE
Floating point comparators.
double ymax
Definition: liblwgeom.h:295
int lwgeom_is_collection(const LWGEOM *geom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1040
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
uint8_t type
Definition: liblwgeom.h:396
static int lwgeom_subdivide_recursive(const LWGEOM *geom, int maxvertices, int depth, LWCOLLECTION *col, const GBOX *clip)
Definition: lwgeom.c:1943
void lwgeom_free(LWGEOM *lwgeom)
Definition: lwgeom.c:1099
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:187
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
Here is the call graph for this function:
Here is the caller graph for this function: