├── .gitignore ├── .vs └── wContour │ └── v14 │ └── .suo ├── Contour.cs ├── Global ├── Border.cs ├── BorderLine.cs ├── BorderPoint.cs ├── EndPoint.cs ├── Extent.cs ├── IJPoint.cs ├── Line.cs ├── PointD.cs ├── PolyLine.cs └── Polygon.cs ├── Interpolate.cs ├── LICENSE.md ├── Legend.cs ├── PointF.cs ├── Properties └── AssemblyInfo.cs ├── README.md ├── bin └── Debug │ └── wContour.dll ├── wContour.csproj ├── wContour.sln └── wContour.xml /.gitignore: -------------------------------------------------------------------------------- 1 | bin/** 2 | .vs/** 3 | obj/** 4 | *.user 5 | *.suo -------------------------------------------------------------------------------- /.vs/wContour/v14/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meteoinfo/wContour_CSharp/dfd67ddb42f0284c318c634e0c96571018f5b7b0/.vs/wContour/v14/.suo -------------------------------------------------------------------------------- /Global/Border.cs: -------------------------------------------------------------------------------- 1 | //****************************** 2 | // Copyright 2012 Yaqiang Wang, 3 | // yaqiang.wang@gmail.com 4 | //****************************** 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Collections; 9 | using System.Text; 10 | 11 | namespace wContour 12 | { 13 | /// 14 | /// Border 15 | /// 16 | public class Border 17 | { 18 | #region Variables 19 | /// 20 | /// Line list 21 | /// 22 | public List LineList; 23 | 24 | #endregion 25 | 26 | #region Constructor 27 | /// 28 | /// Constructor 29 | /// 30 | public Border() 31 | { 32 | LineList = new List(); 33 | } 34 | 35 | #endregion 36 | 37 | #region Properties 38 | /// 39 | /// Get line number 40 | /// 41 | public int LineNum 42 | { 43 | get { return LineList.Count; } 44 | } 45 | 46 | #endregion 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Global/BorderLine.cs: -------------------------------------------------------------------------------- 1 | //****************************** 2 | // Copyright 2012 Yaqiang Wang, 3 | // yaqiang.wang@gmail.com 4 | //****************************** 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Collections; 9 | using System.Text; 10 | 11 | namespace wContour 12 | { 13 | /// 14 | /// Border line 15 | /// 16 | public class BorderLine 17 | { 18 | /// 19 | /// Area 20 | /// 21 | public double area; 22 | /// 23 | /// Extent 24 | /// 25 | public Extent extent = new Extent(); 26 | /// 27 | /// Is outline 28 | /// 29 | public bool isOutLine; 30 | /// 31 | /// Is clockwise 32 | /// 33 | public bool isClockwise; 34 | /// 35 | /// Point list 36 | /// 37 | public List pointList = new List(); 38 | /// 39 | /// IJPoint list 40 | /// 41 | public List ijPointList = new List(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Global/BorderPoint.cs: -------------------------------------------------------------------------------- 1 | //****************************** 2 | // Copyright 2012 Yaqiang Wang, 3 | // yaqiang.wang@gmail.com 4 | //****************************** 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace wContour 11 | { 12 | /// 13 | /// Border point 14 | /// 15 | public class BorderPoint 16 | { 17 | /// 18 | /// Identifer 19 | /// 20 | public int Id; 21 | /// 22 | /// Border index 23 | /// 24 | public int BorderIdx; 25 | /// 26 | /// Border inner index 27 | /// 28 | public int BInnerIdx; 29 | /// 30 | /// Point 31 | /// 32 | public PointD Point = new PointD(); 33 | /// 34 | /// Value 35 | /// 36 | public double Value; 37 | 38 | #region Method 39 | /// 40 | /// Clone 41 | /// 42 | /// cloned borderpoint 43 | public object Clone() 44 | { 45 | BorderPoint aBP = new BorderPoint(); 46 | aBP.Id = Id; 47 | aBP.BorderIdx = BorderIdx; 48 | aBP.BInnerIdx = BInnerIdx; 49 | aBP.Point = Point; 50 | aBP.Value = Value; 51 | 52 | return aBP; 53 | } 54 | 55 | #endregion 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Global/EndPoint.cs: -------------------------------------------------------------------------------- 1 | //****************************** 2 | // Copyright 2012 Yaqiang Wang, 3 | // yaqiang.wang@gmail.com 4 | //****************************** 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace wContour 11 | { 12 | /// 13 | /// End point 14 | /// 15 | public class EndPoint 16 | { 17 | /// 18 | /// Start point 19 | /// 20 | public PointD sPoint = new PointD(); 21 | /// 22 | /// Point 23 | /// 24 | public PointD Point = new PointD(); 25 | /// 26 | /// Index 27 | /// 28 | public int Index; 29 | /// 30 | /// Border Index 31 | /// 32 | public int BorderIdx; 33 | 34 | /// 35 | /// Constructor 36 | /// 37 | public EndPoint() 38 | { 39 | 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Global/Extent.cs: -------------------------------------------------------------------------------- 1 | //****************************** 2 | // Copyright 2012 Yaqiang Wang, 3 | // yaqiang.wang@gmail.com 4 | //****************************** 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace wContour 11 | { 12 | /// 13 | /// Extent 14 | /// 15 | public class Extent 16 | { 17 | /// 18 | /// x minimum 19 | /// 20 | public double xMin; 21 | /// 22 | /// y minimum 23 | /// 24 | public double yMin; 25 | /// 26 | /// x maximum 27 | /// 28 | public double xMax; 29 | /// 30 | /// y maximum 31 | /// 32 | public double yMax; 33 | 34 | #region Constructor 35 | /// 36 | /// Constructor 37 | /// 38 | public Extent() 39 | { 40 | 41 | } 42 | 43 | /// 44 | /// Constructor 45 | /// 46 | /// minimum x 47 | /// maximum x 48 | /// minimum y 49 | /// maximum y 50 | public Extent(double minX, double maxX, double minY, double maxY) 51 | { 52 | xMin = minX; 53 | xMax = maxX; 54 | yMin = minY; 55 | yMax = maxY; 56 | } 57 | 58 | #endregion 59 | 60 | /// 61 | /// Judge if this extent include another extent 62 | /// 63 | /// extent 64 | /// is included 65 | public bool Include(Extent bExtent) 66 | { 67 | if (xMin <= bExtent.xMin && xMax >= bExtent.xMax && yMin <= bExtent.yMin && yMax >= bExtent.yMax) 68 | return true; 69 | else 70 | return false; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Global/IJPoint.cs: -------------------------------------------------------------------------------- 1 | //****************************** 2 | // Copyright 2012 Yaqiang Wang, 3 | // yaqiang.wang@gmail.com 4 | //****************************** 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace wContour 11 | { 12 | /// 13 | /// Point integer, to indicate the position in grid data 14 | /// 15 | public class IJPoint 16 | { 17 | /// 18 | /// I 19 | /// 20 | public int I; 21 | /// 22 | /// J 23 | /// 24 | public int J; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Global/Line.cs: -------------------------------------------------------------------------------- 1 | //****************************** 2 | // Copyright 2012 Yaqiang Wang, 3 | // yaqiang.wang@gmail.com 4 | //****************************** 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace wContour 11 | { 12 | /// 13 | /// Line 14 | /// 15 | public class Line 16 | { 17 | /// 18 | /// Point 1 19 | /// 20 | public PointD P1; 21 | /// 22 | /// Point 2 23 | /// 24 | public PointD P2; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Global/PointD.cs: -------------------------------------------------------------------------------- 1 | //****************************** 2 | // Copyright 2012 Yaqiang Wang, 3 | // yaqiang.wang@gmail.com 4 | //****************************** 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace wContour 11 | { 12 | /// 13 | /// Point - double x/y 14 | /// 15 | public class PointD 16 | { 17 | /// 18 | /// x 19 | /// 20 | public double X; 21 | /// 22 | /// y 23 | /// 24 | public double Y; 25 | 26 | #region Constructor 27 | /// 28 | /// Constructor 29 | /// 30 | public PointD() 31 | { 32 | 33 | } 34 | 35 | /// 36 | /// Constructor 37 | /// 38 | /// x 39 | /// y 40 | public PointD(double x, double y) 41 | { 42 | X = x; 43 | Y = y; 44 | } 45 | 46 | #endregion 47 | 48 | #region Methods 49 | /// 50 | /// Clone 51 | /// 52 | /// Cloned object 53 | public object Clone() 54 | { 55 | return new PointD(X, Y); 56 | } 57 | 58 | #endregion 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Global/PolyLine.cs: -------------------------------------------------------------------------------- 1 | //****************************** 2 | // Copyright 2012 Yaqiang Wang, 3 | // yaqiang.wang@gmail.com 4 | //****************************** 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Collections; 9 | using System.Text; 10 | 11 | namespace wContour 12 | { 13 | /// 14 | /// Polyline 15 | /// 16 | public class PolyLine 17 | { 18 | /// 19 | /// Value 20 | /// 21 | public double Value; 22 | /// 23 | /// Type 24 | /// 25 | public string Type; 26 | /// 27 | /// Border index 28 | /// 29 | public int BorderIdx; 30 | /// 31 | /// Point list 32 | /// 33 | public List PointList; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Global/Polygon.cs: -------------------------------------------------------------------------------- 1 | //****************************** 2 | // Copyright 2012 Yaqiang Wang, 3 | // yaqiang.wang@gmail.com 4 | //****************************** 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace wContour 11 | { 12 | /// 13 | /// Polygon 14 | /// 15 | public class Polygon 16 | { 17 | #region Variables 18 | /// 19 | /// If is border contour polygon 20 | /// 21 | public bool IsBorder; 22 | /// 23 | /// If there is only inner border 24 | /// 25 | public bool IsInnerBorder = false; 26 | /// 27 | /// Start value 28 | /// 29 | public double LowValue; 30 | /// 31 | /// End value 32 | /// 33 | public double HighValue; 34 | /// 35 | /// If clockwise 36 | /// 37 | public bool IsClockWise; 38 | /// 39 | /// Start point index 40 | /// 41 | public int StartPointIdx; 42 | /// 43 | /// If high center 44 | /// 45 | public bool IsHighCenter; 46 | /// 47 | /// Extent - bordering rectangle 48 | /// 49 | public Extent Extent = new Extent(); 50 | /// 51 | /// Area 52 | /// 53 | public double Area; 54 | /// 55 | /// Outline 56 | /// 57 | public PolyLine OutLine = new PolyLine(); 58 | /// 59 | /// Hole lines 60 | /// 61 | public List HoleLines = new List(); 62 | /// 63 | /// Hole index 64 | /// 65 | public int HoleIndex; 66 | 67 | #endregion 68 | 69 | 70 | #region Methods 71 | /// 72 | /// Clone 73 | /// 74 | /// Cloned polygon 75 | public object Clone() 76 | { 77 | Polygon aPolygon = new Polygon(); 78 | aPolygon.IsBorder = IsBorder; 79 | aPolygon.LowValue = LowValue; 80 | aPolygon.HighValue = HighValue; 81 | aPolygon.IsClockWise = IsClockWise; 82 | aPolygon.StartPointIdx = StartPointIdx; 83 | aPolygon.IsHighCenter = IsHighCenter; 84 | aPolygon.Extent = Extent; 85 | aPolygon.Area = Area; 86 | aPolygon.OutLine = OutLine; 87 | aPolygon.HoleLines = new List(HoleLines); 88 | aPolygon.HoleIndex = HoleIndex; 89 | 90 | return aPolygon; 91 | } 92 | 93 | /// 94 | /// Get if has holes 95 | /// 96 | public bool HasHoles 97 | { 98 | get { return (HoleLines.Count > 0); } 99 | } 100 | 101 | /// 102 | /// Add a hole by a polygon 103 | /// 104 | /// polygon 105 | public void AddHole(Polygon aPolygon) 106 | { 107 | HoleLines.Add(aPolygon.OutLine); 108 | } 109 | 110 | /// 111 | /// Add a hole by point list 112 | /// 113 | /// point list 114 | public void AddHole(List pList) 115 | { 116 | if (Contour.IsClockwise(pList)) 117 | pList.Reverse(); 118 | 119 | PolyLine aLine = new PolyLine(); 120 | aLine.PointList = pList; 121 | HoleLines.Add(aLine); 122 | } 123 | 124 | #endregion 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Interpolate.cs: -------------------------------------------------------------------------------- 1 | //****************************** 2 | // Copyright 2012 Yaqiang Wang, 3 | // yaqiang.wang@gmail.com 4 | //****************************** 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace wContour 11 | { 12 | /// 13 | /// Interpolate 14 | /// 15 | public static class Interpolate 16 | { 17 | private const double pi = 14159265358; 18 | private const double twopi = 2.0 * 3.14159265358; 19 | 20 | #region IDW 21 | /// 22 | /// Create grid x/y coordinate arrays with x/y delt 23 | /// 24 | /// X of left-bottom 25 | /// Y of left-bottom 26 | /// X of right-top 27 | /// Y of right-top 28 | /// X delt 29 | /// Y delt 30 | /// Output X array 31 | /// Output Y array 32 | public static void CreateGridXY_Delt(double Xlb, double Ylb, double Xrt, double Yrt, 33 | double XDelt, double YDelt, ref double[] X, ref double[] Y) 34 | { 35 | int i, Xnum, Ynum; 36 | Xnum = (int)((Xrt - Xlb) / XDelt + 1); 37 | Ynum = (int)((Yrt - Ylb) / YDelt + 1); 38 | X = new double[Xnum]; 39 | Y = new double[Ynum]; 40 | for (i = 0; i < Xnum; i++) 41 | { 42 | X[i] = Xlb + i * XDelt; 43 | } 44 | for (i = 0; i < Ynum; i++) 45 | { 46 | Y[i] = Ylb + i * YDelt; 47 | } 48 | } 49 | 50 | /// 51 | /// Create grid x/y coordinate arrays with x/y number 52 | /// 53 | /// X of left-bottom 54 | /// Y of left-bottom 55 | /// X of right-top 56 | /// Y of right-top 57 | /// X number 58 | /// Y number 59 | /// Output X array 60 | /// Output Y array 61 | public static void CreateGridXY_Num(double Xlb, double Ylb, double Xrt, double Yrt, 62 | int Xnum, int Ynum, ref double[] X, ref double[] Y) 63 | { 64 | int i; 65 | double XDelt, YDelt; 66 | X = new double[Xnum]; 67 | Y = new double[Ynum]; 68 | XDelt = (Xrt - Xlb) / Xnum; 69 | YDelt = (Yrt - Ylb) / Ynum; 70 | for (i = 0; i < Xnum; i++) 71 | { 72 | X[i] = Xlb + i * XDelt; 73 | } 74 | for (i = 0; i < Ynum; i++) 75 | { 76 | Y[i] = Ylb + i * YDelt; 77 | } 78 | } 79 | 80 | /// 81 | /// Interpolation with IDW neighbor method 82 | /// 83 | /// Discrete data array 84 | /// Grid X array 85 | /// Grid Y array 86 | /// Number of nearest neighbors 87 | /// Interpolated grid Data 88 | public static double[,] Interpolation_IDW_Neighbor(double[,] SCoords, double[] X, double[] Y, 89 | int NumberOfNearestNeighbors) 90 | { 91 | int rowNum, colNum, pNum; 92 | colNum = X.Length; 93 | rowNum = Y.Length; 94 | pNum = SCoords.GetLength(1); 95 | double[,] GCoords = new double[rowNum, colNum]; 96 | int i, j, p, l, aP; 97 | double w, SV, SW, aMin; 98 | int points; 99 | points = NumberOfNearestNeighbors; 100 | object[,] NW = new object[2, points]; 101 | 102 | //---- Do interpolation 103 | for (i = 0; i < rowNum; i++) 104 | { 105 | for (j = 0; j < colNum; j++) 106 | { 107 | GCoords[i, j] = -999.0; 108 | SV = 0; 109 | SW = 0; 110 | for (p = 0; p < points; p++) 111 | { 112 | if (Math.Pow(X[j] - SCoords[0, p], 2) + Math.Pow(Y[i] - SCoords[1, p], 2) == 0) 113 | { 114 | GCoords[i, j] = SCoords[2, p]; 115 | break; 116 | } 117 | else 118 | { 119 | w = 1 / (Math.Pow(X[j] - SCoords[0, p], 2) + Math.Pow(Y[i] - SCoords[1, p], 2)); 120 | NW[0, p] = w; 121 | NW[1, p] = p; 122 | } 123 | } 124 | if (GCoords[i, j] == -999.0) 125 | { 126 | for (p = points; p < pNum; p++) 127 | { 128 | if (Math.Pow(X[j] - SCoords[0, p], 2) + Math.Pow(Y[i] - SCoords[1, p], 2) == 0) 129 | { 130 | GCoords[i, j] = SCoords[2, p]; 131 | break; 132 | } 133 | else 134 | { 135 | w = 1 / (Math.Pow(X[j] - SCoords[0, p], 2) + Math.Pow(Y[i] - SCoords[1, p], 2)); 136 | aMin = (double)NW[0, 0]; 137 | aP = 0; 138 | for (l = 1; l < points; l++) 139 | { 140 | if ((double)NW[0, l] < aMin) 141 | { 142 | aMin = (double)NW[0, l]; 143 | aP = l; 144 | } 145 | } 146 | if (w > aMin) 147 | { 148 | NW[0, aP] = w; 149 | NW[1, aP] = p; 150 | } 151 | } 152 | } 153 | if (GCoords[i, j] == -999.0) 154 | { 155 | for (p = 0; p < points; p++) 156 | { 157 | SV += (double)NW[0, p] * SCoords[2, (int)NW[1, p]]; 158 | SW += (double)NW[0, p]; 159 | } 160 | GCoords[i, j] = SV / SW; 161 | } 162 | } 163 | } 164 | } 165 | 166 | //---- Smooth with 5 points 167 | double s = 0.5; 168 | for (i = 1; i < rowNum - 1; i++) 169 | { 170 | for (j = 1; j < colNum - 1; j++) 171 | { 172 | GCoords[i, j] = GCoords[i, j] + s / 4 * (GCoords[i + 1, j] + GCoords[i - 1, j] + 173 | GCoords[i, j + 1] + GCoords[i, j - 1] - 4 * GCoords[i, j]); 174 | } 175 | } 176 | 177 | return GCoords; 178 | } 179 | 180 | /// 181 | /// Interpolation with IDW neighbor method 182 | /// 183 | /// Discrete data array 184 | /// Grid X array 185 | /// Grid Y array 186 | /// Number of nearest neighbors 187 | /// Undefine data value 188 | /// Interpolated grid data 189 | public static double[,] Interpolation_IDW_Neighbor(double[,] SCoords, double[] X, double[] Y, 190 | int NumberOfNearestNeighbors, double unDefData) 191 | { 192 | int rowNum, colNum, pNum; 193 | colNum = X.Length; 194 | rowNum = Y.Length; 195 | pNum = SCoords.GetLength(1); 196 | double[,] GCoords = new double[rowNum, colNum]; 197 | int i, j, p, l, aP; 198 | double w, SV, SW, aMin; 199 | int points; 200 | points = NumberOfNearestNeighbors; 201 | double[] AllWeights = new double[pNum]; 202 | object[,] NW = new object[2, points]; 203 | int NWIdx; 204 | 205 | //---- Do interpolation with IDW method 206 | for (i = 0; i < rowNum; i++) 207 | { 208 | for (j = 0; j < colNum; j++) 209 | { 210 | GCoords[i, j] = unDefData; 211 | SV = 0; 212 | SW = 0; 213 | NWIdx = 0; 214 | for (p = 0; p < pNum; p++) 215 | { 216 | if (SCoords[2, p] == unDefData) 217 | { 218 | AllWeights[p] = -1; 219 | continue; 220 | } 221 | if (Math.Pow(X[j] - SCoords[0, p], 2) + Math.Pow(Y[i] - SCoords[1, p], 2) == 0) 222 | { 223 | GCoords[i, j] = SCoords[2, p]; 224 | break; 225 | } 226 | else 227 | { 228 | w = 1 / (Math.Pow(X[j] - SCoords[0, p], 2) + Math.Pow(Y[i] - SCoords[1, p], 2)); 229 | AllWeights[p] = w; 230 | if (NWIdx < points) 231 | { 232 | NW[0, NWIdx] = w; 233 | NW[1, NWIdx] = p; 234 | } 235 | NWIdx += 1; 236 | } 237 | } 238 | 239 | if (GCoords[i, j] == unDefData) 240 | { 241 | for (p = 0; p < pNum; p++) 242 | { 243 | w = AllWeights[p]; 244 | if (w == -1) 245 | continue; 246 | 247 | aMin = (double)NW[0, 0]; 248 | aP = 0; 249 | for (l = 1; l < points; l++) 250 | { 251 | if ((double)NW[0, l] < aMin) 252 | { 253 | aMin = (double)NW[0, l]; 254 | aP = l; 255 | } 256 | } 257 | if (w > aMin) 258 | { 259 | NW[0, aP] = w; 260 | NW[1, aP] = p; 261 | } 262 | } 263 | for (p = 0; p < points; p++) 264 | { 265 | SV += (double)NW[0, p] * SCoords[2, (int)NW[1, p]]; 266 | SW += (double)NW[0, p]; 267 | } 268 | GCoords[i, j] = SV / SW; 269 | } 270 | } 271 | } 272 | 273 | //---- Smooth with 5 points 274 | double s = 0.5; 275 | for (i = 1; i < rowNum - 1; i++) 276 | { 277 | for (j = 1; j < colNum - 1; j++) 278 | GCoords[i, j] = GCoords[i, j] + s / 4 * (GCoords[i + 1, j] + GCoords[i - 1, j] + GCoords[i, j + 1] + 279 | GCoords[i, j - 1] - 4 * GCoords[i, j]); 280 | 281 | } 282 | 283 | return GCoords; 284 | } 285 | 286 | /// 287 | /// Interpolation with IDW neighbor method 288 | /// 289 | /// Discrete data array 290 | /// Grid X array 291 | /// Grid Y array 292 | /// Needed at leat point number 293 | /// Search radius 294 | /// Undefine data 295 | /// Interpolated grid data 296 | public static double[,] Interpolation_IDW_Radius(double[,] SCoords, double[] X, double[] Y, 297 | int NeededPointNum, double radius, double unDefData) 298 | { 299 | int rowNum, colNum, pNum; 300 | colNum = X.Length; 301 | rowNum = Y.Length; 302 | pNum = SCoords.GetLength(1); 303 | double[,] GCoords = new double[rowNum, colNum]; 304 | int i, j, p, vNum; 305 | double w, SV, SW; 306 | bool ifPointGrid; 307 | 308 | //---- Do interpolation 309 | for (i = 0; i < rowNum; i++) 310 | { 311 | for (j = 0; j < colNum; j++) 312 | { 313 | GCoords[i, j] = unDefData; 314 | ifPointGrid = false; 315 | SV = 0; 316 | SW = 0; 317 | vNum = 0; 318 | for (p = 0; p < pNum; p++) 319 | { 320 | if (SCoords[2, p] == unDefData) 321 | continue; 322 | 323 | if (SCoords[0, p] < X[j] - radius || SCoords[0, p] > X[j] + radius || SCoords[1, p] < Y[i] - radius || 324 | SCoords[1, p] > Y[i] + radius) 325 | continue; 326 | 327 | if (Math.Pow(X[j] - SCoords[0, p], 2) + Math.Pow(Y[i] - SCoords[1, p], 2) == 0) 328 | { 329 | GCoords[i, j] = SCoords[2, p]; 330 | ifPointGrid = true; 331 | break; 332 | } 333 | else if (Math.Sqrt(Math.Pow(X[j] - SCoords[0, p], 2) + 334 | Math.Pow(Y[i] - SCoords[1, p], 2)) <= radius) 335 | { 336 | w = 1 / (Math.Pow(X[j] - SCoords[0, p], 2) + Math.Pow(Y[i] - SCoords[1, p], 2)); 337 | SW = SW + w; 338 | SV = SV + SCoords[2, p] * w; 339 | vNum += 1; 340 | } 341 | } 342 | 343 | if (!ifPointGrid) 344 | { 345 | if (vNum >= NeededPointNum) 346 | { 347 | GCoords[i, j] = SV / SW; 348 | } 349 | } 350 | } 351 | } 352 | 353 | //---- Smooth with 5 points 354 | double s = 0.5; 355 | for (i = 1; i < rowNum - 1; i++) 356 | { 357 | for (j = 1; j < colNum - 2; j++) 358 | { 359 | if (GCoords[i, j] == unDefData || GCoords[i + 1, j] == unDefData || GCoords[i - 1, j] == 360 | unDefData || GCoords[i, j + 1] == unDefData || GCoords[i, j - 1] == unDefData) 361 | { 362 | continue; 363 | } 364 | GCoords[i, j] = GCoords[i, j] + s / 4 * (GCoords[i + 1, j] + GCoords[i - 1, j] + GCoords[i, j + 1] + 365 | GCoords[i, j - 1] - 4 * GCoords[i, j]); 366 | } 367 | } 368 | 369 | return GCoords; 370 | } 371 | 372 | /// 373 | /// Interpolate from grid data using bi-linear method 374 | /// 375 | /// input grid data 376 | /// input x coordinates 377 | /// input y coordinates 378 | /// Undefine data 379 | /// output x coordinates 380 | /// output y coordinates 381 | /// Output grid data 382 | public static double[,] Interpolation_Grid(double[,] GridData, double[] X, double[] Y, double unDefData, 383 | ref double[] nX, ref double[] nY) 384 | { 385 | int xNum = X.Length; 386 | int yNum = Y.Length; 387 | int nxNum = X.Length * 2 - 1; 388 | int nyNum = Y.Length * 2 - 1; 389 | nX = new double[nxNum]; 390 | nY = new double[nyNum]; 391 | double[,] nGridData = new double[nyNum, nxNum]; 392 | int i, j; 393 | double a, b, c, d; 394 | List dList = new List(); 395 | for (i = 0; i < nxNum; i++) 396 | { 397 | if (i % 2 == 0) 398 | nX[i] = X[i / 2]; 399 | else 400 | nX[i] = (X[(i - 1) / 2] + X[(i - 1) / 2 + 1]) / 2; 401 | } 402 | for (i = 0; i < nyNum; i++) 403 | { 404 | if (i % 2 == 0) 405 | nY[i] = Y[i / 2]; 406 | else 407 | nY[i] = (Y[(i - 1) / 2] + Y[(i - 1) / 2 + 1]) / 2; 408 | for (j = 0; j < nxNum; j++) 409 | { 410 | if (i % 2 == 0 && j % 2 == 0) 411 | nGridData[i, j] = GridData[i / 2, j / 2]; 412 | else if (i % 2 == 0 && j % 2 != 0) 413 | { 414 | a = GridData[i / 2, (j - 1) / 2]; 415 | b = GridData[i / 2, (j - 1) / 2 + 1]; 416 | dList = new List(); 417 | if (a != unDefData) 418 | dList.Add(a); 419 | if (b != unDefData) 420 | dList.Add(b); 421 | 422 | if (dList.Count == 0) 423 | nGridData[i, j] = unDefData; 424 | else if (dList.Count == 1) 425 | nGridData[i, j] = dList[0]; 426 | else 427 | nGridData[i, j] = (a + b) / 2; 428 | } 429 | else if (i % 2 != 0 && j % 2 == 0) 430 | { 431 | a = GridData[(i - 1) / 2, j / 2]; 432 | b = GridData[(i - 1) / 2 + 1, j / 2]; 433 | dList = new List(); 434 | if (a != unDefData) 435 | dList.Add(a); 436 | if (b != unDefData) 437 | dList.Add(b); 438 | 439 | if (dList.Count == 0) 440 | nGridData[i, j] = unDefData; 441 | else if (dList.Count == 1) 442 | nGridData[i, j] = dList[0]; 443 | else 444 | nGridData[i, j] = (a + b) / 2; 445 | } 446 | else 447 | { 448 | a = GridData[(i - 1) / 2, (j - 1) / 2]; 449 | b = GridData[(i - 1) / 2, (j - 1) / 2 + 1]; 450 | c = GridData[(i - 1) / 2 + 1, (j - 1) / 2 + 1]; 451 | d = GridData[(i - 1) / 2 + 1, (j - 1) / 2]; 452 | dList = new List(); 453 | if (a != unDefData) 454 | dList.Add(a); 455 | if (b != unDefData) 456 | dList.Add(b); 457 | if (c != unDefData) 458 | dList.Add(c); 459 | if (d != unDefData) 460 | dList.Add(d); 461 | 462 | if (dList.Count == 0) 463 | nGridData[i, j] = unDefData; 464 | else if (dList.Count == 1) 465 | nGridData[i, j] = dList[0]; 466 | else 467 | { 468 | double aSum = 0; 469 | foreach (double dd in dList) 470 | aSum += dd; 471 | nGridData[i, j] = aSum / dList.Count; 472 | } 473 | } 474 | } 475 | } 476 | 477 | return nGridData; 478 | } 479 | 480 | #endregion 481 | 482 | #region Cressman 483 | /// 484 | /// Cressman analysis with default radius of 10, 7, 4, 2, 1 485 | /// 486 | /// station data array - x,y,value 487 | /// X array 488 | /// Y array 489 | /// undefine data 490 | /// result grid data 491 | public static double[,] Cressman(double[,] stationData, double[] X, double[] Y, double unDefData) 492 | { 493 | List radList = new List(); 494 | radList.AddRange(new double[] { 10, 7, 4, 2, 1 }); 495 | 496 | return Cressman(stationData, X, Y, unDefData, radList); 497 | } 498 | 499 | /// 500 | /// Cressman analysis 501 | /// 502 | /// station data array - x,y,value 503 | /// X array 504 | /// Y array 505 | /// undefine data 506 | /// radius list 507 | /// result grid data 508 | public static double[,] Cressman(double[,] stationData, double[] X, double[] Y, double unDefData, List radList) 509 | { 510 | double[,] stData = (double[,])stationData.Clone(); 511 | int xNum = X.Length; 512 | int yNum = Y.Length; 513 | int pNum = stData.GetLength(1); 514 | double[,] gridData = new double[yNum, xNum]; 515 | int irad = radList.Count; 516 | int i, j; 517 | 518 | //Loop through each stn report and convert stn lat/lon to grid coordinates 519 | double xMin = X[0]; 520 | double xMax = X[X.Length - 1]; 521 | double yMin = Y[0]; 522 | double yMax = Y[Y.Length - 1]; 523 | double xDelt = X[1] - X[0]; 524 | double yDelt = Y[1] - Y[0]; 525 | double x, y; 526 | double sum = 0, total = 0; 527 | int stNum = 0; 528 | for (i = 0; i < pNum; i++) 529 | { 530 | x = stData[0, i]; 531 | y = stData[1, i]; 532 | stData[0, i] = (x - xMin) / xDelt; 533 | stData[1, i] = (y - yMin) / yDelt; 534 | if (stData[2, i] != unDefData) 535 | { 536 | total += stData[2, i]; 537 | stNum += 1; 538 | } 539 | } 540 | total = total / stNum; 541 | 542 | ////Initial grid values are average of station reports 543 | //for (i = 0; i < yNum; i++) 544 | //{ 545 | // for (j = 0; j < xNum; j++) 546 | // { 547 | // gridData[i, j] = sum; 548 | // } 549 | //} 550 | 551 | //Initial the arrays 552 | double HITOP = -999900000000000000000.0; 553 | double HIBOT = 999900000000000000000.0; 554 | double[,] TOP = new double[yNum, xNum]; 555 | double[,] BOT = new double[yNum, xNum]; 556 | //double[,] GRID = new double[yNum, xNum]; 557 | //int[,] NG = new int[yNum, xNum]; 558 | for (i = 0; i < yNum; i++) 559 | { 560 | for (j = 0; j < xNum; j++) 561 | { 562 | TOP[i, j] = HITOP; 563 | BOT[i, j] = HIBOT; 564 | //GRID[i, j] = 0; 565 | //NG[i, j] = 0; 566 | } 567 | } 568 | 569 | //Initial grid values are average of station reports within the first radius 570 | double rad; 571 | if (radList.Count > 0) 572 | rad = radList[0]; 573 | else 574 | rad = 4; 575 | for (i = 0; i < yNum; i++) 576 | { 577 | y = (double)i; 578 | yMin = y - rad; 579 | yMax = y + rad; 580 | for (j = 0; j < xNum; j++) 581 | { 582 | x = (double)j; 583 | xMin = x - rad; 584 | xMax = x + rad; 585 | stNum = 0; 586 | sum = 0; 587 | for (int s = 0; s < pNum; s++) 588 | { 589 | double val = stData[2, s]; 590 | double sx = stData[0, s]; 591 | double sy = stData[1, s]; 592 | if (sx < 0 || sx >= xNum - 1 || sy < 0 || sy >= yNum - 1) 593 | continue; 594 | 595 | if (val == unDefData || sx < xMin || sx > xMax || sy < yMin || sy > yMax) 596 | continue; 597 | 598 | double dis = Math.Sqrt(Math.Pow(sx - x, 2) + Math.Pow(sy - y, 2)); 599 | if (dis > rad) 600 | continue; 601 | 602 | sum += val; 603 | stNum += 1; 604 | if (TOP[i, j] < val) 605 | TOP[i, j] = val; 606 | if (BOT[i, j] > val) 607 | BOT[i, j] = val; 608 | } 609 | if (stNum == 0) 610 | { 611 | gridData[i, j] = unDefData; 612 | //gridData[i, j] = total; 613 | } 614 | else 615 | gridData[i, j] = sum / stNum; 616 | } 617 | } 618 | 619 | //Perform the objective analysis 620 | for (int p = 0; p < irad; p++) 621 | { 622 | rad = radList[p]; 623 | for (i = 0; i < yNum; i++) 624 | { 625 | y = (double)i; 626 | yMin = y - rad; 627 | yMax = y + rad; 628 | for (j = 0; j < xNum; j++) 629 | { 630 | if (gridData[i, j] == unDefData) 631 | continue; 632 | 633 | x = (double)j; 634 | xMin = x - rad; 635 | xMax = x + rad; 636 | sum = 0; 637 | double wSum = 0; 638 | for (int s = 0; s < pNum; s++) 639 | { 640 | double val = stData[2, s]; 641 | double sx = stData[0, s]; 642 | double sy = stData[1, s]; 643 | if (sx < 0 || sx >= xNum - 1 || sy < 0 || sy >= yNum - 1) 644 | continue; 645 | 646 | if (val == unDefData || sx < xMin || sx > xMax || sy < yMin || sy > yMax) 647 | continue; 648 | 649 | double dis = Math.Sqrt(Math.Pow(sx - x, 2) + Math.Pow(sy - y, 2)); 650 | if (dis > rad) 651 | continue; 652 | 653 | int i1 = (int)sy; 654 | int j1 = (int)sx; 655 | int i2 = i1 + 1; 656 | int j2 = j1 + 1; 657 | double a = gridData[i1, j1]; 658 | double b = gridData[i1, j2]; 659 | double c = gridData[i2, j1]; 660 | double d = gridData[i2, j2]; 661 | List dList = new List(); 662 | if (a != unDefData) 663 | dList.Add(a); 664 | if (b != unDefData) 665 | dList.Add(b); 666 | if (c != unDefData) 667 | dList.Add(c); 668 | if (d != unDefData) 669 | dList.Add(d); 670 | 671 | double calVal; 672 | if (dList.Count == 0) 673 | continue; 674 | else if (dList.Count == 1) 675 | calVal = dList[0]; 676 | else if (dList.Count <= 3) 677 | { 678 | double aSum = 0; 679 | foreach (double dd in dList) 680 | aSum += dd; 681 | calVal = aSum / dList.Count; 682 | } 683 | else 684 | { 685 | double x1val = a + (c - a) * (sy - i1); 686 | double x2val = b + (d - b) * (sy - i1); 687 | calVal = x1val + (x2val - x1val) * (sx - j1); 688 | } 689 | double eVal = val - calVal; 690 | double w = (rad * rad - dis * dis) / (rad * rad + dis * dis); 691 | sum += eVal * w; 692 | wSum += w; 693 | } 694 | if (wSum < 0.000001) 695 | { 696 | gridData[i, j] = unDefData; 697 | } 698 | else 699 | { 700 | double aData = gridData[i, j] + sum / wSum; 701 | gridData[i, j] = Math.Max(BOT[i, j], Math.Min(TOP[i, j], aData)); 702 | } 703 | } 704 | } 705 | } 706 | 707 | //Return 708 | return gridData; 709 | } 710 | 711 | ///// 712 | ///// Cressman analysis 713 | ///// 714 | ///// station data array - x,y,value 715 | ///// X array 716 | ///// Y array 717 | ///// undefine data 718 | ///// radii list 719 | ///// result grid data 720 | //public static double[,] CressmanR(double[,] stationData, double[] GX, double[] GY, double unDefData, List radList) 721 | //{ 722 | // int MXI = GY.Length; 723 | // int MXJ = GX.Length; 724 | // int II = MXI; 725 | // int JJ = MXJ; 726 | 727 | // double[,] FIELD = new double[MXI, MXJ]; 728 | // int[,] NG = new int[MXI, MXJ]; 729 | // double[,] TOP = new double[MXI, MXJ]; 730 | // double[,] BOT = new double[MXI, MXJ]; 731 | // double[,] GRID = new double[MXI, MXJ]; 732 | // double[,] SW = new double[MXI, MXJ]; 733 | // double[,] WS = new double[MXI, MXJ]; 734 | // double TOTAL, ASTA; 735 | 736 | // int MXSTA = stationData.GetLength(1); 737 | // int NSTA = MXSTA; 738 | // double[] STDATA = new double[MXSTA]; 739 | // double[] STAX = new double[MXSTA]; 740 | // double[] STAY = new double[MXSTA]; 741 | // int I, J; 742 | // double xMin = GX[0]; 743 | // double xMax = GX[GX.Length - 1]; 744 | // double yMin = GY[0]; 745 | // double yMax = GY[GY.Length - 1]; 746 | // double xDelt = GX[1] - GX[0]; 747 | // double yDelt = GY[1] - GY[0]; 748 | // for (I = 0; I < MXSTA; I++) 749 | // { 750 | // STDATA[I] = stationData[2, I]; 751 | // //STAX[I] = stationData[0, I]; 752 | // //STAY[I] = stationData[1, I]; 753 | // STAX[I] = (stationData[0, I] - xMin) / xDelt; 754 | // STAY[I] = (stationData[1, I] - yMin) / yDelt; 755 | // } 756 | // double HITOP = -999900000000000000000.0; 757 | // double HIBOT = 999900000000000000000.0; 758 | // TOTAL = 0.0; 759 | // ASTA = 0.0; 760 | // for (J = 0; J < NSTA; J++) 761 | // { 762 | // if (Math.Abs(STDATA[J]) != unDefData) 763 | // { 764 | // TOTAL = TOTAL + STDATA[J]; 765 | // ASTA = ASTA + 1.0; 766 | // } 767 | // } 768 | // if (ASTA == 0.0) 769 | // { 770 | // //No effective station data 771 | // return null; 772 | // } 773 | // TOTAL = TOTAL / ASTA; 774 | // for (J = 0; J < JJ; J++) 775 | // { 776 | // for (I = 0; I < II; I++) 777 | // FIELD[I, J] = TOTAL; 778 | // } 779 | // //C 780 | // //C NOW DO THE CRESSMAN ANALYSIS 781 | // //C 782 | // for (J = 0; J < JJ; J++) 783 | // { 784 | // for (I = 0; I < II; I++) 785 | // { 786 | // //C 787 | // //C INITIALIZE THE ARRAYS 788 | // //C 789 | // TOP[I, J] = HITOP; 790 | // BOT[I, J] = HIBOT; 791 | // GRID[I, J] = 0.0; 792 | // NG[I, J] = 0; 793 | // } 794 | // } 795 | 796 | // double RADM = radList[0]; 797 | // double RADL = RADM - 1.0; 798 | // int JL, JM, IL, IM; 799 | // for (int N = 0; N < NSTA; N++) 800 | // { 801 | // if (STDATA[N] == unDefData) 802 | // continue; 803 | 804 | // //C 805 | // //C FOR EACH STATION, CHECK THE X/Y COORDINATES 806 | // //C INITIALIZE THE GRID PT ARRAY USING AVAILABLE DATA WITHIN A 807 | // //C RADIUS OF RADM GRID POINTS OF THE GRID POINT OF INTEREST. 808 | // //C 809 | // JL = (int)Math.Max(1.0, STAY[N] - RADL); 810 | // JM = (int)Math.Min((double)JJ, STAY[N] + RADM); 811 | // IL = (int)Math.Max(1.0, STAX[N] - RADL); 812 | // IM = (int)Math.Min((double)II, STAX[N] + RADM); 813 | // for (J = JL - 1; J < JM; J++) 814 | // { 815 | // for (I = IL - 1; I < IM; I++) 816 | // { 817 | // if (STDATA[N] > TOP[I, J]) 818 | // TOP[I, J] = STDATA[N]; 819 | // if (STDATA[N] < BOT[I, J]) 820 | // BOT[I, J] = STDATA[N]; 821 | // GRID[I, J] = GRID[I, J] + STDATA[N]; 822 | // NG[I, J] = NG[I, J] + 1; 823 | // } 824 | // } 825 | // } 826 | // //C 827 | // //C FORM 1ST GUESS FIELD BY COMPUTING AN AVERAGE VALUE FIELD 828 | // //C 829 | // for (J = 0; J < JJ; J++) 830 | // { 831 | // for (I = 0; I < II; I++) 832 | // { 833 | // //C 834 | // //C GRID=-9999 IF NO STA VALUES INFLUENCE A PARTICULAR GRID POINT 835 | // //C 836 | // if (NG[I, J] > 0) 837 | // GRID[I, J] = GRID[I, J] / (double)NG[I, J]; 838 | // else 839 | // //C GRID(I,J)=-9999. 840 | // GRID[I, J] = TOTAL; 841 | 842 | // //C 843 | // //C THE 1ST GUESS IS THE AVERAGE VALUE OF ALL STA OBS SURROUNDING 844 | // //C THE PARTICULAR GRID POINT. 845 | // //C 846 | // } 847 | // } 848 | 849 | // //C 850 | // //C DO NPASS ITERATIONS OR PASSES FOR THE ANALYSIS 851 | // //C 852 | // int NPASS = radList.Count; 853 | // for (int ITER = 0; ITER < NPASS; ITER++) 854 | // { 855 | // RADM = radList[ITER]; 856 | // RADL = RADM - 1.0; 857 | // double RSQ = RADM * RADM; 858 | // for (J = 0; J < JJ; J++) 859 | // { 860 | // for (I = 0; I < II; I++) 861 | // { 862 | // WS[I, J] = 0.0; 863 | // SW[I, J] = 0.0; 864 | // } 865 | // } 866 | // //C 867 | // //C ON EACH PASS, USE ALL OF THE STATION VALUES 868 | // //C 869 | // for (int N = 0; N < NSTA; N++) 870 | // { 871 | // if (STDATA[N] == unDefData) 872 | // continue; 873 | 874 | // if (STAX[N] < 0 || STAX[N] >= JJ - 1 || STAY[N] < 0 || STAY[N] >= II - 1) 875 | // continue; 876 | 877 | // double X = STAX[N]; 878 | // double Y = STAY[N]; 879 | // int IX = (int)X; 880 | // int JY = (int)Y; 881 | // double DX = X - (double)IX; 882 | // double DY = Y - (double)JY; 883 | // //C 884 | // //C FROM THE GUESS FIELD INTERPOLATE TO EACH STATION 885 | // //C 886 | // double GT = GRID[IX, JY] + (GRID[IX + 1, JY] - GRID[IX, JY]) * DX 887 | // + (GRID[IX, JY + 1] - GRID[IX, JY]) * DY 888 | // + (GRID[IX, JY] - GRID[IX + 1, JY] - 889 | // GRID[IX, JY + 1] + GRID[IX + 1, JY + 1]) * DX * DY; 890 | // //C 891 | // //C DIFFERENCE BETWEEN THE STA VALUE(OBS) AND THE INTERP. VALUE 892 | // //C 893 | // double DV = STDATA[N] - GT; 894 | // //C 895 | // //C SET UP THE LIMITS OF THE SPHERE OF INFLUENCE 896 | // //C 897 | // JL = (int)Math.Max(1.0, Y - RADL); 898 | // double YL = JL; 899 | // JM = (int)Math.Min((double)JJ, Y + RADM); 900 | // IL = (int)Math.Max(1.0, X - RADL); 901 | // double XL = IL; 902 | // IM = (int)Math.Min((double)II, X + RADM); 903 | // double YJ = YL - Y - 1.0; 904 | // for (J = JL - 1; J < JM; J++) 905 | // { 906 | // YJ = YJ + 1.0; 907 | // double DD = YJ * YJ; 908 | // double XI = XL - X - 1.0; 909 | // for (I = IL - 1; I < IM; I++) 910 | // { 911 | // XI = XI + 1.0; 912 | // //C 913 | // //C CALCULATE THE STA DIST FROM THE GRID PT 914 | // //C 915 | // double D2 = DD + XI * XI; 916 | // //C 917 | // //C CHECK IF THE STA IS CLOSE TO THE GRID PT TO INFLUENCE IT 918 | // //C 919 | // if (D2 <= RSQ) 920 | // { 921 | // //C 922 | // //C CALCULATE THE CORRECTION FACTOR 923 | // //C 924 | // double CCF = (RSQ - D2) / (RSQ + D2); 925 | // SW[I, J] = SW[I, J] + CCF; 926 | // WS[I, J] = WS[I, J] + CCF * DV; 927 | // } 928 | // } 929 | // } 930 | // } 931 | // for (J = 0; J < JJ; J++) 932 | // { 933 | // for (I = 0; I < II; I++) 934 | // { 935 | // if (SW[I, J] >= 0.00001) 936 | // { 937 | // //C 938 | // //C GRID PT VALUE IS CORRECTED BY AN AVERAGE CORRECTION VALUE 939 | // //C 940 | // double PP = GRID[I, J] + WS[I, J] / SW[I, J]; 941 | // GRID[I, J] = Math.Max(BOT[I, J], Math.Min(TOP[I, J], PP)); 942 | // } 943 | // } 944 | // } 945 | // } 946 | 947 | // for (J = 0; J < JJ; J++) 948 | // { 949 | // for (I = 0; I < II; I++) 950 | // { 951 | // GRID[I, J] = Math.Min(HIBOT, Math.Max(HITOP, GRID[I, J])); 952 | // FIELD[I, J] = GRID[I, J]; 953 | // } 954 | // } 955 | // return FIELD; 956 | //} 957 | 958 | #endregion 959 | 960 | #region Others 961 | /// 962 | /// Assign point value to grid value 963 | /// 964 | /// point value array 965 | /// X coordinate 966 | /// Y coordinate 967 | /// undefined value 968 | /// grid data 969 | public static double[,] AssignPointToGrid(double[,] SCoords, double[] X, double[] Y, 970 | double unDefData) 971 | { 972 | int rowNum, colNum, pNum; 973 | colNum = X.Length; 974 | rowNum = Y.Length; 975 | pNum = SCoords.GetLength(1); 976 | double[,] GCoords = new double[rowNum, colNum]; 977 | double dX = X[1] - X[0]; 978 | double dY = Y[1] - Y[0]; 979 | int[,] pNums = new int[rowNum, colNum]; 980 | 981 | for (int i = 0; i < rowNum; i++) 982 | { 983 | for (int j = 0; j < colNum; j++) 984 | { 985 | pNums[i, j] = 0; 986 | GCoords[i, j] = 0.0; 987 | } 988 | } 989 | 990 | for (int p = 0; p < pNum; p++) 991 | { 992 | if (DoubleEquals(SCoords[2, p], unDefData)) 993 | continue; 994 | 995 | double x = SCoords[0, p]; 996 | double y = SCoords[1, p]; 997 | if (x < X[0] || x > X[colNum - 1]) 998 | continue; 999 | if (y < Y[0] || y > Y[rowNum - 1]) 1000 | continue; 1001 | 1002 | int j = (int)((x - X[0]) / dX); 1003 | int i = (int)((y - Y[0]) / dY); 1004 | pNums[i, j] += 1; 1005 | GCoords[i, j] += SCoords[2, p]; 1006 | } 1007 | 1008 | for (int i = 0; i < rowNum; i++) 1009 | { 1010 | for (int j = 0; j < colNum; j++) 1011 | { 1012 | if (pNums[i, j] == 0) 1013 | GCoords[i, j] = unDefData; 1014 | else 1015 | GCoords[i, j] = GCoords[i, j] / pNums[i, j]; 1016 | } 1017 | } 1018 | 1019 | return GCoords; 1020 | } 1021 | 1022 | private static bool DoubleEquals(double a, double b) 1023 | { 1024 | //if (Math.Abs(a - b) < 0.000001) 1025 | if (Math.Abs(a / b - 1) < 0.00000000001) 1026 | return true; 1027 | else 1028 | return false; 1029 | } 1030 | 1031 | #endregion 1032 | 1033 | } 1034 | } 1035 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /Legend.cs: -------------------------------------------------------------------------------- 1 | //****************************** 2 | // Copyright 2012 Yaqiang Wang, 3 | // yaqiang.wang@gmail.com 4 | //****************************** 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Collections; 9 | using System.Text; 10 | 11 | namespace wContour 12 | { 13 | /// 14 | /// Legend class 15 | /// 16 | public class Legend 17 | { 18 | /// 19 | /// Legend parameter 20 | /// 21 | public struct legendPara 22 | { 23 | /// 24 | /// If is vertical 25 | /// 26 | public bool isVertical; 27 | /// 28 | /// Start point 29 | /// 30 | public PointD startPoint; 31 | /// 32 | /// Length 33 | /// 34 | public double length; 35 | /// 36 | /// Width 37 | /// 38 | public double width; 39 | /// 40 | /// Contour values 41 | /// 42 | public double[] contourValues; 43 | /// 44 | /// If is triangle 45 | /// 46 | public bool isTriangle; 47 | } 48 | 49 | /// 50 | /// Legend polygon 51 | /// 52 | public struct lPolygon 53 | { 54 | /// 55 | /// Value 56 | /// 57 | public double value; 58 | /// 59 | /// If is first 60 | /// 61 | public bool isFirst; 62 | /// 63 | /// Point list 64 | /// 65 | public List pointList; 66 | } 67 | 68 | /// 69 | /// Create legend polygons 70 | /// 71 | /// legend parameters 72 | /// legend polygons 73 | public static List CreateLegend(legendPara aLegendPara) 74 | { 75 | List polygonList = new List(); 76 | List pList = new List(); 77 | lPolygon aLPolygon; 78 | PointD aPoint; 79 | int i, pNum; 80 | double aLength; 81 | bool ifRectangle; 82 | 83 | pNum = aLegendPara.contourValues.Length + 1; 84 | aLength = aLegendPara.length / pNum; 85 | if (aLegendPara.isVertical) 86 | { 87 | for (i = 0; i < pNum; i++) 88 | { 89 | pList = new List(); 90 | ifRectangle = true; 91 | if (i == 0) 92 | { 93 | aLPolygon.value = aLegendPara.contourValues[0]; 94 | aLPolygon.isFirst = true; 95 | if (aLegendPara.isTriangle) 96 | { 97 | aPoint = new PointD(); 98 | aPoint.X = aLegendPara.startPoint.X + aLegendPara.width / 2; 99 | aPoint.Y = aLegendPara.startPoint.Y; 100 | pList.Add(aPoint); 101 | aPoint = new PointD(); 102 | aPoint.X = aLegendPara.startPoint.X + aLegendPara.width; 103 | aPoint.Y = aLegendPara.startPoint.Y + aLength; 104 | pList.Add(aPoint); 105 | aPoint = new PointD(); 106 | aPoint.X = aLegendPara.startPoint.X; 107 | aPoint.Y = aLegendPara.startPoint.Y + aLength; 108 | pList.Add(aPoint); 109 | ifRectangle = false; 110 | } 111 | } 112 | else 113 | { 114 | aLPolygon.value = aLegendPara.contourValues[i - 1]; 115 | aLPolygon.isFirst = false; 116 | if (i == pNum - 1) 117 | { 118 | if (aLegendPara.isTriangle) 119 | { 120 | aPoint = new PointD(); 121 | aPoint.X = aLegendPara.startPoint.X; 122 | aPoint.Y = aLegendPara.startPoint.Y + i * aLength; 123 | pList.Add(aPoint); 124 | aPoint = new PointD(); 125 | aPoint.X = aLegendPara.startPoint.X + aLegendPara.width; 126 | aPoint.Y = aLegendPara.startPoint.Y + i * aLength; 127 | pList.Add(aPoint); 128 | aPoint = new PointD(); 129 | aPoint.X = aLegendPara.startPoint.X + aLegendPara.width / 2; 130 | aPoint.Y = aLegendPara.startPoint.Y + (i + 1) * aLength; 131 | pList.Add(aPoint); 132 | ifRectangle = false; 133 | } 134 | } 135 | } 136 | 137 | if (ifRectangle) 138 | { 139 | aPoint = new PointD(); 140 | aPoint.X = aLegendPara.startPoint.X; 141 | aPoint.Y = aLegendPara.startPoint.Y + i * aLength; 142 | pList.Add(aPoint); 143 | aPoint = new PointD(); 144 | aPoint.X = aLegendPara.startPoint.X + aLegendPara.width; 145 | aPoint.Y = aLegendPara.startPoint.Y + i * aLength; 146 | pList.Add(aPoint); 147 | aPoint = new PointD(); 148 | aPoint.X = aLegendPara.startPoint.X + aLegendPara.width; 149 | aPoint.Y = aLegendPara.startPoint.Y + (i + 1) * aLength; 150 | pList.Add(aPoint); 151 | aPoint = new PointD(); 152 | aPoint.X = aLegendPara.startPoint.X; 153 | aPoint.Y = aLegendPara.startPoint.Y + (i + 1) * aLength; 154 | pList.Add(aPoint); 155 | } 156 | 157 | pList.Add(pList[0]); 158 | aLPolygon.pointList = pList; 159 | 160 | polygonList.Add(aLPolygon); 161 | } 162 | } 163 | else 164 | { 165 | for (i = 0; i < pNum; i++) 166 | { 167 | pList = new List(); 168 | ifRectangle = true; 169 | if (i == 0) 170 | { 171 | aLPolygon.value = aLegendPara.contourValues[0]; 172 | aLPolygon.isFirst = true; 173 | if (aLegendPara.isTriangle) 174 | { 175 | aPoint = new PointD(); 176 | aPoint.X = aLegendPara.startPoint.X; 177 | aPoint.Y = aLegendPara.startPoint.Y + aLegendPara.width / 2; 178 | pList.Add(aPoint); 179 | aPoint = new PointD(); 180 | aPoint.X = aLegendPara.startPoint.X + aLength; 181 | aPoint.Y = aLegendPara.startPoint.Y; 182 | pList.Add(aPoint); 183 | aPoint = new PointD(); 184 | aPoint.X = aLegendPara.startPoint.X + aLength; 185 | aPoint.Y = aLegendPara.startPoint.Y + aLegendPara.width; 186 | pList.Add(aPoint); 187 | ifRectangle = false; 188 | } 189 | } 190 | else 191 | { 192 | aLPolygon.value = aLegendPara.contourValues[i - 1]; 193 | aLPolygon.isFirst = false; 194 | if (i == pNum - 1) 195 | { 196 | if (aLegendPara.isTriangle) 197 | { 198 | aPoint = new PointD(); 199 | aPoint.X = aLegendPara.startPoint.X + i * aLength; 200 | aPoint.Y = aLegendPara.startPoint.Y; 201 | pList.Add(aPoint); 202 | aPoint = new PointD(); 203 | aPoint.X = aLegendPara.startPoint.X + (i + 1) * aLength; 204 | aPoint.Y = aLegendPara.startPoint.Y + aLegendPara.width / 2; 205 | pList.Add(aPoint); 206 | aPoint = new PointD(); 207 | aPoint.X = aLegendPara.startPoint.X + i * aLength; 208 | aPoint.Y = aLegendPara.startPoint.Y + aLegendPara.width; 209 | pList.Add(aPoint); 210 | ifRectangle = false; 211 | } 212 | } 213 | } 214 | 215 | if (ifRectangle) 216 | { 217 | aPoint = new PointD(); 218 | aPoint.X = aLegendPara.startPoint.X + i * aLength; 219 | aPoint.Y = aLegendPara.startPoint.Y; 220 | pList.Add(aPoint); 221 | aPoint = new PointD(); 222 | aPoint.X = aLegendPara.startPoint.X + (i + 1) * aLength; 223 | aPoint.Y = aLegendPara.startPoint.Y; 224 | pList.Add(aPoint); 225 | aPoint = new PointD(); 226 | aPoint.X = aLegendPara.startPoint.X + (i + 1) * aLength; 227 | aPoint.Y = aLegendPara.startPoint.Y + aLegendPara.width; 228 | pList.Add(aPoint); 229 | aPoint = new PointD(); 230 | aPoint.X = aLegendPara.startPoint.X + i * aLength; 231 | aPoint.Y = aLegendPara.startPoint.Y + aLegendPara.width; 232 | pList.Add(aPoint); 233 | } 234 | 235 | pList.Add(pList[0]); 236 | aLPolygon.pointList = pList; 237 | 238 | polygonList.Add(aLPolygon); 239 | } 240 | } 241 | 242 | return polygonList; 243 | } 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /PointF.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | #if NETSTANDARD1_0 3 | namespace wContour 4 | { 5 | /// 6 | /// A point in space (replaces System.Drawing.PointF) 7 | /// 8 | public struct PointF 9 | { 10 | /// 11 | /// The X-coordinate 12 | /// 13 | public float X { get; } 14 | 15 | /// 16 | /// The Y-coordinate 17 | /// 18 | public float Y { get; } 19 | 20 | /// 21 | /// Create a PointF 22 | /// 23 | public PointF(float x, float y) 24 | { 25 | X = x; 26 | Y = y; 27 | } 28 | 29 | /// 30 | public override string ToString() 31 | { 32 | return $"{nameof(X)}: {X}, {nameof(Y)}: {Y}"; 33 | } 34 | } 35 | } 36 | #endif -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | // Setting ComVisible to false makes the types in this assembly not visible 4 | // to COM components. If you need to access a type in this assembly from 5 | // COM, set the ComVisible attribute to true on that type. 6 | [assembly: ComVisible(false)] 7 | 8 | #if !NETSTANDARD1_0 9 | // The following GUID is for the ID of the typelib if this project is exposed to COM 10 | [assembly: Guid("2f103acd-2c5e-4280-959a-b86961d1c453")] 11 | #endif 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wContour 2 | Contour related algorithms 3 | -------------------------------------------------------------------------------- /bin/Debug/wContour.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meteoinfo/wContour_CSharp/dfd67ddb42f0284c318c634e0c96571018f5b7b0/bin/Debug/wContour.dll -------------------------------------------------------------------------------- /wContour.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netstandard2.1 4 | wContour 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | True 20 | https://github.com/meteoinfo/wContour_CSharp 21 | Copyright © 2009-2017 22 | yaqiang.wang@gmail.com 23 | 1.6.2 24 | 25 | 26 | 27 | 28 | bin\$(Configuration)\$(TargetFramework)\$(ProjectName).xml 29 | full 30 | True 31 | 32 | 33 | -------------------------------------------------------------------------------- /wContour.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Blend for Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wContour", "wContour.csproj", "{D7B062DE-DC49-442E-8538-B80897CECBC1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {D7B062DE-DC49-442E-8538-B80897CECBC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {D7B062DE-DC49-442E-8538-B80897CECBC1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {D7B062DE-DC49-442E-8538-B80897CECBC1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {D7B062DE-DC49-442E-8538-B80897CECBC1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /wContour.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | wContour 5 | 6 | 7 | 8 | 9 | Border 10 | 11 | 12 | 13 | 14 | Line list 15 | 16 | 17 | 18 | 19 | Constructor 20 | 21 | 22 | 23 | 24 | Get line number 25 | 26 | 27 | 28 | 29 | Contour 30 | 31 | 32 | 33 | 34 | Tracing contour lines from the grid data with undefine data 35 | 36 | input grid data 37 | X coordinate array 38 | Y coordinate array 39 | number of contour values 40 | contour value array 41 | Undefine data 42 | borders 43 | data flag array 44 | Contour line list 45 | 46 | 47 | 48 | Tracing contour borders of the grid data with undefined data. 49 | Grid data are from left to right and from bottom to top. 50 | Grid data array: first dimention is Y, second dimention is X. 51 | 52 | grid data 53 | x coordinate 54 | y coordinate 55 | 56 | undefine data 57 | borderline list 58 | 59 | 60 | 61 | Create contour lines from the grid data with undefine data 62 | 63 | input grid data 64 | X coordinate array 65 | Y coordinate array 66 | number of contour values 67 | contour value array 68 | interval of X coordinate 69 | interval of Y coordinate 70 | 71 | Undefine data 72 | Border line list 73 | Contour line list 74 | 75 | 76 | 77 | Create contour lines 78 | 79 | input grid data array 80 | X coordinate array 81 | Y coordinate array 82 | number of contour values 83 | contour value array 84 | Interval of X coordinate 85 | Interval of Y coordinate 86 | 87 | 88 | 89 | 90 | Cut contour lines with a polygon. Return the polylines inside of the polygon 91 | 92 | polyline list 93 | border points of the cut polygon 94 | Inside Polylines after cut 95 | 96 | 97 | 98 | Cut contour lines with a polygon. Return the polylines inside of the polygon 99 | 100 | polyline list 101 | border for cutting 102 | Inside Polylines after cut 103 | 104 | 105 | 106 | Smooth Polylines 107 | 108 | Polyline list 109 | Polyline list after smoothing 110 | 111 | 112 | 113 | Smooth Polylines 114 | 115 | Polyline list 116 | B-Spline scan step (0 - 1) 117 | Polyline list after smoothing 118 | 119 | 120 | 121 | Smooth points 122 | 123 | point list 124 | new points 125 | 126 | 127 | 128 | Tracing polygons from contour lines and borders 129 | 130 | input grid data 131 | contour lines 132 | borders 133 | contour values 134 | traced contour polygons 135 | 136 | 137 | 138 | Create contour polygons 139 | 140 | contour lines 141 | gid data extent 142 | contour values 143 | contour polygons 144 | 145 | 146 | 147 | Create polygons from cutted contour lines 148 | 149 | polylines 150 | Border point list 151 | extent 152 | contour values 153 | contour polygons 154 | 155 | 156 | 157 | Create contour polygons from borders 158 | 159 | Input grid data array 160 | Contour lines 161 | borders 162 | extent 163 | contour value 164 | contour polygons 165 | 166 | 167 | 168 | Judge if a point is in a polygon 169 | 170 | polygon border 171 | point 172 | If the point is in the polygon 173 | 174 | 175 | 176 | Judge if a point is in a polygon 177 | 178 | polygon 179 | point 180 | is in 181 | 182 | 183 | 184 | Clip polylines with a border polygon 185 | 186 | polyline list 187 | cutting border point list 188 | cutted polylines 189 | 190 | 191 | 192 | Clip polygons with a border polygon 193 | 194 | polygon list 195 | cutting border point list 196 | cutted polygons 197 | 198 | 199 | 200 | Tracing stream lines 201 | 202 | U component array 203 | V component array 204 | X coordinate array 205 | Y coordinate array 206 | undefine data 207 | stream line density 208 | streamlines 209 | 210 | 211 | 212 | B-Spline interpolation 213 | 214 | Point list 215 | Is closed or not 216 | Scan step (0 - 1) 217 | Interpolated points 218 | 219 | 220 | 221 | Determin if the point list is clockwise 222 | 223 | point list 224 | clockwise or not 225 | 226 | 227 | 228 | Get cross point of two line segments 229 | 230 | point 1 of line a 231 | point 2 of line a 232 | point 1 of line b 233 | point 2 of line b 234 | cross point 235 | 236 | 237 | 238 | Border line 239 | 240 | 241 | 242 | 243 | Area 244 | 245 | 246 | 247 | 248 | Extent 249 | 250 | 251 | 252 | 253 | Is outline 254 | 255 | 256 | 257 | 258 | Is clockwise 259 | 260 | 261 | 262 | 263 | Point list 264 | 265 | 266 | 267 | 268 | IJPoint list 269 | 270 | 271 | 272 | 273 | Border point 274 | 275 | 276 | 277 | 278 | Identifer 279 | 280 | 281 | 282 | 283 | Border index 284 | 285 | 286 | 287 | 288 | Border inner index 289 | 290 | 291 | 292 | 293 | Point 294 | 295 | 296 | 297 | 298 | Value 299 | 300 | 301 | 302 | 303 | Clone 304 | 305 | cloned borderpoint 306 | 307 | 308 | 309 | End point 310 | 311 | 312 | 313 | 314 | Start point 315 | 316 | 317 | 318 | 319 | Point 320 | 321 | 322 | 323 | 324 | Index 325 | 326 | 327 | 328 | 329 | Border Index 330 | 331 | 332 | 333 | 334 | Constructor 335 | 336 | 337 | 338 | 339 | Extent 340 | 341 | 342 | 343 | 344 | x minimum 345 | 346 | 347 | 348 | 349 | y minimum 350 | 351 | 352 | 353 | 354 | x maximum 355 | 356 | 357 | 358 | 359 | y maximum 360 | 361 | 362 | 363 | 364 | Constructor 365 | 366 | 367 | 368 | 369 | Constructor 370 | 371 | minimum x 372 | maximum x 373 | minimum y 374 | maximum y 375 | 376 | 377 | 378 | Judge if this extent include another extent 379 | 380 | extent 381 | is included 382 | 383 | 384 | 385 | Point integer, to indicate the position in grid data 386 | 387 | 388 | 389 | 390 | I 391 | 392 | 393 | 394 | 395 | J 396 | 397 | 398 | 399 | 400 | Line 401 | 402 | 403 | 404 | 405 | Point 1 406 | 407 | 408 | 409 | 410 | Point 2 411 | 412 | 413 | 414 | 415 | Point - double x/y 416 | 417 | 418 | 419 | 420 | x 421 | 422 | 423 | 424 | 425 | y 426 | 427 | 428 | 429 | 430 | Constructor 431 | 432 | 433 | 434 | 435 | Constructor 436 | 437 | x 438 | y 439 | 440 | 441 | 442 | Clone 443 | 444 | Cloned object 445 | 446 | 447 | 448 | Polygon 449 | 450 | 451 | 452 | 453 | If is border contour polygon 454 | 455 | 456 | 457 | 458 | If there is only inner border 459 | 460 | 461 | 462 | 463 | Start value 464 | 465 | 466 | 467 | 468 | End value 469 | 470 | 471 | 472 | 473 | If clockwise 474 | 475 | 476 | 477 | 478 | Start point index 479 | 480 | 481 | 482 | 483 | If high center 484 | 485 | 486 | 487 | 488 | Extent - bordering rectangle 489 | 490 | 491 | 492 | 493 | Area 494 | 495 | 496 | 497 | 498 | Outline 499 | 500 | 501 | 502 | 503 | Hole lines 504 | 505 | 506 | 507 | 508 | Hole index 509 | 510 | 511 | 512 | 513 | Clone 514 | 515 | Cloned polygon 516 | 517 | 518 | 519 | Get if has holes 520 | 521 | 522 | 523 | 524 | Add a hole by a polygon 525 | 526 | polygon 527 | 528 | 529 | 530 | Add a hole by point list 531 | 532 | point list 533 | 534 | 535 | 536 | Polyline 537 | 538 | 539 | 540 | 541 | Value 542 | 543 | 544 | 545 | 546 | Type 547 | 548 | 549 | 550 | 551 | Border index 552 | 553 | 554 | 555 | 556 | Point list 557 | 558 | 559 | 560 | 561 | Interpolate 562 | 563 | 564 | 565 | 566 | Create grid x/y coordinate arrays with x/y delt 567 | 568 | X of left-bottom 569 | Y of left-bottom 570 | X of right-top 571 | Y of right-top 572 | X delt 573 | Y delt 574 | Output X array 575 | Output Y array 576 | 577 | 578 | 579 | Create grid x/y coordinate arrays with x/y number 580 | 581 | X of left-bottom 582 | Y of left-bottom 583 | X of right-top 584 | Y of right-top 585 | X number 586 | Y number 587 | Output X array 588 | Output Y array 589 | 590 | 591 | 592 | Interpolation with IDW neighbor method 593 | 594 | Discrete data array 595 | Grid X array 596 | Grid Y array 597 | Number of nearest neighbors 598 | Interpolated grid Data 599 | 600 | 601 | 602 | Interpolation with IDW neighbor method 603 | 604 | Discrete data array 605 | Grid X array 606 | Grid Y array 607 | Number of nearest neighbors 608 | Undefine data value 609 | Interpolated grid data 610 | 611 | 612 | 613 | Interpolation with IDW neighbor method 614 | 615 | Discrete data array 616 | Grid X array 617 | Grid Y array 618 | Needed at leat point number 619 | Search radius 620 | Undefine data 621 | Interpolated grid data 622 | 623 | 624 | 625 | Interpolate from grid data using bi-linear method 626 | 627 | input grid data 628 | input x coordinates 629 | input y coordinates 630 | Undefine data 631 | output x coordinates 632 | output y coordinates 633 | Output grid data 634 | 635 | 636 | 637 | Cressman analysis with default radius of 10, 7, 4, 2, 1 638 | 639 | station data array - x,y,value 640 | X array 641 | Y array 642 | undefine data 643 | result grid data 644 | 645 | 646 | 647 | Cressman analysis 648 | 649 | station data array - x,y,value 650 | X array 651 | Y array 652 | undefine data 653 | radius list 654 | result grid data 655 | 656 | 657 | 658 | Assign point value to grid value 659 | 660 | point value array 661 | X coordinate 662 | Y coordinate 663 | undefined value 664 | grid data 665 | 666 | 667 | 668 | Legend class 669 | 670 | 671 | 672 | 673 | Legend parameter 674 | 675 | 676 | 677 | 678 | If is vertical 679 | 680 | 681 | 682 | 683 | Start point 684 | 685 | 686 | 687 | 688 | Length 689 | 690 | 691 | 692 | 693 | Width 694 | 695 | 696 | 697 | 698 | Contour values 699 | 700 | 701 | 702 | 703 | If is triangle 704 | 705 | 706 | 707 | 708 | Legend polygon 709 | 710 | 711 | 712 | 713 | Value 714 | 715 | 716 | 717 | 718 | If is first 719 | 720 | 721 | 722 | 723 | Point list 724 | 725 | 726 | 727 | 728 | Create legend polygons 729 | 730 | legend parameters 731 | legend polygons 732 | 733 | 734 | 735 | --------------------------------------------------------------------------------