PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ FindPolygons()

int FindPolygons ( SHPObject obj,
Ring ***  Out 
)

Definition at line 439 of file shp2pgsql-core.c.

440 {
441  Ring **Outer; /* Pointers to Outer rings */
442  int out_index=0; /* Count of Outer rings */
443  Ring **Inner; /* Pointers to Inner rings */
444  int in_index=0; /* Count of Inner rings */
445  int pi; /* part index */
446 
447 #if POSTGIS_DEBUG_LEVEL > 0
448  static int call = -1;
449  call++;
450 #endif
451 
452  LWDEBUGF(4, "FindPolygons[%d]: allocated space for %d rings\n", call, obj->nParts);
453 
454  /* Allocate initial memory */
455  Outer = (Ring **)malloc(sizeof(Ring *) * obj->nParts);
456  Inner = (Ring **)malloc(sizeof(Ring *) * obj->nParts);
457 
458  /* Iterate over rings dividing in Outers and Inners */
459  for (pi=0; pi < obj->nParts; pi++)
460  {
461  int vi; /* vertex index */
462  int vs; /* start index */
463  int ve; /* end index */
464  int nv; /* number of vertex */
465  double area = 0.0;
466  Ring *ring;
467 
468  /* Set start and end vertexes */
469  if (pi == obj->nParts - 1)
470  ve = obj->nVertices;
471  else
472  ve = obj->panPartStart[pi + 1];
473 
474  vs = obj->panPartStart[pi];
475 
476  /* Compute number of vertexes */
477  nv = ve - vs;
478 
479  /* Allocate memory for a ring */
480  ring = (Ring *)malloc(sizeof(Ring));
481  ring->list = (Point *)malloc(sizeof(Point) * nv);
482  ring->n = nv;
483  ring->next = NULL;
484  ring->linked = 0;
485 
486  /* Iterate over ring vertexes */
487  for (vi = vs; vi < ve; vi++)
488  {
489  int vn = vi+1; /* next vertex for area */
490  if (vn == ve)
491  vn = vs;
492 
493  ring->list[vi - vs].x = obj->padfX[vi];
494  ring->list[vi - vs].y = obj->padfY[vi];
495  ring->list[vi - vs].z = obj->padfZ[vi];
496  ring->list[vi - vs].m = obj->padfM[vi];
497 
498  area += (obj->padfX[vi] * obj->padfY[vn]) -
499  (obj->padfY[vi] * obj->padfX[vn]);
500  }
501 
502  /* Close the ring with first vertex */
503  /*ring->list[vi].x = obj->padfX[vs]; */
504  /*ring->list[vi].y = obj->padfY[vs]; */
505  /*ring->list[vi].z = obj->padfZ[vs]; */
506  /*ring->list[vi].m = obj->padfM[vs]; */
507 
508  /* Clockwise (or single-part). It's an Outer Ring ! */
509  if (area < 0.0 || obj->nParts == 1)
510  {
511  Outer[out_index] = ring;
512  out_index++;
513  }
514  else
515  {
516  /* Counterclockwise. It's an Inner Ring ! */
517  Inner[in_index] = ring;
518  in_index++;
519  }
520  }
521 
522  LWDEBUGF(4, "FindPolygons[%d]: found %d Outer, %d Inners\n", call, out_index, in_index);
523 
524  /* Put the inner rings into the list of the outer rings */
525  /* of which they are within */
526  for (pi = 0; pi < in_index; pi++)
527  {
528  Point pt, pt2;
529  int i;
530  Ring *inner = Inner[pi], *outer = NULL;
531 
532  pt.x = inner->list[0].x;
533  pt.y = inner->list[0].y;
534 
535  pt2.x = inner->list[1].x;
536  pt2.y = inner->list[1].y;
537 
538  /*
539  * If we assume that the case of the "big polygon w/o hole
540  * containing little polygon w/ hold" is ordered so that the
541  * big polygon comes first, then checking the list in reverse
542  * will assign the little polygon's hole to the little polygon
543  * w/o a lot of extra fancy containment logic here
544  */
545  for (i = out_index - 1; i >= 0; i--)
546  {
547  int in;
548 
549  in = PIP(pt, Outer[i]->list, Outer[i]->n);
550  if ( in || PIP(pt2, Outer[i]->list, Outer[i]->n) )
551  {
552  outer = Outer[i];
553  break;
554  }
555  }
556 
557  if (outer)
558  {
559  outer->linked++;
560  while (outer->next)
561  outer = outer->next;
562 
563  outer->next = inner;
564  }
565  else
566  {
567  /* The ring wasn't within any outer rings, */
568  /* assume it is a new outer ring. */
569  LWDEBUGF(4, "FindPolygons[%d]: hole %d is orphan\n", call, pi);
570 
571  Outer[out_index] = inner;
572  out_index++;
573  }
574  }
575 
576  *Out = Outer;
577  /*
578  * Only free the containing Inner array, not the ring elements, because
579  * the rings are now owned by the linked lists in the Outer array elements.
580  */
581  free(Inner);
582 
583  return out_index;
584 }
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
void * malloc(YYSIZE_T)
void free(void *)
int PIP(Point P, Point *V, int n)
PIP(): crossing number test for a point in a polygon input: P = a point, V[] = vertex points of a pol...
Point * list
unsigned int linked
struct struct_ring * next
double * padfX
Definition: shapefil.h:390
int nVertices
Definition: shapefil.h:389
double * padfY
Definition: shapefil.h:391
double * padfZ
Definition: shapefil.h:392
int * panPartStart
Definition: shapefil.h:386
double * padfM
Definition: shapefil.h:393

References free(), struct_ring::linked, struct_ring::list, LWDEBUGF, struct_point::m, malloc(), struct_ring::n, struct_ring::next, tagSHPObject::nParts, tagSHPObject::nVertices, tagSHPObject::padfM, tagSHPObject::padfX, tagSHPObject::padfY, tagSHPObject::padfZ, tagSHPObject::panPartStart, PIP(), struct_point::x, struct_point::y, and struct_point::z.

Referenced by GeneratePolygonGeometry().

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