postgis/postgis/lwgeom_sqlmm.c
Sandro Santilli 149773b6b0 Implement extended ST_CurveToLine signature
Adds lwcurve_linearize function at liblwgeom level.
Turns lwgeom_stroke into a wrapper, keept it for backward compatibility.
Reduces allocations in linearization procedures.

Implements SYMMETRIC and RETAIN_ANGLE flags.
Implements MAX_DEVIATION, MAX_ANGLE and SEGS_PER_QUADRANT configs.

Includes unit and SQL tests.
Includes documentation.

Closes #2464 (maxError configuration is MAX_DEVIATION)
Closes #3772 (balanced output is SYMMETRIC and RETAIN_ANGLE flags)

Document the new ST_CurveToLine signature

git-svn-id: http://svn.osgeo.org/postgis/trunk@15430 b70326c6-7e19-0410-871a-916f4a2858ee
2017-06-19 16:06:59 +00:00

154 lines
4.1 KiB
C

/**********************************************************************
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.net
*
* PostGIS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* PostGIS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
*
**********************************************************************
*
* Copyright 2001-2006 Refractions Research Inc.
*
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include "postgres.h"
#include "fmgr.h"
#include "../postgis_config.h"
#include "liblwgeom.h"
#include "lwgeom_pg.h"
Datum LWGEOM_has_arc(PG_FUNCTION_ARGS);
Datum LWGEOM_curve_segmentize(PG_FUNCTION_ARGS);
Datum LWGEOM_line_desegmentize(PG_FUNCTION_ARGS);
/*******************************************************************************
* Begin PG_FUNCTIONs
******************************************************************************/
PG_FUNCTION_INFO_V1(LWGEOM_has_arc);
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);
}
/*
* Converts any curve segments of the geometry into a linear approximation.
* Curve centers are determined by projecting the defining points into the 2d
* plane. Z and M values are assigned by linear interpolation between
* defining points.
*
* TODO: drop, use ST_CurveToLine instead
*/
PG_FUNCTION_INFO_V1(LWGEOM_curve_segmentize);
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);
}
PG_FUNCTION_INFO_V1(ST_CurveToLine);
Datum ST_CurveToLine(PG_FUNCTION_ARGS)
{
GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
double tol = PG_GETARG_FLOAT8(1);
int toltype = PG_GETARG_INT32(2);
int flags = PG_GETARG_INT32(3);
GSERIALIZED *ret;
LWGEOM *igeom = NULL, *ogeom = NULL;
POSTGIS_DEBUG(2, "ST_CurveToLine called.");
POSTGIS_DEBUGF(3, "tol = %g, typ = %d, flg = %d", tol, toltype, flags);
igeom = lwgeom_from_gserialized(geom);
ogeom = lwcurve_linearize(igeom, tol, toltype, flags);
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);
}
PG_FUNCTION_INFO_V1(LWGEOM_line_desegmentize);
Datum LWGEOM_line_desegmentize(PG_FUNCTION_ARGS)
{
GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
GSERIALIZED *ret;
LWGEOM *igeom = NULL, *ogeom = NULL;
POSTGIS_DEBUG(2, "LWGEOM_line_desegmentize.");
igeom = lwgeom_from_gserialized(geom);
ogeom = lwgeom_unstroke(igeom);
lwgeom_free(igeom);
if (ogeom == NULL)
{
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_NULL();
}
ret = geometry_serialize(ogeom);
lwgeom_free(ogeom);
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_POINTER(ret);
}
/*******************************************************************************
* End PG_FUNCTIONs
******************************************************************************/