Exemple #1
0
/*
 * Construct a polygon from a LWLINE being
 * the shell and an array of LWLINE (possibly NULL) being holes.
 * Pointarrays from intput geoms are cloned.
 * SRID must be the same for each input line.
 * Input lines must have at least 4 points, and be closed.
 */
LWPOLY *
lwpoly_from_lwlines(const LWLINE *shell,
                    uint32_t nholes, const LWLINE **holes)
{
	uint32_t nrings;
	POINTARRAY **rings = lwalloc((nholes+1)*sizeof(POINTARRAY *));
	int srid = shell->srid;
	LWPOLY *ret;

	if ( shell->points->npoints < 4 )
		lwerror("lwpoly_from_lwlines: shell must have at least 4 points");
	if ( ! ptarray_is_closed_2d(shell->points) )
		lwerror("lwpoly_from_lwlines: shell must be closed");
	rings[0] = ptarray_clone_deep(shell->points);

	for (nrings=1; nrings<=nholes; nrings++)
	{
		const LWLINE *hole = holes[nrings-1];

		if ( hole->srid != srid )
			lwerror("lwpoly_from_lwlines: mixed SRIDs in input lines");

		if ( hole->points->npoints < 4 )
			lwerror("lwpoly_from_lwlines: holes must have at least 4 points");
		if ( ! ptarray_is_closed_2d(hole->points) )
			lwerror("lwpoly_from_lwlines: holes must be closed");

		rings[nrings] = ptarray_clone_deep(hole->points);
	}

	ret = lwpoly_construct(srid, NULL, nrings, rings);
	return ret;
}
Exemple #2
0
LWMLINE *
lwmcurve_segmentize(LWMCURVE *mcurve, uint32_t perQuad)
{
	LWMLINE *ogeom;
	LWGEOM *tmp;
	LWGEOM **lines;
	int i;

	LWDEBUGF(2, "lwmcurve_segmentize called, geoms=%d, dim=%d.", mcurve->ngeoms, FLAGS_NDIMS(mcurve->flags));

	lines = lwalloc(sizeof(LWGEOM *)*mcurve->ngeoms);

	for (i = 0; i < mcurve->ngeoms; i++)
	{
		tmp = mcurve->geoms[i];
		if (tmp->type == CIRCSTRINGTYPE)
		{
			lines[i] = (LWGEOM *)lwcircstring_segmentize((LWCIRCSTRING *)tmp, perQuad);
		}
		else if (tmp->type == LINETYPE)
		{
			lines[i] = (LWGEOM *)lwline_construct(mcurve->srid, NULL, ptarray_clone_deep(((LWLINE *)tmp)->points));
		}
		else
		{
			lwerror("Unsupported geometry found in MultiCurve.");
			return NULL;
		}
	}

	ogeom = (LWMLINE *)lwcollection_construct(MULTILINETYPE, mcurve->srid, NULL, mcurve->ngeoms, lines);
	return ogeom;
}
Exemple #3
0
LWMPOLY *
lwmsurface_segmentize(LWMSURFACE *msurface, uint32_t perQuad)
{
	LWMPOLY *ogeom;
	LWGEOM *tmp;
	LWPOLY *poly;
	LWGEOM **polys;
	POINTARRAY **ptarray;
	int i, j;

	LWDEBUG(2, "lwmsurface_segmentize called.");

	polys = lwalloc(sizeof(LWGEOM *)*msurface->ngeoms);

	for (i = 0; i < msurface->ngeoms; i++)
	{
		tmp = msurface->geoms[i];
		if (tmp->type == CURVEPOLYTYPE)
		{
			polys[i] = (LWGEOM *)lwcurvepoly_segmentize((LWCURVEPOLY *)tmp, perQuad);
		}
		else if (tmp->type == POLYGONTYPE)
		{
			poly = (LWPOLY *)tmp;
			ptarray = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
			for (j = 0; j < poly->nrings; j++)
			{
				ptarray[j] = ptarray_clone_deep(poly->rings[j]);
			}
			polys[i] = (LWGEOM *)lwpoly_construct(msurface->srid, NULL, poly->nrings, ptarray);
		}
	}
	ogeom = (LWMPOLY *)lwcollection_construct(MULTIPOLYGONTYPE, msurface->srid, NULL, msurface->ngeoms, polys);
	return ogeom;
}
Exemple #4
0
/*
 * @param icompound input curve polygon
 * @param tol tolerance, semantic driven by tolerance_type
 * @param tolerance_type see LW_LINEARIZE_TOLERANCE_TYPE
 * @param flags see flags in lwarc_linearize
 *
 * @return a newly allocated LWPOLY
 */
