示例#1
0
/**
* Check for ring closure using whatever dimensionality is declared on the 
* pointarray.
*/
int
ptarray_is_closed(const POINTARRAY *in)
{
	return 0 == memcmp(getPoint_internal(in, 0), getPoint_internal(in, in->npoints-1), ptarray_point_size(in));
}
示例#2
0
int
ptarray_is_closed_3d(const POINTARRAY *in)
{
	return 0 == memcmp(getPoint_internal(in, 0), getPoint_internal(in, in->npoints-1), sizeof(POINT3D));
}
示例#3
0
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 = 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;
}
示例#4
0
/*
 * Returns a POINTARRAY with consecutive equal points
 * removed. Equality test on all dimensions of input.
 *
 * Always returns a newly allocated object.
 *
 */
POINTARRAY *
ptarray_remove_repeated_points_minpoints(const POINTARRAY *in, double tolerance, int minpoints)
{
	POINTARRAY* out;
	size_t ptsize;
	size_t ipn, opn;
	const POINT2D *last_point, *this_point;
	double tolsq = tolerance * tolerance;

	if ( minpoints < 1 ) minpoints = 1;

	LWDEBUGF(3, "%s called", __func__);

	/* Single or zero point arrays can't have duplicates */
	if ( in->npoints < 3 ) return ptarray_clone_deep(in);

	ptsize = ptarray_point_size(in);

	LWDEBUGF(3, " ptsize: %d", ptsize);

	/* Allocate enough space for all points */
	out = ptarray_construct(FLAGS_GET_Z(in->flags),
	                        FLAGS_GET_M(in->flags), in->npoints);

	/* Now fill up the actual points (NOTE: could be optimized) */

	opn=1;
	/* Keep the first point */
	memcpy(getPoint_internal(out, 0), getPoint_internal(in, 0), ptsize);
	last_point = getPoint2d_cp(in, 0);
	LWDEBUGF(3, " first point copied, out points: %d", opn);
	for ( ipn = 1; ipn < in->npoints; ++ipn)
	{
		this_point = getPoint2d_cp(in, ipn);
		if ( ipn < in->npoints-minpoints+1 || opn >= minpoints ) /* need extra points to hit minponts */
		{
			if (
				(tolerance == 0 && memcmp(getPoint_internal(in, ipn-1), getPoint_internal(in, ipn), ptsize) == 0) || /* exact dupe */
				(tolerance > 0.0 && distance2d_sqr_pt_pt(last_point, this_point) <= tolsq) /* within the removal tolerance */
			) continue;
		}

		/*
		 * The point is different (see above) from the previous,
		 * so we add it to output
		 */
		memcpy(getPoint_internal(out, opn++), getPoint_internal(in, ipn), ptsize);
		last_point = this_point;
		LWDEBUGF(3, " Point %d differs from point %d. Out points: %d", ipn, ipn-1, opn);
	}
	/* Keep the last point */
	if ( memcmp(last_point, getPoint_internal(in, ipn-1), ptsize) != 0 )
	{
		memcpy(getPoint_internal(out, opn-1), getPoint_internal(in, ipn-1), ptsize);
	}

	LWDEBUGF(3, " in:%d out:%d", out->npoints, opn);
	out->npoints = opn;

	return out;
}
示例#5
0
文件: lwline.c 项目: Vlczech/vtapi
/*
 * convert this line into its serialize form writing it into
 * the given buffer, and returning number of bytes written into
 * the given int pointer.
 * result's first char will be the 8bit type.  See serialized form doc
 */
void
lwline_serialize_buf(LWLINE *line, uchar *buf, size_t *retsize)
{
	char hasSRID;
	uchar *loc;
	int ptsize;
	size_t size;

	LWDEBUGF(2, "lwline_serialize_buf(%p, %p, %p) called",
	         line, buf, retsize);

	if (line == NULL)
		lwerror("lwline_serialize:: given null line");

	if ( TYPE_GETZM(line->type) != TYPE_GETZM(line->points->dims) )
		lwerror("Dimensions mismatch in lwline");

	ptsize = pointArray_ptsize(line->points);

	hasSRID = (line->SRID != -1);

	buf[0] = (uchar) lwgeom_makeType_full(
	             TYPE_HASZ(line->type), TYPE_HASM(line->type),
	             hasSRID, LINETYPE, line->bbox ? 1 : 0);
	loc = buf+1;

	LWDEBUGF(3, "lwline_serialize_buf added type (%d)", line->type);

	if (line->bbox)
	{
		memcpy(loc, line->bbox, sizeof(BOX2DFLOAT4));
		loc += sizeof(BOX2DFLOAT4);

		LWDEBUG(3, "lwline_serialize_buf added BBOX");
	}

	if (hasSRID)
	{
		memcpy(loc, &line->SRID, sizeof(int32));
		loc += sizeof(int32);

		LWDEBUG(3, "lwline_serialize_buf added SRID");
	}

	memcpy(loc, &line->points->npoints, sizeof(uint32));
	loc += sizeof(uint32);

	LWDEBUGF(3, "lwline_serialize_buf added npoints (%d)",
	         line->points->npoints);

	/*copy in points */
	size = line->points->npoints*ptsize;
	memcpy(loc, getPoint_internal(line->points, 0), size);
	loc += size;

	LWDEBUGF(3, "lwline_serialize_buf copied serialized_pointlist (%d bytes)",
	         ptsize * line->points->npoints);

	if (retsize) *retsize = loc-buf;

	/*printBYTES((uchar *)result, loc-buf); */

	LWDEBUGF(3, "lwline_serialize_buf returning (loc: %p, size: %d)",
	         loc, loc-buf);
}
示例#6
0
GEOSGeometry *
LWGEOM2GEOS(const LWGEOM *lwgeom)
{
	GEOSCoordSeq sq;
	GEOSGeom g, shell;
	GEOSGeom *geoms = NULL;
	/*
	LWGEOM *tmp;
	*/
	uint32_t ngeoms, i;
	int geostype;
#if LWDEBUG_LEVEL >= 4
	char *wkt;
#endif

	LWDEBUGF(4, "LWGEOM2GEOS got a %s", lwtype_name(lwgeom->type));

	if (lwgeom_has_arc(lwgeom))
	{
		LWDEBUG(3, "LWGEOM2GEOS: arced geometry found.");

		lwerror("Exception in LWGEOM2GEOS: curved geometry not supported.");
		return NULL;
	}
	
	switch (lwgeom->type)
	{
		LWPOINT *lwp = NULL;
		LWPOLY *lwpoly = NULL;
		LWLINE *lwl = NULL;
		LWCOLLECTION *lwc = NULL;
#if POSTGIS_GEOS_VERSION < 33
		POINTARRAY *pa = NULL;
#endif
		
	case POINTTYPE:
		lwp = (LWPOINT *)lwgeom;
		
		if ( lwgeom_is_empty(lwgeom) )
		{
#if POSTGIS_GEOS_VERSION < 33
			pa = ptarray_construct_empty(lwgeom_has_z(lwgeom), lwgeom_has_m(lwgeom), 2);
			sq = ptarray_to_GEOSCoordSeq(pa);
			shell = GEOSGeom_createLinearRing(sq);
			g = GEOSGeom_createPolygon(shell, NULL, 0);
#else
			g = GEOSGeom_createEmptyPolygon();
#endif
		}
		else
		{
			sq = ptarray_to_GEOSCoordSeq(lwp->point);
			g = GEOSGeom_createPoint(sq);
		}
		if ( ! g )
		{
			/* lwnotice("Exception in LWGEOM2GEOS"); */
			return NULL;
		}
		break;
	case LINETYPE:
		lwl = (LWLINE *)lwgeom;
		if ( lwl->points->npoints == 1 ) {
			/* Duplicate point, to make geos-friendly */
			lwl->points = ptarray_addPoint(lwl->points,
		                           getPoint_internal(lwl->points, 0),
		                           FLAGS_NDIMS(lwl->points->flags),
		                           lwl->points->npoints);
		}
		sq = ptarray_to_GEOSCoordSeq(lwl->points);
		g = GEOSGeom_createLineString(sq);
		if ( ! g )
		{
			/* lwnotice("Exception in LWGEOM2GEOS"); */
			return NULL;
		}
		break;

	case POLYGONTYPE:
		lwpoly = (LWPOLY *)lwgeom;
		if ( lwgeom_is_empty(lwgeom) )
		{
#if POSTGIS_GEOS_VERSION < 33
			POINTARRAY *pa = ptarray_construct_empty(lwgeom_has_z(lwgeom), lwgeom_has_m(lwgeom), 2);
			sq = ptarray_to_GEOSCoordSeq(pa);
			shell = GEOSGeom_createLinearRing(sq);
			g = GEOSGeom_createPolygon(shell, NULL, 0);
#else
			g = GEOSGeom_createEmptyPolygon();
#endif
		}
		else
		{
			sq = ptarray_to_GEOSCoordSeq(lwpoly->rings[0]);
			/* TODO: check ring for being closed and fix if not */
			shell = GEOSGeom_createLinearRing(sq);
			if ( ! shell ) return NULL;
			/*lwerror("LWGEOM2GEOS: exception during polygon shell conversion"); */
			ngeoms = lwpoly->nrings-1;
			if ( ngeoms > 0 )
				geoms = malloc(sizeof(GEOSGeom)*ngeoms);

			for (i=1; i<lwpoly->nrings; ++i)
			{
				sq = ptarray_to_GEOSCoordSeq(lwpoly->rings[i]);
				geoms[i-1] = GEOSGeom_createLinearRing(sq);
				if ( ! geoms[i-1] )
				{
					--i;
					while (i) GEOSGeom_destroy(geoms[--i]);
					free(geoms);
					GEOSGeom_destroy(shell);
					return NULL;
				}
				/*lwerror("LWGEOM2GEOS: exception during polygon hole conversion"); */
			}
			g = GEOSGeom_createPolygon(shell, geoms, ngeoms);
			if (geoms) free(geoms);
		}
		if ( ! g ) return NULL;
		break;
	case MULTIPOINTTYPE:
	case MULTILINETYPE:
	case MULTIPOLYGONTYPE:
	case COLLECTIONTYPE:
		if ( lwgeom->type == MULTIPOINTTYPE )
			geostype = GEOS_MULTIPOINT;
		else if ( lwgeom->type == MULTILINETYPE )
			geostype = GEOS_MULTILINESTRING;
		else if ( lwgeom->type == MULTIPOLYGONTYPE )
			geostype = GEOS_MULTIPOLYGON;
		else
			geostype = GEOS_GEOMETRYCOLLECTION;

		lwc = (LWCOLLECTION *)lwgeom;

		ngeoms = lwc->ngeoms;
		if ( ngeoms > 0 )
			geoms = malloc(sizeof(GEOSGeom)*ngeoms);

		for (i=0; i<ngeoms; ++i)
		{
			GEOSGeometry* g = LWGEOM2GEOS(lwc->geoms[i]);
			if ( ! g )
			{
				while (i) GEOSGeom_destroy(geoms[--i]);
				free(geoms);
				return NULL;
			}
			geoms[i] = g;
		}
		g = GEOSGeom_createCollection(geostype, geoms, ngeoms);
		if ( geoms ) free(geoms);
		if ( ! g ) return NULL;
		break;

	default:
		lwerror("Unknown geometry type: %d - %s", lwgeom->type, lwtype_name(lwgeom->type));
		return NULL;
	}

	GEOSSetSRID(g, lwgeom->srid);

#if LWDEBUG_LEVEL >= 4
	wkt = GEOSGeomToWKT(g);
	LWDEBUGF(4, "LWGEOM2GEOS: GEOSGeom: %s", wkt);
	free(wkt);
#endif

	return g;
}
示例#7
0
/*
 * Serialize a TGEOM to a buf
 * retsize return by reference the allocated buf size
 */
static size_t
tgeom_serialize_buf(const TGEOM *tgeom, uint8_t *buf, size_t *retsize)
{
	int i,j;
	size_t size=0;
	uint8_t *loc=buf;
	int dims = FLAGS_NDIMS(tgeom->flags);

	assert(tgeom);
	assert(buf);

	/* Write in the type. */
	memcpy(loc, &tgeom->type, sizeof(uint8_t));
	loc  += 1;
	size += 1;

	/* Write in the flags. */
	memcpy(loc, &tgeom->flags, sizeof(uint8_t));
	loc  += 1;
	size += 1;

	/* Write in the srid. */
	memcpy(loc, &tgeom->srid, sizeof(uint32_t));
	loc  += 4;
	size += 4;

	/* Write in the bbox. */
	if (tgeom->bbox)
	{
		memcpy(loc, tgeom->bbox, sizeof(BOX3D));
		loc  += sizeof(BOX3D);
		size += sizeof(BOX3D);
	}

	/* Write in the number of edges (0=> EMPTY) */
	memcpy(loc, &tgeom->nedges, sizeof(int));
	loc  += 4;
	size +=4;

	/* Edges */
	for (i=1 ; i <= tgeom->nedges ; i++)
	{
		/* 3DM specific handle */
		if (!FLAGS_GET_Z(tgeom->flags) && FLAGS_GET_M(tgeom->flags))
		{
			memcpy(loc, tgeom->edges[i]->s, 2 * sizeof(double));
			loc  += sizeof(double) * 2;
			memcpy(loc, &(tgeom->edges[i]->s->m), sizeof(double));
			loc  += sizeof(double);

			memcpy(loc, tgeom->edges[i]->e, 2 * sizeof(double));
			loc  += sizeof(double) * 2;
			memcpy(loc, &(tgeom->edges[i]->e->m), sizeof(double));
			loc  += sizeof(double);
		}
		else /* 2D, 3DZ && 4D */
		{
			memcpy(loc, tgeom->edges[i]->s, dims * sizeof(double));
			loc  += sizeof(double) * dims;
			memcpy(loc, tgeom->edges[i]->e, dims * sizeof(double));
			loc  += sizeof(double) * dims;
		}
		memcpy(loc, &tgeom->edges[i]->count, sizeof(int));
		loc  += 4;

		size += sizeof(double) * dims * 2 + 4;
	}

	/* Write in the number of faces */
	memcpy(loc, &tgeom->nfaces, sizeof(int));
	loc  += 4;
	size += 4;

	/* Faces */
	for (i=0 ; i < tgeom->nfaces ; i++)
	{
		/* Write in the number of edges */
		memcpy(loc, &tgeom->faces[i]->nedges, sizeof(int));
		loc  += 4;
		size += 4;

		/* Write in the edges array */
		memcpy(loc, tgeom->faces[i]->edges,
		       sizeof(int) * tgeom->faces[i]->nedges);
		loc  += 4 * tgeom->faces[i]->nedges;
		size += 4 * tgeom->faces[i]->nedges;

		/* Write the number of rings */
		memcpy(loc, &tgeom->faces[i]->nrings, sizeof(int));
		loc  += 4;
		size += 4;

		for (j=0 ; j < tgeom->faces[i]->nrings ; j++)
		{
			/* Write the number of points */
			memcpy(loc, &tgeom->faces[i]->rings[j]->npoints, sizeof(int));
			loc  += 4;
			size += 4;

			/* Write the points */
			memcpy(loc, getPoint_internal(tgeom->faces[i]->rings[j], 0),
			       sizeof(double) * dims * tgeom->faces[i]->rings[j]->npoints);
			loc  += sizeof(double) * dims * tgeom->faces[i]->rings[j]->npoints;
			size += sizeof(double) * dims * tgeom->faces[i]->rings[j]->npoints;
		}
	}

	if (retsize) *retsize = size;

	return (size_t) (loc - buf);
}