/// <summary> /// Computes an IDW surface interpolation using a gradient to take into account differces from a raster /// Usefull for climatological data as perform a temperature correction based on terrain elevation /// </summary> /// <param name="OutputGTiffFile"></param> public static void IdwTemperaturesWithElevationCorrection(string OutputGTiffFile, List <Geometry> Points) { // Datos del malla de salida int EPSG = 23030; double CellSize = 10000; double CellSizeX = CellSize; double CellSizeY = CellSize; double xMin = 360000; double yMax = 4830000; int NumCols = 59; int NumRows = 39; double yMin = yMax - (NumRows * CellSize); double xMax = xMin + (NumCols * CellSize); var CorrectionGradient = -0.65d; var IdwExponent = 3d; //--------------------------------------------- // Filter points with NoData in value or in elevation //--------------------------------------------- Points = Points.Where(po => !double.IsNaN(po.GetM(0)) && !double.IsNaN(po.GetZ(0))).ToList(); logger.Trace($"INICIANDO con {Points.Count} termómetros."); //--------------------------------------------- // Compute weights for each point and raster cell //--------------------------------------------- var weights = new Dictionary <Geometry, double[, ]>(); var locker = new object(); Parallel.ForEach(Points, (p) => { double dXPunto = p.GetX(0); double dYPunto = p.GetY(0); // Para cada celda del mallado de la aplicación double[,] coeficients = new double[NumRows, NumCols]; for (int i = 0; i < NumRows; i++) { for (int j = 0; j < NumCols; j++) { double CellX = xMin + (j * CellSizeX) + (CellSizeX / 2); double CellY = yMax - ((i * CellSizeY) + (CellSizeY / 2)); // Se calcula la distancia entre celda y punto como número de pasos, para evitar valores muy grandes double distancia = System.Math.Sqrt(System.Math.Pow((dXPunto - CellX), 2) / (CellSizeX) + System.Math.Pow((dYPunto - CellY), 2) / (CellSizeY)); distancia = Math.Max(distancia, 0.0000001d); // Se calculan coeficientes, multiplicados por una costante, para evitar valores muy pequeños coeficients[i, j] = (1 / (System.Math.Pow(distancia, IdwExponent))) * (10 ^ 3); } } lock (locker) weights.Add(p, coeficients); }); logger.Trace($"Pesos computados."); //--------------------------------------------- // Compute elevations for each raster cell from DEM // AKIIII => read with gdal, retornar double.NAN en caso de nulo //--------------------------------------------- double GetElevation(double x, double y) { return(200d); }; //--------------------------------------------- // Compute raster values //--------------------------------------------- var ResultData = new float[NumRows, NumCols]; for (int i = 0; i < NumRows; i++) { for (int j = 0; j < NumCols; j++) { ResultData[i, j] = float.NaN; } } double CellValue; double WeightsSum;// Acumula la suma de los coeficientes válidos para luego dividir por ella //------------------------------------------------------------ // Iterar por todas las celdas del mallado a crear //------------------------------------------------------------ for (int i = 0; i < NumRows; i++) { logger.Trace($"Tratando fila {i} de {NumRows}."); for (int j = 0; j < NumCols; j++) { // Inicializar CellValue = 0d; WeightsSum = 0d; //------------------------------------------------------------ // Calcular el valor para la celda i,j //------------------------------------------------------------ // Obtner el sumatorio de los C1V1 + C2V2 + ... + CnVn foreach (var p in Points) { double dValAux = p.GetM(0); double Elevation = p.GetZ(0); if (!double.IsNaN(dValAux)) { //------------------------------------------------------------------------- // Aplicamos corrección de valor por cota: // Búsqueda de la cota de la celda //------------------------------------------------------------------------- double dCeldaX = xMin + (i * CellSizeX) + (CellSizeX / 2d); double dCeldaY = yMax - ((j * CellSizeY) + (CellSizeY / 2d)); // Get current cell elevation double CellElevation = GetElevation(dCeldaX, dCeldaY); //------------------------------------------------------------------------------------------ // No se aplica el gradiente termométrico a las celdas sobre las que no tenemos cota //------------------------------------------------------------------------------------------ if (!double.IsNaN(CellElevation)) { //--------------------------------------------- // Cálculo del valor de temperatura modificado //--------------------------------------------- dValAux += CorrectionGradient * (CellElevation - Elevation) / 100; } double weight = weights[p][i, j]; CellValue += weight * dValAux; WeightsSum += weight; } } // Obtener el valor dividiendo por SUM(C1 ... Cn) if (WeightsSum != 0) { ResultData[i, j] = (float)(CellValue / WeightsSum); } } } // Create results raster logger.Trace($"Creando gtif..."); var datos = new float[NumRows * NumCols]; var cont = 0; for (int i = NumRows - 1; i >= 0; i--) { for (int j = 0; j < NumCols; j++) { datos[cont] = ResultData[i, j]; cont++; } } // Create output GTiff if (File.Exists(OutputGTiffFile)) { File.Delete(OutputGTiffFile); } string EsriWkt = GdalUtils.EPSG2WKT(EPSG); var GeoTrans = new[] { xMin, CellSize, 0, yMin, 0, CellSize }; GdalUtils.CreateRaster("GTiff", OutputGTiffFile, NumRows, NumCols, xMin, yMin, CellSize, EsriWkt, GeoTrans, new List <float[]>() { datos }, null, null); logger.Trace($"Creado {OutputGTiffFile}"); }
public static void Info(string FileName, bool ShowBands) { try { /* -------------------------------------------------------------------- */ /* Open dataset. */ /* -------------------------------------------------------------------- */ Dataset ds = Gdal.Open(FileName, Access.GA_ReadOnly); if (ds == null) { Console.WriteLine("Can't open " + FileName); System.Environment.Exit(-1); } Console.WriteLine("Raster dataset parameters:"); Console.WriteLine(" Projection: " + ds.GetProjectionRef()); Console.WriteLine(" RasterCount: " + ds.RasterCount); Console.WriteLine(" RasterSize (" + ds.RasterXSize + "," + ds.RasterYSize + ")"); /* -------------------------------------------------------------------- */ /* Get driver */ /* -------------------------------------------------------------------- */ Driver drv = ds.GetDriver(); if (drv == null) { Console.WriteLine("Can't get driver."); System.Environment.Exit(-1); } Console.WriteLine("Using driver " + drv.LongName); /* -------------------------------------------------------------------- */ /* Get metadata */ /* -------------------------------------------------------------------- */ string[] metadata = ds.GetMetadata(""); if (metadata.Length > 0) { Console.WriteLine(" Metadata:"); for (int iMeta = 0; iMeta < metadata.Length; iMeta++) { Console.WriteLine(" " + iMeta + ": " + metadata[iMeta]); } Console.WriteLine(""); } /* -------------------------------------------------------------------- */ /* Report "IMAGE_STRUCTURE" metadata. */ /* -------------------------------------------------------------------- */ metadata = ds.GetMetadata("IMAGE_STRUCTURE"); if (metadata.Length > 0) { Console.WriteLine(" Image Structure Metadata:"); for (int iMeta = 0; iMeta < metadata.Length; iMeta++) { Console.WriteLine(" " + iMeta + ": " + metadata[iMeta]); } Console.WriteLine(""); } /* -------------------------------------------------------------------- */ /* Report subdatasets. */ /* -------------------------------------------------------------------- */ metadata = ds.GetMetadata("SUBDATASETS"); if (metadata.Length > 0) { Console.WriteLine(" Subdatasets:"); for (int iMeta = 0; iMeta < metadata.Length; iMeta++) { Console.WriteLine(" " + iMeta + ": " + metadata[iMeta]); } Console.WriteLine(""); } /* -------------------------------------------------------------------- */ /* Report geolocation. */ /* -------------------------------------------------------------------- */ metadata = ds.GetMetadata("GEOLOCATION"); if (metadata.Length > 0) { Console.WriteLine(" Geolocation:"); for (int iMeta = 0; iMeta < metadata.Length; iMeta++) { Console.WriteLine(" " + iMeta + ": " + metadata[iMeta]); } Console.WriteLine(""); } string GetPosition(Dataset ds, double column, double row) { var d = GdalUtils.GDALInfoGetPosition(ds, column, row); return($"{d[0].ToString()} , {d[1].ToString()} "); } /* -------------------------------------------------------------------- */ /* Report corners. */ /* -------------------------------------------------------------------- */ Console.WriteLine("Corner Coordinates:"); Console.WriteLine(" Upper Left (" + GetPosition(ds, 0.0, 0.0) + ")"); Console.WriteLine(" Lower Left (" + GetPosition(ds, 0.0, ds.RasterYSize) + ")"); Console.WriteLine(" Upper Right (" + GetPosition(ds, ds.RasterXSize, 0.0) + ")"); Console.WriteLine(" Lower Right (" + GetPosition(ds, ds.RasterXSize, ds.RasterYSize) + ")"); Console.WriteLine(" Center (" + GetPosition(ds, ds.RasterXSize / 2, ds.RasterYSize / 2) + ")"); Console.WriteLine(""); /* -------------------------------------------------------------------- */ /* Report projection. */ /* -------------------------------------------------------------------- */ string projection = ds.GetProjectionRef(); if (projection != null) { SpatialReference srs = new SpatialReference(null); if (srs.ImportFromWkt(ref projection) == 0) { string wkt; srs.ExportToPrettyWkt(out wkt, 0); Console.WriteLine("Coordinate System is:"); Console.WriteLine(wkt); } else { Console.WriteLine("Coordinate System is:"); Console.WriteLine(projection); } } /* -------------------------------------------------------------------- */ /* Report GCPs. */ /* -------------------------------------------------------------------- */ if (ds.GetGCPCount( ) > 0) { Console.WriteLine("GCP Projection: ", ds.GetGCPProjection()); GCP[] GCPs = ds.GetGCPs(); for (int i = 0; i < ds.GetGCPCount(); i++) { Console.WriteLine("GCP[" + i + "]: Id=" + GCPs[i].Id + ", Info=" + GCPs[i].Info); Console.WriteLine(" (" + GCPs[i].GCPPixel + "," + GCPs[i].GCPLine + ") -> (" + GCPs[i].GCPX + "," + GCPs[i].GCPY + "," + GCPs[i].GCPZ + ")"); Console.WriteLine(""); } Console.WriteLine(""); double[] transform = new double[6]; Gdal.GCPsToGeoTransform(GCPs, transform, 0); Console.WriteLine("GCP Equivalent geotransformation parameters: ", ds.GetGCPProjection()); for (int i = 0; i < 6; i++) { Console.WriteLine("t[" + i + "] = " + transform[i].ToString()); } Console.WriteLine(""); } /* -------------------------------------------------------------------- */ /* Get raster band */ /* -------------------------------------------------------------------- */ for (int iBand = 1; iBand <= ds.RasterCount && ShowBands; iBand++) { Band band = ds.GetRasterBand(iBand); Console.WriteLine("Band " + iBand + " :"); Console.WriteLine(" DataType: " + Gdal.GetDataTypeName(band.DataType)); Console.WriteLine(" ColorInterpretation: " + Gdal.GetColorInterpretationName(band.GetRasterColorInterpretation())); ColorTable ct = band.GetRasterColorTable(); if (ct != null) { Console.WriteLine(" Band has a color table with " + ct.GetCount() + " entries."); } Console.WriteLine(" Description: " + band.GetDescription()); Console.WriteLine(" Size (" + band.XSize + "," + band.YSize + ")"); int BlockXSize, BlockYSize; band.GetBlockSize(out BlockXSize, out BlockYSize); Console.WriteLine(" BlockSize (" + BlockXSize + "," + BlockYSize + ")"); double val; int hasval; band.GetMinimum(out val, out hasval); if (hasval != 0) { Console.WriteLine(" Minimum: " + val.ToString()); } band.GetMaximum(out val, out hasval); if (hasval != 0) { Console.WriteLine(" Maximum: " + val.ToString()); } band.GetNoDataValue(out val, out hasval); if (hasval != 0) { Console.WriteLine(" NoDataValue: " + val.ToString()); } band.GetOffset(out val, out hasval); if (hasval != 0) { Console.WriteLine(" Offset: " + val.ToString()); } band.GetScale(out val, out hasval); if (hasval != 0) { Console.WriteLine(" Scale: " + val.ToString()); } for (int iOver = 0; iOver < band.GetOverviewCount(); iOver++) { Band over = band.GetOverview(iOver); Console.WriteLine(" OverView " + iOver + " :"); Console.WriteLine(" DataType: " + over.DataType); Console.WriteLine(" Size (" + over.XSize + "," + over.YSize + ")"); Console.WriteLine(" PaletteInterp: " + over.GetRasterColorInterpretation().ToString()); } } } catch (Exception e) { Console.WriteLine("Application error: " + e.Message); } }