PostGIS  3.3.9dev-r@@SVN_REVISION@@

◆ create_multipolygon()

static SHPObject * create_multipolygon ( SHPDUMPERSTATE state,
LWMPOLY lwmultipolygon 
)
static

Definition at line 259 of file pgsql2shp-core.c.

260 {
261  SHPObject *obj;
262  POINT4D p4d;
263  uint32_t i, j, k;
264 
265  double *xpts, *ypts, *zpts, *mpts;
266 
267  int *shpparts, shppointtotal = 0, shppoint = 0, shpringtotal = 0, shpring = 0;
268 
269  /* NOTE: Multipolygons are stored in shapefiles as Polygon* shapes with multiple outer rings */
270 
271  /* First count through each ring of each polygon so we now know much memory is required */
272  for (i = 0; i < lwmultipolygon->ngeoms; i++)
273  {
274  for (j = 0; j < lwmultipolygon->geoms[i]->nrings; j++)
275  {
276  shpringtotal++;
277  shppointtotal += lwmultipolygon->geoms[i]->rings[j]->npoints;
278  }
279  }
280 
281  /* Allocate storage for ring pointers */
282  shpparts = malloc(sizeof(int) * shpringtotal);
283 
284  /* Allocate storage for points */
285  xpts = malloc(sizeof(double) * shppointtotal);
286  ypts = malloc(sizeof(double) * shppointtotal);
287  zpts = malloc(sizeof(double) * shppointtotal);
288  mpts = malloc(sizeof(double) * shppointtotal);
289 
290  LWDEBUGF(4, "Total number of rings: %d Total number of points: %d", shpringtotal, shppointtotal);
291 
292  /* Iterate through each ring of each polygon in turn */
293  for (i = 0; i < lwmultipolygon->ngeoms; i++)
294  {
295  for (j = 0; j < lwmultipolygon->geoms[i]->nrings; j++)
296  {
297  /* For each ring, store the integer coordinate offset for the start of each ring */
298  shpparts[shpring] = shppoint;
299 
300  LWDEBUGF(4, "Ring offset: %d", shpring);
301 
302  for (k = 0; k < lwmultipolygon->geoms[i]->rings[j]->npoints; k++)
303  {
304  p4d = getPoint4d(lwmultipolygon->geoms[i]->rings[j], k);
305 
306  xpts[shppoint] = p4d.x;
307  ypts[shppoint] = p4d.y;
308  zpts[shppoint] = p4d.z;
309  mpts[shppoint] = p4d.m;
310 
311  LWDEBUGF(4, "MultiPolygon %d Polygon Ring %d - Point: %g %g %g %g", i, j, xpts[shppoint], ypts[shppoint], zpts[shppoint], mpts[shppoint]);
312 
313  /* Increment the point counter */
314  shppoint++;
315  }
316 
317  /*
318  * First ring should be clockwise,
319  * other rings should be counter-clockwise
320  */
321  if ( j == 0 )
322  {
323  if ( ! is_clockwise(lwmultipolygon->geoms[i]->rings[j]->npoints,
324  &xpts[shpparts[shpring]], &ypts[shpparts[shpring]], NULL) )
325  {
326  LWDEBUG(4, "Outer ring not clockwise, forcing clockwise\n");
327 
328  reverse_points(lwmultipolygon->geoms[i]->rings[j]->npoints,
329  &xpts[shpparts[shpring]], &ypts[shpparts[shpring]],
330  &zpts[shpparts[shpring]], &mpts[shpparts[shpring]]);
331  }
332  }
333  else
334  {
335  if ( is_clockwise(lwmultipolygon->geoms[i]->rings[j]->npoints,
336  &xpts[shpparts[shpring]], &ypts[shpparts[shpring]], NULL) )
337  {
338  LWDEBUGF(4, "Inner ring %d not counter-clockwise, forcing counter-clockwise\n", i);
339 
340  reverse_points(lwmultipolygon->geoms[i]->rings[j]->npoints,
341  &xpts[shpparts[shpring]], &ypts[shpparts[shpring]],
342  &zpts[shpparts[shpring]], &mpts[shpparts[shpring]]);
343  }
344  }
345 
346  /* Increment the ring counter */
347  shpring++;
348  }
349  }
350 
351  obj = SHPCreateObject(state->outshptype, -1, shpringtotal, shpparts, NULL, shppointtotal, xpts, ypts, zpts, mpts);
352 
353  free(xpts);
354  free(ypts);
355  free(zpts);
356  free(mpts);
357  free(shpparts);
358 
359  return obj;
360 }
POINT4D getPoint4d(const POINTARRAY *pa, uint32_t n)
Definition: lwgeom_api.c:108
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
void * malloc(YYSIZE_T)
void free(void *)
static int reverse_points(int num_points, double *x, double *y, double *z, double *m)
static int is_clockwise(int num_points, double *x, double *y, double *z)
SHPObject SHPAPI_CALL1 * SHPCreateObject(int nSHPType, int nShapeId, int nParts, const int *panPartStart, const int *panPartType, int nVertices, const double *padfX, const double *padfY, const double *padfZ, const double *padfM);SHPObject SHPAPI_CALL1(*) SHPCreateSimpleObject(int nSHPType, int nVertices, const double *padfX, const double *padfY, const double *padfZ
uint32_t ngeoms
Definition: liblwgeom.h:581
LWPOLY ** geoms
Definition: liblwgeom.h:576
POINTARRAY ** rings
Definition: liblwgeom.h:534
uint32_t nrings
Definition: liblwgeom.h:539
double m
Definition: liblwgeom.h:429
double x
Definition: liblwgeom.h:429
double z
Definition: liblwgeom.h:429
double y
Definition: liblwgeom.h:429
uint32_t npoints
Definition: liblwgeom.h:442

References free(), LWMPOLY::geoms, getPoint4d(), is_clockwise(), LWDEBUG, LWDEBUGF, POINT4D::m, malloc(), LWMPOLY::ngeoms, POINTARRAY::npoints, LWPOLY::nrings, shp_dumper_state::outshptype, reverse_points(), LWPOLY::rings, SHPCreateObject(), POINT4D::x, POINT4D::y, and POINT4D::z.

Referenced by ShpLoaderGenerateShapeRow().

Here is the call graph for this function:
Here is the caller graph for this function: