PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ buffer()

Datum buffer ( PG_FUNCTION_ARGS  )

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

990 {
991  GEOSBufferParams *bufferparams;
992  GEOSGeometry *g1, *g3 = NULL;
994  LWGEOM *lwg;
995  int quadsegs = 8; /* the default */
996  int singleside = 0; /* the default */
997  enum
998  {
999  ENDCAP_ROUND = 1,
1000  ENDCAP_FLAT = 2,
1001  ENDCAP_SQUARE = 3
1002  };
1003  enum
1004  {
1005  JOIN_ROUND = 1,
1006  JOIN_MITRE = 2,
1007  JOIN_BEVEL = 3
1008  };
1009  const double DEFAULT_MITRE_LIMIT = 5.0;
1010  const int DEFAULT_ENDCAP_STYLE = ENDCAP_ROUND;
1011  const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
1012  double mitreLimit = DEFAULT_MITRE_LIMIT;
1013  int endCapStyle = DEFAULT_ENDCAP_STYLE;
1014  int joinStyle = DEFAULT_JOIN_STYLE;
1015 
1016  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
1017  double size = PG_GETARG_FLOAT8(1);
1018  text *params_text;
1019 
1020  if (PG_NARGS() > 2)
1021  {
1022  params_text = PG_GETARG_TEXT_P(2);
1023  }
1024  else
1025  {
1026  params_text = cstring_to_text("");
1027  }
1028 
1029  /* Empty.Buffer() == Empty[polygon] */
1030  if ( gserialized_is_empty(geom1) )
1031  {
1033  gserialized_get_srid(geom1),
1034  0, 0)); // buffer wouldn't give back z or m anyway
1035  PG_RETURN_POINTER(geometry_serialize(lwg));
1036  }
1037 
1038  lwg = lwgeom_from_gserialized(geom1);
1039 
1040  if (!lwgeom_isfinite(lwg))
1041  {
1042  lwpgerror("Geometry contains invalid coordinates");
1043  PG_RETURN_NULL();
1044  }
1045  lwgeom_free(lwg);
1046 
1047  initGEOS(lwpgnotice, lwgeom_geos_error);
1048 
1049  g1 = POSTGIS2GEOS(geom1);
1050  if (!g1)
1051  HANDLE_GEOS_ERROR("First argument geometry could not be converted to GEOS");
1052 
1053 
1054  if (VARSIZE_ANY_EXHDR(params_text) > 0)
1055  {
1056  char *param;
1057  char *params = text_to_cstring(params_text);
1058 
1059  for (param=params; ; param=NULL)
1060  {
1061  char *key, *val;
1062  param = strtok(param, " ");
1063  if (!param) break;
1064  POSTGIS_DEBUGF(3, "Param: %s", param);
1065 
1066  key = param;
1067  val = strchr(key, '=');
1068  if (!val || *(val + 1) == '\0')
1069  {
1070  lwpgerror("Missing value for buffer parameter %s", key);
1071  break;
1072  }
1073  *val = '\0';
1074  ++val;
1075 
1076  POSTGIS_DEBUGF(3, "Param: %s : %s", key, val);
1077 
1078  if ( !strcmp(key, "endcap") )
1079  {
1080  /* Supported end cap styles:
1081  * "round", "flat", "square"
1082  */
1083  if ( !strcmp(val, "round") )
1084  {
1085  endCapStyle = ENDCAP_ROUND;
1086  }
1087  else if ( !strcmp(val, "flat") ||
1088  !strcmp(val, "butt") )
1089  {
1090  endCapStyle = ENDCAP_FLAT;
1091  }
1092  else if ( !strcmp(val, "square") )
1093  {
1094  endCapStyle = ENDCAP_SQUARE;
1095  }
1096  else
1097  {
1098  lwpgerror("Invalid buffer end cap "
1099  "style: %s (accept: "
1100  "'round', 'flat', 'butt' "
1101  "or 'square'"
1102  ")", val);
1103  break;
1104  }
1105 
1106  }
1107  else if ( !strcmp(key, "join") )
1108  {
1109  if ( !strcmp(val, "round") )
1110  {
1111  joinStyle = JOIN_ROUND;
1112  }
1113  else if ( !strcmp(val, "mitre") ||
1114  !strcmp(val, "miter") )
1115  {
1116  joinStyle = JOIN_MITRE;
1117  }
1118  else if ( !strcmp(val, "bevel") )
1119  {
1120  joinStyle = JOIN_BEVEL;
1121  }
1122  else
1123  {
1124  lwpgerror("Invalid buffer end cap "
1125  "style: %s (accept: "
1126  "'round', 'mitre', 'miter' "
1127  " or 'bevel'"
1128  ")", val);
1129  break;
1130  }
1131  }
1132  else if ( !strcmp(key, "mitre_limit") ||
1133  !strcmp(key, "miter_limit") )
1134  {
1135  /* mitreLimit is a float */
1136  mitreLimit = atof(val);
1137  }
1138  else if ( !strcmp(key, "quad_segs") )
1139  {
1140  /* quadrant segments is an int */
1141  quadsegs = atoi(val);
1142  }
1143  else if ( !strcmp(key, "side") )
1144  {
1145  if ( !strcmp(val, "both") )
1146  {
1147  singleside = 0;
1148  }
1149  else if ( !strcmp(val, "left") )
1150  {
1151  singleside = 1;
1152  }
1153  else if ( !strcmp(val, "right") )
1154  {
1155  singleside = 1;
1156  size *= -1;
1157  }
1158  else
1159  {
1160  lwpgerror("Invalid side parameter: %s (accept: 'right', 'left', 'both')", val);
1161  break;
1162  }
1163  }
1164  else
1165  {
1166  lwpgerror(
1167  "Invalid buffer parameter: %s (accept: 'endcap', 'join', 'mitre_limit', 'miter_limit', 'quad_segs' and 'side')",
1168  key);
1169  break;
1170  }
1171  }
1172  pfree(params); /* was pstrduped */
1173  }
1174 
1175 
1176  POSTGIS_DEBUGF(3, "endCap:%d joinStyle:%d mitreLimit:%g",
1177  endCapStyle, joinStyle, mitreLimit);
1178 
1179  bufferparams = GEOSBufferParams_create();
1180  if (bufferparams)
1181  {
1182  if (GEOSBufferParams_setEndCapStyle(bufferparams, endCapStyle) &&
1183  GEOSBufferParams_setJoinStyle(bufferparams, joinStyle) &&
1184  GEOSBufferParams_setMitreLimit(bufferparams, mitreLimit) &&
1185  GEOSBufferParams_setQuadrantSegments(bufferparams, quadsegs) &&
1186  GEOSBufferParams_setSingleSided(bufferparams, singleside))
1187  {
1188  g3 = GEOSBufferWithParams(g1, bufferparams, size);
1189  }
1190  else
1191  {
1192  lwpgerror("Error setting buffer parameters.");
1193  }
1194  GEOSBufferParams_destroy(bufferparams);
1195  }
1196  else
1197  {
1198  lwpgerror("Error setting buffer parameters.");
1199  }
1200 
1201  GEOSGeom_destroy(g1);
1202 
1203  if (!g3) HANDLE_GEOS_ERROR("GEOSBuffer");
1204 
1205  POSTGIS_DEBUGF(3, "result: %s", GEOSGeomToWKT(g3));
1206 
1207  GEOSSetSRID(g3, gserialized_get_srid(geom1));
1208 
1209  result = GEOS2POSTGIS(g3, gserialized_has_z(geom1));
1210  GEOSGeom_destroy(g3);
1211 
1212  if (!result)
1213  {
1214  elog(ERROR,"GEOS buffer() threw an error (result postgis geometry formation)!");
1215  PG_RETURN_NULL(); /* never get here */
1216  }
1217 
1218  PG_FREE_IF_COPY(geom1, 0);
1219  PG_RETURN_POINTER(result);
1220 }
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:155
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:268
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: gserialized.c:181
int gserialized_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
Definition: gserialized.c:203
void lwgeom_geos_error(const char *fmt,...)
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1218
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:2807
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: