PostGIS  2.3.7dev-r@@SVN_REVISION@@
Datum buffer ( PG_FUNCTION_ARGS  )

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

775 {
776  GSERIALIZED *geom1;
777  double size;
778  GEOSGeometry *g1, *g3;
779  GSERIALIZED *result;
780  int quadsegs = 8; /* the default */
781  int nargs;
782  enum
783  {
784  ENDCAP_ROUND = 1,
785  ENDCAP_FLAT = 2,
786  ENDCAP_SQUARE = 3
787  };
788  enum
789  {
790  JOIN_ROUND = 1,
791  JOIN_MITRE = 2,
792  JOIN_BEVEL = 3
793  };
794  static const double DEFAULT_MITRE_LIMIT = 5.0;
795  static const int DEFAULT_ENDCAP_STYLE = ENDCAP_ROUND;
796  static const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
797 
798  double mitreLimit = DEFAULT_MITRE_LIMIT;
799  int endCapStyle = DEFAULT_ENDCAP_STYLE;
800  int joinStyle = DEFAULT_JOIN_STYLE;
801  char *param;
802  char *params = NULL;
803  LWGEOM *lwg;
804 
805  geom1 = PG_GETARG_GSERIALIZED_P(0);
806  size = PG_GETARG_FLOAT8(1);
807 
808  /* Empty.Buffer() == Empty[polygon] */
809  if ( gserialized_is_empty(geom1) )
810  {
812  gserialized_get_srid(geom1),
813  0, 0)); // buffer wouldn't give back z or m anyway
814  PG_RETURN_POINTER(geometry_serialize(lwg));
815  }
816 
817  nargs = PG_NARGS();
818 
819  initGEOS(lwpgnotice, lwgeom_geos_error);
820 
821  g1 = (GEOSGeometry *)POSTGIS2GEOS(geom1);
822  if ( 0 == g1 ) /* exception thrown at construction */
823  {
824  HANDLE_GEOS_ERROR("First argument geometry could not be converted to GEOS");
825  PG_RETURN_NULL();
826  }
827 
828  if (nargs > 2)
829  {
830  /* We strdup `cause we're going to modify it */
831  params = pstrdup(PG_GETARG_CSTRING(2));
832 
833  POSTGIS_DEBUGF(3, "Params: %s", params);
834 
835  for (param=params; ; param=NULL)
836  {
837  char *key, *val;
838  param = strtok(param, " ");
839  if ( param == NULL ) break;
840  POSTGIS_DEBUGF(3, "Param: %s", param);
841 
842  key = param;
843  val = strchr(key, '=');
844  if ( val == NULL || *(val+1) == '\0' )
845  {
846  lwpgerror("Missing value for buffer "
847  "parameter %s", key);
848  break;
849  }
850  *val = '\0';
851  ++val;
852 
853  POSTGIS_DEBUGF(3, "Param: %s : %s", key, val);
854 
855  if ( !strcmp(key, "endcap") )
856  {
857  /* Supported end cap styles:
858  * "round", "flat", "square"
859  */
860  if ( !strcmp(val, "round") )
861  {
862  endCapStyle = ENDCAP_ROUND;
863  }
864  else if ( !strcmp(val, "flat") ||
865  !strcmp(val, "butt") )
866  {
867  endCapStyle = ENDCAP_FLAT;
868  }
869  else if ( !strcmp(val, "square") )
870  {
871  endCapStyle = ENDCAP_SQUARE;
872  }
873  else
874  {
875  lwpgerror("Invalid buffer end cap "
876  "style: %s (accept: "
877  "'round', 'flat', 'butt' "
878  "or 'square'"
879  ")", val);
880  break;
881  }
882 
883  }
884  else if ( !strcmp(key, "join") )
885  {
886  if ( !strcmp(val, "round") )
887  {
888  joinStyle = JOIN_ROUND;
889  }
890  else if ( !strcmp(val, "mitre") ||
891  !strcmp(val, "miter") )
892  {
893  joinStyle = JOIN_MITRE;
894  }
895  else if ( !strcmp(val, "bevel") )
896  {
897  joinStyle = JOIN_BEVEL;
898  }
899  else
900  {
901  lwpgerror("Invalid buffer end cap "
902  "style: %s (accept: "
903  "'round', 'mitre', 'miter' "
904  " or 'bevel'"
905  ")", val);
906  break;
907  }
908  }
909  else if ( !strcmp(key, "mitre_limit") ||
910  !strcmp(key, "miter_limit") )
911  {
912  /* mitreLimit is a float */
913  mitreLimit = atof(val);
914  }
915  else if ( !strcmp(key, "quad_segs") )
916  {
917  /* quadrant segments is an int */
918  quadsegs = atoi(val);
919  }
920  else
921  {
922  lwpgerror("Invalid buffer parameter: %s (accept: "
923  "'endcap', 'join', 'mitre_limit', "
924  "'miter_limit and "
925  "'quad_segs')", key);
926  break;
927  }
928  }
929 
930  pfree(params); /* was pstrduped */
931 
932  POSTGIS_DEBUGF(3, "endCap:%d joinStyle:%d mitreLimit:%g",
933  endCapStyle, joinStyle, mitreLimit);
934 
935  }
936 
937  g3 = GEOSBufferWithStyle(g1, size, quadsegs, endCapStyle, joinStyle, mitreLimit);
938  GEOSGeom_destroy(g1);
939 
940  if (g3 == NULL)
941  {
942  HANDLE_GEOS_ERROR("GEOSBuffer");
943  PG_RETURN_NULL(); /* never get here */
944  }
945 
946  POSTGIS_DEBUGF(3, "result: %s", GEOSGeomToWKT(g3));
947 
948  GEOSSetSRID(g3, gserialized_get_srid(geom1));
949 
950  result = GEOS2POSTGIS(g3, gserialized_has_z(geom1));
951  GEOSGeom_destroy(g3);
952 
953  if (result == NULL)
954  {
955  elog(ERROR,"GEOS buffer() threw an error (result postgis geometry formation)!");
956  PG_RETURN_NULL(); /* never get here */
957  }
958 
959  PG_FREE_IF_COPY(geom1, 0);
960  PG_RETURN_POINTER(result);
961 }
int gserialized_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
Definition: g_serialized.c:38
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:252
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: g_serialized.c:153
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:137
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:83

Here is the call graph for this function:

Here is the caller graph for this function: