PostGIS  2.5.0dev-r@@SVN_REVISION@@

◆ buffer()

Datum buffer ( PG_FUNCTION_ARGS  )

Definition at line 810 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(), and ST_GeneratePoints().

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

811 {
812  GSERIALIZED *geom1;
813  double size;
814  GEOSBufferParams *bufferparams;
815  GEOSGeometry *g1, *g3 = NULL;
816  GSERIALIZED *result;
817  int quadsegs = 8; /* the default */
818  int nargs;
819  int singleside = 0; /* the default */
820  enum
821  {
822  ENDCAP_ROUND = 1,
823  ENDCAP_FLAT = 2,
824  ENDCAP_SQUARE = 3
825  };
826  enum
827  {
828  JOIN_ROUND = 1,
829  JOIN_MITRE = 2,
830  JOIN_BEVEL = 3
831  };
832  static const double DEFAULT_MITRE_LIMIT = 5.0;
833  static const int DEFAULT_ENDCAP_STYLE = ENDCAP_ROUND;
834  static const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
835 
836  double mitreLimit = DEFAULT_MITRE_LIMIT;
837  int endCapStyle = DEFAULT_ENDCAP_STYLE;
838  int joinStyle = DEFAULT_JOIN_STYLE;
839  char *param;
840  char *params = NULL;
841  LWGEOM *lwg;
842 
843  geom1 = PG_GETARG_GSERIALIZED_P(0);
844  size = PG_GETARG_FLOAT8(1);
845 
846  /* Empty.Buffer() == Empty[polygon] */
847  if ( gserialized_is_empty(geom1) )
848  {
850  gserialized_get_srid(geom1),
851  0, 0)); // buffer wouldn't give back z or m anyway
852  PG_RETURN_POINTER(geometry_serialize(lwg));
853  }
854 
855  nargs = PG_NARGS();
856 
857  initGEOS(lwpgnotice, lwgeom_geos_error);
858 
859  g1 = POSTGIS2GEOS(geom1);
860  if (!g1)
861  HANDLE_GEOS_ERROR("First argument geometry could not be converted to GEOS");
862 
863  if (nargs > 2)
864  {
865  /* We strdup `cause we're going to modify it */
866  params = pstrdup(PG_GETARG_CSTRING(2));
867 
868  POSTGIS_DEBUGF(3, "Params: %s", params);
869 
870  for (param=params; ; param=NULL)
871  {
872  char *key, *val;
873  param = strtok(param, " ");
874  if (!param) break;
875  POSTGIS_DEBUGF(3, "Param: %s", param);
876 
877  key = param;
878  val = strchr(key, '=');
879  if (!val || *(val + 1) == '\0')
880  {
881  lwpgerror("Missing value for buffer "
882  "parameter %s", key);
883  break;
884  }
885  *val = '\0';
886  ++val;
887 
888  POSTGIS_DEBUGF(3, "Param: %s : %s", key, val);
889 
890  if ( !strcmp(key, "endcap") )
891  {
892  /* Supported end cap styles:
893  * "round", "flat", "square"
894  */
895  if ( !strcmp(val, "round") )
896  {
897  endCapStyle = ENDCAP_ROUND;
898  }
899  else if ( !strcmp(val, "flat") ||
900  !strcmp(val, "butt") )
901  {
902  endCapStyle = ENDCAP_FLAT;
903  }
904  else if ( !strcmp(val, "square") )
905  {
906  endCapStyle = ENDCAP_SQUARE;
907  }
908  else
909  {
910  lwpgerror("Invalid buffer end cap "
911  "style: %s (accept: "
912  "'round', 'flat', 'butt' "
913  "or 'square'"
914  ")", val);
915  break;
916  }
917 
918  }
919  else if ( !strcmp(key, "join") )
920  {
921  if ( !strcmp(val, "round") )
922  {
923  joinStyle = JOIN_ROUND;
924  }
925  else if ( !strcmp(val, "mitre") ||
926  !strcmp(val, "miter") )
927  {
928  joinStyle = JOIN_MITRE;
929  }
930  else if ( !strcmp(val, "bevel") )
931  {
932  joinStyle = JOIN_BEVEL;
933  }
934  else
935  {
936  lwpgerror("Invalid buffer end cap "
937  "style: %s (accept: "
938  "'round', 'mitre', 'miter' "
939  " or 'bevel'"
940  ")", val);
941  break;
942  }
943  }
944  else if ( !strcmp(key, "mitre_limit") ||
945  !strcmp(key, "miter_limit") )
946  {
947  /* mitreLimit is a float */
948  mitreLimit = atof(val);
949  }
950  else if ( !strcmp(key, "quad_segs") )
951  {
952  /* quadrant segments is an int */
953  quadsegs = atoi(val);
954  }
955  else if ( !strcmp(key, "side") ||
956  !strcmp(key, "side") )
957  {
958  if ( !strcmp(val, "both") )
959  {
960  singleside = 0;
961  }
962  else if ( !strcmp(val, "left") )
963  {
964  singleside = 1;
965  }
966  else if ( !strcmp(val, "right") )
967  {
968  singleside = 1;
969  size *= -1;
970  }
971  else
972  {
973  lwpgerror("Invalid side "
974  "parameter: %s (accept: "
975  "'right', 'left', 'both' "
976  ")", val);
977  break;
978  }
979  }
980  else
981  {
982  lwpgerror("Invalid buffer parameter: %s (accept: "
983  "'endcap', 'join', 'mitre_limit', "
984  "'miter_limit', 'quad_segs' and "
985  "'side')", key);
986  break;
987  }
988  }
989 
990  pfree(params); /* was pstrduped */
991 
992  POSTGIS_DEBUGF(3, "endCap:%d joinStyle:%d mitreLimit:%g",
993  endCapStyle, joinStyle, mitreLimit);
994 
995  }
996 
997  bufferparams = GEOSBufferParams_create();
998  if (bufferparams)
999  {
1000  if (GEOSBufferParams_setEndCapStyle(bufferparams, endCapStyle) &&
1001  GEOSBufferParams_setJoinStyle(bufferparams, joinStyle) &&
1002  GEOSBufferParams_setMitreLimit(bufferparams, mitreLimit) &&
1003  GEOSBufferParams_setQuadrantSegments(bufferparams, quadsegs) &&
1004  GEOSBufferParams_setSingleSided(bufferparams, singleside))
1005  {
1006  g3 = GEOSBufferWithParams(g1, bufferparams, size);
1007  }
1008  else
1009  {
1010  lwpgerror("Error setting buffer parameters.");
1011  }
1012  GEOSBufferParams_destroy(bufferparams);
1013  }
1014  else
1015  {
1016  lwpgerror("Error setting buffer parameters.");
1017  }
1018 
1019  GEOSGeom_destroy(g1);
1020 
1021  if (!g3) HANDLE_GEOS_ERROR("GEOSBuffer");
1022 
1023  POSTGIS_DEBUGF(3, "result: %s", GEOSGeomToWKT(g3));
1024 
1025  GEOSSetSRID(g3, gserialized_get_srid(geom1));
1026 
1027  result = GEOS2POSTGIS(g3, gserialized_has_z(geom1));
1028  GEOSGeom_destroy(g3);
1029 
1030  if (!result)
1031  {
1032  elog(ERROR,"GEOS buffer() threw an error (result postgis geometry formation)!");
1033  PG_RETURN_NULL(); /* never get here */
1034  }
1035 
1036  PG_FREE_IF_COPY(geom1, 0);
1037  PG_RETURN_POINTER(result);
1038 }
int gserialized_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
Definition: g_serialized.c:45
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:320
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: g_serialized.c:178
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:161
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:99
Here is the call graph for this function:
Here is the caller graph for this function: