PostGIS  2.5.7dev-r@@SVN_REVISION@@

◆ buffer()

Datum buffer ( PG_FUNCTION_ARGS  )

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

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

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(), encode_ptarray(), encode_ptarray_initial(), init_homogenizebuffer(), lwcollection_build_buffer(), lwcollection_homogenize(), 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: