544{
547 ArrayType *maskArray;
548 Oid etype;
549 Datum *maskElements;
550 bool *maskNulls;
551 int16 typlen;
552 bool typbyval;
553 char typalign;
554 int ndims = 0;
555 int num;
556 int *maskDims;
558
559
560 int i = 0;
561 int noerr = 0;
562 int allnull = 0;
563 int allempty = 0;
564 int noband = 0;
565
569
571
572 if (PG_ARGISNULL(0))
573 PG_RETURN_NULL();
574
575
577 if (arg == NULL) {
578 elog(ERROR, "RASTER_nMapAlgebra: Could not initialize argument structure");
579 PG_RETURN_NULL();
580 }
581
582
585 elog(ERROR, "RASTER_nMapAlgebra: Could not process rastbandarg");
586 PG_RETURN_NULL();
587 }
588
589 POSTGIS_RT_DEBUGF(4,
"allnull, allempty, noband = %d, %d, %d", allnull, allempty, noband);
590
591
593 elog(NOTICE, "All input rasters are NULL. Returning NULL");
595 PG_RETURN_NULL();
596 }
597
598
599 if (!PG_ARGISNULL(2)) {
601
602
606 elog(ERROR, "RASTER_nMapAlgebra: Invalid pixel type: %s", pixtypename);
607 PG_RETURN_NULL();
608 }
609 }
610
611
612 if (!PG_ARGISNULL(3)){
613 arg->
distance[0] = PG_GETARG_INT32(3);
614 }else{
616 }
617
618 if (!PG_ARGISNULL(4)){
619 arg->
distance[1] = PG_GETARG_INT32(4);
620 }else{
622 }
625 elog(ERROR, "RASTER_nMapAlgebra: Distance for X and Y axis must be greater than or equal to zero");
626 PG_RETURN_NULL();
627 }
628
629
630 if (!PG_ARGISNULL(5)) {
633 }
635
636
638 if (PG_ARGISNULL(6)) {
639 elog(NOTICE, "Custom extent is NULL. Returning NULL");
641 PG_RETURN_NULL();
642 }
643
645
646
650 elog(ERROR, "RASTER_nMapAlgebra: Could not deserialize custom extent");
651 PG_RETURN_NULL();
652 }
654 elog(NOTICE, "Custom extent is an empty raster. Returning empty raster");
656
658 if (raster == NULL) {
659 elog(ERROR, "RASTER_nMapAlgebra: Could not create empty raster");
660 PG_RETURN_NULL();
661 }
662
665 if (!pgraster) PG_RETURN_NULL();
666
667 SET_VARSIZE(pgraster, pgraster->
size);
668 PG_RETURN_POINTER(pgraster);
669 }
670 }
671
672
673
674 if( PG_ARGISNULL(7) ){
677 }
678 else {
679 maskArray = PG_GETARG_ARRAYTYPE_P(7);
680 etype = ARR_ELEMTYPE(maskArray);
681 get_typlenbyvalalign(etype,&typlen,&typbyval,&typalign);
682
683 switch (etype) {
684 case FLOAT4OID:
685 case FLOAT8OID:
686 break;
687 default:
689 elog(ERROR,"RASTER_nMapAlgebra: Mask data type must be FLOAT8 or FLOAT4");
690 PG_RETURN_NULL();
691 }
692
693 ndims = ARR_NDIM(maskArray);
694
695 if (ndims != 2) {
696 elog(ERROR, "RASTER_nMapAlgebra: Mask Must be a 2D array");
698 PG_RETURN_NULL();
699 }
700
701 maskDims = ARR_DIMS(maskArray);
702
703 if (maskDims[0] % 2 == 0 || maskDims[1] % 2 == 0) {
704 elog(ERROR,"RASTER_nMapAlgebra: Mask dimensions must be odd");
706 PG_RETURN_NULL();
707 }
708
709 deconstruct_array(
710 maskArray,
711 etype,
712 typlen, typbyval,typalign,
713 &maskElements,&maskNulls,&num
714 );
715
716 if (num < 1 || num != (maskDims[0] * maskDims[1])) {
717 if (num) {
718 pfree(maskElements);
719 pfree(maskNulls);
720 }
721 elog(ERROR, "RASTER_nMapAlgebra: Could not deconstruct new values array");
723 PG_RETURN_NULL();
724 }
725
726
727 arg->
mask->
values = palloc(
sizeof(
double*)* maskDims[0]);
728 arg->
mask->
nodata = palloc(
sizeof(
int*)*maskDims[0]);
729 for (i = 0; i < maskDims[0]; i++) {
730 arg->
mask->
values[i] = (
double*) palloc(
sizeof(
double) * maskDims[1]);
731 arg->
mask->
nodata[i] = (
int*) palloc(
sizeof(
int) * maskDims[1]);
732 }
733
734
735 i = 0;
736 for (y = 0;
y < maskDims[0];
y++) {
737 for (x = 0;
x < maskDims[1];
x++) {
738 if (maskNulls[i]) {
741 }
742 else {
743 switch (etype) {
744 case FLOAT4OID:
745 arg->
mask->
values[
y][
x] = (double) DatumGetFloat4(maskElements[i]);
747 break;
748 case FLOAT8OID:
749 arg->
mask->
values[
y][
x] = (double) DatumGetFloat8(maskElements[i]);
751 }
752 }
753 i++;
754 }
755 }
756
757
760 if (maskDims[0] == 1 && maskDims[1] == 1) {
763 }
764 else {
767 }
768 }
769
770
771 if (PG_ARGISNULL(8) || !PG_GETARG_BOOL(8)) {
772 if (arg->
mask != NULL)
774 }else{
777 }
778
779 noerr = 1;
780
781
783 elog(NOTICE, "All input rasters are empty. Returning empty raster");
784 noerr = 0;
785 }
786
788 elog(NOTICE, "All input rasters do not have bands at indicated indexes. Returning empty raster");
789 noerr = 0;
790 }
791 if (!noerr) {
793
795 if (raster == NULL) {
796 elog(ERROR, "RASTER_nMapAlgebra: Could not create empty raster");
797 PG_RETURN_NULL();
798 }
799
802 if (!pgraster) PG_RETURN_NULL();
803
804 SET_VARSIZE(pgraster, pgraster->
size);
805 PG_RETURN_POINTER(pgraster);
806 }
807
808
809 if (!PG_ARGISNULL(1) || get_fn_expr_argtype(fcinfo->flinfo, 1) == REGPROCEDUREOID) {
812
813
815
816
817 noerr = 0;
819 noerr = 1;
820 }
821
823 noerr = 2;
824 }
825
826
827 if (
828 get_func_result_type(
831 NULL
832 ) != TYPEFUNC_SCALAR
833 ) {
834 noerr = 3;
835 }
836
837 if (!(
842 )) {
843 noerr = 4;
844 }
845
846
847
848
849
850
851 if (noerr != 0) {
853 switch (noerr) {
854 case 4:
855 elog(ERROR, "RASTER_nMapAlgebra: Function provided must return a double precision, float, int or smallint");
856 break;
857 case 3:
858 elog(ERROR, "RASTER_nMapAlgebra: Function provided must return scalar (double precision, float, int, smallint)");
859 break;
860 case 2:
861 elog(ERROR, "RASTER_nMapAlgebra: Function provided must have three input parameters");
862 break;
863 case 1:
864 elog(ERROR, "RASTER_nMapAlgebra: Function provided must return double precision, not resultset");
865 break;
866 }
867 PG_RETURN_NULL();
868 }
869
871 elog(NOTICE, "Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
872
873
874#if POSTGIS_PGSQL_VERSION < 120
876
878#else
882 InvalidOid,
883 NULL,
884 NULL);
885
889#endif
890
891
892 if (!PG_ARGISNULL(9))
893#if POSTGIS_PGSQL_VERSION < 120
895#else
897#endif
898 else {
900
901
902#if POSTGIS_PGSQL_VERSION < 120
904 construct_empty_array(TEXTOID)
905 );
907#else
908 arg->
callback.
ufc_info->args[2].value = PointerGetDatum(construct_empty_array(TEXTOID));
910#endif
911 }
912 else {
913#if POSTGIS_PGSQL_VERSION < 120
916#else
919#endif
920 }
921 }
922 }
923 else {
925 elog(ERROR, "RASTER_nMapAlgebra: callbackfunc must be provided");
926 PG_RETURN_NULL();
927 }
928
929
930
934 break;
937 break;
938 default:
939 i = 0;
940 break;
941 }
942
946 break;
947 }
950 }
952
953
956
957
961 else
963
965
966
968 if (itrset == NULL) {
970 elog(ERROR, "RASTER_nMapAlgebra: Could not allocate memory for iterator arguments");
971 PG_RETURN_NULL();
972 }
973
974
979 }
980
981
991 &raster
992 );
993
994
995 pfree(itrset);
997
999 elog(ERROR, "RASTER_nMapAlgebra: Could not run raster iterator function");
1000 PG_RETURN_NULL();
1001 }
1002 else if (raster == NULL)
1003 PG_RETURN_NULL();
1004
1007
1009
1010 if (!pgraster)
1011 PG_RETURN_NULL();
1012
1013 SET_VARSIZE(pgraster, pgraster->
size);
1014 PG_RETURN_POINTER(pgraster);
1015}
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
rt_extenttype rt_util_extent_type(const char *name)
const char * rt_pixtype_name(rt_pixtype pixtype)
double rt_band_get_min_value(rt_band band)
Returns the minimal possible value for the band according to the pixel type.
rt_errorstate rt_raster_iterator(rt_iterator itrset, uint16_t itrcount, rt_extenttype extenttype, rt_raster customextent, rt_pixtype pixtype, uint8_t hasnodata, double nodataval, uint16_t distancex, uint16_t distancey, rt_mask mask, void *userarg, int(*callback)(rt_iterator_arg arg, void *userarg, double *value, int *nodata), rt_raster *rtnraster)
n-raster iterator.
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 * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
char * text_to_cstring(const text *textptr)
char * rtpg_trim(const char *input)
char * rtpg_strtoupper(char *str)
static rtpg_nmapalgebra_arg rtpg_nmapalgebra_arg_init()
static void rtpg_nmapalgebra_arg_destroy(rtpg_nmapalgebra_arg arg)
static int rtpg_nmapalgebra_rastbandarg_process(rtpg_nmapalgebra_arg arg, ArrayType *array, int *allnull, int *allempty, int *noband)
static int rtpg_nmapalgebra_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)
rtpg_nmapalgebra_callback_arg callback
FunctionCallInfoData ufc_info