Exemplo n.º 1
0
Datum ST_InterpolatePoint(PG_FUNCTION_ARGS)
{
	GSERIALIZED *gser_line = PG_GETARG_GSERIALIZED_P(0);
	GSERIALIZED *gser_point = PG_GETARG_GSERIALIZED_P(1);
	LWGEOM *lwline;
	LWPOINT *lwpoint;

	if ( gserialized_get_type(gser_line) != LINETYPE )
	{
		elog(ERROR,"ST_InterpolatePoint: 1st argument isn't a line");
		PG_RETURN_NULL();
	}
	if ( gserialized_get_type(gser_point) != POINTTYPE )
	{
		elog(ERROR,"ST_InterpolatePoint: 2st argument isn't a point");
		PG_RETURN_NULL();
	}

	error_if_srid_mismatch(gserialized_get_srid(gser_line), gserialized_get_srid(gser_point));

	if ( ! gserialized_has_m(gser_line) )
	{
		elog(ERROR,"ST_InterpolatePoint only accepts geometries that have an M dimension");
		PG_RETURN_NULL();
	}
	
	lwpoint = lwgeom_as_lwpoint(lwgeom_from_gserialized(gser_point));
	lwline = lwgeom_from_gserialized(gser_line);
	
	PG_RETURN_FLOAT8(lwgeom_interpolate_point(lwline, lwpoint));
}
Exemplo n.º 2
0
Datum LWGEOM_line_locate_point(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
	GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
	LWLINE *lwline;
	LWPOINT *lwpoint;
	POINTARRAY *pa;
	POINT4D p, p_proj;
	double ret;

	if ( gserialized_get_type(geom1) != LINETYPE )
	{
		elog(ERROR,"line_locate_point: 1st arg isn't a line");
		PG_RETURN_NULL();
	}
	if ( gserialized_get_type(geom2) != POINTTYPE )
	{
		elog(ERROR,"line_locate_point: 2st arg isn't a point");
		PG_RETURN_NULL();
	}

	error_if_srid_mismatch(gserialized_get_srid(geom1), gserialized_get_srid(geom2));

	lwline = lwgeom_as_lwline(lwgeom_from_gserialized(geom1));
	lwpoint = lwgeom_as_lwpoint(lwgeom_from_gserialized(geom2));

	pa = lwline->points;
	lwpoint_getPoint4d_p(lwpoint, &p);

	ret = ptarray_locate_point(pa, &p, NULL, &p_proj);

	PG_RETURN_FLOAT8(ret);
}
Exemplo n.º 3
0
Datum BOX3D_construct(PG_FUNCTION_ARGS)
{
	GSERIALIZED *min = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	GSERIALIZED *max = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
	BOX3D *result = palloc(sizeof(BOX3D));
	LWGEOM *minpoint, *maxpoint;
	POINT3DZ minp, maxp;

	minpoint = lwgeom_from_gserialized(min);
	maxpoint = lwgeom_from_gserialized(max);

	if ( minpoint->type != POINTTYPE ||
	     maxpoint->type != POINTTYPE )
	{
		elog(ERROR, "BOX3D_construct: args must be points");
		PG_RETURN_NULL();
	}

	error_if_srid_mismatch(minpoint->srid, maxpoint->srid);

	getPoint3dz_p(((LWPOINT *)minpoint)->point, 0, &minp);
	getPoint3dz_p(((LWPOINT *)maxpoint)->point, 0, &maxp);

	result->xmax = maxp.x;
	result->ymax = maxp.y;
	result->zmax = maxp.z;

	result->xmin = minp.x;
	result->ymin = minp.y;
	result->zmin = minp.z;

	result->srid = minpoint->srid;

	PG_RETURN_POINTER(result);
}
Exemplo n.º 4
0
Datum ST_LineCrossingDirection(PG_FUNCTION_ARGS)
{
	int type1, type2, rv;
	LWLINE *l1 = NULL;
	LWLINE *l2 = NULL;
	GSERIALIZED *geom1 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	GSERIALIZED *geom2 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));

	error_if_srid_mismatch(gserialized_get_srid(geom1), gserialized_get_srid(geom2));

	type1 = gserialized_get_type(geom1);
	type2 = gserialized_get_type(geom2);

	if ( type1 != LINETYPE || type2 != LINETYPE )
	{
		elog(ERROR,"This function only accepts LINESTRING as arguments.");
		PG_RETURN_NULL();
	}

	l1 = lwgeom_as_lwline(lwgeom_from_gserialized(geom1));
	l2 = lwgeom_as_lwline(lwgeom_from_gserialized(geom2));

	rv = lwline_crossing_direction(l1, l2);

	PG_FREE_IF_COPY(geom1, 0);
	PG_FREE_IF_COPY(geom2, 1);

	PG_RETURN_INT32(rv);

}
int
geography_tree_distance(const GSERIALIZED* g1, const GSERIALIZED* g2, const SPHEROID* s, double tolerance, double* distance)
{
    CIRC_NODE* circ_tree1 = NULL;
    CIRC_NODE* circ_tree2 = NULL;
    LWGEOM* lwgeom1 = NULL;
    LWGEOM* lwgeom2 = NULL;
    POINT4D pt1, pt2;

    lwgeom1 = lwgeom_from_gserialized(g1);
    lwgeom2 = lwgeom_from_gserialized(g2);
    circ_tree1 = lwgeom_calculate_circ_tree(lwgeom1);
    circ_tree2 = lwgeom_calculate_circ_tree(lwgeom2);
    lwgeom_startpoint(lwgeom1, &pt1);
    lwgeom_startpoint(lwgeom2, &pt2);

    if ( CircTreePIP(circ_tree1, g1, &pt2) || CircTreePIP(circ_tree2, g2, &pt1) )
    {
        *distance = 0.0;
    }
    else
    {
        /* Calculate tree/tree distance */
        *distance = circ_tree_distance_tree(circ_tree1, circ_tree2, s, tolerance);
    }

    circ_tree_free(circ_tree1);
    circ_tree_free(circ_tree2);
    lwgeom_free(lwgeom1);
    lwgeom_free(lwgeom2);
    return LW_SUCCESS;
}
Exemplo n.º 6
0
Datum geometry_distance_spheroid(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
	GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
	SPHEROID *sphere = (SPHEROID *)PG_GETARG_POINTER(2);
	int type1 = gserialized_get_type(geom1);
	int type2 = gserialized_get_type(geom2);
	bool use_spheroid = PG_GETARG_BOOL(3);
	LWGEOM *lwgeom1, *lwgeom2;
	double distance;

	/* Calculate some other parameters on the spheroid */
	spheroid_init(sphere, sphere->a, sphere->b);

	/* Catch sphere special case and re-jig spheroid appropriately */
	if ( ! use_spheroid )
	{
		sphere->a = sphere->b = sphere->radius;
	}

	if ( ! ( type1 == POINTTYPE || type1 == LINETYPE || type1 == POLYGONTYPE ||
	         type1 == MULTIPOINTTYPE || type1 == MULTILINETYPE || type1 == MULTIPOLYGONTYPE ))
	{
		elog(ERROR, "geometry_distance_spheroid: Only point/line/polygon supported.\n");
		PG_RETURN_NULL();
	}

	if ( ! ( type2 == POINTTYPE || type2 == LINETYPE || type2 == POLYGONTYPE ||
	         type2 == MULTIPOINTTYPE || type2 == MULTILINETYPE || type2 == MULTIPOLYGONTYPE ))
	{
		elog(ERROR, "geometry_distance_spheroid: Only point/line/polygon supported.\n");
		PG_RETURN_NULL();
	}


	if (gserialized_get_srid(geom1) != gserialized_get_srid(geom2))
	{
		elog(ERROR, "geometry_distance_spheroid: Operation on two GEOMETRIES with different SRIDs\n");
		PG_RETURN_NULL();
	}

	/* Get #LWGEOM structures */
	lwgeom1 = lwgeom_from_gserialized(geom1);
	lwgeom2 = lwgeom_from_gserialized(geom2);
	
	/* We are going to be calculating geodetic distances */
	lwgeom_set_geodetic(lwgeom1, LW_TRUE);
	lwgeom_set_geodetic(lwgeom2, LW_TRUE);

	distance = lwgeom_distance_spheroid(lwgeom1, lwgeom2, sphere, 0.0);

	PG_RETURN_FLOAT8(distance);

}
Exemplo n.º 7
0
Datum LWGEOM_curve_segmentize(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
	int32 perQuad = PG_GETARG_INT32(1);
	GSERIALIZED *ret;
	LWGEOM *igeom = NULL, *ogeom = NULL;

	POSTGIS_DEBUG(2, "LWGEOM_curve_segmentize called.");

	if (perQuad < 0)
	{
		elog(ERROR, "2nd argument must be positive.");
		PG_RETURN_NULL();
	}

	POSTGIS_DEBUGF(3, "perQuad = %d", perQuad);

	igeom = lwgeom_from_gserialized(geom);
	ogeom = lwgeom_stroke(igeom, perQuad);
	lwgeom_free(igeom);
	
	if (ogeom == NULL) 
		PG_RETURN_NULL();
		
	ret = geometry_serialize(ogeom);
	lwgeom_free(ogeom);
	PG_FREE_IF_COPY(geom, 0);
	PG_RETURN_POINTER(ret);
}
Exemplo n.º 8
0
Datum LWGEOM_m_point(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom;
	LWPOINT *point = NULL;
	LWGEOM *lwgeom;
	POINT3DM p;

	geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));

	if ( gserialized_get_type(geom) != POINTTYPE )
		lwerror("Argument to M() must be a point");

	lwgeom = lwgeom_from_gserialized(geom);
	point = lwgeom_as_lwpoint(lwgeom);
	
	if ( lwgeom_is_empty(lwgeom) )
		PG_RETURN_NULL();

	/* no M in input */
	if ( ! FLAGS_GET_M(point->flags) ) PG_RETURN_NULL();

	getPoint3dm_p(point->point, 0, &p);

	PG_FREE_IF_COPY(geom, 0);

	PG_RETURN_FLOAT8(p.m);
}
Exemplo n.º 9
0
Datum LWGEOM_pointn_linestring(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	int where = PG_GETARG_INT32(1);
	LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
	LWPOINT *lwpoint = NULL;
	int type = lwgeom->type;
	
	/* Can't handle crazy index! */
	if ( where < 1 )
		PG_RETURN_NULL();

	if ( type == LINETYPE || type == CIRCSTRINGTYPE )
	{
		/* OGC index starts at one, so we substract first. */
		lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, where - 1);
	}

	lwgeom_free(lwgeom);
	PG_FREE_IF_COPY(geom, 0);

	if ( ! lwpoint )
		PG_RETURN_NULL();

	PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(lwpoint)));
}
Exemplo n.º 10
0
Datum LWGEOM_numinteriorrings_polygon(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
	LWPOLY *poly = NULL;
	LWCURVEPOLY *curvepoly = NULL;
	int result = -1;

	if ( lwgeom->type == POLYGONTYPE )
	{
		poly = lwgeom_as_lwpoly(lwgeom);
		result = poly->nrings - 1;
	}
	else if ( lwgeom->type == CURVEPOLYTYPE )
	{
		curvepoly = lwgeom_as_lwcurvepoly(lwgeom);
		result = curvepoly->nrings - 1;
	}
	
	lwgeom_free(lwgeom);
	PG_FREE_IF_COPY(geom, 0);
	
	if ( result < 0 )
		PG_RETURN_NULL();

	PG_RETURN_INT32(result);
}
Exemplo n.º 11
0
Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
	LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
	LWPOINT *lwpoint = NULL;
	int type = lwgeom->type;

	if ( type == LINETYPE || type == CIRCSTRINGTYPE )
	{
		LWLINE *line = (LWLINE*)lwgeom;
		if ( line->points )
			lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, line->points->npoints - 1);
	}
	else if ( type == COMPOUNDTYPE )
	{
		lwpoint = lwcompound_get_endpoint((LWCOMPOUND*)lwgeom);
	}

	lwgeom_free(lwgeom);
	PG_FREE_IF_COPY(geom, 0);

	if ( ! lwpoint )
		PG_RETURN_NULL();

	PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(lwpoint)));
}
Exemplo n.º 12
0
Datum LWGEOM_z_point(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom;
	LWPOINT *point = NULL;
	LWGEOM *lwgeom;
	POINT3DZ p;

	geom = PG_GETARG_GSERIALIZED_P(0);

	if ( gserialized_get_type(geom) != POINTTYPE )
		lwpgerror("Argument to ST_Z() must be a point");

	lwgeom = lwgeom_from_gserialized(geom);
	point = lwgeom_as_lwpoint(lwgeom);
	
	if ( lwgeom_is_empty(lwgeom) )
		PG_RETURN_NULL();

	/* no Z in input */
	if ( ! gserialized_has_z(geom) ) PG_RETURN_NULL();

	getPoint3dz_p(point->point, 0, &p);

	PG_FREE_IF_COPY(geom, 0);

	PG_RETURN_FLOAT8(p.z);
}
Datum LWGEOM_SetEffectiveArea(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
	GSERIALIZED *result;
	int type = gserialized_get_type(geom);
	LWGEOM *in;
	LWGEOM *out;
	double area=0;
	int set_area=0;

	if ( type == POINTTYPE || type == MULTIPOINTTYPE )
		PG_RETURN_POINTER(geom);

	if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) )
		area = PG_GETARG_FLOAT8(1);

	if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) )
	set_area = PG_GETARG_INT32(2);

	in = lwgeom_from_gserialized(geom);

	out = lwgeom_set_effective_area(in,set_area, area);
	if ( ! out ) PG_RETURN_NULL();

	/* COMPUTE_BBOX TAINTING */
	if ( in->bbox ) lwgeom_add_bbox(out);

	result = geometry_serialize(out);
	lwgeom_free(out);
	PG_FREE_IF_COPY(geom, 0);
	PG_RETURN_POINTER(result);
}
Datum LWGEOM_simplify2d(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
	double dist = PG_GETARG_FLOAT8(1);
	GSERIALIZED *result;
	int type = gserialized_get_type(geom);
	LWGEOM *in, *out;
	bool preserve_collapsed = false;

	/* Handle optional argument to preserve collapsed features */
	if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
		preserve_collapsed = true;

	/* Can't simplify points! */
	if ( type == POINTTYPE || type == MULTIPOINTTYPE )
		PG_RETURN_POINTER(geom);
		
	in = lwgeom_from_gserialized(geom);

	out = lwgeom_simplify(in, dist, preserve_collapsed);
	if ( ! out ) PG_RETURN_NULL();

	/* COMPUTE_BBOX TAINTING */
	if ( in->bbox ) lwgeom_add_bbox(out);

	result = geometry_serialize(out);
	lwgeom_free(out);
	PG_FREE_IF_COPY(geom, 0);
	PG_RETURN_POINTER(result);
}
Exemplo n.º 15
0
Datum LWGEOM_simplify2d(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
	GSERIALIZED *result;
  int type = gserialized_get_type(geom);
	LWGEOM *in;
	LWGEOM *out;
	double dist;

  if ( type == POINTTYPE || type == MULTIPOINTTYPE )
    PG_RETURN_POINTER(geom);

	dist = PG_GETARG_FLOAT8(1);
	in = lwgeom_from_gserialized(geom);

	out = lwgeom_simplify(in, dist);
	if ( ! out ) PG_RETURN_NULL();

	/* COMPUTE_BBOX TAINTING */
	if ( in->bbox ) lwgeom_add_bbox(out);

	result = geometry_serialize(out);
	lwgeom_free(out);
	PG_FREE_IF_COPY(geom, 0);
	PG_RETURN_POINTER(result);
}
Exemplo n.º 16
0
Datum geography_as_binary(PG_FUNCTION_ARGS)
{
	LWGEOM *lwgeom = NULL;
	uint8_t *wkb = NULL;
	bytea *wkb_result;
	size_t wkb_size = 0;
	GSERIALIZED *g = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));

	/* Get our lwgeom form */
	lwgeom = lwgeom_from_gserialized(g);

	if ( gserialized_ndims(g) > 2 )
	{
		/* Strip out the higher dimensions */
		LWGEOM *tmp = lwgeom_force_2d(lwgeom);
		lwgeom_free(lwgeom);
		lwgeom = tmp;
	}
	
	/* Create WKB */
	wkb = lwgeom_to_wkb(lwgeom, WKB_SFSQL, &wkb_size);
	
	/* Copy to varlena pointer */
	wkb_result = palloc(wkb_size + VARHDRSZ);
	SET_VARSIZE(wkb_result, wkb_size + VARHDRSZ);
	memcpy(VARDATA(wkb_result), wkb, wkb_size);

	/* Clean up */
	pfree(wkb);
	lwgeom_free(lwgeom);

	PG_RETURN_BYTEA_P(wkb_result);
}
Exemplo n.º 17
0
Datum LWGEOM_asText(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom;
	LWGEOM *lwgeom;
	char *wkt;
	size_t wkt_size;
	text *result;

	POSTGIS_DEBUG(2, "Called.");

	geom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	lwgeom = lwgeom_from_gserialized(geom);

	/* Write to WKT and free the geometry */
	wkt = lwgeom_to_wkt(lwgeom, WKT_ISO, DBL_DIG, &wkt_size);
	lwgeom_free(lwgeom);
	POSTGIS_DEBUGF(3, "WKT size = %d, WKT length = %d", wkt_size, strlen(wkt));

	/* Write to text and free the WKT */
	result = cstring2text(wkt);
	pfree(wkt);

	/* Return the text */
	PG_FREE_IF_COPY(geom, 0);
	PG_RETURN_TEXT_P(result);
}
Exemplo n.º 18
0
Datum ST_AddMeasure(PG_FUNCTION_ARGS)
{
	GSERIALIZED *gin = PG_GETARG_GSERIALIZED_P(0);
	GSERIALIZED *gout;
	double start_measure = PG_GETARG_FLOAT8(1);
	double end_measure = PG_GETARG_FLOAT8(2);
	LWGEOM *lwin, *lwout;
	int type = gserialized_get_type(gin);

	/* Raise an error if input is not a linestring or multilinestring */
	if ( type != LINETYPE && type != MULTILINETYPE )
	{
		lwpgerror("Only LINESTRING and MULTILINESTRING are supported");
		PG_RETURN_NULL();
	}

	lwin = lwgeom_from_gserialized(gin);
	if ( type == LINETYPE )
		lwout = (LWGEOM*)lwline_measured_from_lwline((LWLINE*)lwin, start_measure, end_measure);
	else
		lwout = (LWGEOM*)lwmline_measured_from_lwmline((LWMLINE*)lwin, start_measure, end_measure);

	lwgeom_free(lwin);

	if ( lwout == NULL )
		PG_RETURN_NULL();

	gout = geometry_serialize(lwout);
	lwgeom_free(lwout);

	PG_RETURN_POINTER(gout);
}
Exemplo n.º 19
0
Datum LWGEOM_length_ellipsoid_linestring(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
	LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
	SPHEROID *sphere = (SPHEROID *) PG_GETARG_POINTER(1);
	double length = 0.0;

	/* EMPTY things have no length */
	if ( lwgeom_is_empty(lwgeom) )
	{
		lwgeom_free(lwgeom);
		PG_RETURN_FLOAT8(0.0);
	}

	length = lwgeom_length_spheroid(lwgeom, sphere);
	lwgeom_free(lwgeom);
	PG_FREE_IF_COPY(geom, 0);

	/* Something went wrong... */
	if ( length < 0.0 )
	{
		elog(ERROR, "lwgeom_length_spheroid returned length < 0.0");
		PG_RETURN_NULL();
	}

	/* Clean up */
	PG_RETURN_FLOAT8(length);
}
Exemplo n.º 20
0
Datum ST_CleanGeometry(PG_FUNCTION_ARGS)
{
#if POSTGIS_GEOS_VERSION < 33
	elog(ERROR, "You need GEOS-3.3.0 or up for ST_CleanGeometry");
	PG_RETURN_NULL();
#else /* POSTGIS_GEOS_VERSION >= 33 */

	GSERIALIZED *in, *out;
	LWGEOM *lwgeom_in, *lwgeom_out;

	in = PG_GETARG_GSERIALIZED_P(0);
	lwgeom_in = lwgeom_from_gserialized(in);

	/* Short-circuit: empty geometry are the cleanest ! */
#if 0
	if ( lwgeom_is_empty(lwgeom_in) )
	{
		out = geometry_serialize(lwgeom_in);
		PG_FREE_IF_COPY(in, 0);
		PG_RETURN_POINTER(out);
	}
#endif

	lwgeom_out = lwgeom_clean(lwgeom_in);
	if ( ! lwgeom_out )
	{
		PG_FREE_IF_COPY(in, 0);
		PG_RETURN_NULL();
	}

	out = geometry_serialize(lwgeom_out);
	PG_RETURN_POINTER(out);

#endif /* POSTGIS_GEOS_VERSION >= 33 */
}
Exemplo n.º 21
0
Datum ST_LocateBetween(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom_in = PG_GETARG_GSERIALIZED_P(0);
	double from = PG_GETARG_FLOAT8(1);
	double to = PG_GETARG_FLOAT8(2);
	double offset = PG_GETARG_FLOAT8(3);
	LWCOLLECTION *geom_out = NULL;
	LWGEOM *line_in = NULL;
	static char ordinate = 'M'; /* M */

	if ( ! gserialized_has_m(geom_in) )
	{
		elog(ERROR,"This function only accepts geometries that have an M dimension.");
		PG_RETURN_NULL();
	}

	/* This should be a call to ST_LocateAlong! */
	if ( to == from )
	{
		PG_RETURN_DATUM(DirectFunctionCall3(ST_LocateAlong, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), PG_GETARG_DATUM(3)));
	}

	line_in = lwgeom_from_gserialized(geom_in);
	geom_out = lwgeom_clip_to_ordinate_range(line_in,  ordinate, from, to, offset);	
	lwgeom_free(line_in);
	PG_FREE_IF_COPY(geom_in, 0);

	if ( ! geom_out )
	{
		elog(ERROR,"lwline_clip_to_ordinate_range returned null");
		PG_RETURN_NULL();
	}

	PG_RETURN_POINTER(geometry_serialize((LWGEOM*)geom_out));
}
Exemplo n.º 22
0
Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom_in = PG_GETARG_GSERIALIZED_P(0);
	double from = PG_GETARG_FLOAT8(1);
	double to = PG_GETARG_FLOAT8(2);
	LWCOLLECTION *geom_out = NULL;
	LWGEOM *line_in = NULL;
	static char ordinate = 'Z'; /* Z */
	static double offset = 0.0;

	if ( ! gserialized_has_z(geom_in) )
	{
		elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING with Z dimensions.");
		PG_RETURN_NULL();
	}

	line_in = lwgeom_from_gserialized(geom_in);
	geom_out = lwgeom_clip_to_ordinate_range(line_in,  ordinate, from, to, offset);	
	lwgeom_free(line_in);
	PG_FREE_IF_COPY(geom_in, 0);

	if ( ! geom_out )
	{
		elog(ERROR,"lwline_clip_to_ordinate_range returned null");
		PG_RETURN_NULL();
	}

	PG_RETURN_POINTER(geometry_serialize((LWGEOM*)geom_out));
}
Exemplo n.º 23
0
Datum BOX2D_construct(PG_FUNCTION_ARGS)
{
	GSERIALIZED *pgmin = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	GSERIALIZED *pgmax = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
	GBOX *result;
	LWPOINT *minpoint, *maxpoint;
	double min, max, tmp;

	minpoint = (LWPOINT*)lwgeom_from_gserialized(pgmin);
	maxpoint = (LWPOINT*)lwgeom_from_gserialized(pgmax);

	if ( (minpoint->type != POINTTYPE) || (maxpoint->type != POINTTYPE) )
	{
		elog(ERROR, "GBOX_construct: arguments must be points");
		PG_RETURN_NULL();
	}

	error_if_srid_mismatch(minpoint->srid, maxpoint->srid);

	result = gbox_new(gflags(0, 0, 0));

	/* Process X min/max */
	min = lwpoint_get_x(minpoint);
	max = lwpoint_get_x(maxpoint);
	if ( min > max ) 
	{
		tmp = min;
		min = max;
		max = tmp;
	}
	result->xmin = min;
	result->xmax = max;

	/* Process Y min/max */
	min = lwpoint_get_y(minpoint);
	max = lwpoint_get_y(maxpoint);
	if ( min > max ) 
	{
		tmp = min;
		min = max;
		max = tmp;
	}
	result->ymin = min;
	result->ymax = max;

	PG_RETURN_POINTER(result);
}
Exemplo n.º 24
0
/**
* Peak into a #GSERIALIZED datum to find the bounding box. If the
* box is there, copy it out and return it. If not, calculate the box from the
* full object and return the box based on that. If no box is available,
* return #LW_FAILURE, otherwise #LW_SUCCESS.
*/
int 
gserialized_datum_get_gidx_p(Datum gsdatum, GIDX *gidx)
{
	GSERIALIZED *gpart;
	int result = LW_SUCCESS;

	POSTGIS_DEBUG(4, "entered function");

	/*
	** The most info we need is the 8 bytes of serialized header plus the 32 bytes
	** of floats necessary to hold the 8 floats of the largest XYZM index
	** bounding box, so 40 bytes.
	*/
	gpart = (GSERIALIZED*)PG_DETOAST_DATUM_SLICE(gsdatum, 0, 40);

	POSTGIS_DEBUGF(4, "got flags %d", gpart->flags);

	/* Do we even have a serialized bounding box? */
	if ( FLAGS_GET_BBOX(gpart->flags) )
	{
		/* Yes! Copy it out into the GIDX! */
		size_t size = gbox_serialized_size(gpart->flags);
		POSTGIS_DEBUG(4, "copying box out of serialization");
		memcpy(gidx->c, gpart->data, size);
		/* if M is present but Z is not, pad Z and shift M */
		if ( FLAGS_GET_M(gpart->flags) && ! FLAGS_GET_Z(gpart->flags) )
		{
			size += 2 * sizeof(float);
			GIDX_SET_MIN(gidx,3,GIDX_GET_MIN(gidx,2));
			GIDX_SET_MAX(gidx,3,GIDX_GET_MAX(gidx,2));
			GIDX_SET_MIN(gidx,2,-1*FLT_MAX);
			GIDX_SET_MAX(gidx,2,FLT_MAX);
		}
		SET_VARSIZE(gidx, VARHDRSZ + size);
		result = LW_SUCCESS;
	}
	else
	{
		/* No, we need to calculate it from the full object. */
		GSERIALIZED *g = (GSERIALIZED*)PG_DETOAST_DATUM(gsdatum);
		LWGEOM *lwgeom = lwgeom_from_gserialized(g);
		GBOX gbox;
		if ( lwgeom_calculate_gbox(lwgeom, &gbox) == LW_FAILURE )
		{
			POSTGIS_DEBUG(4, "could not calculate bbox, returning failure");
			lwgeom_free(lwgeom);
			return LW_FAILURE;
		}
		lwgeom_free(lwgeom);
		result = gidx_from_gbox_p(gbox, gidx);
	}
	
	if ( result == LW_SUCCESS )
	{
		POSTGIS_DEBUGF(4, "got gidx %s", gidx_to_string(gidx));
	}

	return result;
}
Exemplo n.º 25
0
Datum LWGEOM_has_arc(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
	LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
	uint32 result = lwgeom_has_arc(lwgeom);
	lwgeom_free(lwgeom);
	PG_RETURN_BOOL(result == 1);
}
Exemplo n.º 26
0
Datum BOX3D_combine(PG_FUNCTION_ARGS)
{
	BOX3D *box = (BOX3D*)PG_GETARG_POINTER(0);
	GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_POINTER(1));
	LWGEOM *lwgeom = NULL;
	BOX3D *result = NULL;
	GBOX gbox;
	int rv;

	/* Can't do anything with null inputs */
	if  ( (box == NULL) && (geom == NULL) )
		PG_RETURN_NULL();

	/* Null geometry but non-null box, return the box */
	if (geom == NULL)
	{
		result = palloc(sizeof(BOX3D));
		memcpy(result, box, sizeof(BOX3D));
		PG_RETURN_POINTER(result);
	}

	/* Deserialize geometry and *calculate( the box */
	/* We can't use the cached box because it's fload, we *must* calculate */
	lwgeom = lwgeom_from_gserialized(geom);
	rv = lwgeom_calculate_gbox(lwgeom, &gbox);
	lwgeom_free(lwgeom);

	/* If we couldn't calculate the box, return what we know */
	if ( rv == LW_FAILURE )
	{
		PG_FREE_IF_COPY(geom, 1);
		/* No geom box, no input box, so null return */
		if ( box == NULL )
			PG_RETURN_NULL();
		result = palloc(sizeof(BOX3D));
		memcpy(result, box, sizeof(BOX3D));
		PG_RETURN_POINTER(result);
	}

	/* Null box and non-null geometry, just return the geometry box */
	if ( box == NULL )
	{
		PG_FREE_IF_COPY(geom, 1);
		result = box3d_from_gbox(&gbox);
		PG_RETURN_POINTER(result);
	}

	result = palloc(sizeof(BOX3D));
	result->xmax = Max(box->xmax, gbox.xmax);
	result->ymax = Max(box->ymax, gbox.ymax);
	result->zmax = Max(box->zmax, gbox.zmax);
	result->xmin = Min(box->xmin, gbox.xmin);
	result->ymin = Min(box->ymin, gbox.ymin);
	result->zmin = Min(box->zmin, gbox.zmin);

	PG_FREE_IF_COPY(geom, 1);
	PG_RETURN_POINTER(result);
}
Exemplo n.º 27
0
Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS)
{
	GSERIALIZED *gin = PG_GETARG_GSERIALIZED_P(0);
	GSERIALIZED *gout;
	double start_measure = PG_GETARG_FLOAT8(1);
	double end_measure = PG_GETARG_FLOAT8(2);
	LWGEOM *lwin, *lwout;
	int hasz = gserialized_has_z(gin);
	int hasm = gserialized_has_m(gin);
	int type;

	elog(WARNING,"ST_Locate_Between_Measures and ST_Locate_Along_Measure were deprecated in 2.2.0. Please use ST_LocateAlong and ST_LocateBetween");

	if ( end_measure < start_measure )
	{
		lwpgerror("locate_between_m: 2nd arg must be bigger then 1st arg");
		PG_RETURN_NULL();
	}
	
	/*
	 * Return error if input doesn't have a measure
	 */
	if ( ! hasm )
	{
		lwpgerror("Geometry argument does not have an 'M' ordinate");
		PG_RETURN_NULL();
	}

	/*
	 * Raise an error if input is a polygon, a multipolygon
	 * or a collection
	 */
	type = gserialized_get_type(gin);

	if ( type == POLYGONTYPE || type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE )
	{
		lwpgerror("Areal or Collection types are not supported");
		PG_RETURN_NULL();
	}

	lwin = lwgeom_from_gserialized(gin);

	lwout = lwgeom_locate_between_m(lwin,
	                                start_measure, end_measure);

	lwgeom_free(lwin);

	if ( lwout == NULL )
	{
		lwout = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, 
		            gserialized_get_srid(gin), hasz, hasm);
	}

	gout = geometry_serialize(lwout);
	lwgeom_free(lwout);

	PG_RETURN_POINTER(gout);
}
Exemplo n.º 28
0
Datum transform(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom;
	GSERIALIZED *result=NULL;
	LWGEOM *lwgeom;
	projPJ input_pj, output_pj;
	int32 output_srid, input_srid;

	output_srid = PG_GETARG_INT32(1);
	if (output_srid == SRID_UNKNOWN)
	{
		elog(ERROR,"%d is an invalid target SRID",SRID_UNKNOWN);
		PG_RETURN_NULL();
	}

	geom = (GSERIALIZED *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
	input_srid = gserialized_get_srid(geom);
	if ( input_srid == SRID_UNKNOWN )
	{
		PG_FREE_IF_COPY(geom, 0);
		elog(ERROR,"Input geometry has unknown (%d) SRID",SRID_UNKNOWN);
		PG_RETURN_NULL();
	}

	/*
	 * If input SRID and output SRID are equal, return geometry
	 * without transform it
	 */
	if ( input_srid == output_srid )
		PG_RETURN_POINTER(PG_GETARG_DATUM(0));

	if ( GetProjectionsUsingFCInfo(fcinfo, input_srid, output_srid, &input_pj, &output_pj) == LW_FAILURE )
	{
		PG_FREE_IF_COPY(geom, 0);
		elog(ERROR,"Failure reading projections from spatial_ref_sys.");
		PG_RETURN_NULL();
	}
	
	/* now we have a geometry, and input/output PJ structs. */
	lwgeom = lwgeom_from_gserialized(geom);
	lwgeom_transform(lwgeom, input_pj, output_pj);
	lwgeom->srid = output_srid;

	/* Re-compute bbox if input had one (COMPUTE_BBOX TAINTING) */
	if ( lwgeom->bbox )
	{
		lwgeom_drop_bbox(lwgeom);
		lwgeom_add_bbox(lwgeom);
	}

	result = geometry_serialize(lwgeom);
	lwgeom_free(lwgeom);
	PG_FREE_IF_COPY(geom, 0);

	PG_RETURN_POINTER(result); /* new geometry */
}
Exemplo n.º 29
0
Datum LWGEOM_length2d_ellipsoid(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
	SPHEROID *sphere = (SPHEROID *) PG_GETARG_POINTER(1);
	LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
	double dist = lwgeom_length_spheroid(lwgeom, sphere);
	lwgeom_free(lwgeom);
	PG_FREE_IF_COPY(geom, 0);
	PG_RETURN_FLOAT8(dist);
}
Exemplo n.º 30
0
Datum LWGEOM_isclosed(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
	int closed = lwgeom_is_closed(lwgeom);
	
	lwgeom_free(lwgeom);
	PG_FREE_IF_COPY(geom, 0);
	PG_RETURN_BOOL(closed);
}