527{
530 ArrayType *maskArray;
531 Oid etype;
532 Datum *maskElements;
533 bool *maskNulls;
534 int16 typlen;
535 bool typbyval;
536 char typalign;
537 int ndims = 0;
538 int num;
539 int *maskDims;
541
542
543 int i = 0;
544 int noerr = 0;
545 int allnull = 0;
546 int allempty = 0;
547 int noband = 0;
548
552
554
555 if (PG_ARGISNULL(0))
556 PG_RETURN_NULL();
557
558
560 if (arg == NULL) {
561 elog(ERROR, "RASTER_nMapAlgebra: Could not initialize argument structure");
562 PG_RETURN_NULL();
563 }
564
565
568 elog(ERROR, "RASTER_nMapAlgebra: Could not process rastbandarg");
569 PG_RETURN_NULL();
570 }
571
572 POSTGIS_RT_DEBUGF(4,
"allnull, allempty, noband = %d, %d, %d", allnull, allempty, noband);
573
574
576 elog(NOTICE, "All input rasters are NULL. Returning NULL");
578 PG_RETURN_NULL();
579 }
580
581
582 if (!PG_ARGISNULL(2)) {
583 char *pixtypename = text_to_cstring(PG_GETARG_TEXT_P(2));
584
585
589 elog(ERROR, "RASTER_nMapAlgebra: Invalid pixel type: %s", pixtypename);
590 PG_RETURN_NULL();
591 }
592 }
593
594
595 if (!PG_ARGISNULL(3)){
596 arg->
distance[0] = PG_GETARG_INT32(3);
597 }else{
599 }
600
601 if (!PG_ARGISNULL(4)){
602 arg->
distance[1] = PG_GETARG_INT32(4);
603 }else{
605 }
608 elog(ERROR, "RASTER_nMapAlgebra: Distance for X and Y axis must be greater than or equal to zero");
609 PG_RETURN_NULL();
610 }
611
612
613 if (!PG_ARGISNULL(5)) {
616 }
618
619
621 if (PG_ARGISNULL(6)) {
622 elog(NOTICE, "Custom extent is NULL. Returning NULL");
624 PG_RETURN_NULL();
625 }
626
628
629
633 elog(ERROR, "RASTER_nMapAlgebra: Could not deserialize custom extent");
634 PG_RETURN_NULL();
635 }
637 elog(NOTICE, "Custom extent is an empty raster. Returning empty raster");
639
641 if (raster == NULL) {
642 elog(ERROR, "RASTER_nMapAlgebra: Could not create empty raster");
643 PG_RETURN_NULL();
644 }
645
648 if (!pgraster) PG_RETURN_NULL();
649
650 SET_VARSIZE(pgraster, pgraster->
size);
651 PG_RETURN_POINTER(pgraster);
652 }
653 }
654
655
656
657 if( PG_ARGISNULL(7) ){
660 }
661 else {
662 maskArray = PG_GETARG_ARRAYTYPE_P(7);
663 etype = ARR_ELEMTYPE(maskArray);
664 get_typlenbyvalalign(etype,&typlen,&typbyval,&typalign);
665
666 switch (etype) {
667 case FLOAT4OID:
668 case FLOAT8OID:
669 break;
670 default:
672 elog(ERROR,"RASTER_nMapAlgebra: Mask data type must be FLOAT8 or FLOAT4");
673 PG_RETURN_NULL();
674 }
675
676 ndims = ARR_NDIM(maskArray);
677
678 if (ndims != 2) {
679 elog(ERROR, "RASTER_nMapAlgebra: Mask Must be a 2D array");
681 PG_RETURN_NULL();
682 }
683
684 maskDims = ARR_DIMS(maskArray);
685
686 if (maskDims[0] % 2 == 0 || maskDims[1] % 2 == 0) {
687 elog(ERROR,"RASTER_nMapAlgebra: Mask dimensions must be odd");
689 PG_RETURN_NULL();
690 }
691
692 deconstruct_array(
693 maskArray,
694 etype,
695 typlen, typbyval,typalign,
696 &maskElements,&maskNulls,&num
697 );
698
699 if (num < 1 || num != (maskDims[0] * maskDims[1])) {
700 if (num) {
701 pfree(maskElements);
702 pfree(maskNulls);
703 }
704 elog(ERROR, "RASTER_nMapAlgebra: Could not deconstruct new values array");
706 PG_RETURN_NULL();
707 }
708
709
710 arg->
mask->
values = palloc(
sizeof(
double*)* maskDims[0]);
711 arg->
mask->
nodata = palloc(
sizeof(
int*)*maskDims[0]);
712 for (i = 0; i < maskDims[0]; i++) {
713 arg->
mask->
values[i] = (
double*) palloc(
sizeof(
double) * maskDims[1]);
714 arg->
mask->
nodata[i] = (
int*) palloc(
sizeof(
int) * maskDims[1]);
715 }
716
717
718 i = 0;
719 for (y = 0;
y < maskDims[0];
y++) {
720 for (x = 0;
x < maskDims[1];
x++) {
721 if (maskNulls[i]) {
724 }
725 else {
726 switch (etype) {
727 case FLOAT4OID:
728 arg->
mask->
values[
y][
x] = (double) DatumGetFloat4(maskElements[i]);
730 break;
731 case FLOAT8OID:
732 arg->
mask->
values[
y][
x] = (double) DatumGetFloat8(maskElements[i]);
734 }
735 }
736 i++;
737 }
738 }
739
740
743 if (maskDims[0] == 1 && maskDims[1] == 1) {
746 }
747 else {
750 }
751 }
752
753
754 if (PG_ARGISNULL(8) || !PG_GETARG_BOOL(8)) {
755 if (arg->
mask != NULL)
757 }else{
760 }
761
762 noerr = 1;
763
764
766 elog(NOTICE, "All input rasters are empty. Returning empty raster");
767 noerr = 0;
768 }
769
771 elog(NOTICE, "All input rasters do not have bands at indicated indexes. Returning empty raster");
772 noerr = 0;
773 }
774 if (!noerr) {
776
778 if (raster == NULL) {
779 elog(ERROR, "RASTER_nMapAlgebra: Could not create empty raster");
780 PG_RETURN_NULL();
781 }
782
785 if (!pgraster) PG_RETURN_NULL();
786
787 SET_VARSIZE(pgraster, pgraster->
size);
788 PG_RETURN_POINTER(pgraster);
789 }
790
791
792 if (!PG_ARGISNULL(1) || get_fn_expr_argtype(fcinfo->flinfo, 1) == REGPROCEDUREOID) {
795
796
798
799
800 noerr = 0;
802 noerr = 1;
803 }
804
806 noerr = 2;
807 }
808
809
810 if (
811 get_func_result_type(
814 NULL
815 ) != TYPEFUNC_SCALAR
816 ) {
817 noerr = 3;
818 }
819
820 if (!(
825 )) {
826 noerr = 4;
827 }
828
829
830
831
832
833
834 if (noerr != 0) {
836 switch (noerr) {
837 case 4:
838 elog(ERROR, "RASTER_nMapAlgebra: Function provided must return a double precision, float, int or smallint");
839 break;
840 case 3:
841 elog(ERROR, "RASTER_nMapAlgebra: Function provided must return scalar (double precision, float, int, smallint)");
842 break;
843 case 2:
844 elog(ERROR, "RASTER_nMapAlgebra: Function provided must have three input parameters");
845 break;
846 case 1:
847 elog(ERROR, "RASTER_nMapAlgebra: Function provided must return double precision, not resultset");
848 break;
849 }
850 PG_RETURN_NULL();
851 }
852
854 elog(NOTICE, "Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
855
856
860 InvalidOid,
861 NULL,
862 NULL);
863
867
868 if (!PG_ARGISNULL(9))
870 else {
872
873
874 arg->
callback.
ufc_info->args[2].value = PointerGetDatum(construct_empty_array(TEXTOID));
876 }
877 else {
880 }
881 }
882 }
883 else {
885 elog(ERROR, "RASTER_nMapAlgebra: callbackfunc must be provided");
886 PG_RETURN_NULL();
887 }
888
889
890
894 break;
897 break;
898 default:
899 i = 0;
900 break;
901 }
902
906 break;
907 }
910 }
912
913
916
917
921 else
923
925
926
928 if (itrset == NULL) {
930 elog(ERROR, "RASTER_nMapAlgebra: Could not allocate memory for iterator arguments");
931 PG_RETURN_NULL();
932 }
933
934
939 }
940
941
951 &raster
952 );
953
954
955 pfree(itrset);
957
959 elog(ERROR, "RASTER_nMapAlgebra: Could not run raster iterator function");
960 PG_RETURN_NULL();
961 }
962 else if (raster == NULL)
963 PG_RETURN_NULL();
964
967
969
970 if (!pgraster)
971 PG_RETURN_NULL();
972
973 SET_VARSIZE(pgraster, pgraster->
size);
974 PG_RETURN_POINTER(pgraster);
975}
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 * rtpg_trim(const char *input)
char * rtpg_strtoupper(char *str)
static void rtpg_nmapalgebra_arg_destroy(rtpg_nmapalgebra_arg arg)
static rtpg_nmapalgebra_arg rtpg_nmapalgebra_arg_init(void)
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
FunctionCallInfo ufc_info