private static int GetIDWNeighborsBrute(InterpolationPoint InCellPoint, ref List <InterpolationPoint> InPointCache, out List <InterpolationPoint> OutNeighbors, IDWNeighborhoodType NeighborhoodType, int NeighborhoodCount, double NeighborhoodDistance, string ProjUnits)
        {
            SortInterpolationPointsByDistanceBrute(InCellPoint, ref InPointCache, ProjUnits);

            OutNeighbors = new List <InterpolationPoint>();
            int numPts = 0;

            if (NeighborhoodType == IDWNeighborhoodType.Variable) //Taking NeighborhoodCount number of nearest points
            {
                if (NeighborhoodDistance == -1)                   //Then take NeighborhoodCount number of nearest points
                {
                    foreach (InterpolationPoint npoint in InPointCache)
                    {
                        OutNeighbors.Add(new InterpolationPoint(npoint.X, npoint.Y, npoint.Value, npoint.Distance));
                        numPts++;
                        if (numPts >= NeighborhoodCount)
                        {
                            break;
                        }
                    }
                }
                else //Take NeighborhoodCount of nearest points that are a maximum of NeighborhoodDistance away
                {
                    foreach (InterpolationPoint npoint in InPointCache)
                    {
                        if (npoint.Distance <= NeighborhoodDistance)
                        {
                            OutNeighbors.Add(new InterpolationPoint(npoint.X, npoint.Y, npoint.Value, npoint.Distance));
                            numPts++;
                            if (numPts >= NeighborhoodCount)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            else if (NeighborhoodType == IDWNeighborhoodType.Fixed) //Taking all points in fixed distance
            {
                foreach (InterpolationPoint npoint in InPointCache)
                {
                    if (npoint.Distance <= NeighborhoodDistance)
                    {
                        OutNeighbors.Add(new InterpolationPoint(npoint.X, npoint.Y, npoint.Value, npoint.Distance));
                    }
                }
                if (OutNeighbors.Count < NeighborhoodCount) //Test for minimum number of points found
                {
                    return(-1);
                    //Error
                }
            }
            else
            {
                return(-1);
                //Error
            }
            return(0);
        }
        /// <summary>
        /// Inverse Distance Weighting Interpolation
        /// </summary>
        /// <param name="InPointsPath">Input point shapefile path to interpolate</param>
        /// <param name="InValueFieldIndex">Input field index where interpolation value is stored</param>
        /// <param name="OutGridPath">Output grid path where interpolation is stored</param>
        /// <param name="CellSize">Cell Size for output grid. Default lower of points extent height or width divided by 250</param>
        /// <param name="Power">Power variable for IDW algorithm. 0 lt p lt 1 will give sharp changes. >1 will give smoother. Default 2.</param>
        /// <param name="NeighborhoodType">Variable is a variable number of nearest points. Fixed is all points in a fixed distance</param>
        /// <param name="NeighborhoodCount">Variable Count is either number of nearest points to use. Fixed Count is minimum points needed to find valid interpolation</param>
        /// <param name="NeighborhoodDistance">Variable Distance is a maximum distance of nearest points. Fixed Distance is distance to use to select points</param>
        /// <param name="callback">A callback for progress information</param>
        public static void IDWBrute(string InPointsPath, int InValueFieldIndex, string OutGridPath, double CellSize, double Power, IDWNeighborhoodType NeighborhoodType, int NeighborhoodCount, double NeighborhoodDistance, MapWinGIS.ICallback callback)
        {
            int newperc = 0, oldperc = 0;

            List <InterpolationPoint> pointsCache;
            string proj, projUnits;

            MapWinGIS.Extents pointsExtents;
            CachePointsBrute(InPointsPath, InValueFieldIndex, out pointsCache, out proj, out projUnits, out pointsExtents, callback);

            MapWinGIS.Grid outGrid;
            DataManagement.DeleteGrid(ref OutGridPath);
            double NoDataValue = -32768;

            CreateGridFromExtents(pointsExtents, CellSize, proj, NoDataValue, OutGridPath, out outGrid);

            //Cycle grid and find interpolated value for each cell
            List <InterpolationPoint> neighbors;
            InterpolationPoint        cellPoint;
            int    nr = outGrid.Header.NumberRows;
            int    nc = outGrid.Header.NumberCols;
            double sumWeight, sumWeightAndVal;

            newperc = 0;
            oldperc = 0;
            for (int row = 0; row < nr; row++)
            {
                newperc = Convert.ToInt32((Convert.ToDouble(row) / Convert.ToDouble(nr)) * 100);
                if (callback != null)
                {
                    callback.Progress("Status", newperc, "IDW Row " + row);
                }

                newperc = 0;
                oldperc = 0;
                for (int col = 0; col < nc; col++)
                {
                    newperc = Convert.ToInt32((Convert.ToDouble(col) / Convert.ToDouble(nc)) * 100);
                    if ((newperc > oldperc))
                    {
                        if (callback != null)
                        {
                            callback.Progress("Status", newperc, "IDW Row " + row.ToString() + "  Col " + col.ToString());
                        }
                        oldperc = newperc;
                    }

                    cellPoint = new InterpolationPoint();
                    outGrid.CellToProj(col, row, out cellPoint.X, out cellPoint.Y);
                    GetIDWNeighborsBrute(cellPoint, ref pointsCache, out neighbors, NeighborhoodType, NeighborhoodCount, NeighborhoodDistance, projUnits);

                    sumWeightAndVal = 0;
                    sumWeight       = 0;

                    foreach (InterpolationPoint npoint in neighbors)
                    {
                        sumWeightAndVal += GetIDWeightBrute(cellPoint, npoint, projUnits, Power) * npoint.Value;
                        sumWeight       += GetIDWeightBrute(cellPoint, npoint, projUnits, Power);
                    }

                    outGrid.set_Value(col, row, (sumWeightAndVal / sumWeight));
                }
            }

            outGrid.Save(OutGridPath, MapWinGIS.GridFileType.UseExtension, null);
            outGrid.Close();
        }
        private static int GetIDWNeighbors(double[] InCellPoint, ref KDTreeDLL.KDTree InPointsTree, ref double[][] InPoints, out int[] Neighbors, IDWNeighborhoodType NeighborhoodType, int NeighborhoodCount, double NeighborhoodDistance, string ProjUnits)
        {
            int tmpIdx;

            Neighbors = new int[1];
            if (NeighborhoodType == IDWNeighborhoodType.Variable) //Taking NeighborhoodCount number of nearest points
            {
                if (NeighborhoodDistance == -1)                   //Then take NeighborhoodCount number of nearest points
                {
                    Object[] ptIndexObjs = InPointsTree.nearest(InCellPoint, NeighborhoodCount);
                    if (ptIndexObjs.Length == 0)
                    {
                        return(-1);
                    }
                    Neighbors = new int[ptIndexObjs.Length];
                    for (int i = 0; i < ptIndexObjs.Length; i++)
                    {
                        Neighbors[i] = (int)ptIndexObjs[i];
                    }
                }
                else //Take NeighborhoodCount of nearest points that are a maximum of NeighborhoodDistance away
                {
                    Object[] ptIndexObjs = InPointsTree.nearest(InCellPoint, NeighborhoodCount);
                    if (ptIndexObjs.Length == 0)
                    {
                        return(-1);
                    }
                    Neighbors = new int[ptIndexObjs.Length];
                    for (int i = 0; i < ptIndexObjs.Length; i++)
                    {
                        tmpIdx = (int)ptIndexObjs[i];
                        if (SpatialOperations.Distance(InCellPoint[0], InCellPoint[1], InPoints[tmpIdx][0], InPoints[tmpIdx][1], ProjUnits) <= NeighborhoodDistance)
                        {
                            Neighbors[i] = tmpIdx;
                        }
                        else
                        {
                            Neighbors[i] = -1;
                        }
                    }
                }
            }
            else if (NeighborhoodType == IDWNeighborhoodType.Fixed) //Taking all points in fixed distance
            {
                //Something

                //if (OutNeighbors.Count < NeighborhoodCount) //Test for minimum number of points found
                //{
                //    return -1;
                //    //Error
                //}
            }
            else
            {
                return(-1);
                //Error
            }
            return(0);
        }
        /// <summary>
        /// Inverse Distance Weighting Interpolation
        /// </summary>
        /// <param name="InPointsPath">Input point shapefile path to interpolate</param>
        /// <param name="InValueFieldIndex">Input field index where interpolation value is stored</param>
        /// <param name="OutGridPath">Output grid path where interpolation is stored</param>
        /// <param name="CellSize">Cell Size for output grid. Default lower of points extent height or width divided by 250</param>
        /// <param name="Power">Power variable for IDW algorithm. 0 lt p lt 1 will give sharp changes. >1 will give smoother. Default 2.</param>
        /// <param name="NeighborhoodType">Variable is a variable number of nearest points. Fixed is all points in a fixed distance</param>
        /// <param name="NeighborhoodCount">Variable Count is either number of nearest points to use. Fixed Count is minimum points needed to find valid interpolation</param>
        /// <param name="NeighborhoodDistance">Variable Distance is a maximum distance of nearest points. Fixed Distance is distance to use to select points</param>
        /// <param name="callback">A callback for progress information</param>
        public static void IDW(string InPointsPath, int InValueFieldIndex, string OutGridPath, double CellSize, double Power, IDWNeighborhoodType NeighborhoodType, int NeighborhoodCount, double NeighborhoodDistance, MapWinGIS.ICallback callback)
        {
            int newperc = 0, oldperc = 0;

            KDTreeDLL.KDTree pointsTree;
            double[][]       Points;
            double[]         PointVals;
            string           proj, projUnits;

            MapWinGIS.Extents pointsExtents;
            CachePoints(InPointsPath, InValueFieldIndex, out pointsTree, out Points, out PointVals, out proj, out projUnits, out pointsExtents, callback);

            MapWinGIS.Grid outGrid;
            DataManagement.DeleteGrid(ref OutGridPath);
            double NoDataValue = -32768;

            CreateGridFromExtents(pointsExtents, CellSize, proj, NoDataValue, OutGridPath, out outGrid);

            //Cycle grid and find interpolated value for each cell

            int    nr = outGrid.Header.NumberRows;
            int    nc = outGrid.Header.NumberCols;
            double sumWeight, sumWeightAndVal, projX, projY;

            int[]    neighbors;
            double[] CellPoint;
            newperc = 0;
            oldperc = 0;
            for (int row = 0; row < nr; row++)
            {
                newperc = Convert.ToInt32((Convert.ToDouble(row) / Convert.ToDouble(nr)) * 100);
                if (callback != null)
                {
                    callback.Progress("Status", newperc, "IDW Row " + row.ToString() + "/" + nr.ToString());
                }
                oldperc = newperc;

                newperc = 0;
                oldperc = 0;
                for (int col = 0; col < nc; col++)
                {
                    outGrid.CellToProj(col, row, out projX, out projY);
                    CellPoint    = new double[2];
                    CellPoint[0] = projX;
                    CellPoint[1] = projY;

                    if (GetIDWNeighbors(CellPoint, ref pointsTree, ref Points, out neighbors, NeighborhoodType, NeighborhoodCount, NeighborhoodDistance, projUnits) == 0)
                    {
                        sumWeightAndVal = 0;
                        sumWeight       = 0;

                        for (int i = 0; i < neighbors.Length; i++)
                        {
                            sumWeightAndVal += GetIDWeight(CellPoint, Points[neighbors[i]], projUnits, Power) * PointVals[neighbors[i]];
                            sumWeight       += GetIDWeight(CellPoint, Points[neighbors[i]], projUnits, Power);
                        }
                        outGrid.set_Value(col, row, (sumWeightAndVal / sumWeight));
                    }
                }
            }

            outGrid.Save(OutGridPath, MapWinGIS.GridFileType.UseExtension, null);
            outGrid.Close();
            if (callback != null)
            {
                callback.Progress("Status", 0, "");
            }
        }
 /// <summary>
 /// Inverse Distance Weighting Interpolation
 /// </summary>
 /// <param name="InPointsPath">Input point shapefile path to interpolate</param>
 /// <param name="InValueFieldIndex">Input field index where interpolation value is stored</param>
 /// <param name="OutGridPath">Output grid path where interpolation is stored</param>
 /// <param name="CellSize">Cell Size for output grid. Default lower of points extent height or width divided by 250</param>
 /// <param name="Power">Power variable for IDW algorithm. 0 lt p lt 1 will give sharp changes. >1 will give smoother. Default 2.</param>
 /// <param name="NeighborhoodType">Variable is a variable number of nearest points. Fixed is all points in a fixed distance</param>
 public static void IDW(string InPointsPath, int InValueFieldIndex, string OutGridPath, double CellSize, double Power, IDWNeighborhoodType NeighborhoodType)
 {
     if (NeighborhoodType == IDWNeighborhoodType.Variable)
     {
         IDW(InPointsPath, InValueFieldIndex, OutGridPath, CellSize, Power, NeighborhoodType, 12, -1, null);
     }
     else
     {
         IDW(InPointsPath, InValueFieldIndex, OutGridPath, CellSize, Power, NeighborhoodType, 0, 5 * CellSize, null);
     }
 }
 /// <summary>
 /// Inverse Distance Weighting Interpolation
 /// </summary>
 /// <param name="InPointsPath">Input point shapefile path to interpolate</param>
 /// <param name="InValueFieldIndex">Input field index where interpolation value is stored</param>
 /// <param name="OutGridPath">Output grid path where interpolation is stored</param>
 /// <param name="CellSize">Cell Size for output grid. Default lower of points extent height or width divided by 250</param>
 /// <param name="NeighborhoodType">Variable is a variable number of nearest points. Fixed is all points in a fixed distance</param>
 public static void IDW(string InPointsPath, int InValueFieldIndex, string OutGridPath, double CellSize, IDWNeighborhoodType NeighborhoodType)
 {
     IDW(InPointsPath, InValueFieldIndex, OutGridPath, CellSize, 2.0, NeighborhoodType);
 }