PostGIS  3.1.6dev-r@@SVN_REVISION@@

◆ buffer()

Datum buffer ( PG_FUNCTION_ARGS  )

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

1027 {
1028  GEOSBufferParams *bufferparams;
1029  GEOSGeometry *g1, *g3 = NULL;
1031  LWGEOM *lwg;
1032  int quadsegs = 8; /* the default */
1033  int singleside = 0; /* the default */
1034  enum
1035  {
1036  ENDCAP_ROUND = 1,
1037  ENDCAP_FLAT = 2,
1038  ENDCAP_SQUARE = 3
1039  };
1040  enum
1041  {
1042  JOIN_ROUND = 1,
1043  JOIN_MITRE = 2,
1044  JOIN_BEVEL = 3
1045  };
1046  const double DEFAULT_MITRE_LIMIT = 5.0;
1047  const int DEFAULT_ENDCAP_STYLE = ENDCAP_ROUND;
1048  const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
1049  double mitreLimit = DEFAULT_MITRE_LIMIT;
1050  int endCapStyle = DEFAULT_ENDCAP_STYLE;
1051  int joinStyle = DEFAULT_JOIN_STYLE;
1052 
1053  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
1054  double size = PG_GETARG_FLOAT8(1);
1055  text *params_text;
1056 
1057  if (PG_NARGS() > 2)
1058  {
1059  params_text = PG_GETARG_TEXT_P(2);
1060  }
1061  else
1062  {
1063  params_text = cstring_to_text("");
1064  }
1065 
1066  /* Empty.Buffer() == Empty[polygon] */
1067  if ( gserialized_is_empty(geom1) )
1068  {
1070  gserialized_get_srid(geom1),
1071  0, 0)); // buffer wouldn't give back z or m anyway
1072  PG_RETURN_POINTER(geometry_serialize(lwg));
1073  }
1074 
1075  lwg = lwgeom_from_gserialized(geom1);
1076 
1077  if (!lwgeom_isfinite(lwg))
1078  {
1079  lwpgerror("Geometry contains invalid coordinates");
1080  PG_RETURN_NULL();
1081  }
1082  lwgeom_free(lwg);
1083 
1084  initGEOS(lwpgnotice, lwgeom_geos_error);
1085 
1086  g1 = POSTGIS2GEOS(geom1);
1087  if (!g1)
1088  HANDLE_GEOS_ERROR("First argument geometry could not be converted to GEOS");
1089 
1090 
1091  if (VARSIZE_ANY_EXHDR(params_text) > 0)
1092  {
1093  char *param;
1094  char *params = text_to_cstring(params_text);
1095 
1096  for (param=params; ; param=NULL)
1097  {
1098  char *key, *val;
1099  param = strtok(param, " ");
1100  if (!param) break;
1101  POSTGIS_DEBUGF(3, "Param: %s", param);
1102 
1103  key = param;
1104  val = strchr(key, '=');
1105  if (!val || *(val + 1) == '\0')
1106  {
1107  lwpgerror("Missing value for buffer parameter %s", key);
1108  break;
1109  }
1110  *val = '\0';
1111  ++val;
1112 
1113  POSTGIS_DEBUGF(3, "Param: %s : %s", key, val);
1114 
1115  if ( !strcmp(key, "endcap") )
1116  {
1117  /* Supported end cap styles:
1118  * "round", "flat", "square"
1119  */
1120  if ( !strcmp(val, "round") )
1121  {
1122  endCapStyle = ENDCAP_ROUND;
1123  }
1124  else if ( !strcmp(val, "flat") ||
1125  !strcmp(val, "butt") )
1126  {
1127  endCapStyle = ENDCAP_FLAT;
1128  }
1129  else if ( !strcmp(val, "square") )
1130  {
1131  endCapStyle = ENDCAP_SQUARE;
1132  }
1133  else
1134  {
1135  lwpgerror("Invalid buffer end cap "
1136  "style: %s (accept: "
1137  "'round', 'flat', 'butt' "
1138  "or 'square'"
1139  ")", val);
1140  break;
1141  }
1142 
1143  }
1144  else if ( !strcmp(key, "join") )
1145  {
1146  if ( !strcmp(val, "round") )
1147  {
1148  joinStyle = JOIN_ROUND;
1149  }
1150  else if ( !strcmp(val, "mitre") ||
1151  !strcmp(val, "miter") )
1152  {
1153  joinStyle = JOIN_MITRE;
1154  }
1155  else if ( !strcmp(val, "bevel") )
1156  {
1157  joinStyle = JOIN_BEVEL;
1158  }
1159  else
1160  {
1161  lwpgerror("Invalid buffer end cap "
1162  "style: %s (accept: "
1163  "'round', 'mitre', 'miter' "
1164  " or 'bevel'"
1165  ")", val);
1166  break;
1167  }
1168  }
1169  else if ( !strcmp(key, "mitre_limit") ||
1170  !strcmp(key, "miter_limit") )
1171  {
1172  /* mitreLimit is a float */
1173  mitreLimit = atof(val);
1174  }
1175  else if ( !strcmp(key, "quad_segs") )
1176  {
1177  /* quadrant segments is an int */
1178  quadsegs = atoi(val);
1179  }
1180  else if ( !strcmp(key, "side") )
1181  {
1182  if ( !strcmp(val, "both") )
1183  {
1184  singleside = 0;
1185  }
1186  else if ( !strcmp(val, "left") )
1187  {
1188  singleside = 1;
1189  }
1190  else if ( !strcmp(val, "right") )
1191  {
1192  singleside = 1;
1193  size *= -1;
1194  }
1195  else
1196  {
1197  lwpgerror("Invalid side parameter: %s (accept: 'right', 'left', 'both')", val);
1198  break;
1199  }
1200  }
1201  else
1202  {
1203  lwpgerror(
1204  "Invalid buffer parameter: %s (accept: 'endcap', 'join', 'mitre_limit', 'miter_limit', 'quad_segs' and 'side')",
1205  key);
1206  break;
1207  }
1208  }
1209  pfree(params); /* was pstrduped */
1210  }
1211 
1212 
1213  POSTGIS_DEBUGF(3, "endCap:%d joinStyle:%d mitreLimit:%g",
1214  endCapStyle, joinStyle, mitreLimit);
1215 
1216  bufferparams = GEOSBufferParams_create();
1217  if (bufferparams)
1218  {
1219  if (GEOSBufferParams_setEndCapStyle(bufferparams, endCapStyle) &&
1220  GEOSBufferParams_setJoinStyle(bufferparams, joinStyle) &&
1221  GEOSBufferParams_setMitreLimit(bufferparams, mitreLimit) &&
1222  GEOSBufferParams_setQuadrantSegments(bufferparams, quadsegs) &&
1223  GEOSBufferParams_setSingleSided(bufferparams, singleside))
1224  {
1225  g3 = GEOSBufferWithParams(g1, bufferparams, size);
1226  }
1227  else
1228  {
1229  lwpgerror("Error setting buffer parameters.");
1230  }
1231  GEOSBufferParams_destroy(bufferparams);
1232  }
1233  else
1234  {
1235  lwpgerror("Error setting buffer parameters.");
1236  }
1237 
1238  GEOSGeom_destroy(g1);
1239 
1240  if (!g3) HANDLE_GEOS_ERROR("GEOSBuffer");
1241 
1242  POSTGIS_DEBUGF(3, "result: %s", GEOSGeomToWKT(g3));
1243 
1244  GEOSSetSRID(g3, gserialized_get_srid(geom1));
1245 
1246  result = GEOS2POSTGIS(g3, gserialized_has_z(geom1));
1247  GEOSGeom_destroy(g3);
1248 
1249  if (!result)
1250  {
1251  elog(ERROR,"GEOS buffer() threw an error (result postgis geometry formation)!");
1252  PG_RETURN_NULL(); /* never get here */
1253  }
1254 
1255  PG_FREE_IF_COPY(geom1, 0);
1256  PG_RETURN_POINTER(result);
1257 }
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:1138
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:312
int lwgeom_isfinite(const LWGEOM *lwgeom)
Check if a LWGEOM has any non-finite (NaN or Inf) coordinates.
Definition: lwgeom.c:2540
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: