PostGIS  2.3.7dev-r@@SVN_REVISION@@
static int lwgeom_subdivide_recursive ( const LWGEOM geom,
int  maxvertices,
int  depth,
LWCOLLECTION col,
const GBOX clip 
)
static

Definition at line 1912 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_subdivide().

1913 {
1914  const int maxdepth = 50;
1915  int nvertices = 0;
1916  int i, n = 0;
1917  double width = clip->xmax - clip->xmin;
1918  double height = clip->ymax - clip->ymin;
1919  GBOX subbox1, subbox2;
1920  LWGEOM *clipped1, *clipped2;
1921 
1922  if ( geom->type == POLYHEDRALSURFACETYPE || geom->type == TINTYPE )
1923  {
1924  lwerror("%s: unsupported geometry type '%s'", __func__, lwtype_name(geom->type));
1925  }
1926 
1927  if ( width == 0.0 && height == 0.0 )
1928  {
1929  if ( geom->type == POINTTYPE )
1930  {
1932  return 1;
1933  }
1934  else
1935  {
1936  return 0;
1937  }
1938  }
1939 
1940  /* Always just recurse into collections */
1941  if ( lwgeom_is_collection(geom) && geom->type != MULTIPOINTTYPE )
1942  {
1943  LWCOLLECTION *incol = (LWCOLLECTION*)geom;
1944  int n = 0;
1945  for ( i = 0; i < incol->ngeoms; i++ )
1946  {
1947  /* Don't increment depth yet, since we aren't actually subdividing geomtries yet */
1948  n += lwgeom_subdivide_recursive(incol->geoms[i], maxvertices, depth, col, clip);
1949  }
1950  return n;
1951  }
1952 
1953  /* But don't go too far. 2^50 ~= 10^15, that's enough subdivision */
1954  /* Just add what's left */
1955  if ( depth > maxdepth )
1956  {
1958  return 0;
1959  }
1960 
1961  nvertices = lwgeom_count_vertices(geom);
1962  /* Skip empties entirely */
1963  if ( nvertices == 0 )
1964  {
1965  return 0;
1966  }
1967 
1968  /* If it is under the vertex tolerance, just add it, we're done */
1969  if ( nvertices < maxvertices )
1970  {
1972  return 1;
1973  }
1974 
1975  subbox1 = subbox2 = *clip;
1976  if ( width > height )
1977  {
1978  subbox1.xmax = subbox2.xmin = (clip->xmin + clip->xmax)/2;
1979  }
1980  else
1981  {
1982  subbox1.ymax = subbox2.ymin = (clip->ymin + clip->ymax)/2;
1983  }
1984 
1985  if ( height == 0 )
1986  {
1987  subbox1.ymax += FP_TOLERANCE;
1988  subbox2.ymax += FP_TOLERANCE;
1989  subbox1.ymin -= FP_TOLERANCE;
1990  subbox2.ymin -= FP_TOLERANCE;
1991  }
1992 
1993  if ( width == 0 )
1994  {
1995  subbox1.xmax += FP_TOLERANCE;
1996  subbox2.xmax += FP_TOLERANCE;
1997  subbox1.xmin -= FP_TOLERANCE;
1998  subbox2.xmin -= FP_TOLERANCE;
1999  }
2000 
2001  clipped1 = lwgeom_clip_by_rect(geom, subbox1.xmin, subbox1.ymin, subbox1.xmax, subbox1.ymax);
2002  clipped2 = lwgeom_clip_by_rect(geom, subbox2.xmin, subbox2.ymin, subbox2.xmax, subbox2.ymax);
2003 
2004  ++depth;
2005 
2006  if ( clipped1 )
2007  {
2008  n += lwgeom_subdivide_recursive(clipped1, maxvertices, depth, col, &subbox1);
2009  lwgeom_free(clipped1);
2010  }
2011 
2012  if ( clipped2 )
2013  {
2014  n += lwgeom_subdivide_recursive(clipped2, maxvertices, depth, col, &subbox2);
2015  lwgeom_free(clipped2);
2016  }
2017 
2018  return n;
2019 
2020 }
double xmax
Definition: liblwgeom.h:292
LWGEOM * lwgeom_clip_by_rect(const LWGEOM *geom1, double x0, double y0, double x1, double y1)
#define MULTIPOINTTYPE
Definition: liblwgeom.h:87
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:96
int lwgeom_count_vertices(const LWGEOM *geom)
Count points in an LWGEOM.
Definition: lwgeom.c:1153
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep-clone an LWGEOM object.
Definition: lwgeom.c:446
double ymin
Definition: liblwgeom.h:293
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:216
double xmin
Definition: liblwgeom.h:291
LWGEOM ** geoms
Definition: liblwgeom.h:508
#define TINTYPE
Definition: liblwgeom.h:98
#define FP_TOLERANCE
Floating point comparators.
double ymax
Definition: liblwgeom.h:294
int lwgeom_is_collection(const LWGEOM *geom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1004
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:84
uint8_t type
Definition: liblwgeom.h:395
static int lwgeom_subdivide_recursive(const LWGEOM *geom, int maxvertices, int depth, LWCOLLECTION *col, const GBOX *clip)
Definition: lwgeom.c:1912
void lwgeom_free(LWGEOM *lwgeom)
Definition: lwgeom.c:1063
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:102

Here is the call graph for this function:

Here is the caller graph for this function: