diff --git a/MES_Wind.suo b/MES_Wind.suo index 4030410b4a4da32b5b73e3a69587c8d63aed5a9b..963ad17b0195b271a5473314469fe0a4f425d36b 100644 Binary files a/MES_Wind.suo and b/MES_Wind.suo differ diff --git a/MES_Wind/PRM_wind.cs b/MES_Wind/PRM_wind.cs index aafa4647187219c174b83b12820b26aa992667a8..2a56229dfdaee55a28ca295f6a4f00516bf3732b 100644 --- a/MES_Wind/PRM_wind.cs +++ b/MES_Wind/PRM_wind.cs @@ -5,6 +5,17 @@ using System.Text; namespace MES_Wind { + public class PRM_index + { + public int Row; + public int Col; + public PRM_index(int Row, int Col) + { + this.Row = Row; + this.Col = Col; + } + public PRM_index() : this(0, 0) { } + } public class PRM_coordinate { public double X; @@ -77,22 +88,32 @@ namespace MES_Wind } + + enum PRMFunctionType + { + PRMFunctionVelocityX = 0, + PRMFunctionVelocityY = 1, + PRMFunctionClimate5 = 2, + PRMFunctionClimate10 = 3, + PRMFunctionClimate15 = 4 + } class PRM_wind { //prognistic raster info List<List<PRM_raster_cell_prognostic>> prognostic_cells; PRM_cell_size prognostic_cellsize; + double[] prognostic_AffineCoefficients; //climate raster info List<List<PRM_raster_cell_climate>> climate_cells; PRM_cell_size climate_cellsize; + double[] climate_AffineCoefficients; //lines collection List<PRM_Line> powerlines; - #region "control parameters" + // must be implemented. AffineCoefficients like in DotSpatial using for projections public double dist_threshold; - #endregion List<PRM_Line> brokenPowerLinesAfterCheck() @@ -160,9 +181,12 @@ namespace MES_Wind } else { - double uwind = 0; // interpol(coords, Uwind_raster); - double vwind = 0; // interpol(coords, Vwind_raster); - double climwind = 0; // interpol(coords, clim_layer); + // TODO Implement climate15 + PRMFunctionType climateType = useClimate10 ? PRMFunctionType.PRMFunctionClimate10 : PRMFunctionType.PRMFunctionClimate5; + PRM_coordinate coords = new PRM_coordinate((coord1.X + coord2.X) / 2, (coord1.Y + coord2.Y) / 2); + double uwind = interpol(coords, PRMFunctionType.PRMFunctionVelocityX); + double vwind = interpol(coords, PRMFunctionType.PRMFunctionVelocityY); + double climwind = interpol(coords, climateType); double umod = Math.Sqrt(uwind * uwind + vwind * vwind); ; double angleline = Math.Atan2((coord2.Y - coord1.Y), (coord2.X - coord1.X)); double anglewind = Math.Atan2(vwind, uwind) - angleline; @@ -192,6 +216,207 @@ namespace MES_Wind return false; } + double[] affineCoefficients(PRMFunctionType functionType) + { + switch (functionType) + { + case PRMFunctionType.PRMFunctionVelocityX: + case PRMFunctionType.PRMFunctionVelocityY: + { + return prognostic_AffineCoefficients; + } + case PRMFunctionType.PRMFunctionClimate5: + case PRMFunctionType.PRMFunctionClimate10: + case PRMFunctionType.PRMFunctionClimate15: + { + return climate_AffineCoefficients; + } + default: + break; + } + return null; + } + + // Taken from DotSpatial https://github.com/ViceIce/DotSpatial/blob/22c156c7646b1595d88d2523c066a9c6ab4d3a53/DotSpatial.Data/RasterBoundsExt.cs + // RasterBoundsExt.cs. Define AffineCoefficients like this. + PRM_index projectionToCell(PRM_coordinate coordinate, PRMFunctionType functionType) + { + double[] c = affineCoefficients(functionType); + double rw, cl; + if (c[2] == 0 && c[4] == 0) + { + // If we don't have skew terms, then the x and y terms are independent. + // also both of the other tests will have divide by zero errors and fail. + cl = (coordinate.X - c[0]) / c[1]; + rw = (coordinate.Y - c[3]) / c[5]; + } + else if (c[2] != 0) + { + // this equation will have divide by zero if c[2] is zero, but works if c[4] is zero + double div = (c[5] * c[1]) / c[2] - c[4]; + cl = (c[3] + (c[5] * coordinate.X) / c[2] - (c[5] * c[0]) / c[2] - coordinate.Y) / div; + rw = (coordinate.X - c[0] - c[1] * cl) / c[2]; + } + else + { + double div = (c[4] * c[2] / c[1] - c[5]); + rw = (c[3] + c[4] * coordinate.X / c[1] - c[4] * c[0] / c[1] - coordinate.Y) / div; + cl = (coordinate.X - c[2] * rw - c[0]) / c[1]; + } + int iRow = (int)Math.Round(rw); + int iCol = (int)Math.Round(cl); + + if (iRow < 0 || iCol < 0 || iRow >= countInList(functionType, true) || iCol >= countInList(functionType, false)) + { + return new PRM_index(); + } + + return new PRM_index(iRow, iCol); + } + PRM_coordinate cellToProjection(PRM_index index, PRMFunctionType functionType) + { + switch (functionType) { + case PRMFunctionType.PRMFunctionVelocityX: + case PRMFunctionType.PRMFunctionVelocityY: + { + return prognostic_cells[index.Row][index.Col].coords; + } + case PRMFunctionType.PRMFunctionClimate5: + case PRMFunctionType.PRMFunctionClimate10: + case PRMFunctionType.PRMFunctionClimate15: + { + return climate_cells[index.Row][index.Col].coords; + } + default: + break; + } + return null; + } + + int countInList(PRMFunctionType functionType, bool forRows) + { + switch (functionType) + { + case PRMFunctionType.PRMFunctionVelocityX: + case PRMFunctionType.PRMFunctionVelocityY: + { + return forRows ? prognostic_cells.Count : prognostic_cells[0].Count; + } + case PRMFunctionType.PRMFunctionClimate5: + case PRMFunctionType.PRMFunctionClimate10: + case PRMFunctionType.PRMFunctionClimate15: + { + return forRows ? climate_cells.Count : climate_cells[0].Count; + } + default: + break; + } + return 0; + } + + double valueForFunction(PRMFunctionType functionType, PRM_index index) + { + switch (functionType) + { + case PRMFunctionType.PRMFunctionVelocityX: + { + return prognostic_cells[index.Row][index.Col].velocityX; + } + case PRMFunctionType.PRMFunctionVelocityY: + { + return prognostic_cells[index.Row][index.Col].velocityY; + } + case PRMFunctionType.PRMFunctionClimate5: + { + return climate_cells[index.Row][index.Col].wind5; + } + case PRMFunctionType.PRMFunctionClimate10: + { + return climate_cells[index.Row][index.Col].wind10; + } + case PRMFunctionType.PRMFunctionClimate15: + { + return climate_cells[index.Row][index.Col].wind15; + } + default: + break; + } + return 0; + } + PRM_cell_size cellSizeForFunction(PRMFunctionType functionType) + { + switch (functionType) + { + case PRMFunctionType.PRMFunctionVelocityX: + case PRMFunctionType.PRMFunctionVelocityY: + { + return prognostic_cellsize; + } + case PRMFunctionType.PRMFunctionClimate5: + case PRMFunctionType.PRMFunctionClimate10: + case PRMFunctionType.PRMFunctionClimate15: + { + return climate_cellsize; + } + default: + break; + } + throw new Exception("There is no cell size"); + } + + double interpol(PRM_coordinate coords, PRMFunctionType functionType) + { + // select directions for projections + const bool normalX = true;// true - East, false West + const bool normalY = false;// true - North, false South + PRM_index rc = projectionToCell(coords, functionType); + PRM_coordinate center = cellToProjection(rc, functionType); + double xDiff = coords.X - center.X; + double yDiff = coords.Y - center.Y; + //calculate second index + int row2, col2; + if ((xDiff >= 0 && normalX) || (!normalX && xDiff < 0)) + { + row2 = rc.Row >= countInList(functionType, true) - 1 ? rc.Row - 1 : rc.Row + 1; + } + else + { + row2 = rc.Row > 0 ? rc.Row - 1 : rc.Row + 1; + } + if ((yDiff >= 0 && normalY) || (!normalY && yDiff < 0)) + { + col2 = rc.Col >= countInList(functionType, false) - 1 ? rc.Col - 1 : rc.Col + 1; + } + else + { + col2 = rc.Col > 0 ? rc.Col - 1 : rc.Col + 1; + } + // indexes and values at bounds + PRM_index rcBotLeft = new PRM_index(Math.Min(row2, rc.Row), Math.Min(col2, rc.Col)); + PRM_index rcBotRight = new PRM_index(Math.Max(row2, rc.Row), Math.Min(col2, rc.Col)); + PRM_index rcTopLeft = new PRM_index(Math.Min(row2, rc.Row), Math.Max(col2, rc.Col)); + PRM_index rcTopRight = new PRM_index(Math.Max(row2, rc.Row), Math.Max(col2, rc.Col)); + double valBotLeft = valueForFunction(functionType, rcBotLeft); + double valBotRight = valueForFunction(functionType, rcBotRight); + double valTopLeft = valueForFunction(functionType, rcTopLeft); + double valTopRight = valueForFunction(functionType, rcTopRight); + PRM_coordinate origin = cellToProjection(rcBotLeft, functionType); + //PRM_coordinate last = cellToProjection(rcTopRight, functionType);//test only + // sizes for cell + double hx = cellSizeForFunction(functionType).width; + double hy = cellSizeForFunction(functionType).height; + // coefficients + double px = (coords.X - origin.X) / hx; + double py = (coords.Y - origin.Y) / hy; + // inverse directions + px *= normalX ? 1 : -1; + py *= normalY ? 1 : -1; + // interpolation + double top = (1 - px) * valTopLeft + px * valTopRight; + double bot = (1 - px) * valBotLeft + px * valBotRight; + double rval = (1 - py) * bot + py * top; + return rval; + } } } diff --git a/MES_Wind/bin/Debug/MES_Wind.exe b/MES_Wind/bin/Debug/MES_Wind.exe index d535522614768b7cea2f49811fa90d36672e073b..f031dcc5bcc2790f370967249b673245d0c951f6 100644 Binary files a/MES_Wind/bin/Debug/MES_Wind.exe and b/MES_Wind/bin/Debug/MES_Wind.exe differ diff --git a/MES_Wind/bin/Debug/MES_Wind.pdb b/MES_Wind/bin/Debug/MES_Wind.pdb index e5d3a29a70385188af2c839cba1a82e69703c3a8..e80f5a87b8c908184c02966da01ce3ee81416ea1 100644 Binary files a/MES_Wind/bin/Debug/MES_Wind.pdb and b/MES_Wind/bin/Debug/MES_Wind.pdb differ diff --git a/MES_Wind/bin/Debug/MES_Wind.vshost.exe b/MES_Wind/bin/Debug/MES_Wind.vshost.exe index 8f90da475a8319aa76856e089ccc9e517eeb134a..6b241bcd65a4769673693b96129ef13ae25e17ec 100644 Binary files a/MES_Wind/bin/Debug/MES_Wind.vshost.exe and b/MES_Wind/bin/Debug/MES_Wind.vshost.exe differ diff --git a/MES_Wind/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/MES_Wind/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache index 15af49b1dfb60189d9d6571b791bd6be84bdd821..7cf58ab2b496264ee3362bef88ddbb563a0ac98a 100644 Binary files a/MES_Wind/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache and b/MES_Wind/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ diff --git a/MES_Wind/obj/Debug/MES_Wind.csproj.GenerateResource.Cache b/MES_Wind/obj/Debug/MES_Wind.csproj.GenerateResource.Cache index 841ec97ca6ee6741d8eb5e88f7fe856fb28143a5..3f373bbace73c90f3ad31154deb02bff74781c87 100644 Binary files a/MES_Wind/obj/Debug/MES_Wind.csproj.GenerateResource.Cache and b/MES_Wind/obj/Debug/MES_Wind.csproj.GenerateResource.Cache differ diff --git a/MES_Wind/obj/Debug/MES_Wind.csprojResolveAssemblyReference.cache b/MES_Wind/obj/Debug/MES_Wind.csprojResolveAssemblyReference.cache index 1d0fb07dceec79f9379efd70c284457e0cda4277..20f5483f93cd240d8699dca1731f4e7325d8ad1b 100644 Binary files a/MES_Wind/obj/Debug/MES_Wind.csprojResolveAssemblyReference.cache and b/MES_Wind/obj/Debug/MES_Wind.csprojResolveAssemblyReference.cache differ diff --git a/MES_Wind/obj/Debug/MES_Wind.exe b/MES_Wind/obj/Debug/MES_Wind.exe index d535522614768b7cea2f49811fa90d36672e073b..f031dcc5bcc2790f370967249b673245d0c951f6 100644 Binary files a/MES_Wind/obj/Debug/MES_Wind.exe and b/MES_Wind/obj/Debug/MES_Wind.exe differ diff --git a/MES_Wind/obj/Debug/MES_Wind.pdb b/MES_Wind/obj/Debug/MES_Wind.pdb index e5d3a29a70385188af2c839cba1a82e69703c3a8..e80f5a87b8c908184c02966da01ce3ee81416ea1 100644 Binary files a/MES_Wind/obj/Debug/MES_Wind.pdb and b/MES_Wind/obj/Debug/MES_Wind.pdb differ