PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ buffer()

Datum buffer ( PG_FUNCTION_ARGS  )

Definition at line 849 of file postgis/lwgeom_geos.c.

References geometry_serialize(), GEOS2POSTGIS(), gserialized_get_srid(), gserialized_has_z(), gserialized_is_empty(), HANDLE_GEOS_ERROR, lwgeom_geos_error(), lwpoly_as_lwgeom(), lwpoly_construct_empty(), PG_FUNCTION_INFO_V1(), POSTGIS2GEOS(), and ST_GeneratePoints().

Referenced by do_test_s64_roundtrip(), do_test_u64_roundtrip(), lwcollection_homogenize(), main(), mvt_geom(), ST_AsMVTGeom(), and topologypreservesimplify().

850 {
851  GSERIALIZED *geom1;
852  double size;
853  GEOSGeometry *g1, *g3;
854  GSERIALIZED *result;
855  int quadsegs = 8; /* the default */
856  int nargs;
857  enum
858  {
859  ENDCAP_ROUND = 1,
860  ENDCAP_FLAT = 2,
861  ENDCAP_SQUARE = 3
862  };
863  enum
864  {
865  JOIN_ROUND = 1,
866  JOIN_MITRE = 2,
867  JOIN_BEVEL = 3
868  };
869  static const double DEFAULT_MITRE_LIMIT = 5.0;
870  static const int DEFAULT_ENDCAP_STYLE = ENDCAP_ROUND;
871  static const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
872 
873  double mitreLimit = DEFAULT_MITRE_LIMIT;
874  int endCapStyle = DEFAULT_ENDCAP_STYLE;
875  int joinStyle = DEFAULT_JOIN_STYLE;
876  char *param;
877  char *params = NULL;
878  LWGEOM *lwg;
879 
880  geom1 = PG_GETARG_GSERIALIZED_P(0);
881  size = PG_GETARG_FLOAT8(1);
882 
883  /* Empty.Buffer() == Empty[polygon] */
884  if ( gserialized_is_empty(geom1) )
885  {
887  gserialized_get_srid(geom1),
888  0, 0)); // buffer wouldn't give back z or m anyway
889  PG_RETURN_POINTER(geometry_serialize(lwg));
890  }
891 
892  nargs = PG_NARGS();
893 
894  initGEOS(lwpgnotice, lwgeom_geos_error);
895 
896  g1 = (GEOSGeometry *)POSTGIS2GEOS(geom1);
897  if ( 0 == g1 ) /* exception thrown at construction */
898  {
899  HANDLE_GEOS_ERROR("First argument geometry could not be converted to GEOS");
900  PG_RETURN_NULL();
901  }
902 
903  if (nargs > 2)
904  {
905  /* We strdup `cause we're going to modify it */
906  params = pstrdup(PG_GETARG_CSTRING(2));
907 
908  POSTGIS_DEBUGF(3, "Params: %s", params);
909 
910  for (param=params; ; param=NULL)
911  {
912  char *key, *val;
913  param = strtok(param, " ");
914  if ( param == NULL ) break;
915  POSTGIS_DEBUGF(3, "Param: %s", param);
916 
917  key = param;
918  val = strchr(key, '=');
919  if ( val == NULL || *(val+1) == '\0' )
920  {
921  lwpgerror("Missing value for buffer "
922  "parameter %s", key);
923  break;
924  }
925  *val = '\0';
926  ++val;
927 
928  POSTGIS_DEBUGF(3, "Param: %s : %s", key, val);
929 
930  if ( !strcmp(key, "endcap") )
931  {
932  /* Supported end cap styles:
933  * "round", "flat", "square"
934  */
935  if ( !strcmp(val, "round") )
936  {
937  endCapStyle = ENDCAP_ROUND;
938  }
939  else if ( !strcmp(val, "flat") ||
940  !strcmp(val, "butt") )
941  {
942  endCapStyle = ENDCAP_FLAT;
943  }
944  else if ( !strcmp(val, "square") )
945  {
946  endCapStyle = ENDCAP_SQUARE;
947  }
948  else
949  {
950  lwpgerror("Invalid buffer end cap "
951  "style: %s (accept: "
952  "'round', 'flat', 'butt' "
953  "or 'square'"
954  ")", val);
955  break;
956  }
957 
958  }
959  else if ( !strcmp(key, "join") )
960  {
961  if ( !strcmp(val, "round") )
962  {
963  joinStyle = JOIN_ROUND;
964  }
965  else if ( !strcmp(val, "mitre") ||
966  !strcmp(val, "miter") )
967  {
968  joinStyle = JOIN_MITRE;
969  }
970  else if ( !strcmp(val, "bevel") )
971  {
972  joinStyle = JOIN_BEVEL;
973  }
974  else
975  {
976  lwpgerror("Invalid buffer end cap "
977  "style: %s (accept: "
978  "'round', 'mitre', 'miter' "
979  " or 'bevel'"
980  ")", val);
981  break;
982  }
983  }
984  else if ( !strcmp(key, "mitre_limit") ||
985  !strcmp(key, "miter_limit") )
986  {
987  /* mitreLimit is a float */
988  mitreLimit = atof(val);
989  }
990  else if ( !strcmp(key, "quad_segs") )
991  {
992  /* quadrant segments is an int */
993  quadsegs = atoi(val);
994  }
995  else
996  {
997  lwpgerror("Invalid buffer parameter: %s (accept: "
998  "'endcap', 'join', 'mitre_limit', "
999  "'miter_limit and "
1000  "'quad_segs')", key);
1001  break;
1002  }
1003  }
1004 
1005  pfree(params); /* was pstrduped */
1006 
1007  POSTGIS_DEBUGF(3, "endCap:%d joinStyle:%d mitreLimit:%g",
1008  endCapStyle, joinStyle, mitreLimit);
1009 
1010  }
1011 
1012  g3 = GEOSBufferWithStyle(g1, size, quadsegs, endCapStyle, joinStyle, mitreLimit);
1013  GEOSGeom_destroy(g1);
1014 
1015  if (g3 == NULL)
1016  {
1017  HANDLE_GEOS_ERROR("GEOSBuffer");
1018  PG_RETURN_NULL(); /* never get here */
1019  }
1020 
1021  POSTGIS_DEBUGF(3, "result: %s", GEOSGeomToWKT(g3));
1022 
1023  GEOSSetSRID(g3, gserialized_get_srid(geom1));
1024 
1025  result = GEOS2POSTGIS(g3, gserialized_has_z(geom1));
1026  GEOSGeom_destroy(g3);
1027 
1028  if (result == NULL)
1029  {
1030  elog(ERROR,"GEOS buffer() threw an error (result postgis geometry formation)!");
1031  PG_RETURN_NULL(); /* never get here */
1032  }
1033 
1034  PG_FREE_IF_COPY(geom1, 0);
1035  PG_RETURN_POINTER(result);
1036 }
int gserialized_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
Definition: g_serialized.c:45
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:288
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: g_serialized.c:179
void lwgeom_geos_error(const char *fmt,...)
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
GEOSGeometry * POSTGIS2GEOS(GSERIALIZED *pglwgeom)
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:161
GSERIALIZED * GEOS2POSTGIS(GEOSGeom geom, char want3d)
#define HANDLE_GEOS_ERROR(label)
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: g_serialized.c:100
Here is the call graph for this function:
Here is the caller graph for this function: