PostGIS  2.1.10dev-r@@SVN_REVISION@@
int FindPolygons ( SHPObject obj,
Ring ***  Out 
)

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

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

Referenced by GeneratePolygonGeometry().

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

Here is the call graph for this function:

Here is the caller graph for this function: