/// <summary> /// Executes the Area tool with programatic input /// Ping delete static for external testing /// </summary> /// <param name="input">The input raster</param> /// <param name="output">The output polygon feature set</param> /// <param name="zField">The field name containing the values to interpolate</param> /// <param name="cellSize">The double geographic size of the raster cells to create</param> /// <param name="power">The double power representing the inverse</param> /// <param name="neighborType">Fixed distance of fixed number of neighbors</param> /// <param name="pointCount">The number of neighbors to include if the neighborhood type /// is Fixed</param> /// <param name="distance">Points further from the raster cell than this distance are not included /// in the calculation if the neighborhood type is Fixed Distance.</param> /// <param name="output">The output raster where values are stored. The filename is used, but the number /// of rows and columns will be computed from the cellSize and input featureset</param> /// <param name="cancelProgressHandler">A progress handler for receiving progress messages</param> /// <returns>A boolean, true if the IDW process worked correctly</returns> public bool Execute(IFeatureSet input, string zField, double cellSize, double power, NeighborhoodType neighborType, int pointCount, double distance, IRaster output, ICancelProgressHandler cancelProgressHandler) { //Validates the input and output data if (input == null || output == null) return false; //If the cellSize is 0 we calculate a cellsize based on the input extents if (cellSize == 0) cellSize = input.Envelope.Width / 255; //Defines the dimesions and position of the raster int numColumns = Convert.ToInt32(Math.Round(input.Envelope.Width / cellSize)); int numRows = Convert.ToInt32(Math.Round(input.Envelope.Height / cellSize)); output = Raster.Create(output.Filename, "",numColumns, numRows, 1, typeof(double), new[] {""} ); output.CellHeight = cellSize; output.CellWidth = cellSize; output.Xllcenter = input.Envelope.Minimum.X + (cellSize/2); output.Yllcenter = input.Envelope.Minimum.Y + (cellSize/2); //Used to calculate progress int lastUpdate=0; //Populates the KD tree MapWindow.Analysis.Topology.KDTree.KDTree kd = new MapWindow.Analysis.Topology.KDTree.KDTree(2); List<int> randomList = new List<int>(); for (int i = 0; i < input.Features.Count; i++) { randomList.Add(i); } Random rnd = new Random(); List<int> completed = new List<int>(); while (randomList.Count > 0) { int index = rnd.Next(0,randomList.Count -1); Coordinate coord = input.Features[randomList[index]].Coordinates[0]; while (kd.Search(coord.ToArray()) != null) coord.X = coord.X * 1.000000000000001D; kd.Insert(coord.ToArray(), input.Features[randomList[index]]); completed.Add(randomList[index]); randomList.RemoveAt(index); } System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); //Makes sure we don't try to search for more points then exist if (kd.Count < pointCount) pointCount = kd.Count; if (neighborType == NeighborhoodType.FixedCount) { //we add all the old features to output for (int x = 0; x < numColumns; x++) { for (int y = 0; y < numRows; y++) { //Gets the pointCount number of cells closest to the current cell Coordinate cellCenter = output.CellToProj(y, x); Double[] pixelCoord = new double[2]; pixelCoord[0] = output.CellToProj(y, x).X; pixelCoord[1] = output.CellToProj(y, x).Y; sw.Start(); object[] result = kd.Nearest(pixelCoord, pointCount); sw.Stop(); //Sets up the IDW numerator and denominator double top = 0; double bottom = 0; foreach (object feat in result) { IFeature featurePt = feat as Feature; if (featurePt == null) continue; double distanceToCell = cellCenter.Distance(featurePt.Coordinates[0]); if (distanceToCell <= distance || distance == 0) { //If we can't convert the value to a double throw it out try { Convert.ToDouble(featurePt.DataRow[zField]); } catch { continue; } if (power == 2) { top += (1 / (distanceToCell * distanceToCell)) * Convert.ToDouble(featurePt.DataRow[zField]); bottom += (1 / (distanceToCell* distanceToCell)); } else { top += (1 / Math.Pow(distanceToCell, power)) * Convert.ToDouble(featurePt.DataRow[zField]); bottom += (1 / Math.Pow(distanceToCell, power)); } } } output.Value[y, x] = top / bottom; } //Checks if we need to update the status bar if (Convert.ToInt32(Convert.ToDouble(x*numRows ) / Convert.ToDouble(numColumns * numRows) * 100) > lastUpdate) { lastUpdate = Convert.ToInt32(Convert.ToDouble(x * numRows) / Convert.ToDouble(numColumns * numRows) * 100); cancelProgressHandler.Progress("", lastUpdate, "Cell: " + (x * numRows) + " of " + (numColumns * numRows)); if (cancelProgressHandler.Cancel) return false; } } System.Diagnostics.Debug.WriteLine(sw.ElapsedMilliseconds); } output.Save(); return true; }
private double KDTreeTestForecastingValue(List <double> QPreviousT, List <double> QT, int KValue) { MapWindow.Analysis.Topology.KDTree.KDTree KD = new MapWindow.Analysis.Topology.KDTree.KDTree(2); double[] Corordinates = new double[2]; for (int i = 1; i < QT.Count; i++) { //X Coordinate for Previous Day records [t-1] Corordinates[0] = QPreviousT[i]; //Y Coordinate for Current Day records [t] Corordinates[1] = QT[i]; object Val = (object)(Corordinates); KD.Insert(Corordinates, Val); } //This is guess X coordinate value,which means the one day before the forecasting day value double LastdayValue = QT[QT.Count - 1]; double PreviousDay = QPreviousT[QPreviousT.Count - 1]; //This is guess Y coordinate value,which means the forecasting day value double GuessValue = LastdayValue + ((LastdayValue - PreviousDay) / 2); double[] Finalcheck = new double[2]; //X Coordinate Finalcheck[0] = LastdayValue; //Y Coordinate Finalcheck[1] = GuessValue; object[] val = KD.Nearest(Finalcheck, KValue); double XDistance; double XSqrDistance; double YDistance; double YSqrDistance; List <double> finalDistnace = new List <double>(); List <double> finalWeights = new List <double>(); double weight = 0; double distance = 0; for (int j = 0; j < val.Length; j++) { double[] val2 = (double[])(val[j]); XDistance = LastdayValue - val2[0]; XSqrDistance = XDistance * XDistance; YDistance = GuessValue - val2[1]; finalWeights.Add(val2[1]); YSqrDistance = YDistance * YDistance; finalDistnace.Add(Math.Sqrt(XSqrDistance + YSqrDistance)); } for (int k = 0; k < finalDistnace.Count; k++) { if (finalDistnace[k] == 0) { weight += finalWeights[k] / 1.0; distance += 1 / 1.0; } else { weight += finalWeights[k] / finalDistnace[k]; distance += 1 / finalDistnace[k]; } } double forecastingValue = weight / distance; // KD.Delete(Corordinates); return(forecastingValue); }