Ticket #413: postgis-offsetCurve-RafalMagda.patch

File postgis-offsetCurve-RafalMagda.patch, 6.4 KB (added by rafalmag, 6 years ago)

usage: svn co http://svn.osgeo.org/postgis/trunk/ -r 5389 && patch -p0 < postgis-offsetCurve-RafalMagda?.patch

  • postgis/lwgeom_geos.c

    diff -uNr trunk/postgis/lwgeom_geos.c trunk-patched/postgis/lwgeom_geos.c
    old new  
    4545Datum isvalidreason(PG_FUNCTION_ARGS);
    4646Datum isvaliddetail(PG_FUNCTION_ARGS);
    4747Datum buffer(PG_FUNCTION_ARGS);
     48Datum offsetcurve(PG_FUNCTION_ARGS);
    4849Datum intersection(PG_FUNCTION_ARGS);
    4950Datum convexhull(PG_FUNCTION_ARGS);
    5051Datum topologypreservesimplify(PG_FUNCTION_ARGS);
     
    12771278        PG_RETURN_POINTER(result);
    12781279}
    12791280
     1281PG_FUNCTION_INFO_V1(offsetcurve);
     1282Datum offsetcurve(PG_FUNCTION_ARGS)
     1283{
     1284#if POSTGIS_GEOS_VERSION >= 32
     1285        PG_LWGEOM       *geom1;
     1286        double  size;
     1287        GEOSGeometry *g1, *g3;
     1288        PG_LWGEOM *result;
     1289        int quadsegs = 8; /* the default */
     1290        int nargs;
     1291
     1292        enum
     1293        {
     1294                JOIN_ROUND = 1,
     1295                JOIN_MITRE = 2,
     1296                JOIN_BEVEL = 3
     1297        };
     1298        static const double DEFAULT_MITRE_LIMIT = 5.0;
     1299        static const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
     1300
     1301        double mitreLimit = DEFAULT_MITRE_LIMIT;
     1302        int joinStyle  = DEFAULT_JOIN_STYLE;
     1303        int leftSide = 0;
     1304        char *param;
     1305        char *params = NULL;
     1306
     1307
     1308        PROFSTART(PROF_QRUN);
     1309        // geom arg
     1310        geom1 = (PG_LWGEOM *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
     1311        // distance/size arg
     1312        size = PG_GETARG_FLOAT8(1);
     1313       
     1314
     1315        nargs = PG_NARGS();
     1316
     1317        initGEOS(lwnotice, lwnotice);
     1318
     1319        PROFSTART(PROF_P2G1);
     1320        g1 = (GEOSGeometry *)POSTGIS2GEOS(geom1);
     1321        PROFSTOP(PROF_P2G1);
     1322
     1323        // side arg
     1324        param = pstrdup(PG_GETARG_CSTRING(2));
     1325        POSTGIS_DEBUGF(3, "Param side: %s", param);
     1326        if ( !strcmp(param, "left") )
     1327                leftSide = 1;
     1328        else if( !strcmp(param, "right") )
     1329                leftSide = 0;
     1330        else
     1331        {
     1332                lwerror("Invalid side string, "
     1333                        "accept: "
     1334                        "'left' or 'right' ");
     1335        }
     1336       
     1337        // options arg (optional)
     1338        if (nargs > 3)
     1339        {
     1340                /* We strdup `cause we're going to modify it */
     1341                params = pstrdup(PG_GETARG_CSTRING(3));
     1342
     1343                POSTGIS_DEBUGF(3, "Params: %s", params);
     1344
     1345                for (param=params; ; param=NULL)
     1346                {
     1347                        char *key, *val;
     1348                        param = strtok(param, " ");
     1349                        if ( param == NULL ) break;
     1350                        POSTGIS_DEBUGF(3, "Param: %s", param);
     1351
     1352                        key = param;
     1353                        val = strchr(key, '=');
     1354                        if ( val == NULL || *(val+1) == '\0' )
     1355                        {
     1356                                lwerror("Missing value for buffer "
     1357                                        "parameter %s", key);
     1358                                break;
     1359                        }
     1360                        *val = '\0';
     1361                        ++val;
     1362
     1363                        POSTGIS_DEBUGF(3, "Param: %s : %s", key, val);
     1364
     1365                        if ( !strcmp(key, "join") )
     1366                        {
     1367                                if ( !strcmp(val, "round") )
     1368                                {
     1369                                        joinStyle = JOIN_ROUND;
     1370                                }
     1371                                else if ( !strcmp(val, "mitre") ||
     1372                                          !strcmp(val, "miter")    )
     1373                                {
     1374                                        joinStyle = JOIN_MITRE;
     1375                                }
     1376                                else if ( !strcmp(val, "bevel") )
     1377                                {
     1378                                        joinStyle = JOIN_BEVEL;
     1379                                }
     1380                                else
     1381                                {
     1382                                        lwerror("Invalid buffer end cap "
     1383                                                "style: %s (accept: "
     1384                                                "'round', 'mitre', 'miter' "
     1385                                                " or 'bevel'"
     1386                                                ")", val);
     1387                                        break;
     1388                                }
     1389                        }
     1390                        else if ( !strcmp(key, "mitre_limit") ||
     1391                                  !strcmp(key, "miter_limit")    )
     1392                        {
     1393                                /* mitreLimit is a float */
     1394                                mitreLimit = atof(val);
     1395                        }
     1396                        else if ( !strcmp(key, "quad_segs") )
     1397                        {
     1398                                /* quadrant segments is an int */
     1399                                quadsegs = atoi(val);
     1400                        }
     1401                        else
     1402                        {
     1403                                lwerror("Invalid buffer parameter: %s (accept: "
     1404                                        "'join', 'mitre_limit', "
     1405                                        "'miter_limit and "
     1406                                        "'quad_segs')", key);
     1407                                break;
     1408                        }
     1409                }
     1410
     1411                pfree(params); /* was pstrduped */
     1412
     1413                POSTGIS_DEBUGF(3, "joinStyle:%d mitreLimit:%g",
     1414                               joinStyle, mitreLimit);
     1415
     1416        }
     1417
     1418        PROFSTART(PROF_GRUN);
     1419        g3 = GEOSSingleSidedBuffer(g1, size, quadsegs,
     1420                                 joinStyle, mitreLimit, leftSide);
     1421        PROFSTOP(PROF_GRUN);
     1422
     1423        if (g3 == NULL)
     1424        {
     1425                elog(ERROR,"GEOS singleSidedBuffer() threw an error!");
     1426                GEOSGeom_destroy(g1);
     1427                PG_RETURN_NULL(); /* never get here */
     1428        }
     1429
     1430        POSTGIS_DEBUGF(3, "result: %s", GEOSGeomToWKT(g3));
     1431
     1432        GEOSSetSRID(g3, pglwgeom_getSRID(geom1));
     1433
     1434        PROFSTART(PROF_G2P);
     1435        result = GEOS2POSTGIS(g3, TYPE_HASZ(geom1->type));
     1436        PROFSTOP(PROF_G2P);
     1437
     1438        if (result == NULL)
     1439        {
     1440                GEOSGeom_destroy(g1);
     1441                GEOSGeom_destroy(g3);
     1442                elog(ERROR,"GEOS singleSidedBuffer() threw an error (result postgis geometry formation)!");
     1443                PG_RETURN_NULL(); /* never get here */
     1444        }
     1445        GEOSGeom_destroy(g1);
     1446        GEOSGeom_destroy(g3);
     1447
     1448
     1449        /* compressType(result); */
     1450
     1451        PROFSTOP(PROF_QRUN);
     1452        PROFREPORT("geos",geom1, NULL, result);
     1453
     1454        PG_FREE_IF_COPY(geom1, 0);
     1455
     1456        PG_RETURN_POINTER(result);
     1457#else /* POSTGIS_GEOS_VERSION < 32 */
     1458        lwerror("The GEOS version this postgis binary "
     1459        "was compiled against (%d) doesn't support "
     1460        "offsetcurve function "
     1461        "(needs 3.2 or higher)",
     1462        POSTGIS_GEOS_VERSION);
     1463                       
     1464        elog(ERROR,"offsetcurve() only in GEOS version >= 3.2 ! Please recompile PostGIS using GEOS version >= 3.2");
     1465        PG_RETURN_NULL(); /* never get here */
     1466#endif /* POSTGIS_GEOS_VERSION < 32 */ 
     1467}
     1468
     1469
    12801470PG_FUNCTION_INFO_V1(intersection);
    12811471Datum intersection(PG_FUNCTION_ARGS)
    12821472{
  • postgis/postgis.sql.in.c

    diff -uNr trunk/postgis/postgis.sql.in.c trunk-patched/postgis/postgis.sql.in.c
    old new  
    38863886        AS 'SELECT ST_Buffer($1, $2, $3)'
    38873887        LANGUAGE 'SQL' IMMUTABLE STRICT;
    38883888
     3889-- Availability: 2.0.0 - requires GEOS-3.2 or higher
     3890CREATE OR REPLACE FUNCTION _ST_OffsetCurve(geometry,float8,cstring,cstring)
     3891        RETURNS geometry
     3892        AS 'MODULE_PATHNAME','offsetcurve'
     3893        LANGUAGE 'C' IMMUTABLE STRICT
     3894        COST 100;
     3895
     3896-- Availability: 2.0.0 - requires GEOS-3.2 or higher
     3897CREATE OR REPLACE FUNCTION ST_OffsetCurve(geometry,float8,text,text)
     3898        RETURNS geometry
     3899        AS $$ SELECT _ST_OffsetCurve($1, $2,
     3900                CAST( regexp_replace($3, '^[0123456789]+$',
     3901                        'quad_segs='||$3) AS cstring),
     3902                CAST( $4 AS cstring)
     3903                )
     3904           $$
     3905        LANGUAGE 'SQL' IMMUTABLE STRICT;
     3906
     3907-- Availability: 2.0.0 - requires GEOS-3.2 or higher
     3908CREATE OR REPLACE FUNCTION _ST_OffsetCurve(geometry,float8,cstring)
     3909        RETURNS geometry
     3910        AS 'MODULE_PATHNAME','offsetcurve'
     3911        LANGUAGE 'C' IMMUTABLE STRICT
     3912        COST 100;
     3913
     3914-- Availability: 2.0.0 - requires GEOS-3.2 or higher
     3915CREATE OR REPLACE FUNCTION ST_OffsetCurve(geometry,float8,text)
     3916        RETURNS geometry
     3917        AS $$ SELECT _ST_OffsetCurve($1, $2,
     3918                CAST( regexp_replace($3, '^[0123456789]+$',
     3919                        'quad_segs='||$3) AS cstring)
     3920                )
     3921           $$
     3922        LANGUAGE 'SQL' IMMUTABLE STRICT;
     3923
    38893924-- Deprecation in 1.2.3
    38903925CREATE OR REPLACE FUNCTION convexhull(geometry)
    38913926        RETURNS geometry