PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ buffer()

Datum buffer ( PG_FUNCTION_ARGS  )

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

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

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: