Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}