示例#1
0
/*
 * Return a LWGEOM pointer from an TGEOM struct
 * Geometries are NOT copied
 */
LWGEOM*
lwgeom_from_tgeom(TGEOM *tgeom)
{
	int i, j, k;
	LWGEOM *geom;
	POINTARRAY *dpa;
	POINTARRAY **ppa;
	int hasz, hasm, edge_id;
	int dims=0;

	assert(tgeom);

	hasz=FLAGS_GET_Z(tgeom->flags);
	hasm=FLAGS_GET_M(tgeom->flags);

	geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, tgeom->srid, hasz, hasm);

	switch (tgeom->type)
	{
	case TINTYPE:
		geom->type = TINTYPE;
		for (i=0 ; i < tgeom->nfaces ; i++)
		{
			FLAGS_SET_Z(dims, hasz?1:0);
			FLAGS_SET_M(dims, hasm?1:0);
			dpa = ptarray_construct_empty(hasz, hasm, 4);

			for (j=0 ; j < tgeom->faces[i]->nedges ; j++)
			{
				edge_id = tgeom->faces[i]->edges[j];
				LWDEBUGF(3, "TIN edge_id: %i\n", edge_id);

				assert(edge_id);
				if (edge_id > 0)
					ptarray_append_point(dpa, tgeom->edges[edge_id]->s, LW_TRUE);
				else
					ptarray_append_point(dpa, tgeom->edges[-edge_id]->e, LW_TRUE);
			}

			edge_id = tgeom->faces[i]->edges[0];
			LWDEBUGF(3, "TIN edge_id: %i\n", edge_id);
			if (edge_id > 0)
				ptarray_append_point(dpa, tgeom->edges[edge_id]->s, LW_TRUE); 
			else
				ptarray_append_point(dpa, tgeom->edges[-edge_id]->e, LW_TRUE); 

			geom = (LWGEOM *) lwtin_add_lwtriangle((LWTIN *) geom,
			                                       lwtriangle_construct(tgeom->srid, NULL, dpa));
		}
		break;

	case POLYHEDRALSURFACETYPE:
		geom->type = POLYHEDRALSURFACETYPE;
		for (i=0 ; i < tgeom->nfaces ; i++)
		{
			FLAGS_SET_Z(dims, hasz?1:0);
			FLAGS_SET_M(dims, hasm?1:0);;
			dpa = ptarray_construct_empty(hasz, hasm, 4);

			for (j=0 ; j < tgeom->faces[i]->nedges ; j++)
			{
				edge_id = tgeom->faces[i]->edges[j];
				assert(edge_id);
				LWDEBUGF(3, "POLYHEDRALSURFACE edge_id: %i\n", edge_id);
				if (edge_id > 0)
					ptarray_append_point(dpa, tgeom->edges[edge_id]->s, LW_TRUE);
				else
					ptarray_append_point(dpa, tgeom->edges[-edge_id]->e, LW_TRUE);
			}

			edge_id = tgeom->faces[i]->edges[0];
			LWDEBUGF(3, "POLYHEDRALSURFACE edge_id: %i\n", edge_id);
			if (edge_id > 0)
				ptarray_append_point(dpa, tgeom->edges[edge_id]->s, LW_TRUE);
			else
				ptarray_append_point(dpa, tgeom->edges[-edge_id]->e, LW_TRUE);

			ppa = lwalloc(sizeof(POINTARRAY*)
			              * (tgeom->faces[i]->nrings + 1));
			ppa[0] = dpa;
			for (k=0; k < tgeom->faces[i]->nrings ; k++)
				ppa[k+1] = tgeom->faces[i]->rings[k];

			geom = (LWGEOM *) lwpsurface_add_lwpoly((LWPSURFACE *) geom,
			                                        lwpoly_construct(tgeom->srid, NULL, k + 1, ppa));
		}
		break;

	default:
		lwerror("lwgeom_from_tgeom: Unkwnown type %i - %s\n",
		        tgeom->type, lwtype_name(tgeom->type));
	}

	if (geom->srid == 0) geom->srid = SRID_UNKNOWN;

	return geom;
}
示例#2
0
LWGEOM*
pta_unstroke(const POINTARRAY *points, int type, int srid)
{
	int i = 0, j, k;
	POINT4D a1, a2, a3, b;
	POINT4D first, center;
	char *edges_in_arcs;
	int found_arc = LW_FALSE;
	int current_arc = 1;
	int num_edges;
	int edge_type; /* non-zero if edge is part of an arc */
	int start, end;
	LWCOLLECTION *outcol;
	/* Minimum number of edges, per quadrant, required to define an arc */
	const unsigned int min_quad_edges = 2;

	/* Die on null input */
	if ( ! points )
		lwerror("pta_unstroke called with null pointarray");

	/* Null on empty input? */
	if ( points->npoints == 0 )
		return NULL;

	/* We can't desegmentize anything shorter than four points */
	if ( points->npoints < 4 )
	{
		/* Return a linestring here*/
		lwerror("pta_unstroke needs implementation for npoints < 4");
	}

	/* Allocate our result array of vertices that are part of arcs */
	num_edges = points->npoints - 1;
	edges_in_arcs = lwalloc(num_edges + 1);
	memset(edges_in_arcs, 0, num_edges + 1);

	/* We make a candidate arc of the first two edges, */
	/* And then see if the next edge follows it */
	while( i < num_edges-2 )
	{
		unsigned int arc_edges;
		double num_quadrants;
		double angle;

		found_arc = LW_FALSE;
		/* Make candidate arc */
		getPoint4d_p(points, i  , &a1);
		getPoint4d_p(points, i+1, &a2);
		getPoint4d_p(points, i+2, &a3);
		memcpy(&first, &a1, sizeof(POINT4D));

		for( j = i+3; j < num_edges+1; j++ )
		{
			LWDEBUGF(4, "i=%d, j=%d", i, j);
			getPoint4d_p(points, j, &b);
			/* Does this point fall on our candidate arc? */
			if ( pt_continues_arc(&a1, &a2, &a3, &b) )
			{
				/* Yes. Mark this edge and the two preceding it as arc components */
				LWDEBUGF(4, "pt_continues_arc #%d", current_arc);
				found_arc = LW_TRUE;
				for ( k = j-1; k > j-4; k-- )
					edges_in_arcs[k] = current_arc;
			}
			else
			{
				/* No. So we're done with this candidate arc */
				LWDEBUG(4, "pt_continues_arc = false");
				current_arc++;
				break;
			}

			memcpy(&a1, &a2, sizeof(POINT4D));
			memcpy(&a2, &a3, sizeof(POINT4D));
			memcpy(&a3,  &b, sizeof(POINT4D));
		}
		/* Jump past all the edges that were added to the arc */
		if ( found_arc )
		{
			/* Check if an arc was composed by enough edges to be
			 * really considered an arc
			 * See http://trac.osgeo.org/postgis/ticket/2420
			 */
			arc_edges = j - 1 - i;
			LWDEBUGF(4, "arc defined by %d edges found", arc_edges);
			if ( first.x == b.x && first.y == b.y ) {
				LWDEBUG(4, "arc is a circle");
				num_quadrants = 4;
			}
			else {
				lw_arc_center((POINT2D*)&first, (POINT2D*)&b, (POINT2D*)&a1, (POINT2D*)&center);
				angle = lw_arc_angle((POINT2D*)&first, (POINT2D*)&center, (POINT2D*)&b);
        int p2_side = lw_segment_side((POINT2D*)&first, (POINT2D*)&a1, (POINT2D*)&b);
        if ( p2_side >= 0 ) angle = -angle;

				if ( angle < 0 ) angle = 2 * M_PI + angle;
				num_quadrants = ( 4 * angle ) / ( 2 * M_PI );
				LWDEBUGF(4, "arc angle (%g %g, %g %g, %g %g) is %g (side is %d), quandrants:%g", first.x, first.y, center.x, center.y, b.x, b.y, angle, p2_side, num_quadrants);
			}
			/* a1 is first point, b is last point */
			if ( arc_edges < min_quad_edges * num_quadrants ) {
				LWDEBUGF(4, "Not enough edges for a %g quadrants arc, %g needed", num_quadrants, min_quad_edges * num_quadrants);
				for ( k = j-1; k >= i; k-- )
					edges_in_arcs[k] = 0;
			}

			i = j-1;
		}
		else
		{
			/* Mark this edge as a linear edge */
			edges_in_arcs[i] = 0;
			i = i+1;
		}
	}

#if POSTGIS_DEBUG_LEVEL > 3
	{
		char *edgestr = lwalloc(num_edges+1);
		for ( i = 0; i < num_edges; i++ )
		{
			if ( edges_in_arcs[i] )
				edgestr[i] = 48 + edges_in_arcs[i];
			else
				edgestr[i] = '.';
		}
		edgestr[num_edges] = 0;
		LWDEBUGF(3, "edge pattern %s", edgestr);
		lwfree(edgestr);
	}
#endif

	start = 0;
	edge_type = edges_in_arcs[0];
	outcol = lwcollection_construct_empty(COMPOUNDTYPE, srid, ptarray_has_z(points), ptarray_has_m(points));
	for( i = 1; i < num_edges; i++ )
	{
		if( edge_type != edges_in_arcs[i] )
		{
			end = i - 1;
			lwcollection_add_lwgeom(outcol, geom_from_pa(points, srid, edge_type, start, end));
			start = i;
			edge_type = edges_in_arcs[i];
		}
	}
	lwfree(edges_in_arcs); /* not needed anymore */

	/* Roll out last item */
	end = num_edges - 1;
	lwcollection_add_lwgeom(outcol, geom_from_pa(points, srid, edge_type, start, end));

	/* Strip down to singleton if only one entry */
	if ( outcol->ngeoms == 1 )
	{
		LWGEOM *outgeom = outcol->geoms[0];
		outcol->ngeoms = 0; lwcollection_free(outcol);
		return outgeom;
	}
	return lwcollection_as_lwgeom(outcol);
}
示例#3
0
LWCOMPOUND *
lwcompound_construct_empty(int srid, char hasz, char hasm)
{
	LWCOMPOUND *ret = (LWCOMPOUND*)lwcollection_construct_empty(COMPOUNDTYPE, srid, hasz, hasm);
	return ret;
}