PostGIS  3.3.9dev-r@@SVN_REVISION@@

◆ buffer()

Datum buffer ( PG_FUNCTION_ARGS  )

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

935 {
936  GEOSBufferParams *bufferparams;
937  GEOSGeometry *g1, *g3 = NULL;
939  LWGEOM *lwg;
940  int quadsegs = 8; /* the default */
941  int singleside = 0; /* the default */
942  enum
943  {
944  ENDCAP_ROUND = 1,
945  ENDCAP_FLAT = 2,
946  ENDCAP_SQUARE = 3
947  };
948  enum
949  {
950  JOIN_ROUND = 1,
951  JOIN_MITRE = 2,
952  JOIN_BEVEL = 3
953  };
954  const double DEFAULT_MITRE_LIMIT = 5.0;
955  const int DEFAULT_ENDCAP_STYLE = ENDCAP_ROUND;
956  const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
957  double mitreLimit = DEFAULT_MITRE_LIMIT;
958  int endCapStyle = DEFAULT_ENDCAP_STYLE;
959  int joinStyle = DEFAULT_JOIN_STYLE;
960 
961  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
962  double size = PG_GETARG_FLOAT8(1);
963  text *params_text;
964 
965  if (PG_NARGS() > 2)
966  {
967  params_text = PG_GETARG_TEXT_P(2);
968  }
969  else
970  {
971  params_text = cstring_to_text("");
972  }
973 
974  /* Empty.Buffer() == Empty[polygon] */
975  if ( gserialized_is_empty(geom1) )
976  {
978  gserialized_get_srid(geom1),
979  0, 0)); // buffer wouldn't give back z or m anyway
980  PG_RETURN_POINTER(geometry_serialize(lwg));
981  }
982 
983  lwg = lwgeom_from_gserialized(geom1);
984 
985  if (!lwgeom_isfinite(lwg))
986  {
987  lwpgerror("Geometry contains invalid coordinates");
988  PG_RETURN_NULL();
989  }
990  lwgeom_free(lwg);
991 
992  initGEOS(lwpgnotice, lwgeom_geos_error);
993 
994  g1 = POSTGIS2GEOS(geom1);
995  if (!g1)
996  HANDLE_GEOS_ERROR("First argument geometry could not be converted to GEOS");
997 
998 
999  if (VARSIZE_ANY_EXHDR(params_text) > 0)
1000  {
1001  char *param;
1002  char *params = text_to_cstring(params_text);
1003 
1004  for (param=params; ; param=NULL)
1005  {
1006  char *key, *val;
1007  param = strtok(param, " ");
1008  if (!param) break;
1009  POSTGIS_DEBUGF(3, "Param: %s", param);
1010 
1011  key = param;
1012  val = strchr(key, '=');
1013  if (!val || *(val + 1) == '\0')
1014  {
1015  lwpgerror("Missing value for buffer parameter %s", key);
1016  break;
1017  }
1018  *val = '\0';
1019  ++val;
1020 
1021  POSTGIS_DEBUGF(3, "Param: %s : %s", key, val);
1022 
1023  if ( !strcmp(key, "endcap") )
1024  {
1025  /* Supported end cap styles:
1026  * "round", "flat", "square"
1027  */
1028  if ( !strcmp(val, "round") )
1029  {
1030  endCapStyle = ENDCAP_ROUND;
1031  }
1032  else if ( !strcmp(val, "flat") ||
1033  !strcmp(val, "butt") )
1034  {
1035  endCapStyle = ENDCAP_FLAT;
1036  }
1037  else if ( !strcmp(val, "square") )
1038  {
1039  endCapStyle = ENDCAP_SQUARE;
1040  }
1041  else
1042  {
1043  lwpgerror("Invalid buffer end cap "
1044  "style: %s (accept: "
1045  "'round', 'flat', 'butt' "
1046  "or 'square'"
1047  ")", val);
1048  break;
1049  }
1050 
1051  }
1052  else if ( !strcmp(key, "join") )
1053  {
1054  if ( !strcmp(val, "round") )
1055  {
1056  joinStyle = JOIN_ROUND;
1057  }
1058  else if ( !strcmp(val, "mitre") ||
1059  !strcmp(val, "miter") )
1060  {
1061  joinStyle = JOIN_MITRE;
1062  }
1063  else if ( !strcmp(val, "bevel") )
1064  {
1065  joinStyle = JOIN_BEVEL;
1066  }
1067  else
1068  {
1069  lwpgerror("Invalid buffer end cap "
1070  "style: %s (accept: "
1071  "'round', 'mitre', 'miter' "
1072  " or 'bevel'"
1073  ")", val);
1074  break;
1075  }
1076  }
1077  else if ( !strcmp(key, "mitre_limit") ||
1078  !strcmp(key, "miter_limit") )
1079  {
1080  /* mitreLimit is a float */
1081  mitreLimit = atof(val);
1082  }
1083  else if ( !strcmp(key, "quad_segs") )
1084  {
1085  /* quadrant segments is an int */
1086  quadsegs = atoi(val);
1087  }
1088  else if ( !strcmp(key, "side") )
1089  {
1090  if ( !strcmp(val, "both") )
1091  {
1092  singleside = 0;
1093  }
1094  else if ( !strcmp(val, "left") )
1095  {
1096  singleside = 1;
1097  }
1098  else if ( !strcmp(val, "right") )
1099  {
1100  singleside = 1;
1101  size *= -1;
1102  }
1103  else
1104  {
1105  lwpgerror("Invalid side parameter: %s (accept: 'right', 'left', 'both')", val);
1106  break;
1107  }
1108  }
1109  else
1110  {
1111  lwpgerror(
1112  "Invalid buffer parameter: %s (accept: 'endcap', 'join', 'mitre_limit', 'miter_limit', 'quad_segs' and 'side')",
1113  key);
1114  break;
1115  }
1116  }
1117  pfree(params); /* was pstrduped */
1118  }
1119 
1120 
1121  POSTGIS_DEBUGF(3, "endCap:%d joinStyle:%d mitreLimit:%g",
1122  endCapStyle, joinStyle, mitreLimit);
1123 
1124  bufferparams = GEOSBufferParams_create();
1125  if (bufferparams)
1126  {
1127  if (GEOSBufferParams_setEndCapStyle(bufferparams, endCapStyle) &&
1128  GEOSBufferParams_setJoinStyle(bufferparams, joinStyle) &&
1129  GEOSBufferParams_setMitreLimit(bufferparams, mitreLimit) &&
1130  GEOSBufferParams_setQuadrantSegments(bufferparams, quadsegs) &&
1131  GEOSBufferParams_setSingleSided(bufferparams, singleside))
1132  {
1133  g3 = GEOSBufferWithParams(g1, bufferparams, size);
1134  }
1135  else
1136  {
1137  lwpgerror("Error setting buffer parameters.");
1138  }
1139  GEOSBufferParams_destroy(bufferparams);
1140  }
1141  else
1142  {
1143  lwpgerror("Error setting buffer parameters.");
1144  }
1145 
1146  GEOSGeom_destroy(g1);
1147 
1148  if (!g3) HANDLE_GEOS_ERROR("GEOSBuffer");
1149 
1150  POSTGIS_DEBUGF(3, "result: %s", GEOSGeomToWKT(g3));
1151 
1152  GEOSSetSRID(g3, gserialized_get_srid(geom1));
1153 
1154  result = GEOS2POSTGIS(g3, gserialized_has_z(geom1));
1155  GEOSGeom_destroy(g3);
1156 
1157  if (!result)
1158  {
1159  elog(ERROR,"GEOS buffer() threw an error (result postgis geometry formation)!");
1160  PG_RETURN_NULL(); /* never get here */
1161  }
1162 
1163  PG_FREE_IF_COPY(geom1, 0);
1164  PG_RETURN_POINTER(result);
1165 }
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:267
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: gserialized.c:126
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:239
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: gserialized.c:152
int gserialized_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
Definition: gserialized.c:174
void lwgeom_geos_error(const char *fmt,...)
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1155
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:329
int lwgeom_isfinite(const LWGEOM *lwgeom)
Check if a LWGEOM has any non-finite (NaN or Inf) coordinates.
Definition: lwgeom.c:2707
LWPOLY * lwpoly_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwpoly.c:161
#define HANDLE_GEOS_ERROR(label)
GSERIALIZED * GEOS2POSTGIS(GEOSGeom geom, char want3d)
GEOSGeometry * POSTGIS2GEOS(const GSERIALIZED *pglwgeom)

References GEOS2POSTGIS(), gserialized_get_srid(), gserialized_has_z(), gserialized_is_empty(), HANDLE_GEOS_ERROR, lwgeom_free(), lwgeom_from_gserialized(), lwgeom_geos_error(), lwgeom_isfinite(), lwpoly_as_lwgeom(), lwpoly_construct_empty(), POSTGIS2GEOS(), and result.

Referenced by do_test_s64_roundtrip(), do_test_u64_roundtrip(), encode_ptarray(), encode_ptarray_initial(), init_homogenizebuffer(), lwcollection_build_buffer(), lwcollection_homogenize(), lwgeom_to_wkb_buffer(), lwgeom_to_wkb_varlena(), lwgeom_to_wkb_write_buf(), mvt_clip_and_validate(), mvt_clip_and_validate_geos(), mvt_geom(), spatial_index_read_extent(), and ST_AsMVTGeom().

Here is the call graph for this function:
Here is the caller graph for this function: