int FindPolygons(SHPObject *obj, Ring ***Out) { Ring **Outer; /* Pointers to Outer rings */ int out_index=0; /* Count of Outer rings */ Ring **Inner; /* Pointers to Inner rings */ int in_index=0; /* Count of Inner rings */ int pi; /* part index */ #if POSTGIS_DEBUG_LEVEL > 0 static int call = -1; call++; #endif LWDEBUGF(4, "FindPolygons[%d]: allocated space for %d rings\n", call, obj->nParts); /* Allocate initial memory */ Outer = (Ring **)malloc(sizeof(Ring *) * obj->nParts); Inner = (Ring **)malloc(sizeof(Ring *) * obj->nParts); /* Iterate over rings dividing in Outers and Inners */ for (pi=0; pi < obj->nParts; pi++) { int vi; /* vertex index */ int vs; /* start index */ int ve; /* end index */ int nv; /* number of vertex */ double area = 0.0; Ring *ring; /* Set start and end vertexes */ if (pi == obj->nParts - 1) ve = obj->nVertices; else ve = obj->panPartStart[pi + 1]; vs = obj->panPartStart[pi]; /* Compute number of vertexes */ nv = ve - vs; /* Allocate memory for a ring */ ring = (Ring *)malloc(sizeof(Ring)); ring->list = (Point *)malloc(sizeof(Point) * nv); ring->n = nv; ring->next = NULL; ring->linked = 0; /* Iterate over ring vertexes */ for (vi = vs; vi < ve; vi++) { int vn = vi+1; /* next vertex for area */ if (vn == ve) vn = vs; ring->list[vi - vs].x = obj->padfX[vi]; ring->list[vi - vs].y = obj->padfY[vi]; ring->list[vi - vs].z = obj->padfZ[vi]; ring->list[vi - vs].m = obj->padfM[vi]; area += (obj->padfX[vi] * obj->padfY[vn]) - (obj->padfY[vi] * obj->padfX[vn]); } /* Close the ring with first vertex */ /*ring->list[vi].x = obj->padfX[vs]; */ /*ring->list[vi].y = obj->padfY[vs]; */ /*ring->list[vi].z = obj->padfZ[vs]; */ /*ring->list[vi].m = obj->padfM[vs]; */ /* Clockwise (or single-part). It's an Outer Ring ! */ if (area < 0.0 || obj->nParts == 1) { Outer[out_index] = ring; out_index++; } else { /* Counterclockwise. It's an Inner Ring ! */ Inner[in_index] = ring; in_index++; } } LWDEBUGF(4, "FindPolygons[%d]: found %d Outer, %d Inners\n", call, out_index, in_index); /* Put the inner rings into the list of the outer rings */ /* of which they are within */ for (pi = 0; pi < in_index; pi++) { Point pt, pt2; int i; Ring *inner = Inner[pi], *outer = NULL; pt.x = inner->list[0].x; pt.y = inner->list[0].y; pt2.x = inner->list[1].x; pt2.y = inner->list[1].y; for (i = 0; i < out_index; i++) { int in; in = PIP(pt, Outer[i]->list, Outer[i]->n); if ( in || PIP(pt2, Outer[i]->list, Outer[i]->n) ) { outer = Outer[i]; break; } /*fprintf(stderr, "!PIP %s\nOUTE %s\n", dump_ring(inner), dump_ring(Outer[i])); */ } if (outer) { outer->linked++; while (outer->next) outer = outer->next; outer->next = inner; } else { /* The ring wasn't within any outer rings, */ /* assume it is a new outer ring. */ LWDEBUGF(4, "FindPolygons[%d]: hole %d is orphan\n", call, pi); Outer[out_index] = inner; out_index++; } } *Out = Outer; free(Inner); return out_index; }
int FindPolygons(SHPObject *obj, Ring ***Out) { Ring **Outer; /* Pointers to Outer rings */ int out_index=0; /* Count of Outer rings */ Ring **Inner; /* Pointers to Inner rings */ int in_index=0; /* Count of Inner rings */ int pi; /* part index */ #if POSTGIS_DEBUG_LEVEL > 0 static int call = -1; call++; #endif LWDEBUGF(4, "FindPolygons[%d]: allocated space for %d rings\n", call, obj->nParts); /* Allocate initial memory */ Outer = (Ring **)malloc(sizeof(Ring *) * obj->nParts); Inner = (Ring **)malloc(sizeof(Ring *) * obj->nParts); /* Iterate over rings dividing in Outers and Inners */ for (pi=0; pi < obj->nParts; pi++) { int vi; /* vertex index */ int vs; /* start index */ int ve; /* end index */ int nv; /* number of vertex */ double area = 0.0; Ring *ring; /* Set start and end vertexes */ if (pi == obj->nParts - 1) ve = obj->nVertices; else ve = obj->panPartStart[pi + 1]; vs = obj->panPartStart[pi]; /* Compute number of vertexes */ nv = ve - vs; /* Allocate memory for a ring */ ring = (Ring *)malloc(sizeof(Ring)); ring->list = (Point *)malloc(sizeof(Point) * nv); ring->n = nv; ring->next = NULL; ring->linked = 0; /* Iterate over ring vertexes */ for (vi = vs; vi < ve; vi++) { int vn = vi+1; /* next vertex for area */ if (vn == ve) vn = vs; ring->list[vi - vs].x = obj->padfX[vi]; ring->list[vi - vs].y = obj->padfY[vi]; ring->list[vi - vs].z = obj->padfZ[vi]; ring->list[vi - vs].m = obj->padfM[vi]; area += (obj->padfX[vi] * obj->padfY[vn]) - (obj->padfY[vi] * obj->padfX[vn]); } /* Close the ring with first vertex */ /*ring->list[vi].x = obj->padfX[vs]; */ /*ring->list[vi].y = obj->padfY[vs]; */ /*ring->list[vi].z = obj->padfZ[vs]; */ /*ring->list[vi].m = obj->padfM[vs]; */ /* Clockwise (or single-part). It's an Outer Ring ! */ if (area < 0.0 || obj->nParts == 1) { Outer[out_index] = ring; out_index++; } else { /* Counterclockwise. It's an Inner Ring ! */ Inner[in_index] = ring; in_index++; } } LWDEBUGF(4, "FindPolygons[%d]: found %d Outer, %d Inners\n", call, out_index, in_index); /* Put the inner rings into the list of the outer rings */ /* of which they are within */ for (pi = 0; pi < in_index; pi++) { Point pt, pt2; int i; Ring *inner = Inner[pi], *outer = NULL; pt.x = inner->list[0].x; pt.y = inner->list[0].y; pt2.x = inner->list[1].x; pt2.y = inner->list[1].y; /* * If we assume that the case of the "big polygon w/o hole * containing little polygon w/ hold" is ordered so that the * big polygon comes first, then checking the list in reverse * will assign the little polygon's hole to the little polygon * w/o a lot of extra fancy containment logic here */ for (i = out_index - 1; i >= 0; i--) { int in; in = PIP(pt, Outer[i]->list, Outer[i]->n); if ( in || PIP(pt2, Outer[i]->list, Outer[i]->n) ) { outer = Outer[i]; break; } } if (outer) { outer->linked++; while (outer->next) outer = outer->next; outer->next = inner; } else { /* The ring wasn't within any outer rings, */ /* assume it is a new outer ring. */ LWDEBUGF(4, "FindPolygons[%d]: hole %d is orphan\n", call, pi); Outer[out_index] = inner; out_index++; } } *Out = Outer; /* * Only free the containing Inner array, not the ring elements, because * the rings are now owned by the linked lists in the Outer array elements. */ free(Inner); return out_index; }