PostGIS  2.5.0beta2dev-r@@SVN_REVISION@@

◆ buffer()

Datum buffer ( PG_FUNCTION_ARGS  )

Definition at line 794 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().

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