Return a raster of the provided geometry.
2514 {
2516 uint32_t i = 0;
2517 int err = 0;
2518
2520
2521 int _dim[2] = {0};
2522 double _scale[2] = {0};
2523 double _skew[2] = {0};
2524
2525 OGRErr ogrerr;
2526 OGRGeometryH src_geom;
2527 OGREnvelope src_env;
2529 OGRwkbGeometryType wkbtype = wkbUnknown;
2530
2531 int ul_user = 0;
2532
2533 CPLErr cplerr;
2534 double _gt[6] = {0};
2535 GDALDriverH _drv = NULL;
2536 int unload_drv = 0;
2537 GDALDatasetH _ds = NULL;
2538 GDALRasterBandH _band = NULL;
2539
2540 uint16_t _width = 0;
2541 uint16_t _height = 0;
2542
2544
2545 assert(NULL != wkb);
2546 assert(0 != wkb_len);
2547
2548
2550 if (arg == NULL) {
2551 rterror(
"rt_raster_gdal_rasterize: Could not initialize internal variables");
2552 return NULL;
2553 }
2554
2555
2556 if (num_bands < 1) {
2559
2562
2565
2568
2571
2574 }
2575 else {
2578
2584 }
2585
2586
2587 if (NULL != srs && strlen(srs)) {
2588 arg->
src_sr = OSRNewSpatialReference(NULL);
2589 if (OSRSetFromUserInput(arg->
src_sr, srs) != OGRERR_NONE) {
2590 rterror(
"rt_raster_gdal_rasterize: Could not create OSR spatial reference using the provided srs: %s", srs);
2592 return NULL;
2593 }
2594 }
2595
2596
2597 ogrerr = OGR_G_CreateFromWkb((
unsigned char *) wkb, arg->
src_sr, &src_geom, wkb_len);
2598 if (ogrerr != OGRERR_NONE) {
2599 rterror(
"rt_raster_gdal_rasterize: Could not create OGR Geometry from WKB");
2600
2602
2603
2604 return NULL;
2605 }
2606
2607
2608 if (OGR_G_IsEmpty(src_geom)) {
2609 rtinfo(
"Geometry provided is empty. Returning empty raster");
2610
2611 OGR_G_DestroyGeometry(src_geom);
2613
2614
2616 }
2617
2618
2619 OGR_G_GetEnvelope(src_geom, &src_env);
2621
2622 RASTER_DEBUGF(3,
"Suggested raster envelope: %f, %f, %f, %f",
2624
2625
2626 if (
2627 (NULL != scale_x) &&
2628 (NULL != scale_y) &&
2631 ) {
2632
2633 _scale[0] = fabs(*scale_x);
2634 _scale[1] = fabs(*scale_y);
2635 }
2636
2637 else if ((NULL != width) && (NULL != height) && (*width != 0) && (*height != 0))
2638 {
2639 _dim[0] = abs(*width);
2640 _dim[1] = abs(*height);
2641
2643 _scale[0] = fabs((extent.
MaxX - extent.
MinX) / _dim[0]);
2644 else
2645 _scale[0] = 1.;
2646
2648 _scale[1] = fabs((extent.
MaxY - extent.
MinY) / _dim[1]);
2649 else
2650 _scale[1] = 1.;
2651 }
2652 else {
2653 rterror(
"rt_raster_gdal_rasterize: Values must be provided for width and height or X and Y of scale");
2654
2655 OGR_G_DestroyGeometry(src_geom);
2657
2658
2659 return NULL;
2660 }
2661 RASTER_DEBUGF(3,
"scale (x, y) = %f, %f", _scale[0], -1 * _scale[1]);
2663
2664
2665 if (NULL != skew_x) {
2666 _skew[0] = *skew_x;
2667
2668
2669
2670
2671
2672 if (
2673 NULL != scale_x &&
2674 *scale_x < 0.
2675 ) {
2676 _skew[0] *= -1;
2677 }
2678 }
2679 if (NULL != skew_y) {
2680 _skew[1] = *skew_y;
2681
2682
2683
2684
2685
2686 if (
2687 NULL != scale_y &&
2688 *scale_y > 0.
2689 ) {
2690 _skew[1] *= -1;
2691 }
2692 }
2693
2694
2695
2696
2697
2698
2699
2700
2701 wkbtype = wkbFlatten(OGR_G_GetGeometryType(src_geom));
2702 if ((
2703 (wkbtype == wkbPoint) ||
2704 (wkbtype == wkbMultiPoint) ||
2705 (wkbtype == wkbLineString) ||
2706 (wkbtype == wkbMultiLineString)
2707 ) &&
2708 _dim[0] == 0 &&
2709 _dim[1] == 0
2710 ) {
2711
2712#if POSTGIS_GDAL_VERSION > 10800
2713
2714 RASTER_DEBUG(3,
"Adjusting extent for GDAL > 1.8 by half the scale on X-axis");
2715 extent.
MinX -= (_scale[0] / 2.);
2716 extent.
MaxX += (_scale[0] / 2.);
2717
2718 RASTER_DEBUG(3,
"Adjusting extent for GDAL > 1.8 by half the scale on Y-axis");
2719 extent.
MinY -= (_scale[1] / 2.);
2720 extent.
MaxY += (_scale[1] / 2.);
2721
2722#else
2723
2724 RASTER_DEBUG(3,
"Adjusting extent for GDAL <= 1.8 by the scale on X-axis");
2725 extent.
MinX -= _scale[0];
2726 extent.
MaxX += _scale[0];
2727
2728 RASTER_DEBUG(3,
"Adjusting extent for GDAL <= 1.8 by the scale on Y-axis");
2729 extent.
MinY -= _scale[1];
2730 extent.
MaxY += _scale[1];
2731
2732#endif
2733
2734
2737
2740 }
2741
2742
2744 {
2746
2748
2750 extent,
2751 _skew,
2752 _scale,
2753 0.01
2754 );
2755 if (skewedrast == NULL) {
2756 rterror(
"rt_raster_gdal_rasterize: Could not compute skewed raster");
2757
2758 OGR_G_DestroyGeometry(src_geom);
2760
2761
2762 return NULL;
2763 }
2764
2765 _dim[0] = skewedrast->
width;
2766 _dim[1] = skewedrast->
height;
2767
2770
2772 }
2773
2774
2775 if (!_dim[0])
2776 _dim[0] = (int) fmax((fabs(extent.
MaxX - extent.
MinX) + (_scale[0] / 2.)) / _scale[0], 1);
2777 if (!_dim[1])
2778 _dim[1] = (int) fmax((fabs(extent.
MaxY - extent.
MinY) + (_scale[1] / 2.)) / _scale[1], 1);
2779
2780
2782 if (rast == NULL) {
2783 rterror(
"rt_raster_gdal_rasterize: Out of memory allocating temporary raster");
2784
2785 OGR_G_DestroyGeometry(src_geom);
2787
2788
2789 return NULL;
2790 }
2791
2792
2796
2798 RASTER_DEBUGF(3,
"Temp raster's geotransform: %f, %f, %f, %f, %f, %f",
2799 _gt[0], _gt[1], _gt[2], _gt[3], _gt[4], _gt[5]);
2800 RASTER_DEBUGF(3,
"Temp raster's dimensions (width x height): %d x %d",
2801 _dim[0], _dim[1]);
2802
2803
2804 if (
2805 NULL != ul_xw &&
2806 NULL != ul_yw
2807 ) {
2808 ul_user = 1;
2809
2810 RASTER_DEBUGF(4,
"Using user-specified upper-left corner: %f, %f", *ul_xw, *ul_yw);
2811
2812
2816 }
2817 else if (
2818 ((NULL != ul_xw) && (NULL == ul_yw)) ||
2819 ((NULL == ul_xw) && (NULL != ul_yw))
2820 ) {
2821 rterror(
"rt_raster_gdal_rasterize: Both X and Y upper-left corner values must be provided");
2822
2824 OGR_G_DestroyGeometry(src_geom);
2826
2827
2828 return NULL;
2829 }
2830
2831
2832 if (
2833 !ul_user && (
2834 (NULL != grid_xw) || (NULL != grid_yw)
2835 )
2836 ) {
2837
2838 if (
2839 ((NULL != grid_xw) && (NULL == grid_yw)) ||
2840 ((NULL == grid_xw) && (NULL != grid_yw))
2841 ) {
2842 rterror(
"rt_raster_gdal_rasterize: Both X and Y alignment values must be provided");
2843
2845 OGR_G_DestroyGeometry(src_geom);
2847
2848
2849 return NULL;
2850 }
2851
2852 RASTER_DEBUGF(4,
"Aligning extent to user-specified grid: %f, %f", *grid_xw, *grid_yw);
2853
2854 do {
2855 double _r[2] = {0};
2856 double _w[2] = {0};
2857
2858
2860 RASTER_DEBUG(3,
"Skipping raster alignment as it is already aligned to grid");
2861 break;
2862 }
2863
2867
2868
2870 rast,
2872 &(_r[0]), &(_r[1]),
2873 NULL
2875 rterror(
"rt_raster_gdal_rasterize: Could not compute raster pixel for spatial coordinates");
2876
2878 OGR_G_DestroyGeometry(src_geom);
2880
2881
2882 return NULL;
2883 }
2884
2886 rast,
2887 _r[0], _r[1],
2888 &(_w[0]), &(_w[1]),
2889 NULL
2891 rterror(
"rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
2892
2894 OGR_G_DestroyGeometry(src_geom);
2896
2897
2898 return NULL;
2899 }
2900
2901
2903 if (NULL == width)
2905 else if (NULL == scale_x) {
2906 double _c[2] = {0};
2907
2909
2910
2912 rast,
2914 &(_c[0]), &(_c[1]),
2915 NULL
2917 rterror(
"rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
2918
2920 OGR_G_DestroyGeometry(src_geom);
2922
2923
2924 return NULL;
2925 }
2926
2927 rast->scaleX = fabs((_c[0] - _w[0]) / ((
double)
rast->width));
2928 }
2929 }
2931 if (NULL == height)
2933 else if (NULL == scale_y) {
2934 double _c[2] = {0};
2935
2937
2938
2940 rast,
2942 &(_c[0]), &(_c[1]),
2943 NULL
2945 rterror(
"rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
2946
2948 OGR_G_DestroyGeometry(src_geom);
2950
2951
2952 return NULL;
2953 }
2954
2955 rast->scaleY = -1 * fabs((_c[1] - _w[1]) / ((
double)
rast->height));
2956 }
2957 }
2958
2960 }
2961 while (0);
2962 }
2963
2964
2965
2966
2967
2968
2969 _dim[0] =
rast->width;
2970 _dim[1] =
rast->height;
2972
2973
2974 if ((
2975 (NULL != scale_x) && (*scale_x < 0.)
2976 ) || (
2977 (NULL != scale_y) && (*scale_y > 0)
2978 )) {
2979 double _w[2] = {0};
2980
2981
2982 if (
2983 (NULL != scale_x) &&
2984 (*scale_x < 0.)
2985 ) {
2987
2989 rast,
2990 _dim[0], 0,
2991 &(_w[0]), &(_w[1]),
2992 NULL
2994 rterror(
"rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
2995
2997 OGR_G_DestroyGeometry(src_geom);
2999
3000
3001 return NULL;
3002 }
3003
3004 _gt[0] = _w[0];
3005 _gt[1] = *scale_x;
3006
3007
3008 if (NULL != skew_x &&
FLT_NEQ(*skew_x, 0.0))
3009 _gt[2] = *skew_x;
3010 }
3011
3012 if (
3013 (NULL != scale_y) &&
3014 (*scale_y > 0)
3015 ) {
3017
3019 rast,
3020 0, _dim[1],
3021 &(_w[0]), &(_w[1]),
3022 NULL
3024 rterror(
"rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
3025
3027 OGR_G_DestroyGeometry(src_geom);
3029
3030
3031 return NULL;
3032 }
3033
3034 _gt[3] = _w[1];
3035 _gt[5] = *scale_y;
3036
3037
3038 if (NULL != skew_y &&
FLT_NEQ(*skew_y, 0.0))
3039 _gt[4] = *skew_y;
3040 }
3041 }
3042
3045
3046 RASTER_DEBUGF(3,
"Applied geotransform: %f, %f, %f, %f, %f, %f",
3047 _gt[0], _gt[1], _gt[2], _gt[3], _gt[4], _gt[5]);
3048 RASTER_DEBUGF(3,
"Raster dimensions (width x height): %d x %d",
3049 _dim[0], _dim[1]);
3050
3051
3054 GDALRegister_MEM();
3055 unload_drv = 1;
3056 }
3057 _drv = GDALGetDriverByName("MEM");
3058 if (NULL == _drv) {
3059 rterror(
"rt_raster_gdal_rasterize: Could not load the MEM GDAL driver");
3060
3061 OGR_G_DestroyGeometry(src_geom);
3063
3064
3065 return NULL;
3066 }
3067
3068
3069 if (unload_drv) {
3071 GDALDeregisterDriver(_drv);
3072 }
3073
3074 _ds = GDALCreate(_drv, "", _dim[0], _dim[1], 0, GDT_Byte, NULL);
3075 if (NULL == _ds) {
3076 rterror(
"rt_raster_gdal_rasterize: Could not create a GDALDataset to rasterize the geometry into");
3077
3078 OGR_G_DestroyGeometry(src_geom);
3080
3081 if (unload_drv) GDALDestroyDriver(_drv);
3082
3083 return NULL;
3084 }
3085
3086
3087 cplerr = GDALSetGeoTransform(_ds, _gt);
3088 if (cplerr != CE_None) {
3089 rterror(
"rt_raster_gdal_rasterize: Could not set geotransform on GDALDataset");
3090
3091 OGR_G_DestroyGeometry(src_geom);
3093
3094
3095 GDALClose(_ds);
3096 if (unload_drv) GDALDestroyDriver(_drv);
3097
3098 return NULL;
3099 }
3100
3101
3102 if (NULL != arg->
src_sr) {
3103 char *_srs = NULL;
3104 OSRExportToWkt(arg->
src_sr, &_srs);
3105
3106 cplerr = GDALSetProjection(_ds, _srs);
3107 CPLFree(_srs);
3108 if (cplerr != CE_None) {
3109 rterror(
"rt_raster_gdal_rasterize: Could not set projection on GDALDataset");
3110
3111 OGR_G_DestroyGeometry(src_geom);
3113
3114
3115 GDALClose(_ds);
3116 if (unload_drv) GDALDestroyDriver(_drv);
3117
3118 return NULL;
3119 }
3120 }
3121
3122
3123 for (i = 0; i < arg->
numbands; i++) {
3124 err = 0;
3125
3126 do {
3127
3129 if (cplerr != CE_None) {
3130 rterror(
"rt_raster_gdal_rasterize: Could not add band to GDALDataset");
3131 err = 1;
3132 break;
3133 }
3134
3135 _band = GDALGetRasterBand(_ds, i + 1);
3136 if (NULL == _band) {
3137 rterror(
"rt_raster_gdal_rasterize: Could not get band %d from GDALDataset", i + 1);
3138 err = 1;
3139 break;
3140 }
3141
3142
3145 cplerr = GDALSetRasterNoDataValue(_band, arg->
nodata[i]);
3146 if (cplerr != CE_None) {
3147 rterror(
"rt_raster_gdal_rasterize: Could not set nodata value");
3148 err = 1;
3149 break;
3150 }
3151 RASTER_DEBUGF(4,
"NODATA value set to %f", GDALGetRasterNoDataValue(_band, NULL));
3152 }
3153
3154
3155 cplerr = GDALFillRaster(_band, arg->
init[i], 0);
3156 if (cplerr != CE_None) {
3157 rterror(
"rt_raster_gdal_rasterize: Could not set initial value");
3158 err = 1;
3159 break;
3160 }
3161 }
3162 while (0);
3163
3164 if (err) {
3165
3166 OGR_G_DestroyGeometry(src_geom);
3168
3169
3170
3171 GDALClose(_ds);
3172 if (unload_drv) GDALDestroyDriver(_drv);
3173
3174 return NULL;
3175 }
3176 }
3177
3180
3181
3182 cplerr = GDALRasterizeGeometries(
3183 _ds,
3185 1, &src_geom,
3186 NULL, NULL,
3188 options,
3189 NULL, NULL
3190 );
3191 if (cplerr != CE_None) {
3192 rterror(
"rt_raster_gdal_rasterize: Could not rasterize geometry");
3193
3194 OGR_G_DestroyGeometry(src_geom);
3196
3197
3198 GDALClose(_ds);
3199 if (unload_drv) GDALDestroyDriver(_drv);
3200
3201 return NULL;
3202 }
3203
3204
3205 GDALFlushCache(_ds);
3208
3209 OGR_G_DestroyGeometry(src_geom);
3210
3211
3212 GDALClose(_ds);
3213 if (unload_drv) GDALDestroyDriver(_drv);
3214
3215 if (NULL == rast) {
3216 rterror(
"rt_raster_gdal_rasterize: Could not rasterize geometry");
3217 return NULL;
3218 }
3219
3220
3223
3224
3225 for (i = 0; i < arg->
numbands; i++) {
3226 uint8_t *
data = NULL;
3229
3230 double val = 0;
3231 int nodata = 0;
3232 int hasnodata = 0;
3233 double nodataval = 0;
3236
3238 if (oldband == NULL) {
3239 rterror(
"rt_raster_gdal_rasterize: Could not get band %d of output raster", i);
3242 return NULL;
3243 }
3244
3245
3247 continue;
3248
3249
3251 if (hasnodata)
3253
3254
3256 if (data == NULL) {
3257 rterror(
"rt_raster_gdal_rasterize: Could not allocate memory for band data");
3260 return NULL;
3261 }
3263
3264
3266 _width, _height,
3268 hasnodata, nodataval,
3269 data
3270 );
3271 if (band == NULL) {
3272 rterror(
"rt_raster_gdal_rasterize: Could not create band");
3276 return NULL;
3277 }
3278
3279
3281
3282
3283 for (x = 0;
x < _width;
x++) {
3284 for (y = 0;
y < _height;
y++) {
3287 rterror(
"rt_raster_gdal_rasterize: Could not get pixel value");
3291 return NULL;
3292 }
3293
3294 if (nodata)
3295 val = nodataval;
3296
3299 rterror(
"rt_raster_gdal_rasterize: Could not set pixel value");
3303 return NULL;
3304 }
3305 }
3306 }
3307
3308
3310 if (oldband == NULL) {
3311 rterror(
"rt_raster_gdal_rasterize: Could not replace band %d of output raster", i);
3315 return NULL;
3316 }
3317
3318
3320 }
3321
3323
3325
3327}
rt_band rt_band_new_inline(uint16_t width, uint16_t height, rt_pixtype pixtype, uint32_t hasnodata, double nodataval, uint8_t *data)
Create an in-db rt_band with no data.
void rt_band_set_ownsdata_flag(rt_band band, int flag)
void rterror(const char *fmt,...) __attribute__((format(printf
Wrappers used for reporting errors and info.
void * rtalloc(size_t size)
Wrappers used for managing memory.
#define RASTER_DEBUG(level, msg)
#define RASTER_DEBUGF(level, msg,...)
void void rtinfo(const char *fmt,...) __attribute__((format(printf
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
GDALDataType rt_util_pixtype_to_gdal_datatype(rt_pixtype pt)
Convert rt_pixtype to GDALDataType.
rt_errorstate rt_band_set_pixel(rt_band band, int x, int y, double val, int *converted)
Set single pixel's value.
void rt_band_destroy(rt_band band)
Destroy a raster band.
int rt_util_gdal_driver_registered(const char *drv)
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
void rtdealloc(void *mem)
void rt_util_from_ogr_envelope(OGREnvelope env, rt_envelope *ext)
int rt_pixtype_size(rt_pixtype pixtype)
Return size in bytes of a value in the given pixtype.
rt_errorstate rt_raster_cell_to_geopoint(rt_raster raster, double xr, double yr, double *xw, double *yw, double *gt)
Convert an xr, yr raster point to an xw, yw point on map.
void rt_raster_set_scale(rt_raster raster, double scaleX, double scaleY)
Set scale in projection units.
rt_errorstate rt_raster_geopoint_to_cell(rt_raster raster, double xw, double yw, double *xr, double *yr, double *igt)
Convert an xw,yw map point to a xr,yr cell coordinate.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
void rt_raster_set_skews(rt_raster raster, double skewX, double skewY)
Set skews about the X and Y axis.
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
rt_raster rt_raster_compute_skewed_raster(rt_envelope extent, double *skew, double *scale, double tolerance)
rt_raster rt_raster_from_gdal_dataset(GDALDatasetH ds)
Return a raster from a GDAL dataset.
static void _rti_rasterize_arg_destroy(_rti_rasterize_arg arg)
rt_band rt_raster_replace_band(rt_raster raster, rt_band band, int index)
Replace band at provided index with new band.
uint16_t rt_raster_get_height(rt_raster raster)
rt_band rt_raster_get_band(rt_raster raster, int n)
Return Nth band, or NULL if unavailable.
uint16_t rt_raster_get_width(rt_raster raster)
static _rti_rasterize_arg _rti_rasterize_arg_init()
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
void rt_raster_set_offsets(rt_raster raster, double x, double y)
Set insertion points in projection units.
OGRSpatialReferenceH src_sr