PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ RASTER_InterpolateRaster()

Datum RASTER_InterpolateRaster ( PG_FUNCTION_ARGS  )

Definition at line 656 of file rtpg_gdal.c.

657 {
658  rt_pgraster *in_pgrast = NULL;
659  rt_pgraster *out_pgrast = NULL;
660  rt_raster in_rast = NULL;
661  rt_raster out_rast = NULL;
662  uint32_t out_rast_bands[1] = {0};
663  rt_band in_band = NULL;
664  rt_band out_band = NULL;
665  int band_number;
666  uint16_t in_band_width, in_band_height;
667  uint32_t npoints;
668  rt_pixtype in_band_pixtype;
669  GDALDataType in_band_gdaltype;
670  size_t in_band_gdaltype_size;
671 
672  rt_envelope env;
673 
674  GDALGridAlgorithm algorithm;
675  text *options_txt = NULL;
676  void *options_struct = NULL;
677  CPLErr err;
678  uint8_t *out_data;
679  rt_errorstate rterr;
680 
681  /* Input points */
682  LWPOINTITERATOR *iterator;
683  POINT4D pt;
684  size_t coord_count = 0;
685  LWGEOM *lwgeom;
686  double *xcoords, *ycoords, *zcoords;
687 
688  GSERIALIZED *gser = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
689 
690  /* Z value is required to drive the grid heights */
691  if (!gserialized_has_z(gser))
692  elog(ERROR, "%s: input geometry does not have Z values", __func__);
693 
694  /* Cannot process empties */
695  if (gserialized_is_empty(gser))
696  PG_RETURN_NULL();
697 
698  in_pgrast = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(2));
699  in_rast = rt_raster_deserialize(in_pgrast, FALSE);
700  if (!in_rast)
701  elog(ERROR, "%s: Could not deserialize raster", __func__);
702 
703  /* GDAL cannot grid a skewed raster */
704  if (rt_raster_get_x_skew(in_rast) != 0.0 ||
705  rt_raster_get_y_skew(in_rast) != 0.0) {
706  elog(ERROR, "%s: Cannot generate a grid into a skewed raster",__func__);
707  }
708 
709  /* Flat JSON map of options from user */
710  options_txt = PG_GETARG_TEXT_P(1);
711  /* 1-base band number from user */
712  band_number = PG_GETARG_INT32(3);
713  if (band_number < 1)
714  elog(ERROR, "%s: Invalid band number %d", __func__, band_number);
715 
716  lwgeom = lwgeom_from_gserialized(gser);
717  npoints = lwgeom_count_vertices(lwgeom);
718  /* This shouldn't happen, but just in case... */
719  if (npoints < 1)
720  elog(ERROR, "%s: Geometry has no points", __func__);
721 
722  in_band = rt_raster_get_band(in_rast, band_number-1);
723  if (!in_band)
724  elog(ERROR, "%s: Cannot access raster band %d", __func__, band_number);
725 
726 
727  rterr = rt_raster_get_envelope(in_rast, &env);
728  if (rterr == ES_ERROR)
729  elog(ERROR, "%s: Unable to calculate envelope", __func__);
730 
731  /* Get geometry of input raster */
732  in_band_width = rt_band_get_width(in_band);
733  in_band_height = rt_band_get_height(in_band);
734  in_band_pixtype = rt_band_get_pixtype(in_band);
735  in_band_gdaltype = rt_util_pixtype_to_gdal_datatype(in_band_pixtype);
736  in_band_gdaltype_size = GDALGetDataTypeSizeBytes(in_band_gdaltype);
737 
738  /* Quickly copy options struct into local memory context, so we */
739  /* don't have malloc'ed memory lying around */
740  // if (err == CE_None && options_struct) {
741  // void *tmp = options_struct;
742  // switch (algorithm) {
743  // case GGA_InverseDistanceToAPower:
744  // options_struct = palloc(sizeof(GDALGridInverseDistanceToAPowerOptions));
745  // memcpy(options_struct, tmp, sizeof(GDALGridInverseDistanceToAPowerOptions));
746  // break;
747  // case GGA_InverseDistanceToAPowerNearestNeighbor:
748  // options_struct = palloc(sizeof(GDALGridInverseDistanceToAPowerNearestNeighborOptions));
749  // memcpy(options_struct, tmp, sizeof(GDALGridInverseDistanceToAPowerNearestNeighborOptions));
750  // break;
751  // case GGA_MovingAverage:
752  // options_struct = palloc(sizeof(GDALGridMovingAverageOptions));
753  // memcpy(options_struct, tmp, sizeof(GDALGridMovingAverageOptions));
754  // break;
755  // case GGA_NearestNeighbor:
756  // options_struct = palloc(sizeof(GDALGridNearestNeighborOptions));
757  // memcpy(options_struct, tmp, sizeof(GDALGridNearestNeighborOptions));
758  // break;
759  // case GGA_Linear:
760  // options_struct = palloc(sizeof(GDALGridLinearOptions));
761  // memcpy(options_struct, tmp, sizeof(GDALGridLinearOptions));
762  // break;
763  // default:
764  // elog(ERROR, "%s: Unsupported gridding algorithm %d", __func__, algorithm);
765  // }
766  // free(tmp);
767  // }
768 
769  /* Prepare destination grid buffer for output */
770  out_data = palloc(in_band_gdaltype_size * in_band_width * in_band_height);
771 
772  /* Prepare input points for processing */
773  xcoords = palloc(sizeof(double) * npoints);
774  ycoords = palloc(sizeof(double) * npoints);
775  zcoords = palloc(sizeof(double) * npoints);
776 
777  /* Populate input points */
778  iterator = lwpointiterator_create(lwgeom);
779  while(lwpointiterator_next(iterator, &pt) == LW_SUCCESS) {
780  if (coord_count >= npoints)
781  elog(ERROR, "%s: More points from iterator than expected", __func__);
782  xcoords[coord_count] = pt.x;
783  ycoords[coord_count] = pt.y;
784  zcoords[coord_count] = pt.z;
785  coord_count++;
786  }
787  lwpointiterator_destroy(iterator);
788 
789  /* Extract algorithm and options from options text */
790  /* This malloc's the options struct, so clean up right away */
791  err = ParseAlgorithmAndOptions(
792  text_to_cstring(options_txt),
793  &algorithm,
794  &options_struct);
795  if (err != CE_None) {
796  if (options_struct) free(options_struct);
797  elog(ERROR, "%s: Unable to parse options string: %s", __func__, CPLGetLastErrorMsg());
798  }
799 
800  /* Run the gridding algorithm */
801  err = GDALGridCreate(
802  algorithm, options_struct,
803  npoints, xcoords, ycoords, zcoords,
804  env.MinX, env.MaxX, env.MinY, env.MaxY,
805  in_band_width, in_band_height,
806  in_band_gdaltype, out_data,
807  rtpg_util_gdal_progress_func, /* GDALProgressFunc */
808  NULL /* ProgressArgs */
809  );
810 
811  /* Quickly clean up malloc'ed memory */
812  if (options_struct)
813  free(options_struct);
814 
815  if (err != CE_None) {
816  elog(ERROR, "%s: GDALGridCreate failed: %s", __func__, CPLGetLastErrorMsg());
817  }
818 
819  out_rast_bands[0] = band_number-1;
820  out_rast = rt_raster_from_band(in_rast, out_rast_bands, 1);
821  out_band = rt_raster_get_band(out_rast, 0);
822  if (!out_band)
823  elog(ERROR, "%s: Cannot access output raster band", __func__);
824 
825  /* Copy the data from the output buffer into the destination band */
826  for (uint32_t y = 0; y < in_band_height; y++) {
827  size_t offset = (in_band_height-y-1) * (in_band_gdaltype_size * in_band_width);
828  rterr = rt_band_set_pixel_line(out_band, 0, y, out_data + offset, in_band_width);
829  }
830 
831  out_pgrast = rt_raster_serialize(out_rast);
832  rt_raster_destroy(out_rast);
833  rt_raster_destroy(in_rast);
834 
835  if (NULL == out_pgrast) PG_RETURN_NULL();
836 
837  SET_VARSIZE(out_pgrast, out_pgrast->size);
838  PG_RETURN_POINTER(out_pgrast);
839 }
#define FALSE
Definition: dbfopen.c:72
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:268
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: gserialized.c:181
int gserialized_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
Definition: gserialized.c:203
LWPOINTITERATOR * lwpointiterator_create(const LWGEOM *g)
Create a new LWPOINTITERATOR over supplied LWGEOM*.
Definition: lwiterator.c:243
int lwpointiterator_next(LWPOINTITERATOR *s, POINT4D *p)
Attempts to assign the next point in the iterator to p, and advances the iterator to the next point.
Definition: lwiterator.c:210
#define LW_SUCCESS
Definition: liblwgeom.h:97
void lwpointiterator_destroy(LWPOINTITERATOR *s)
Free all memory associated with the iterator.
Definition: lwiterator.c:268
uint32_t lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1309
uint16_t rt_band_get_width(rt_band band)
Return width of this band.
Definition: rt_band.c:791
double rt_raster_get_x_skew(rt_raster raster)
Get skew about the X axis.
Definition: rt_raster.c:185
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:86
rt_pixtype
Definition: librtcore.h:187
GDALDataType rt_util_pixtype_to_gdal_datatype(rt_pixtype pt)
Convert rt_pixtype to GDALDataType.
Definition: rt_util.c:124
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_serialize.c:521
rt_errorstate
Enum definitions.
Definition: librtcore.h:181
@ ES_ERROR
Definition: librtcore.h:183
rt_errorstate rt_band_set_pixel_line(rt_band band, int x, int y, void *vals, uint32_t len)
Set values of multiple pixels.
Definition: rt_band.c:1004
rt_raster rt_raster_from_band(rt_raster raster, uint32_t *bandNums, int count)
Construct a new rt_raster from an existing rt_raster and an array of band numbers.
Definition: rt_raster.c:1341
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
Definition: rt_band.c:782
rt_errorstate rt_raster_get_envelope(rt_raster raster, rt_envelope *env)
Get raster's envelope.
Definition: rt_raster.c:782
double rt_raster_get_y_skew(rt_raster raster)
Get skew about the Y axis.
Definition: rt_raster.c:194
uint16_t rt_band_get_height(rt_band band)
Return height of this band.
Definition: rt_band.c:800
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_serialize.c:725
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
Definition: rt_raster.c:385
void free(void *)
static int rtpg_util_gdal_progress_func(double dfComplete, const char *pszMessage, void *pProgressArg)
Definition: rtpg_gdal.c:630
double x
Definition: liblwgeom.h:414
double z
Definition: liblwgeom.h:414
double y
Definition: liblwgeom.h:414
double MinX
Definition: librtcore.h:167
double MaxX
Definition: librtcore.h:168
double MinY
Definition: librtcore.h:169
double MaxY
Definition: librtcore.h:170
Struct definitions.
Definition: librtcore.h:2440

References ES_ERROR, FALSE, free(), gserialized_has_z(), gserialized_is_empty(), LW_SUCCESS, lwgeom_count_vertices(), lwgeom_from_gserialized(), lwpointiterator_create(), lwpointiterator_destroy(), lwpointiterator_next(), rt_envelope::MaxX, rt_envelope::MaxY, rt_envelope::MinX, rt_envelope::MinY, rt_band_get_height(), rt_band_get_pixtype(), rt_band_get_width(), rt_band_set_pixel_line(), rt_raster_deserialize(), rt_raster_destroy(), rt_raster_from_band(), rt_raster_get_band(), rt_raster_get_envelope(), rt_raster_get_x_skew(), rt_raster_get_y_skew(), rt_raster_serialize(), rt_util_pixtype_to_gdal_datatype(), rtpg_util_gdal_progress_func(), rt_raster_serialized_t::size, POINT4D::x, POINT4D::y, pixval::y, and POINT4D::z.

Here is the call graph for this function: