PostGIS  3.2.2dev-r@@SVN_REVISION@@

◆ buffer()

Datum buffer ( PG_FUNCTION_ARGS  )

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

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