static LWPOLY *
lwcurvepoly_linearize(const LWCURVEPOLY *curvepoly, double tol,
                       LW_LINEARIZE_TOLERANCE_TYPE tolerance_type,
                       int flags)
{
	LWPOLY *ogeom;
	LWGEOM *tmp;
	LWLINE *line;
	POINTARRAY **ptarray;
	int i;

	LWDEBUG(2, "lwcurvepoly_linearize called.");

	ptarray = lwalloc(sizeof(POINTARRAY *)*curvepoly->nrings);

	for (i = 0; i < curvepoly->nrings; i++)
	{
		tmp = curvepoly->rings[i];
		if (tmp->type == CIRCSTRINGTYPE)
		{
			line = lwcircstring_linearize((LWCIRCSTRING *)tmp, tol, tolerance_type, flags);
			ptarray[i] = ptarray_clone_deep(line->points);
			lwline_free(line);
		}
		else if (tmp->type == LINETYPE)
		{
			line = (LWLINE *)tmp;
			ptarray[i] = ptarray_clone_deep(line->points);
		}
		else if (tmp->type == COMPOUNDTYPE)
		{
			line = lwcompound_linearize((LWCOMPOUND *)tmp, tol, tolerance_type, flags);
			ptarray[i] = ptarray_clone_deep(line->points);
			lwline_free(line);
		}
		else
		{
			lwerror("Invalid ring type found in CurvePoly.");
			return NULL;
		}
	}

	ogeom = lwpoly_construct(curvepoly->srid, NULL, curvepoly->nrings, ptarray);
	return ogeom;
}
Exemple #5
0
LWPOLY *
lwcurvepoly_segmentize(const LWCURVEPOLY *curvepoly, uint32_t perQuad)
{
	LWPOLY *ogeom;
	LWGEOM *tmp;
	LWLINE *line;
	POINTARRAY **ptarray;
	int i;

	LWDEBUG(2, "lwcurvepoly_segmentize called.");

	ptarray = lwalloc(sizeof(POINTARRAY *)*curvepoly->nrings);

	for (i = 0; i < curvepoly->nrings; i++)
	{
		tmp = curvepoly->rings[i];
		if (tmp->type == CIRCSTRINGTYPE)
		{
			line = lwcircstring_segmentize((LWCIRCSTRING *)tmp, perQuad);
			ptarray[i] = ptarray_clone_deep(line->points);
			lwfree(line);
		}
		else if (tmp->type == LINETYPE)
		{
			line = (LWLINE *)tmp;
			ptarray[i] = ptarray_clone_deep(line->points);
		}
		else if (tmp->type == COMPOUNDTYPE)
		{
			line = lwcompound_segmentize((LWCOMPOUND *)tmp, perQuad);
			ptarray[i] = ptarray_clone_deep(line->points);
			lwfree(line);
		}
		else
		{
			lwerror("Invalid ring type found in CurvePoly.");
			return NULL;
		}
	}

	ogeom = lwpoly_construct(curvepoly->srid, NULL, curvepoly->nrings, ptarray);
	return ogeom;
}
Exemple #6
0
/* Deep clone LWPOLY object. POINTARRAY are copied, as is ring array */
LWPOLY *
lwpoly_clone_deep(const LWPOLY *g)
{
	int i;
	LWPOLY *ret = lwalloc(sizeof(LWPOLY));
	memcpy(ret, g, sizeof(LWPOLY));
	if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
	ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
	for ( i = 0; i < ret->nrings; i++ )
	{
		ret->rings[i] = ptarray_clone_deep(g->rings[i]);
	}
	FLAGS_SET_READONLY(ret->flags,0);
	return ret;
}
Exemple #7
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(POINTARRAY *in)
{
	POINTARRAY* out;
	size_t ptsize;
	size_t ipn, opn;

	LWDEBUG(3, "ptarray_remove_repeated_points called.");

	/* 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;
	memcpy(getPoint_internal(out, 0), getPoint_internal(in, 0), ptsize);
	LWDEBUGF(3, " first point copied, out points: %d", opn);
	for (ipn=1; ipn<in->npoints; ++ipn)
	{
		if ( (ipn==in->npoints-1 && opn==1) || memcmp(getPoint_internal(in, ipn-1),
		        getPoint_internal(in, ipn), ptsize) )
		{
			/* The point is different from the previous,
			 * we add it to output */
			memcpy(getPoint_internal(out, opn++),
			       getPoint_internal(in, ipn), ptsize);
			LWDEBUGF(3, " Point %d differs from point %d. Out points: %d",
			         ipn, ipn-1, opn);
		}
	}

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

	return out;
}
Exemple #8
0
/*
 * Construct a triangle from a LWLINE being
 * the shell
 * Pointarray from intput geom are cloned.
 * Input line must have 4 points, and be closed.
 */
LWTRIANGLE *
lwtriangle_from_lwline(const LWLINE *shell)
{
	LWTRIANGLE *ret;
	POINTARRAY *pa;

	if ( shell->points->npoints != 4 )
		lwerror("lwtriangle_from_lwline: shell must have exactly 4 points");

	if (   (!FLAGS_GET_Z(shell->flags) && !ptarray_is_closed_2d(shell->points)) ||
	        (FLAGS_GET_Z(shell->flags) && !ptarray_is_closed_3d(shell->points)) )
		lwerror("lwtriangle_from_lwline: shell must be closed");

	pa = ptarray_clone_deep(shell->points);
	ret = lwtriangle_construct(shell->srid, NULL, pa);

	if (lwtriangle_is_repeated_points(ret))
		lwerror("lwtriangle_from_lwline: some points are repeated in triangle");

	return ret;
}
Exemple #9
0
/**
 * @param mcurve input compound curve
 * @param tol tolerance, semantic driven by tolerance_type
 * @param tolerance_type see LW_LINEARIZE_TOLERANCE_TYPE
 * @param flags see flags in lwarc_linearize
 *
 * @return a newly allocated LWMLINE
 */
static LWMLINE *
lwmcurve_linearize(const LWMCURVE *mcurve, double tol,
                    LW_LINEARIZE_TOLERANCE_TYPE type,
                    int flags)
{
	LWMLINE *ogeom;
	LWGEOM **lines;
	int i;

	LWDEBUGF(2, "lwmcurve_linearize called, geoms=%d, dim=%d.", mcurve->ngeoms, FLAGS_NDIMS(mcurve->flags));

	lines = lwalloc(sizeof(LWGEOM *)*mcurve->ngeoms);

	for (i = 0; i < mcurve->ngeoms; i++)
	{
		const LWGEOM *tmp = mcurve->geoms[i];
		if (tmp->type == CIRCSTRINGTYPE)
		{
			lines[i] = (LWGEOM *)lwcircstring_linearize((LWCIRCSTRING *)tmp, tol, type, flags);
		}
		else if (tmp->type == LINETYPE)
		{
			lines[i] = (LWGEOM *)lwline_construct(mcurve->srid, NULL, ptarray_clone_deep(((LWLINE *)tmp)->points));
		}
		else if (tmp->type == COMPOUNDTYPE)
		{
			lines[i] = (LWGEOM *)lwcompound_linearize((LWCOMPOUND *)tmp, tol, type, flags);
		}
		else
		{
			lwerror("Unsupported geometry found in MultiCurve.");
			return NULL;
		}
	}

	ogeom = (LWMLINE *)lwcollection_construct(MULTILINETYPE, mcurve->srid, NULL, mcurve->ngeoms, lines);
	return ogeom;
}
Exemple #10
0
/**
 * @param msurface input multi surface
 * @param tol tolerance, semantic driven by tolerance_type
 * @param tolerance_type see LW_LINEARIZE_TOLERANCE_TYPE
 * @param flags see flags in lwarc_linearize
 *
 * @return a newly allocated LWMPOLY
 */
static LWMPOLY *
lwmsurface_linearize(const LWMSURFACE *msurface, double tol,
                      LW_LINEARIZE_TOLERANCE_TYPE type,
                      int flags)
{
	LWMPOLY *ogeom;
	LWGEOM *tmp;
	LWPOLY *poly;
	LWGEOM **polys;
	POINTARRAY **ptarray;
	int i, j;

	LWDEBUG(2, "lwmsurface_linearize called.");

	polys = lwalloc(sizeof(LWGEOM *)*msurface->ngeoms);

	for (i = 0; i < msurface->ngeoms; i++)
	{
		tmp = msurface->geoms[i];
		if (tmp->type == CURVEPOLYTYPE)
		{
			polys[i] = (LWGEOM *)lwcurvepoly_linearize((LWCURVEPOLY *)tmp, tol, type, flags);
		}
		else if (tmp->type == POLYGONTYPE)
		{
			poly = (LWPOLY *)tmp;
			ptarray = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
			for (j = 0; j < poly->nrings; j++)
			{
				ptarray[j] = ptarray_clone_deep(poly->rings[j]);
			}
			polys[i] = (LWGEOM *)lwpoly_construct(msurface->srid, NULL, poly->nrings, ptarray);
		}
	}
	ogeom = (LWMPOLY *)lwcollection_construct(MULTIPOLYGONTYPE, msurface->srid, NULL, msurface->ngeoms, polys);
	return ogeom;
}
Exemple #11
0
/**
 * Parse kml:coordinates
 */
static POINTARRAY* parse_kml_coordinates(xmlNodePtr xnode, bool *hasz)
{
	xmlChar *kml_coord;
	bool digit, found;
	POINTARRAY *dpa;
	int kml_dims;
	char *p, *q;
	POINT4D pt;

	if (xnode == NULL) lwerror("invalid KML representation");

	for (found = false ; xnode != NULL ; xnode = xnode->next)
	{
		if (xnode->type != XML_ELEMENT_NODE) continue;
		if (!is_kml_namespace(xnode, false)) continue;
		if (strcmp((char *) xnode->name, "coordinates")) continue;

		found = true;
		break;
	}
	if (!found) lwerror("invalid KML representation");

	/* We begin to retrieve coordinates string */
	kml_coord = xmlNodeGetContent(xnode);
	p = (char *) kml_coord;

	/* KML coordinates pattern:     x1,y1 x2,y2
	 *                              x1,y1,z1 x2,y2,z2
	*/

	/* Now we create PointArray from coordinates values */
	/* HasZ, !HasM, 1pt */
	dpa = ptarray_construct_empty(1, 0, 1);

	for (q = p, kml_dims=0, digit = false ; *p ; p++)
	{

		if (isdigit(*p)) digit = true;  /* One state parser */

		/* Coordinate Separator */
		if (*p == ',')
		{
			*p = '\0';
			kml_dims++;

			if (*(p+1) == '\0') lwerror("invalid KML representation");

			if      (kml_dims == 1) pt.x = parse_kml_double(q, true, true);
			else if (kml_dims == 2) pt.y = parse_kml_double(q, true, true);
			q = p+1;

			/* Tuple Separator (or end string) */
		}
		else if (digit && (isspace(*p) || *(p+1) == '\0'))
		{
			if (isspace(*p)) *p = '\0';
			kml_dims++;

			if (kml_dims < 2 || kml_dims > 3)
				lwerror("invalid KML representation");

			if (kml_dims == 3)
				pt.z = parse_kml_double(q, true, true);
			else
			{
				pt.y = parse_kml_double(q, true, true);
				*hasz = false;
			}

			ptarray_append_point(dpa, &pt, LW_FALSE);
			digit = false;
			q = p+1;
			kml_dims = 0;

		}
	}

	xmlFree(kml_coord);

	/* TODO: we shouldn't need to clone here */
	return ptarray_clone_deep(dpa);
}
Exemple #12
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;
}
Exemple #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;
}