Example #1
0
void G3d_setNullValue(void *c, int nofElts, int type)
{
    if (type == FCELL_TYPE) {
	G_set_f_null_value((float *)c, nofElts);
	return;
    }

    G_set_d_null_value((double *)c, nofElts);
}
Example #2
0
/*
 * Allocates or resets raster data in host memory, returning a 
 * pointer to it. The operation is performed within the given
 * OpenCL context. Raster data is initialized to the given value.
 *
 * CONTEXT *ctx ........... an active OpenCL context.
 * int nrows .............. the number of rows in the DEM.
 * int ncols .............. the number of columns in the DEM.
 * RASTER_MAP_TYPE rtype .. DEM element data type.
 * FCELL init_value ....... initial value used for reseting or allocating
 *                          raster data. If NAN is given, the raster is
 *                          nullified.
 * void *alloc_ptr ........ a pointer to previously allocated memory. 
 *                          If it is valie, the memory is just set to
 *                          'init_value' without new memory allocation.
 *
 */
FCELL* alloc_raster (CONTEXT *ctx,
                     const int nrows, const int ncols, 
                     RASTER_MAP_TYPE rtype,
                     FCELL init_value,
                     void *alloc_ptr) 
{
    int i,j;

    if (rtype != FCELL_TYPE)
    {
        G_fatal_error ("Wrong element data type in 'null_raster'");
        return NULL;
    }
    else
    {
        FCELL *dem_device;

        if (alloc_ptr == NULL)
        {
            G_message ("Allocating NULL raster data into memory ...");

            /* allocate raster DEM data */
            dem_device = (FCELL *) clmalloc (ctx, 
                                   nrows * ncols * G_raster_size (rtype), 0);
        }
        else
        {
            G_message ("Resetting memory ...");
            dem_device = alloc_ptr;
        }

        /* Initialize the whole piece of memory */
        if (init_value == NAN)
        {
            G_set_f_null_value (dem_device, nrows * ncols);
        }
        else
        {
            for (i=0; i<nrows; i++)
            {
                for (j=0; j<ncols; j++)
                {
                    dem_device[i*ncols+j] = init_value;
                }
            }
        }

        /* Return a pointer to the allocated resources */
        return dem_device;
    }
}
Example #3
0
/* Saves map file from 2d array. NULL must be 0. Also meanwhile calculates area and volume. */
void save_map(FCELL ** out, int out_fd, int rows, int cols, int flag,
	      FCELL * min_depth, FCELL * max_depth, double *area,
	      double *volume)
{
    int row, col;
    double cellsize = -1;

    G_debug(1, "Saving new map");

    if (G_begin_cell_area_calculations() == 0 || G_begin_cell_area_calculations() == 1) {	/* All cells have constant size... */
	cellsize = G_area_of_cell_at_row(0);
    }
    G_debug(1, "Cell area: %f", cellsize);

    for (row = 0; row < rows; row++) {
	if (cellsize == -1)	/* Get LatLon current rows cell size */
	    cellsize = G_area_of_cell_at_row(row);
	for (col = 0; col < cols; col++) {
	    if (flag == 1)	/* Create negative map */
		out[row][col] = 0 - out[row][col];
	    if (out[row][col] == 0) {
		G_set_f_null_value(&out[row][col], 1);
	    }
	    if (out[row][col] > 0 || out[row][col] < 0) {
		G_debug(5, "volume %f += cellsize %f  * value %f [%d,%d]",
			*volume, cellsize, out[row][col], row, col);
		*area += cellsize;
		*volume += cellsize * out[row][col];
	    }

	    /* Get min/max depth. Can be usefull ;) */
	    if (out[row][col] > *max_depth)
		*max_depth = out[row][col];
	    if (out[row][col] < *min_depth)
		*min_depth = out[row][col];
	}
	if (G_put_f_raster_row(out_fd, out[row]) == -1)
	    G_fatal_error(_("Failed writing output raster map row %d"), row);
	G_percent(row + 1, rows, 5);
    }
}
Example #4
0
GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
                                  const char * pszMapset,
                                  const char * pszCellName )

{
    struct Cell_head	sCellInfo;

    // Note: GISDBASE, LOCATION_NAME ans MAPSET was set in GRASSDataset::Open

    this->poDS = poDS;
    this->nBand = nBand;
    this->valid = false;

    this->pszCellName = G_store ( (char *) pszCellName );
    this->pszMapset = G_store ( (char *) pszMapset );

    G_get_cellhd( (char *) pszCellName, (char *) pszMapset, &sCellInfo );
    nGRSType = G_raster_map_type( (char *) pszCellName, (char *) pszMapset );

/* -------------------------------------------------------------------- */
/*      Get min/max values.                                             */
/* -------------------------------------------------------------------- */
    struct FPRange sRange;

    if( G_read_fp_range( (char *) pszCellName, (char *) pszMapset, 
                         &sRange ) == -1 )
    {
        bHaveMinMax = FALSE;
    }
    else
    {
        bHaveMinMax = TRUE;
        G_get_fp_range_min_max( &sRange, &dfCellMin, &dfCellMax );
    }

/* -------------------------------------------------------------------- */
/*      Setup band type, and preferred nodata value.                    */
/* -------------------------------------------------------------------- */
    // Negative values are also (?) stored as 4 bytes (format = 3) 
    //       => raster with format < 3 has only positive values

    // GRASS modules usually do not waste space and only the format necessary to keep 
    // full raster values range is used -> no checks if shorter type could be used
    
    if( nGRSType == CELL_TYPE ) {
	if ( sCellInfo.format == 0 ) {  // 1 byte / cell -> possible range 0,255
	    if ( bHaveMinMax && dfCellMin > 0 ) {
                this->eDataType = GDT_Byte;
		dfNoData = 0.0;
	    } else if ( bHaveMinMax && dfCellMax < 255 ) {
                this->eDataType = GDT_Byte;
		dfNoData = 255.0;
	    } else { // maximum is not known or full range is used
		this->eDataType = GDT_UInt16;
		dfNoData = 256.0;
	    }
	    nativeNulls = false;
	} else if ( sCellInfo.format == 1 ) {  // 2 bytes / cell -> possible range 0,65535
	    if ( bHaveMinMax && dfCellMin > 0 ) {
		this->eDataType = GDT_UInt16;
		dfNoData = 0.0;
	    } else if ( bHaveMinMax && dfCellMax < 65535 ) {
                this->eDataType = GDT_UInt16;
		dfNoData = 65535;
	    } else { // maximum is not known or full range is used
		CELL cval;
		this->eDataType = GDT_Int32; 
		G_set_c_null_value ( &cval, 1);
		dfNoData = (double) cval;
		nativeNulls = true;
	    }
	    nativeNulls = false;
	} else {  // 3-4 bytes 
	    CELL cval;
	    this->eDataType = GDT_Int32;
	    G_set_c_null_value ( &cval, 1);
	    dfNoData = (double) cval;
	    nativeNulls = true;
	}
    } 
    else if( nGRSType == FCELL_TYPE ) {
	FCELL fval;
        this->eDataType = GDT_Float32;
	G_set_f_null_value ( &fval, 1);
	dfNoData = (double) fval;
	nativeNulls = true;
    }
    else if( nGRSType == DCELL_TYPE )
    {
	DCELL dval;
        this->eDataType = GDT_Float64;
	G_set_d_null_value ( &dval, 1);
	dfNoData = (double) dval;
	nativeNulls = true;
    }

    nBlockXSize = poDS->nRasterXSize;;
    nBlockYSize = 1;

    G_set_window( &(((GRASSDataset *)poDS)->sCellInfo) );
    if ( (hCell = G_open_cell_old((char *) pszCellName, (char *) pszMapset)) < 0 ) {
	CPLError( CE_Warning, CPLE_AppDefined, "GRASS: Cannot open raster '%s'", pszCellName );
	return;
    }
    G_copy((void *) &sOpenWindow, (void *) &(((GRASSDataset *)poDS)->sCellInfo), sizeof(struct Cell_head));

/* -------------------------------------------------------------------- */
/*      Do we have a color table?                                       */
/* -------------------------------------------------------------------- */
    poCT = NULL;
    if( G_read_colors( (char *) pszCellName, (char *) pszMapset, &sGrassColors ) == 1 )
    {
	int maxcolor; 
	CELL min, max;

	G_get_color_range ( &min, &max, &sGrassColors);

        if ( bHaveMinMax ) {
	    if ( max < dfCellMax ) {
	       maxcolor = max;
            } else {
	       maxcolor = (int) ceil ( dfCellMax );
	    }
	    if ( maxcolor > GRASS_MAX_COLORS ) { 
		maxcolor = GRASS_MAX_COLORS;
                CPLDebug( "GRASS", "Too many values, color table cut to %d entries.", maxcolor );
	    }
	} else {
	    if ( max < GRASS_MAX_COLORS ) {
	       maxcolor = max;
            } else {
	       maxcolor = GRASS_MAX_COLORS;
               CPLDebug( "GRASS", "Too many values, color table set to %d entries.", maxcolor );
	    }
        }
	    
        poCT = new GDALColorTable();
        for( int iColor = 0; iColor <= maxcolor; iColor++ )
        {
            int	nRed, nGreen, nBlue;
            GDALColorEntry    sColor;

#if GRASS_VERSION_MAJOR  >= 7
            if( Rast_get_c_color( &iColor, &nRed, &nGreen, &nBlue, &sGrassColors ) )
#else
            if( G_get_color( iColor, &nRed, &nGreen, &nBlue, &sGrassColors ) )
#endif
            {
                sColor.c1 = nRed;
                sColor.c2 = nGreen;
                sColor.c3 = nBlue;
                sColor.c4 = 255;

                poCT->SetColorEntry( iColor, &sColor );
            }
            else
            {
                sColor.c1 = 0;
                sColor.c2 = 0;
                sColor.c3 = 0;
                sColor.c4 = 0;

                poCT->SetColorEntry( iColor, &sColor );
            }
        }
	    
	/* Create metadata enries for color table rules */
	char key[200], value[200];
	int rcount = G_colors_count ( &sGrassColors );

	sprintf ( value, "%d", rcount );
	this->SetMetadataItem( "COLOR_TABLE_RULES_COUNT", value );

	/* Add the rules in reverse order */
	for ( int i = rcount-1; i >= 0; i-- ) {
	    DCELL val1, val2;
	    unsigned char r1, g1, b1, r2, g2, b2;

	     G_get_f_color_rule ( &val1, &r1, &g1, &b1, &val2, &r2, &g2, &b2, &sGrassColors, i );
		

	     sprintf ( key, "COLOR_TABLE_RULE_RGB_%d", rcount-i-1 );
	     sprintf ( value, "%e %e %d %d %d %d %d %d", val1, val2, r1, g1, b1, r2, g2, b2 );
	     this->SetMetadataItem( key, value );
	}
    } else {
	this->SetMetadataItem( "COLOR_TABLE_RULES_COUNT", "0" );
    }
    
    this->valid = true;
}
Example #5
0
int QgsGrassGisLib::readRasterRow( int fd, void * buf, int row, RASTER_MAP_TYPE data_type, bool noDataAsZero )
{
    if ( row < 0 || row >= mRows )
    {
        QgsDebugMsg( QString( "row %1 out of range 0 - %2" ).arg( row ).arg( mRows ) );
        return 0;
    }

    // TODO: use cached block with more rows
    Raster raster = mRasters.value( fd );
    //if ( !raster.provider ) return -1;
    if ( !raster.input ) return -1;

    // Create extent for current row
    QgsRectangle blockRect = mExtent;
    double yRes = mExtent.height() / mRows;
    double yMax = mExtent.yMaximum() - yRes * row;
    //QgsDebugMsg( QString( "height = %1 mRows = %2" ).arg( mExtent.height() ).arg( mRows ) );
    //QgsDebugMsg( QString( "row = %1 yRes = %2 yRes * row = %3" ).arg( row ).arg( yRes ).arg( yRes * row ) );
    //QgsDebugMsg( QString( "mExtent.yMaximum() = %1 yMax = %2" ).arg( mExtent.yMaximum() ).arg( yMax ) );
    blockRect.setYMaximum( yMax );
    blockRect.setYMinimum( yMax - yRes );

    QgsRasterBlock *block = raster.input->block( raster.band, blockRect, mColumns, 1 );
    if ( !block ) return -1;

    QGis::DataType requestedType = qgisRasterType( data_type );

    //QgsDebugMsg( QString("data_type = %1").arg(data_type) );
    //QgsDebugMsg( QString("requestedType = %1").arg(requestedType) );
    //QgsDebugMsg( QString("requestedType size = %1").arg( QgsRasterBlock::typeSize( requestedType ) ) );
    //QgsDebugMsg( QString("block->dataType = %1").arg( block->dataType() ) );

    block->convert( requestedType );

    memcpy( buf, block->bits( 0 ), QgsRasterBlock::typeSize( requestedType ) * mColumns );

    for ( int i = 0; i < mColumns; i++ )
    {
        QgsDebugMsgLevel( QString( "row = %1 i = %2 val = %3 isNoData = %4" ).arg( row ).arg( i ).arg( block->value( i ) ).arg( block->isNoData( i ) ), 5 );
        //(( CELL * ) buf )[i] = i;
        if ( block->isNoData( 0, i ) )
        {
            if ( noDataAsZero )
            {
                switch ( data_type )
                {
                case CELL_TYPE:
                    G_zero(( char * ) &(( CELL * ) buf )[i], G_raster_size( data_type ) );
                    break;
                case FCELL_TYPE:
                    G_zero(( char * ) &(( FCELL * ) buf )[i], G_raster_size( data_type ) );
                    break;
                case DCELL_TYPE:
                    G_zero(( char * ) &(( DCELL * ) buf )[i], G_raster_size( data_type ) );
                    break;
                default:
                    break;
                }
            }
            else
            {
                switch ( data_type )
                {
                case CELL_TYPE:
                    G_set_c_null_value( &(( CELL * ) buf )[i], 1 );
                    break;
                case FCELL_TYPE:
                    G_set_f_null_value( &(( FCELL * ) buf )[i], 1 );
                    break;
                case DCELL_TYPE:
                    G_set_d_null_value( &(( DCELL * ) buf )[i], 1 );
                    break;
                default:
                    break;
                }
            }
        }
        //else
        //{
        //memcpy( &( buf[i] ), block->bits( 0, i ), 4 );
        //buf[i] = (int)  block->value( 0, i);
        //QgsDebugMsg( QString("buf[i] = %1").arg(buf[i]));
        //}
    }
    delete block;
    return 1;

}
Example #6
0
int main(int argc, char *argv[])
{
    char *input;
    char *output;
    char *title;
    FILE *fd;
    int cf;
    struct Cell_head cellhd;
    CELL *cell;
    FCELL *fcell;
    DCELL *dcell;
    int row, col;
    int nrows, ncols;
    static int missingval;
    int rtype;
    double mult_fact;
    double x;
    struct GModule *module;
    struct History history;
    struct
    {
	struct Option *input, *output, *type, *title, *mult;
    } parm;


    G_gisinit(argv[0]);

    module = G_define_module();
    module->keywords = _("raster, import");
    module->description =
	_("Converts an ESRI ARC/INFO ascii raster file (GRID) "
	  "into a (binary) raster map layer.");

    parm.input = G_define_option();
    parm.input->key = "input";
    parm.input->type = TYPE_STRING;
    parm.input->required = YES;
    parm.input->description =
	_("ARC/INFO ASCII raster file (GRID) to be imported");
    parm.input->gisprompt = "old_file,file,input";

    parm.output = G_define_standard_option(G_OPT_R_OUTPUT);

    parm.type = G_define_option();
    parm.type->key = "type";
    parm.type->type = TYPE_STRING;
    parm.type->required = NO;
    parm.type->options = "CELL,FCELL,DCELL";
    parm.type->answer = "FCELL";
    parm.type->description = _("Storage type for resultant raster map");

    parm.title = G_define_option();
    parm.title->key = "title";
    parm.title->key_desc = "\"phrase\"";
    parm.title->type = TYPE_STRING;
    parm.title->required = NO;
    parm.title->description = _("Title for resultant raster map");

    parm.mult = G_define_option();
    parm.mult->key = "mult";
    parm.mult->type = TYPE_DOUBLE;
    parm.mult->answer = "1.0";
    parm.mult->required = NO;
    parm.mult->description = _("Multiplier for ASCII data");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);
    input = parm.input->answer;
    output = parm.output->answer;
    if (title = parm.title->answer)
	G_strip(title);

    sscanf(parm.mult->answer, "%lf", &mult_fact);
    if (strcmp("CELL", parm.type->answer) == 0)
	rtype = CELL_TYPE;
    else if (strcmp("DCELL", parm.type->answer) == 0)
	rtype = DCELL_TYPE;
    else
	rtype = FCELL_TYPE;

    if (strcmp("-", input) == 0) {
	Tmp_file = G_tempfile();
	if (NULL == (Tmp_fd = fopen(Tmp_file, "w+")))
	    G_fatal_error(_("Unable to open temporary file <%s>"), Tmp_file);
	unlink(Tmp_file);
	if (0 > file_cpy(stdin, Tmp_fd))
	    exit(EXIT_FAILURE);
	fd = Tmp_fd;
    }
    else
	fd = fopen(input, "r");

    if (fd == NULL)
	G_fatal_error(_("Unable to open input file <%s>"), input);

    if (!gethead(fd, &cellhd, &missingval))
	G_fatal_error(_("Can't get cell header"));

    nrows = cellhd.rows;
    ncols = cellhd.cols;
    if (G_set_window(&cellhd) < 0)
	G_fatal_error(_("Can't set window"));

    if (nrows != G_window_rows())
	G_fatal_error(_("OOPS: rows changed from %d to %d"), nrows,
		      G_window_rows());
    if (ncols != G_window_cols())
	G_fatal_error(_("OOPS: cols changed from %d to %d"), ncols,
		      G_window_cols());

    switch (rtype) {
    case CELL_TYPE:
	cell = G_allocate_c_raster_buf();
	break;
    case FCELL_TYPE:
	fcell = G_allocate_f_raster_buf();
	break;
    case DCELL_TYPE:
	dcell = G_allocate_d_raster_buf();
	break;
    }
    cf = G_open_raster_new(output, rtype);
    if (cf < 0)
	G_fatal_error(_("Unable to create raster map <%s>"), output);

    for (row = 0; row < nrows; row++) {
	G_percent(row, nrows, 5);
	for (col = 0; col < ncols; col++) {
	    if (fscanf(fd, "%lf", &x) != 1) {
		G_unopen_cell(cf);
		G_fatal_error(_("Data conversion failed at row %d, col %d"),
			      row + 1, col + 1);
	    }
	    switch (rtype) {
	    case CELL_TYPE:
		if ((int)x == missingval)
		    G_set_c_null_value(cell + col, 1);
		else
		    cell[col] = (CELL) x *mult_fact;

		break;
	    case FCELL_TYPE:
		if ((int)x == missingval)
		    G_set_f_null_value(fcell + col, 1);
		else
		    fcell[col] = (FCELL) x *mult_fact;

		break;
	    case DCELL_TYPE:
		if ((int)x == missingval)
		    G_set_d_null_value(dcell + col, 1);
		else
		    dcell[col] = (DCELL) x *mult_fact;

		break;
	    }
	}
	switch (rtype) {
	case CELL_TYPE:
	    G_put_c_raster_row(cf, cell);
	    break;
	case FCELL_TYPE:
	    G_put_f_raster_row(cf, fcell);
	    break;
	case DCELL_TYPE:
	    G_put_d_raster_row(cf, dcell);
	    break;
	}
    }
    /* G_message(_("CREATING SUPPORT FILES FOR %s"), output); */
    G_close_cell(cf);
    if (title)
	G_put_cell_title(output, title);
    G_short_history(output, "raster", &history);
    G_command_history(&history);
    G_write_history(output, &history);


    exit(EXIT_SUCCESS);
}
Example #7
0
int calculateF(int fd, area_des ad, double *result)
{
    FCELL *buf;
    FCELL *buf_sup;
    FCELL corrCell;
    FCELL precCell;
    FCELL supCell;
    int i, j;
    int mask_fd = -1, *mask_buf;
    int ris = 0;
    int masked = FALSE;
    int areaPatch = 0;		/*if all cells are null areaPatch=0 */
    long npatch = 0;
    long np = 0;
    long tot = 0;
    long zero = 0;
    long totCorr = 0;
    long idCorr = 0;
    long lastId = 0;
    long doppi = 0;
    long *mask_patch_sup;
    long *mask_patch_corr;
    double indice = 0;
    double somma = 0;
    double area = 0;
    double mn = 0;
    double sd = 0;
    double cv = 0;
    avlID_tree albero = NULL;
    avlID_table *array = NULL;
    generic_cell gc;

    gc.t = FCELL_TYPE;

    /* open mask if needed */
    if (ad->mask == 1) {
	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
	    return RLI_ERRORE;
	mask_buf = G_malloc(ad->cl * sizeof(int));
	if (mask_buf == NULL) {
	    G_fatal_error("malloc mask_buf failed");
	    return RLI_ERRORE;
	}
	masked = TRUE;
    }
    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
    if (mask_patch_sup == NULL) {
	G_fatal_error("malloc mask_patch_sup failed");
	return RLI_ERRORE;
    }
    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
    if (mask_patch_corr == NULL) {
	G_fatal_error("malloc mask_patch_corr failed");
	return RLI_ERRORE;
    }
    buf_sup = G_allocate_f_raster_buf();
    if (buf_sup == NULL) {
	G_fatal_error("malloc buf_sup failed");
	return RLI_ERRORE;
    }
    buf = G_allocate_f_raster_buf();
    if (buf == NULL) {
	G_fatal_error("malloc buf failed");
	return RLI_ERRORE;
    }
    G_set_f_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
    for (i = 0; i < ad->cl; i++) {
	mask_patch_sup[i] = 0;
	mask_patch_corr[i] = 0;
    }
    for (j = 0; j < ad->rl; j++)
	/*for each raster row */

    {
	if (j > 0) {
	    buf_sup = RLI_get_fcell_raster_row(fd, j - 1 + ad->y, ad);
	}
	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
	if (masked) {
	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
		G_fatal_error("mask read failed");
		return RLI_ERRORE;
	    }
	}
	G_set_f_null_value(&precCell, 1);
	for (i = 0; i < ad->cl; i++) {
	    /* for each fcell in the row */
	    area++;
	    corrCell = buf[i + ad->x];
	    if (masked && mask_buf[i + ad->x] == 0) {
		G_set_f_null_value(&corrCell, 1);
		area--;
	    }
	    if (!(G_is_null_value(&corrCell, gc.t))) {
		areaPatch++;
		if (i > 0)
		    precCell = buf[i - 1 + ad->x];
		if (j == 0)
		    G_set_f_null_value(&supCell, 1);

		else
		    supCell = buf_sup[i + ad->x];

		if (corrCell != precCell)
		    /*        ?
		     *      1 2
		     * */
		{
		    if (corrCell != supCell)
			/*        3
			 *      1 2
			 * */
		    {

			/*new patch */
			if (idCorr == 0) {	/*first patch */
			    lastId = 1;
			    idCorr = 1;
			    totCorr = 1;
			    mask_patch_corr[i] = idCorr;
			}

			else
			    /*not first patch */
			    /* put in the tree the previous value */
			{
			    if (albero == NULL) {
				albero = avlID_make(idCorr, totCorr);
				if (albero == NULL) {
				    G_fatal_error("avlID_make error");
				    return RLI_ERRORE;
				}
				npatch++;
			    }

			    else
				/*tree not empty */
			    {
				ris = avlID_add(&albero, idCorr, totCorr);
				switch (ris) {
				case AVL_ERR:

				    {
					G_fatal_error("avlID_add error");
					return RLI_ERRORE;
				    }
				case AVL_ADD:

				    {
					npatch++;
					break;
				    }
				case AVL_PRES:

				    {
					break;
				    }
				default:

				    {
					G_fatal_error
					    ("avlID_add unknown error");
					return RLI_ERRORE;
				    }
				}
			    }
			    totCorr = 1;
			    lastId++;
			    idCorr = lastId;
			    mask_patch_corr[i] = idCorr;
			}
		    }

		    else
			/*current cell and upper cell are equal */
			/*        2
			 *      1 2
			 * */
		    {
			if (albero == NULL) {
			    albero = avlID_make(idCorr, totCorr);
			    if (albero == NULL) {
				G_fatal_error("avlID_make error");
				return RLI_ERRORE;
			    }
			    npatch++;
			}
			else {	/*tree not null */

			    ris = avlID_add(&albero, idCorr, totCorr);
			    switch (ris) {
			    case AVL_ERR:
				{
				    G_fatal_error("avlID_add error");
				    return RLI_ERRORE;
				}
			    case AVL_ADD:
				{
				    npatch++;
				    break;
				}
			    case AVL_PRES:
				{
				    break;
				}
			    default:
				{
				    G_fatal_error("avlID_add unknown error");
				    return RLI_ERRORE;
				}
			    }
			}

			idCorr = mask_patch_sup[i];
			mask_patch_corr[i] = idCorr;
			totCorr = 1;
		    }
		}
		else {		/*current cell and previuos cell are equal */
		    /*        ?
		     *      1 1
		     */

		    if (corrCell == supCell) {	/*current cell and upper cell are equal */
			/*        1
			 *      1 1
			 */
			if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
			    long r = 0;
			    long del = mask_patch_sup[i];


			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */

			    if (r == 0) {
				G_fatal_error("avlID_sub error");
				return RLI_ERRORE;
			    }

			    /*Remove one patch because it makes part of a patch already found */
			    ris = avlID_add(&albero, idCorr, r);

			    switch (ris) {
			    case AVL_ERR:
				{
				    G_fatal_error("avlID_add error");
				    return RLI_ERRORE;
				}
			    case AVL_ADD:
				{
				    npatch++;
				    break;
				}
			    case AVL_PRES:
				{
				    break;
				}
			    default:
				{
				    G_fatal_error("avlID_add unknown error");
				    return RLI_ERRORE;
				}
			    }
			    r = i;
			    while (r < ad->cl) {
				if (mask_patch_sup[r] == del) {
				    mask_patch_sup[r] = idCorr;
				}

				r++;
			    }

			    mask_patch_corr[i] = idCorr;
			}
			else {
			    mask_patch_corr[i] = idCorr;
			}
		    }
		    else {	/*current cell and upper cell are not equal */
			/*        2
			 *      1 1
			 */
			mask_patch_corr[i] = idCorr;
		    }

		    totCorr++;
		}
	    }
	    else {		/*cell is null or is not to consider */

		mask_patch_corr[i] = 0;

	    }
	}

	{
	    int ii;
	    long c;

	    for (ii = 0; ii < ad->cl; ii++) {
		c = mask_patch_corr[ii];
		mask_patch_sup[ii] = c;
		mask_patch_corr[ii] = 0;
	    }
	}


    }




    if (areaPatch != 0) {
	if (albero == NULL) {
	    albero = avlID_make(idCorr, totCorr);
	    if (albero == NULL) {
		G_fatal_error("avlID_make error");
		return RLI_ERRORE;
	    }
	    npatch++;
	}

	else {
	    ris = avlID_add(&albero, idCorr, totCorr);
	    switch (ris) {
	    case AVL_ERR:

		{
		    G_fatal_error("avlID_add error");
		    return RLI_ERRORE;
		}
	    case AVL_ADD:

		{
		    npatch++;
		    break;
		}
	    case AVL_PRES:

		{
		    break;
		}
	    default:

		{
		    G_fatal_error("avlID_add unknown error");
		    return RLI_ERRORE;
		}
	    }
	}
	array = G_malloc(npatch * sizeof(avlID_tableRow));
	if (array == NULL) {
	    G_fatal_error("malloc array failed");
	    return RLI_ERRORE;
	}
	tot = avlID_to_array(albero, zero, array);
	if (tot != npatch) {
	    G_warning
		("avlID_to_array unaspected value. the result could be wrong");
	    return RLI_ERRORE;
	}
	for (i = 0; i < npatch; i++) {
	    if (array[i]->tot == 0) {
		doppi++;
	    }
	}
	np = npatch;
	npatch = npatch - doppi;
	mn = areaPatch / npatch;

	/* calculate summary */
	for (i = 0; i < np; i++) {
	    long areaPi = 0;
	    double diff;

	    if (array[i]->tot != 0) {
		ris = ris + array[i]->tot;
		areaPi = (double)array[i]->tot;
		diff = areaPi - mn;
		somma = somma + (diff * diff);
	    }
	}
	sd = sqrt(somma / npatch);
	cv = sd * 100 / mn;
	indice = cv;
	G_free(array);
    }

    else
	indice = (double)(-1);
    if (masked)
	G_free(mask_buf);
    G_free(mask_patch_sup);
    *result = indice;
    return RLI_OK;
}