PostGIS  2.5.0dev-r@@SVN_REVISION@@
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(), and POSTGIS2GEOS().

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

811 {
812  GSERIALIZED *geom1;
813  double size;
814  GEOSGeometry *g1, *g3;
815  GSERIALIZED *result;
816  int quadsegs = 8; /* the default */
817  int nargs;
818  enum
819  {
820  ENDCAP_ROUND = 1,
821  ENDCAP_FLAT = 2,
822  ENDCAP_SQUARE = 3
823  };
824  enum
825  {
826  JOIN_ROUND = 1,
827  JOIN_MITRE = 2,
828  JOIN_BEVEL = 3
829  };
830  static const double DEFAULT_MITRE_LIMIT = 5.0;
831  static const int DEFAULT_ENDCAP_STYLE = ENDCAP_ROUND;
832  static const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
833 
834  double mitreLimit = DEFAULT_MITRE_LIMIT;
835  int endCapStyle = DEFAULT_ENDCAP_STYLE;
836  int joinStyle = DEFAULT_JOIN_STYLE;
837  char *param;
838  char *params = NULL;
839  LWGEOM *lwg;
840 
841  geom1 = PG_GETARG_GSERIALIZED_P(0);
842  size = PG_GETARG_FLOAT8(1);
843 
844  /* Empty.Buffer() == Empty[polygon] */
845  if ( gserialized_is_empty(geom1) )
846  {
848  gserialized_get_srid(geom1),
849  0, 0)); // buffer wouldn't give back z or m anyway
850  PG_RETURN_POINTER(geometry_serialize(lwg));
851  }
852 
853  nargs = PG_NARGS();
854 
855  initGEOS(lwpgnotice, lwgeom_geos_error);
856 
857  g1 = (GEOSGeometry *)POSTGIS2GEOS(geom1);
858  if (!g1)
859  HANDLE_GEOS_ERROR("First argument geometry could not be converted to GEOS");
860 
861  if (nargs > 2)
862  {
863  /* We strdup `cause we're going to modify it */
864  params = pstrdup(PG_GETARG_CSTRING(2));
865 
866  POSTGIS_DEBUGF(3, "Params: %s", params);
867 
868  for (param=params; ; param=NULL)
869  {
870  char *key, *val;
871  param = strtok(param, " ");
872  if (!param) break;
873  POSTGIS_DEBUGF(3, "Param: %s", param);
874 
875  key = param;
876  val = strchr(key, '=');
877  if (!val || *(val + 1) == '\0')
878  {
879  lwpgerror("Missing value for buffer "
880  "parameter %s", key);
881  break;
882  }
883  *val = '\0';
884  ++val;
885 
886  POSTGIS_DEBUGF(3, "Param: %s : %s", key, val);
887 
888  if ( !strcmp(key, "endcap") )
889  {
890  /* Supported end cap styles:
891  * "round", "flat", "square"
892  */
893  if ( !strcmp(val, "round") )
894  {
895  endCapStyle = ENDCAP_ROUND;
896  }
897  else if ( !strcmp(val, "flat") ||
898  !strcmp(val, "butt") )
899  {
900  endCapStyle = ENDCAP_FLAT;
901  }
902  else if ( !strcmp(val, "square") )
903  {
904  endCapStyle = ENDCAP_SQUARE;
905  }
906  else
907  {
908  lwpgerror("Invalid buffer end cap "
909  "style: %s (accept: "
910  "'round', 'flat', 'butt' "
911  "or 'square'"
912  ")", val);
913  break;
914  }
915 
916  }
917  else if ( !strcmp(key, "join") )
918  {
919  if ( !strcmp(val, "round") )
920  {
921  joinStyle = JOIN_ROUND;
922  }
923  else if ( !strcmp(val, "mitre") ||
924  !strcmp(val, "miter") )
925  {
926  joinStyle = JOIN_MITRE;
927  }
928  else if ( !strcmp(val, "bevel") )
929  {
930  joinStyle = JOIN_BEVEL;
931  }
932  else
933  {
934  lwpgerror("Invalid buffer end cap "
935  "style: %s (accept: "
936  "'round', 'mitre', 'miter' "
937  " or 'bevel'"
938  ")", val);
939  break;
940  }
941  }
942  else if ( !strcmp(key, "mitre_limit") ||
943  !strcmp(key, "miter_limit") )
944  {
945  /* mitreLimit is a float */
946  mitreLimit = atof(val);
947  }
948  else if ( !strcmp(key, "quad_segs") )
949  {
950  /* quadrant segments is an int */
951  quadsegs = atoi(val);
952  }
953  else
954  {
955  lwpgerror("Invalid buffer parameter: %s (accept: "
956  "'endcap', 'join', 'mitre_limit', "
957  "'miter_limit and "
958  "'quad_segs')", key);
959  break;
960  }
961  }
962 
963  pfree(params); /* was pstrduped */
964 
965  POSTGIS_DEBUGF(3, "endCap:%d joinStyle:%d mitreLimit:%g",
966  endCapStyle, joinStyle, mitreLimit);
967 
968  }
969 
970  g3 = GEOSBufferWithStyle(g1, size, quadsegs, endCapStyle, joinStyle, mitreLimit);
971  GEOSGeom_destroy(g1);
972 
973  if (!g3) HANDLE_GEOS_ERROR("GEOSBuffer");
974 
975  POSTGIS_DEBUGF(3, "result: %s", GEOSGeomToWKT(g3));
976 
977  GEOSSetSRID(g3, gserialized_get_srid(geom1));
978 
979  result = GEOS2POSTGIS(g3, gserialized_has_z(geom1));
980  GEOSGeom_destroy(g3);
981 
982  if (!result)
983  {
984  elog(ERROR,"GEOS buffer() threw an error (result postgis geometry formation)!");
985  PG_RETURN_NULL(); /* never get here */
986  }
987 
988  PG_FREE_IF_COPY(geom1, 0);
989  PG_RETURN_POINTER(result);
990 }
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:319
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:159
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: