예제 #1
0
char *
lwcollection_summary(LWCOLLECTION *col, int offset)
{
	size_t size = 128;
	char *result;
	char *tmp;
	int i;
	char *pad="";

	LWDEBUG(2, "lwcollection_summary called");

	result = (char *)lwalloc(size);

	sprintf(result, "%*.s%s[%s] with %d elements\n",
	        offset, pad, lwgeom_typename(TYPE_GETTYPE(col->type)),
	        lwgeom_typeflags(col->type),
	        col->ngeoms);

	for (i=0; i<col->ngeoms; i++)
	{
		tmp = lwgeom_summary(col->geoms[i], offset+2);
		size += strlen(tmp)+1;
		result = lwrealloc(result, size);

		LWDEBUGF(4, "Reallocated %d bytes for result", size);

		strcat(result, tmp);
		lwfree(tmp);
	}

	LWDEBUG(3, "lwcollection_summary returning");

	return result;
}
예제 #2
0
파일: ptarray.c 프로젝트: gbroccolo/postgis
/*
* Add a point into a pointarray. Only adds as many dimensions as the 
* pointarray supports.
*/
int
ptarray_insert_point(POINTARRAY *pa, const POINT4D *p, int where)
{
	size_t point_size = ptarray_point_size(pa);
	LWDEBUGF(5,"pa = %p; p = %p; where = %d", pa, p, where);
	LWDEBUGF(5,"pa->npoints = %d; pa->maxpoints = %d", pa->npoints, pa->maxpoints);
	
	if ( FLAGS_GET_READONLY(pa->flags) ) 
	{
		lwerror("ptarray_insert_point: called on read-only point array");
		return LW_FAILURE;
	}
	
	/* Error on invalid offset value */
	if ( where > pa->npoints || where < 0)
	{
		lwerror("ptarray_insert_point: offset out of range (%d)", where);
		return LW_FAILURE;
	}
	
	/* If we have no storage, let's allocate some */
	if( pa->maxpoints == 0 || ! pa->serialized_pointlist ) 
	{
		pa->maxpoints = 32;
		pa->npoints = 0;
		pa->serialized_pointlist = lwalloc(ptarray_point_size(pa) * pa->maxpoints);
	}

	/* Error out if we have a bad situation */
	if ( pa->npoints > pa->maxpoints )
	{
		lwerror("npoints (%d) is greated than maxpoints (%d)", pa->npoints, pa->maxpoints);
		return LW_FAILURE;
	}
	
	/* Check if we have enough storage, add more if necessary */
	if( pa->npoints == pa->maxpoints )
	{
		pa->maxpoints *= 2;
		pa->serialized_pointlist = lwrealloc(pa->serialized_pointlist, ptarray_point_size(pa) * pa->maxpoints);
	}
	
	/* Make space to insert the new point */
	if( where < pa->npoints )
	{
		size_t copy_size = point_size * (pa->npoints - where);
		memmove(getPoint_internal(pa, where+1), getPoint_internal(pa, where), copy_size);
		LWDEBUGF(5,"copying %d bytes to start vertex %d from start vertex %d", copy_size, where+1, where);
	}
	
	/* We have one more point */
	++pa->npoints;
	
	/* Copy the new point into the gap */
	ptarray_set_point4d(pa, where, p);
	LWDEBUGF(5,"copying new point to start vertex %d", point_size, where);
	
	return LW_SUCCESS;
}
예제 #3
0
/*
 * Add a LWTRIANGLE inside a tgeom
 * Copy geometries from LWTRIANGLE
 */
static TGEOM*
tgeom_add_triangle(TGEOM *tgeom, LWTRIANGLE *triangle)
{
	int i;

	assert(tgeom);
	assert(triangle);

	if ((tgeom->nfaces + 1) == INT_MAX)
		lwerror("tgeom_add_triangle: Unable to alloc more than %i faces", INT_MAX);

	/* Integrity checks on subgeom, dims and srid */
	if (tgeom->type != TINTYPE)
		lwerror("tgeom_add_triangle: Unable to handle %s - %s type",
		        tgeom->type, lwtype_name(tgeom->type));

	if (FLAGS_NDIMS(tgeom->flags) != FLAGS_NDIMS(triangle->flags))
		lwerror("tgeom_add_triangle: Mixed dimension");

	if (tgeom->srid != triangle->srid
	        && (tgeom->srid != 0 && triangle->srid != SRID_UNKNOWN))
		lwerror("tgeom_add_triangle: Mixed srid. Tgeom: %i / Triangle: %i",
		        tgeom->srid, triangle->srid);

	/* handle face array allocation */
	if (tgeom->maxfaces == 0)
	{
		tgeom->faces = lwalloc(sizeof(TFACE*) * 2);
		tgeom->maxfaces = 2;
	}
	if ((tgeom->maxfaces - 1) == tgeom->nfaces)
	{
		tgeom->faces = lwrealloc(tgeom->faces,
		                         sizeof(TFACE*) * tgeom->maxfaces * 2);
		tgeom->maxfaces *= 2;
	}

	/* add an empty face */
	tgeom->faces[tgeom->nfaces] = lwalloc(sizeof(TFACE));
	tgeom->faces[tgeom->nfaces]->rings = NULL;
	tgeom->faces[tgeom->nfaces]->nrings = 0;
	tgeom->faces[tgeom->nfaces]->nedges = 0;
	tgeom->faces[tgeom->nfaces]->maxedges = 0;

	/* Compute edge on triangle */
	for (i=1 ; i < triangle->points->npoints ; i++)
	{
		POINT4D p1, p2;

		getPoint4d_p(triangle->points, i-1, &p1);
		getPoint4d_p(triangle->points, i,   &p2);

		tgeom_add_face_edge(tgeom, tgeom->nfaces, &p1, &p2);
	}

	tgeom->nfaces++;

	return tgeom;
}
예제 #4
0
/**
 * Ensure the collection can hold up at least ngeoms
 */
void lwcollection_reserve(LWCOLLECTION *col, int ngeoms)
{
	if ( ngeoms <= col->maxgeoms ) return;

	/* Allocate more space if we need it */
	do { col->maxgeoms *= 2; } while ( col->maxgeoms < ngeoms );
	col->geoms = lwrealloc(col->geoms, sizeof(LWGEOM*) * col->maxgeoms);
}
예제 #5
0
static LWGEOM*
lwcollection_split(const LWCOLLECTION* lwcoll_in, const LWGEOM* blade_in)
{
	LWGEOM** split_vector=NULL;
	LWCOLLECTION* out;
	size_t split_vector_capacity;
	size_t split_vector_size=0;
	size_t i,j;

	split_vector_capacity=8;
	split_vector = lwalloc(split_vector_capacity * sizeof(LWGEOM*));
	if ( ! split_vector )
	{
		lwerror("Out of virtual memory");
		return NULL;
	}

	for (i=0; i<lwcoll_in->ngeoms; ++i)
	{
		LWCOLLECTION* col;
		LWGEOM* split = lwgeom_split(lwcoll_in->geoms[i], blade_in);
		/* an exception should prevent this from ever returning NULL */
		if ( ! split ) return NULL;

		col = lwgeom_as_lwcollection(split);
		/* Output, if any, will always be a collection */
		assert(col);

		/* Reallocate split_vector if needed */
		if ( split_vector_size + col->ngeoms > split_vector_capacity )
		{
			/* NOTE: we could be smarter on reallocations here */
			split_vector_capacity += col->ngeoms;
			split_vector = lwrealloc(split_vector,
			                         split_vector_capacity * sizeof(LWGEOM*));
			if ( ! split_vector )
			{
				lwerror("Out of virtual memory");
				return NULL;
			}
		}

		for (j=0; j<col->ngeoms; ++j)
		{
			col->geoms[j]->srid = SRID_UNKNOWN; /* strip srid */
			split_vector[split_vector_size++] = col->geoms[j];
		}
		lwfree(col->geoms);
		lwfree(col);
	}

	/* Now split_vector has split_vector_size geometries */
	out = lwcollection_construct(COLLECTIONTYPE, lwcoll_in->srid,
	                             NULL, split_vector_size, split_vector);

	return (LWGEOM*)out;
}
예제 #6
0
int lwcurvepoly_add_ring(LWCURVEPOLY *poly, LWGEOM *ring)
{
	int i;
	
	/* Can't do anything with NULLs */
	if( ! poly || ! ring ) 
	{
		LWDEBUG(4,"NULL inputs!!! quitting");
		return LW_FAILURE;
	}

	/* Check that we're not working with garbage */
	if ( poly->rings == NULL && (poly->nrings || poly->maxrings) )
	{
		LWDEBUG(4,"mismatched nrings/maxrings");
		lwerror("Curvepolygon is in inconsistent state. Null memory but non-zero collection counts.");
	}

	/* Check that we're adding an allowed ring type */
	if ( ! ( ring->type == LINETYPE || ring->type == CIRCSTRINGTYPE || ring->type == COMPOUNDTYPE ) )
	{
		LWDEBUGF(4,"got incorrect ring type: %s",lwtype_name(ring->type));
		return LW_FAILURE;
	}

		
	/* In case this is a truly empty, make some initial space  */
	if ( poly->rings == NULL )
	{
		poly->maxrings = 2;
		poly->nrings = 0;
		poly->rings = (LWGEOM **)lwalloc(poly->maxrings * sizeof(LWGEOM*));
	}

	/* Allocate more space if we need it */
	if ( poly->nrings == poly->maxrings )
	{
		poly->maxrings *= 2;
		poly->rings = (LWGEOM **)lwrealloc(poly->rings, sizeof(LWGEOM*) * poly->maxrings);
	}

	/* Make sure we don't already have a reference to this geom */
	for ( i = 0; i < poly->nrings; i++ )
	{
		if ( poly->rings[i] == ring )
		{
			LWDEBUGF(4, "Found duplicate geometry in collection %p == %p", poly->rings[i], ring);
			return LW_SUCCESS;
		}
	}

	/* Add the ring and increment the ring count */
	poly->rings[poly->nrings] = (LWGEOM*)ring;
	poly->nrings++;
	return LW_SUCCESS;	
}
예제 #7
0
static LWGEOM*
parse_geojson_polygon(json_object *geojson, bool *hasz,  int *root_srid)
{
	LWGEOM *geom;
	POINTARRAY **ppa;
	json_object* rings = NULL;
	int i = 0, j = 0;
	int ring = 0;

	rings = findMemberByName( geojson, "coordinates" );
	if ( ! rings )
		geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);

	ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));

	if( json_type_array == json_object_get_type( rings ) )
	{
		int nPoints;
		json_object* points = NULL;
		ppa[0] = ptarray_construct_empty(1, 0, 1);
		ring = json_object_array_length( rings );
		points = json_object_array_get_idx( rings, 0 );
		nPoints = json_object_array_length( points );

		for (i=0; i < nPoints; i++ )
		{
			json_object* coords = NULL;
			coords = json_object_array_get_idx( points, i );
			parse_geojson_coord(coords, hasz, ppa[0]);
		}

		for(i = 1; i < ring; ++i)
		{
			int nPoints;
			ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, sizeof(POINTARRAY*) * (i + 1));
			ppa[i] = ptarray_construct_empty(1, 0, 1);
			points = json_object_array_get_idx( rings, i );
			nPoints = json_object_array_length( points );
			for (j=0; j < nPoints; j++ )
			{
				json_object* coords = NULL;
				coords = json_object_array_get_idx( points, j );
				parse_geojson_coord(coords, hasz, ppa[i]);
			}
		}
	}

	geom = (LWGEOM *) lwpoly_construct(*root_srid, NULL, ring, ppa);
	return geom;
}
예제 #8
0
/**
* If necessary, expand the stringbuffer_t internal buffer to accomodate the
* specified additional size.
*/
static inline void
stringbuffer_makeroom(stringbuffer_t *s, size_t size_to_add)
{
	size_t current_size = (s->str_end - s->str_start);
	size_t capacity = s->capacity;
	size_t required_size = current_size + size_to_add;

	while (capacity < required_size)
		capacity *= 2;

	if ( capacity > s->capacity )
	{
		s->str_start = lwrealloc(s->str_start, capacity);
		s->capacity = capacity;
		s->str_end = s->str_start + current_size;
	}
}
예제 #9
0
파일: lwpoly.c 프로젝트: ahinz/postgis
/**
* Add a ring to a polygon. Point array will be referenced, not copied.
*/
int
lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa) 
{
	if( ! poly || ! pa ) 
		return LW_FAILURE;
		
	/* We have used up our storage, add some more. */
	if( poly->nrings >= poly->maxrings ) 
	{
		int new_maxrings = 2 * (poly->nrings + 1);
		poly->rings = lwrealloc(poly->rings, new_maxrings * sizeof(POINTARRAY*));
	}
	
	/* Add the new ring entry. */
	poly->rings[poly->nrings] = pa;
	poly->nrings++;
	
	return LW_SUCCESS;
}
예제 #10
0
/**
* If necessary, expand the bytebuffer_t internal buffer to accomodate the
* specified additional size.
*/
static inline void 
bytebuffer_makeroom(bytebuffer_t *s, size_t size_to_add)
{
	LWDEBUGF(2,"Entered bytebuffer_makeroom with space need of %d", size_to_add);
	size_t current_write_size = (s->writecursor - s->buf_start);
	size_t capacity = s->capacity;
	size_t required_size = current_write_size + size_to_add;

	LWDEBUGF(2,"capacity = %d and required size = %d",capacity ,required_size);
	while (capacity < required_size)
		capacity *= 2;

	if ( capacity > s->capacity )
	{
		LWDEBUGF(4,"We need to realloc more memory. New capacity is %d", capacity);
		s->buf_start = lwrealloc(s->buf_start, capacity);
		s->capacity = capacity;
		s->writecursor = s->buf_start + current_write_size;
		s->readcursor = s->buf_start + (s->readcursor - s->buf_start);
	}
	return;
}
예제 #11
0
static LWGEOM*
parse_geojson_multipolygon(json_object *geojson, bool *hasz,  int *root_srid)
{
	LWGEOM *geom = NULL;
	int i, j, k;
	json_object* poObjPolys = NULL;

	if (!*root_srid)
	{
		geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, *root_srid, 1, 0);
	}
	else
	{
		geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, -1, 1, 0);
	}

	poObjPolys = findMemberByName( geojson, "coordinates" );
	if ( ! poObjPolys )
		geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);

	if( json_type_array == json_object_get_type( poObjPolys ) )
	{
		const int nPolys = json_object_array_length( poObjPolys );

		for(i = 0; i < nPolys; ++i)
		{
			POINTARRAY **ppa;
			json_object* poObjPoly = NULL;
			poObjPoly = json_object_array_get_idx( poObjPolys, i );

			ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));

			if( json_type_array == json_object_get_type( poObjPoly ) )
			{
				int nPoints;
				json_object* points = NULL;
				int ring = json_object_array_length( poObjPoly );
				ppa[0] = ptarray_construct_empty(1, 0, 1);

				points = json_object_array_get_idx( poObjPoly, 0 );
				nPoints = json_object_array_length( points );

				for (j=0; j < nPoints; j++ )
				{
					json_object* coords = NULL;
					coords = json_object_array_get_idx( points, j );
					parse_geojson_coord(coords, hasz, ppa[0]);
				}

				for(j = 1; j < ring; ++j)
				{
					int nPoints;
					ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, sizeof(POINTARRAY*) * (j + 1));
					ppa[i] = ptarray_construct_empty(1, 0, 1);
					points = json_object_array_get_idx( poObjPoly, j );

					nPoints = json_object_array_length( points );
					for (k=0; k < nPoints; k++ )
					{
						json_object* coords = NULL;
						coords = json_object_array_get_idx( points, k );
						parse_geojson_coord(coords, hasz, ppa[i]);
					}
				}

				geom = (LWGEOM*)lwmpoly_add_lwpoly((LWMPOLY*)geom,
				                                   (LWPOLY*)lwpoly_construct(*root_srid, NULL, ring, ppa));
			}
		}
	}

	return geom;
}
예제 #12
0
/**
* Takes a potentially heterogeneous collection and returns a homogeneous
* collection consisting only of the specified type.
*/
LWCOLLECTION* lwcollection_extract(LWCOLLECTION *col, int type)
{
	int i = 0;
	LWGEOM **geomlist;
	LWCOLLECTION *outcol;
	int geomlistsize = 16;
	int geomlistlen = 0;
	uint8_t outtype;

	if ( ! col ) return NULL;

	switch (type)
	{
	case POINTTYPE:
		outtype = MULTIPOINTTYPE;
		break;
	case LINETYPE:
		outtype = MULTILINETYPE;
		break;
	case POLYGONTYPE:
		outtype = MULTIPOLYGONTYPE;
		break;
	default:
		lwerror("Only POLYGON, LINESTRING and POINT are supported by lwcollection_extract. %s requested.", lwtype_name(type));
		return NULL;
	}

	geomlist = lwalloc(sizeof(LWGEOM*) * geomlistsize);

	/* Process each sub-geometry */
	for ( i = 0; i < col->ngeoms; i++ )
	{
		int subtype = col->geoms[i]->type;
		/* Don't bother adding empty sub-geometries */
		if ( lwgeom_is_empty(col->geoms[i]) )
		{
			continue;
		}
		/* Copy our sub-types into the output list */
		if ( subtype == type )
		{
			/* We've over-run our buffer, double the memory segment */
			if ( geomlistlen == geomlistsize )
			{
				geomlistsize *= 2;
				geomlist = lwrealloc(geomlist, sizeof(LWGEOM*) * geomlistsize);
			}
			geomlist[geomlistlen] = lwgeom_clone(col->geoms[i]);
			geomlistlen++;
		}
		/* Recurse into sub-collections */
		if ( lwtype_is_collection( subtype ) )
		{
			int j = 0;
			LWCOLLECTION *tmpcol = lwcollection_extract((LWCOLLECTION*)col->geoms[i], type);
			for ( j = 0; j < tmpcol->ngeoms; j++ )
			{
				/* We've over-run our buffer, double the memory segment */
				if ( geomlistlen == geomlistsize )
				{
					geomlistsize *= 2;
					geomlist = lwrealloc(geomlist, sizeof(LWGEOM*) * geomlistsize);
				}
				geomlist[geomlistlen] = tmpcol->geoms[j];
				geomlistlen++;
			}
			lwfree(tmpcol);
		}
	}

	if ( geomlistlen > 0 )
	{
		GBOX gbox;
		outcol = lwcollection_construct(outtype, col->srid, NULL, geomlistlen, geomlist);
		lwgeom_calculate_gbox((LWGEOM *) outcol, &gbox);
		outcol->bbox = gbox_copy(&gbox);
	}
	else
	{
		lwfree(geomlist);
		outcol = lwcollection_construct_empty(outtype, col->srid, FLAGS_GET_Z(col->flags), FLAGS_GET_M(col->flags));
	}

	return outcol;
}
예제 #13
0
/*
 * Add a LWPOLY inside a tgeom
 * Copy geometries from LWPOLY
 */
static TGEOM*
tgeom_add_polygon(TGEOM *tgeom, LWPOLY *poly)
{
	int i;

	assert(tgeom);
	assert(poly);

	if ((tgeom->nfaces + 1) == INT_MAX)
		lwerror("tgeom_add_polygon: Unable to alloc more than %i faces", INT_MAX);

	/* Integrity checks on subgeom, dims and srid */
	if (tgeom->type != POLYHEDRALSURFACETYPE)
		lwerror("tgeom_add_polygon: Unable to handle %s - %s type",
		        tgeom->type, lwtype_name(tgeom->type));

	if (FLAGS_NDIMS(tgeom->flags) != FLAGS_NDIMS(poly->flags))
		lwerror("tgeom_add_polygon: Mixed dimension");

	if (tgeom->srid != poly->srid && (tgeom->srid != 0 && poly->srid != SRID_UNKNOWN))
		lwerror("tgeom_add_polygon: Mixed srid. Tgeom: %i / Polygon: %i",
		        tgeom->srid, poly->srid);

	/* handle face array allocation */
	if (tgeom->maxfaces == 0)
	{
		tgeom->faces = lwalloc(sizeof(TFACE*) * 2);
		tgeom->maxfaces = 2;
	}
	if ((tgeom->maxfaces - 1) == tgeom->nfaces)
	{
		tgeom->faces = lwrealloc(tgeom->faces,
		                         sizeof(TFACE*) * tgeom->maxfaces * 2);
		tgeom->maxfaces *= 2;
	}

	/* add an empty face */
	tgeom->faces[tgeom->nfaces] = lwalloc(sizeof(TFACE));
	tgeom->faces[tgeom->nfaces]->rings = NULL;
	tgeom->faces[tgeom->nfaces]->nrings = 0;
	tgeom->faces[tgeom->nfaces]->nedges = 0;
	tgeom->faces[tgeom->nfaces]->maxedges = 0;

	/* Compute edge on poly external ring */
	for (i=1 ; i < poly->rings[0]->npoints ; i++)
	{
		POINT4D p1, p2;

		getPoint4d_p(poly->rings[0], i-1, &p1);
		getPoint4d_p(poly->rings[0], i,   &p2);
		tgeom_add_face_edge(tgeom, tgeom->nfaces, &p1, &p2);
	}

	/* External ring is already handled by edges */
	tgeom->faces[tgeom->nfaces]->nrings = poly->nrings - 1;

	/* handle rings array allocation */
	if (tgeom->faces[tgeom->nfaces]->nrings >= 1)
		tgeom->faces[tgeom->nfaces]->rings = lwalloc(sizeof(POINTARRAY*)
		                                     * tgeom->faces[tgeom->nfaces]->nrings);

	/* clone internal rings */
	for (i=0 ; i < tgeom->faces[tgeom->nfaces]->nrings ; i++)
		tgeom->faces[tgeom->nfaces]->rings[i]
		= ptarray_clone_deep(poly->rings[i+1]);

	tgeom->nfaces++;

	return tgeom;
}
예제 #14
0
/**
 * Parse KML Polygon
 */
static LWGEOM* parse_kml_polygon(xmlNodePtr xnode, bool *hasz)
{
	int ring;
	xmlNodePtr xa, xb;
	POINTARRAY **ppa = NULL;

	for (xa = xnode->children ; xa != NULL ; xa = xa->next)
	{

		/* Polygon/outerBoundaryIs */
		if (xa->type != XML_ELEMENT_NODE) continue;
		if (!is_kml_namespace(xa, false)) continue;
		if (strcmp((char *) xa->name, "outerBoundaryIs")) continue;

		for (xb = xa->children ; xb != NULL ; xb = xb->next)
		{

			if (xb->type != XML_ELEMENT_NODE) continue;
			if (!is_kml_namespace(xb, false)) continue;
			if (strcmp((char *) xb->name, "LinearRing")) continue;

			ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));
			ppa[0] = parse_kml_coordinates(xb->children, hasz);

			if (ppa[0]->npoints < 4
			        || (!*hasz && !ptarray_isclosed2d(ppa[0]))
			        ||  (*hasz && !ptarray_isclosed3d(ppa[0])))
				lwerror("invalid KML representation");
		}
	}

	for (ring=1, xa = xnode->children ; xa != NULL ; xa = xa->next)
	{

		/* Polygon/innerBoundaryIs */
		if (xa->type != XML_ELEMENT_NODE) continue;
		if (!is_kml_namespace(xa, false)) continue;
		if (strcmp((char *) xa->name, "innerBoundaryIs")) continue;

		for (xb = xa->children ; xb != NULL ; xb = xb->next)
		{

			if (xb->type != XML_ELEMENT_NODE) continue;
			if (!is_kml_namespace(xb, false)) continue;
			if (strcmp((char *) xb->name, "LinearRing")) continue;

			ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa,
			                               sizeof(POINTARRAY*) * (ring + 1));
			ppa[ring] = parse_kml_coordinates(xb->children, hasz);

			if (ppa[ring]->npoints < 4
			        || (!*hasz && !ptarray_isclosed2d(ppa[ring]))
			        ||  (*hasz && !ptarray_isclosed3d(ppa[ring])))
				lwerror("invalid KML representation");

			ring++;
		}
	}

	/* Exterior Ring is mandatory */
	if (ppa == NULL || ppa[0] == NULL) lwerror("invalid KML representation");

	return (LWGEOM *) lwpoly_construct(4326, NULL, ring, ppa);
}
예제 #15
0
파일: ptarray.c 프로젝트: TesseractG/lwgeom
int
ptarray_append_ptarray(POINTARRAY *pa1, POINTARRAY *pa2, double gap_tolerance)
{
	unsigned int poff = 0;
	unsigned int npoints;
	unsigned int ncap;
	unsigned int ptsize;

	/* Check for pathology */
	if( ! pa1 || ! pa2 ) 
	{
		lwerror("ptarray_append_ptarray: null input");
		return LW_FAILURE;
	}

	npoints = pa2->npoints;
	
	if ( ! npoints ) return LW_SUCCESS; /* nothing more to do */

	if( FLAGS_GET_READONLY(pa1->flags) )
	{
		lwerror("ptarray_append_ptarray: target pointarray is read-only");
		return LW_FAILURE;
	}

	if( FLAGS_GET_ZM(pa1->flags) != FLAGS_GET_ZM(pa2->flags) )
	{
		lwerror("ptarray_append_ptarray: appending mixed dimensionality is not allowed");
		return LW_FAILURE;
	}

	ptsize = ptarray_point_size(pa1);

	/* Check for duplicate end point */
	if ( pa1->npoints )
	{
		POINT2D tmp1, tmp2;
		getPoint2d_p(pa1, pa1->npoints-1, &tmp1);
		getPoint2d_p(pa2, 0, &tmp2);

		/* If the end point and start point are the same, then don't copy start point */
		if (p2d_same(&tmp1, &tmp2)) {
			poff = 1;
			--npoints;
		}
		else if ( gap_tolerance == 0 || ( gap_tolerance > 0 &&
		           distance2d_pt_pt(&tmp1, &tmp2) > gap_tolerance ) ) 
		{
			lwerror("Second line start point too far from first line end point");
			return LW_FAILURE;
		} 
	}

	/* Check if we need extra space */
	ncap = pa1->npoints + npoints;
	if ( pa1->maxpoints < ncap )
	{
		pa1->maxpoints = ncap > pa1->maxpoints*2 ?
		                 ncap : pa1->maxpoints*2;
		pa1->serialized_pointlist = (uint8_t *)lwrealloc(pa1->serialized_pointlist, ptsize * pa1->maxpoints);
	}

	memcpy(getPoint_internal(pa1, pa1->npoints),
	       getPoint_internal(pa2, poff), ptsize * npoints);

	pa1->npoints = ncap;

	return LW_SUCCESS;
}
예제 #16
0
/* Initializes and uses GEOS internally */
static LWGEOM*
lwpoly_split_by_line(const LWPOLY* lwpoly_in, const LWLINE* blade_in)
{
	LWCOLLECTION* out;
	GEOSGeometry* g1;
	GEOSGeometry* g2;
	GEOSGeometry* g1_bounds;
	GEOSGeometry* polygons;
	const GEOSGeometry *vgeoms[1];
	int i,n;
	int hasZ = FLAGS_GET_Z(lwpoly_in->flags);


	/* Possible outcomes:
	 *
	 *  1. The line does not split the polygon
	 *      -> Return a collection with single element
	 *  2. The line does split the polygon
	 *      -> Return a collection of all elements resulting from the split
	 */

	initGEOS(lwgeom_geos_error, lwgeom_geos_error);

	g1 = LWGEOM2GEOS((LWGEOM*)lwpoly_in, 0);
	if ( NULL == g1 )
	{
		lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}
	g1_bounds = GEOSBoundary(g1);
	if ( NULL == g1_bounds )
	{
		GEOSGeom_destroy(g1);
		lwerror("GEOSBoundary: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	g2 = LWGEOM2GEOS((LWGEOM*)blade_in, 0);
	if ( NULL == g2 )
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g1_bounds);
		lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	vgeoms[0] = GEOSUnion(g1_bounds, g2);
	if ( NULL == vgeoms[0] )
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g2);
		GEOSGeom_destroy(g1_bounds);
		lwerror("GEOSUnion: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	polygons = GEOSPolygonize(vgeoms, 1);
	if ( NULL == polygons )
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g2);
		GEOSGeom_destroy(g1_bounds);
		GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
		lwerror("GEOSPolygonize: %s", lwgeom_geos_errmsg);
		return NULL;
	}

#if PARANOIA_LEVEL > 0
	if ( GEOSGeomTypeId(polygons) != COLLECTIONTYPE )
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g2);
		GEOSGeom_destroy(g1_bounds);
		GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
		GEOSGeom_destroy(polygons);
		lwerror("%s [%s] Unexpected return from GEOSpolygonize", __FILE__, __LINE__);
		return 0;
	}
#endif

	/* We should now have all polygons, just skip
	 * the ones which are in holes of the original
	 * geometries and return the rest in a collection
	 */
	n = GEOSGetNumGeometries(polygons);
	out = lwcollection_construct_empty(COLLECTIONTYPE, lwpoly_in->srid,
				     hasZ, 0);
	/* Allocate space for all polys */
	out->geoms = lwrealloc(out->geoms, sizeof(LWGEOM*)*n);
	assert(0 == out->ngeoms);
	for (i=0; i<n; ++i)
	{
		GEOSGeometry* pos; /* point on surface */
		const GEOSGeometry* p = GEOSGetGeometryN(polygons, i);
		int contains;

		pos = GEOSPointOnSurface(p);
		if ( ! pos )
		{
			GEOSGeom_destroy(g1);
			GEOSGeom_destroy(g2);
			GEOSGeom_destroy(g1_bounds);
			GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
			GEOSGeom_destroy(polygons);
			lwerror("GEOSPointOnSurface: %s", lwgeom_geos_errmsg);
			return NULL;
		}

		contains = GEOSContains(g1, pos);
		if ( 2 == contains )
		{
			GEOSGeom_destroy(g1);
			GEOSGeom_destroy(g2);
			GEOSGeom_destroy(g1_bounds);
			GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
			GEOSGeom_destroy(polygons);
			GEOSGeom_destroy(pos);
			lwerror("GEOSContains: %s", lwgeom_geos_errmsg);
			return NULL;
		}

		GEOSGeom_destroy(pos);

		if ( 0 == contains )
		{
			/* Original geometry doesn't contain
			 * a point in this ring, must be an hole
			 */
			continue;
		}

		out->geoms[out->ngeoms++] = GEOS2LWGEOM(p, hasZ);
	}

	GEOSGeom_destroy(g1);
	GEOSGeom_destroy(g2);
	GEOSGeom_destroy(g1_bounds);
	GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
	GEOSGeom_destroy(polygons);

	return (LWGEOM*)out;
}
예제 #17
0
/**
* Clip an input MULTILINESTRING between two values, on any ordinate input.
*/
LWCOLLECTION*
lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to)
{
	LWCOLLECTION *lwgeom_out = NULL;

	if ( ! mline )
	{
		lwerror("Null input geometry.");
		return NULL;
	}

	if ( mline->ngeoms == 1)
	{
		lwgeom_out = lwline_clip_to_ordinate_range(mline->geoms[0], ordinate, from, to);
	}
	else
	{
		LWCOLLECTION *col;
		char hasz = lwgeom_has_z(lwmline_as_lwgeom(mline));
		char hasm = lwgeom_has_m(lwmline_as_lwgeom(mline));
		int i, j;
		char homogeneous = 1;
		size_t geoms_size = 0;
		lwgeom_out = lwcollection_construct_empty(MULTILINETYPE, mline->srid, hasz, hasm);
		FLAGS_SET_Z(lwgeom_out->flags, hasz);
		FLAGS_SET_M(lwgeom_out->flags, hasm);
		for ( i = 0; i < mline->ngeoms; i ++ )
		{
			col = lwline_clip_to_ordinate_range(mline->geoms[i], ordinate, from, to);
			if ( col )
			{
				/* Something was left after the clip. */
				if ( lwgeom_out->ngeoms + col->ngeoms > geoms_size )
				{
					geoms_size += 16;
					if ( lwgeom_out->geoms )
					{
						lwgeom_out->geoms = lwrealloc(lwgeom_out->geoms, geoms_size * sizeof(LWGEOM*));
					}
					else
					{
						lwgeom_out->geoms = lwalloc(geoms_size * sizeof(LWGEOM*));
					}
				}
				for ( j = 0; j < col->ngeoms; j++ )
				{
					lwgeom_out->geoms[lwgeom_out->ngeoms] = col->geoms[j];
					lwgeom_out->ngeoms++;
				}
				if ( col->type != mline->type )
				{
					homogeneous = 0;
				}
				/* Shallow free the struct, leaving the geoms behind. */
				if ( col->bbox ) lwfree(col->bbox);
				lwfree(col->geoms);
				lwfree(col);
			}
		}
		lwgeom_drop_bbox((LWGEOM*)lwgeom_out);
		lwgeom_add_bbox((LWGEOM*)lwgeom_out);
		if ( ! homogeneous )
		{
			lwgeom_out->type = COLLECTIONTYPE;
		}
	}

	if ( ! lwgeom_out || lwgeom_out->ngeoms == 0 ) /* Nothing left after clip. */
	{
		return NULL;
	}

	return lwgeom_out;

}
예제 #18
0
/*
 * Add an edge to a face in a tgeom
 * Edge is describded as a starting and an ending point
 * Points are really copied
 * Return the new tgeom pointer
 */
static TGEOM*
tgeom_add_face_edge(TGEOM *tgeom, int face_id, POINT4D *s, POINT4D *e)
{
	int nedges, edge_id;

	assert(tgeom);
	assert(s);
	assert(e);

	edge_id = tgeom_is_edge(tgeom, s, e);

	if (edge_id)
	{
		tgeom->edges[abs(edge_id)]->count++;
		LWDEBUGF(3, "face [%i] Founded Edge: %i\n",
		         face_id, edge_id);
	}
	else
	{
		if ((tgeom->nedges + 1) == INT_MAX)
			lwerror("tgeom_add_face_edge: Unable to alloc more than %i edges", INT_MAX);

		/* alloc edges array */
		if (tgeom->maxedges == 0)
		{
			tgeom->edges = (TEDGE**) lwalloc(sizeof(TEDGE*) * 4);
			tgeom->maxedges = 4;
		}
		if (tgeom->maxedges >= (tgeom->nedges + 1))
		{
			tgeom->edges = (TEDGE **) lwrealloc(tgeom->edges,
			                         sizeof(TEDGE*) * tgeom->maxedges * 2);
			tgeom->maxedges *= 2;
		}

		edge_id = ++tgeom->nedges; /* edge_id is 1 based */
		tgeom->edges[edge_id] = (TEDGE*) lwalloc(sizeof(TEDGE));
		tgeom->edges[edge_id]->s = lwalloc(sizeof(POINT4D));
		tgeom->edges[edge_id]->e = lwalloc(sizeof(POINT4D));
		memcpy(tgeom->edges[edge_id]->s, s, sizeof(POINT4D));
		memcpy(tgeom->edges[edge_id]->e, e, sizeof(POINT4D));
		tgeom->edges[edge_id]->count = 1;

		LWDEBUGF(3, "face [%i] adding edge [%i] (%lf, %lf, %lf, %lf) -> (%lf, %lf, %lf, %lf)\n",
		         face_id, edge_id, s->x, s->y, s->z, s->m, e->x, e->y, e->z, e->m);
	}

	nedges = tgeom->faces[face_id]->nedges;
	if (tgeom->faces[face_id]->maxedges == 0)
	{
		tgeom->faces[face_id]->edges = (int *) lwalloc(sizeof(int) * 4);
		tgeom->faces[face_id]->maxedges = 4;
	}
	if (tgeom->faces[face_id]->maxedges == nedges)
	{
		tgeom->faces[face_id]->edges = (int *) lwrealloc(tgeom->faces[face_id]->edges,
		                               sizeof(int) * tgeom->faces[face_id]->maxedges * 2);
		tgeom->faces[face_id]->maxedges *= 2;
	}

	LWDEBUGF(3, "face [%i] add %i in edge array in %i pos\n",
	         face_id, edge_id, tgeom->faces[face_id]->nedges);

	tgeom->faces[face_id]->edges[nedges]= edge_id;
	tgeom->faces[face_id]->nedges++;

	return tgeom;
}