PostGIS  2.2.8dev-r@@SVN_REVISION@@

◆ buffer()

Datum buffer ( PG_FUNCTION_ARGS  )

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

References geometry_serialize(), GEOS2POSTGIS(), gserialized_get_srid(), gserialized_has_z(), gserialized_is_empty(), HANDLE_GEOS_ERROR, lwgeom_geos_error(), lwpoly_as_lwgeom(), lwpoly_construct_empty(), PG_FUNCTION_INFO_V1(), POSTGIS2GEOS(), POSTGIS_GEOS_VERSION, and ST_OffsetCurve().

Referenced by do_test_s64_roundtrip(), do_test_u64_roundtrip(), lwcollection_homogenize(), main(), and topologypreservesimplify().

1027 {
1028  GSERIALIZED *geom1;
1029  double size;
1030  GEOSGeometry *g1, *g3;
1031  GSERIALIZED *result;
1032  int quadsegs = 8; /* the default */
1033  int nargs;
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  static const double DEFAULT_MITRE_LIMIT = 5.0;
1047  static const int DEFAULT_ENDCAP_STYLE = ENDCAP_ROUND;
1048  static const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
1049 
1050  double mitreLimit = DEFAULT_MITRE_LIMIT;
1051  int endCapStyle = DEFAULT_ENDCAP_STYLE;
1052  int joinStyle = DEFAULT_JOIN_STYLE;
1053  char *param;
1054  char *params = NULL;
1055  LWGEOM *lwg;
1056 
1057  geom1 = PG_GETARG_GSERIALIZED_P(0);
1058  size = PG_GETARG_FLOAT8(1);
1059 
1060  /* Empty.Buffer() == Empty[polygon] */
1061  if ( gserialized_is_empty(geom1) )
1062  {
1064  gserialized_get_srid(geom1),
1065  0, 0)); // buffer wouldn't give back z or m anyway
1066  PG_RETURN_POINTER(geometry_serialize(lwg));
1067  }
1068 
1069  nargs = PG_NARGS();
1070 
1071  initGEOS(lwpgnotice, lwgeom_geos_error);
1072 
1073  g1 = (GEOSGeometry *)POSTGIS2GEOS(geom1);
1074  if ( 0 == g1 ) /* exception thrown at construction */
1075  {
1076  HANDLE_GEOS_ERROR("First argument geometry could not be converted to GEOS");
1077  PG_RETURN_NULL();
1078  }
1079 
1080  if (nargs > 2)
1081  {
1082  /* We strdup `cause we're going to modify it */
1083  params = pstrdup(PG_GETARG_CSTRING(2));
1084 
1085  POSTGIS_DEBUGF(3, "Params: %s", params);
1086 
1087  for (param=params; ; param=NULL)
1088  {
1089  char *key, *val;
1090  param = strtok(param, " ");
1091  if ( param == NULL ) break;
1092  POSTGIS_DEBUGF(3, "Param: %s", param);
1093 
1094  key = param;
1095  val = strchr(key, '=');
1096  if ( val == NULL || *(val+1) == '\0' )
1097  {
1098  lwpgerror("Missing value for buffer "
1099  "parameter %s", key);
1100  break;
1101  }
1102  *val = '\0';
1103  ++val;
1104 
1105  POSTGIS_DEBUGF(3, "Param: %s : %s", key, val);
1106 
1107  if ( !strcmp(key, "endcap") )
1108  {
1109  /* Supported end cap styles:
1110  * "round", "flat", "square"
1111  */
1112  if ( !strcmp(val, "round") )
1113  {
1114  endCapStyle = ENDCAP_ROUND;
1115  }
1116  else if ( !strcmp(val, "flat") ||
1117  !strcmp(val, "butt") )
1118  {
1119  endCapStyle = ENDCAP_FLAT;
1120  }
1121  else if ( !strcmp(val, "square") )
1122  {
1123  endCapStyle = ENDCAP_SQUARE;
1124  }
1125  else
1126  {
1127  lwpgerror("Invalid buffer end cap "
1128  "style: %s (accept: "
1129  "'round', 'flat', 'butt' "
1130  "or 'square'"
1131  ")", val);
1132  break;
1133  }
1134 
1135  }
1136  else if ( !strcmp(key, "join") )
1137  {
1138  if ( !strcmp(val, "round") )
1139  {
1140  joinStyle = JOIN_ROUND;
1141  }
1142  else if ( !strcmp(val, "mitre") ||
1143  !strcmp(val, "miter") )
1144  {
1145  joinStyle = JOIN_MITRE;
1146  }
1147  else if ( !strcmp(val, "bevel") )
1148  {
1149  joinStyle = JOIN_BEVEL;
1150  }
1151  else
1152  {
1153  lwpgerror("Invalid buffer end cap "
1154  "style: %s (accept: "
1155  "'round', 'mitre', 'miter' "
1156  " or 'bevel'"
1157  ")", val);
1158  break;
1159  }
1160  }
1161  else if ( !strcmp(key, "mitre_limit") ||
1162  !strcmp(key, "miter_limit") )
1163  {
1164  /* mitreLimit is a float */
1165  mitreLimit = atof(val);
1166  }
1167  else if ( !strcmp(key, "quad_segs") )
1168  {
1169  /* quadrant segments is an int */
1170  quadsegs = atoi(val);
1171  }
1172  else
1173  {
1174  lwpgerror("Invalid buffer parameter: %s (accept: "
1175  "'endcap', 'join', 'mitre_limit', "
1176  "'miter_limit and "
1177  "'quad_segs')", key);
1178  break;
1179  }
1180  }
1181 
1182  pfree(params); /* was pstrduped */
1183 
1184  POSTGIS_DEBUGF(3, "endCap:%d joinStyle:%d mitreLimit:%g",
1185  endCapStyle, joinStyle, mitreLimit);
1186 
1187  }
1188 
1189 #if POSTGIS_GEOS_VERSION >= 32
1190 
1191  g3 = GEOSBufferWithStyle(g1, size, quadsegs, endCapStyle, joinStyle, mitreLimit);
1192  GEOSGeom_destroy(g1);
1193 
1194 #else /* POSTGIS_GEOS_VERSION < 32 */
1195 
1196  if ( mitreLimit != DEFAULT_MITRE_LIMIT ||
1197  endCapStyle != DEFAULT_ENDCAP_STYLE ||
1198  joinStyle != DEFAULT_JOIN_STYLE )
1199  {
1200  lwpgerror("The GEOS version this PostGIS binary "
1201  "was compiled against (%d) doesn't support "
1202  "specifying a mitre limit != %d or styles different "
1203  "from 'round' (needs 3.2 or higher)",
1204  DEFAULT_MITRE_LIMIT, POSTGIS_GEOS_VERSION);
1205  }
1206 
1207  g3 = GEOSBuffer(g1,size,quadsegs);
1208  GEOSGeom_destroy(g1);
1209 
1210 #endif /* POSTGIS_GEOS_VERSION < 32 */
1211 
1212  if (g3 == NULL)
1213  {
1214  HANDLE_GEOS_ERROR("GEOSBuffer");
1215  PG_RETURN_NULL(); /* never get here */
1216  }
1217 
1218  POSTGIS_DEBUGF(3, "result: %s", GEOSGeomToWKT(g3));
1219 
1220  GEOSSetSRID(g3, gserialized_get_srid(geom1));
1221 
1222  result = GEOS2POSTGIS(g3, gserialized_has_z(geom1));
1223  GEOSGeom_destroy(g3);
1224 
1225  if (result == NULL)
1226  {
1227  elog(ERROR,"GEOS buffer() threw an error (result postgis geometry formation)!");
1228  PG_RETURN_NULL(); /* never get here */
1229  }
1230 
1231  PG_FREE_IF_COPY(geom1, 0);
1232  PG_RETURN_POINTER(result);
1233 }
#define POSTGIS_GEOS_VERSION
Definition: sqldefines.h:10
int gserialized_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
Definition: g_serialized.c:24
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:239
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: g_serialized.c:139
void lwgeom_geos_error(const char *fmt,...)
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
GEOSGeometry * POSTGIS2GEOS(GSERIALIZED *pglwgeom)
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:66
GSERIALIZED * GEOS2POSTGIS(GEOSGeom geom, char want3d)
#define HANDLE_GEOS_ERROR(label)
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: g_serialized.c:69
Here is the call graph for this function:
Here is the caller graph for this function: