/// <summary>
        /// Returns an in-memory shapefile of points from the input shapefile that fall within the polygon.
        /// </summary>
        /// <param name="pointSF">Full path to the point shapefile.</param>
        /// <param name="polygon">The polygon used for clipping the point shapefile.</param>
        /// <param name="result">Full path to where the resulting point shapefile should be saved.</param>
        /// <param name="copyAttributes">True if copying attributes over</param>
        /// <returns>False if an error was encountered, true otherwise.</returns>
        public static bool ClipPointSFWithPolygon(ref MapWinGIS.Shapefile pointSF, ref MapWinGIS.Shape polygon, out MapWinGIS.Shapefile result, bool copyAttributes)
        {
            MapWinUtility.Logger.Dbg("ClipPointSFWithPolygon(pointSF: " + Macro.ParamName(pointSF) + ",\n" +
                                     "                       polygon: " + Macro.ParamName(polygon) + ",\n" +
                                     "                       result: out, \n" +
                                     "                       copyAttributes: " + copyAttributes.ToString() + ",\n");
            MapWinGIS.Shapefile resultSF = new MapWinGIS.ShapefileClass();
            int shpIndex = 0;             //all new shapes will be placed at the beginning of the shapefile

            MapWinGIS.ShpfileType sfType = pointSF.ShapefileType;

            //make sure we are dealing with a valid shapefile type
            if (sfType == MapWinGIS.ShpfileType.SHP_POINT || sfType == MapWinGIS.ShpfileType.SHP_POINTM || sfType == MapWinGIS.ShpfileType.SHP_POINTZ)
            {
                string tempPath = System.IO.Path.GetTempPath() + "resultSF.shp";
                DataManagement.DeleteShapefile(ref tempPath);
                string tmpName;
                //create the result shapeFile if it does not already exist
                //if(resultSF.CreateNew(tempPath, sfType) == false)
                //{
                //    gErrorMsg = "Problem creating the result shapeFile: " + resultSF.get_ErrorMsg(resultSF.LastErrorCode);
                //    Debug.WriteLine(gErrorMsg);
                //    MapWinGeoProc.Error.SetErrorMsg(gErrorMsg);
                //    result = resultSF;
                //    return false;
                //}
                //CDM 8/4/2006 resultSF.CreateNew(resultSFPath, sfType);
                Globals.PrepareResultSF(ref tempPath, ref resultSF, sfType);

                if (copyAttributes)
                {
                    MapWinGIS.Field tmpField, pointField;
                    for (int f = 0; f <= pointSF.NumFields - 1; f++)
                    {
                        tmpField   = new MapWinGIS.Field();
                        pointField = pointSF.get_Field(f);
                        tmpName    = pointField.Name;
                        if (tmpName.Contains("MWShapeID"))
                        {
                            tmpField.Name = "Last_" + tmpName;
                        }
                        else
                        {
                            tmpField.Name = tmpName;
                        }
                        tmpField.Width     = pointField.Width;
                        tmpField.Type      = pointField.Type;
                        tmpField.Precision = pointField.Precision;
                        tmpField.Key       = pointField.Key;
                        resultSF.EditInsertField(tmpField, ref f, null);
                    }
                }

                int             numTargetPoints = pointSF.NumShapes;
                MapWinGIS.Point targetPoint     = new MapWinGIS.PointClass();
                //MapWinGIS.Utils utils = new MapWinGIS.UtilsClass();
                int numParts = polygon.NumParts;
                if (numParts == 0)
                {
                    numParts = 1;
                }
                Globals.Vertex[][] polyVertArray = new Globals.Vertex[numParts][];
                Globals.ConvertPolyToVertexArray(ref polygon, out polyVertArray);

                for (int i = 0; i <= numTargetPoints - 1; i++)
                {
                    targetPoint = pointSF.QuickPoint(i, 0);

                    if (Utils.PointInPoly(ref polyVertArray, ref targetPoint) == true)
                    {
                        resultSF.EditInsertShape(pointSF.get_Shape(i), ref shpIndex);
                        if (copyAttributes)
                        {
                            for (int f = 0; f <= pointSF.NumFields - 1; f++)
                            {
                                bool tmpbool = resultSF.EditCellValue(f, shpIndex, pointSF.get_CellValue(f, i));
                            }
                        }
                    }
                }
            }
            else
            {
                gErrorMsg = "The shapefile is of the wrong type. Should be of type Point.";
                Debug.WriteLine(gErrorMsg);
                MapWinGeoProc.Error.SetErrorMsg(gErrorMsg);
                result = resultSF;
                MapWinUtility.Logger.Dbg(gErrorMsg);
                return(false);
            }
            result = resultSF;
            MapWinUtility.Logger.Dbg("Finished ClipPointSFWithPolygon");
            return(true);
        }
Exemple #2
0
        /// <summary>
        /// Exports the shapes that are selected in the MapWindow view to a new shapefile.
        /// </summary>
        /// <param name="MapWin">A reference to the running MapWindow.</param>
        /// <param name="ExportToSFPath">The full path to where the result shapefile should be saved.</param>
        /// <param name="AddToMap">Indicates that the output should be added to the map view immediately.</param>
        /// <returns>False if an error occurs, true otherwise.</returns>
        public static bool ExportSelectedMWViewShapes(MapWindow.Interfaces.IMapWin MapWin, string ExportToSFPath, bool AddToMap)
        {
            MapWinUtility.Logger.Dbg("ExportSelectedMWViewShapes(MapWin: IMapWin,\n" +
                                     "                           ExportToSFPath: " + ExportToSFPath + ",\n" +
                                     "                           AddToMap: " + AddToMap.ToString() + ")");

            if (MapWin.Layers.NumLayers == 0)
            {
                gErrorMsg = "Please select a layer first.";
                Error.SetErrorMsg(gErrorMsg);
                MapWinUtility.Logger.Dbg(gErrorMsg);
                return(false);
            }
            if (MapWin.View.SelectedShapes.NumSelected == 0)
            {
                gErrorMsg = "There are no selected features to export. Please select a feature first.";
                Error.SetErrorMsg(gErrorMsg);
                MapWinUtility.Logger.Dbg(gErrorMsg);
                return(false);
            }
            MapWinGIS.Shapefile sf     = new MapWinGIS.Shapefile();
            MapWinGIS.Shapefile tollSF = new MapWinGIS.Shapefile();
            MapWinGIS.Field     fld    = new MapWinGIS.Field();
            MapWinGIS.Shape     seg    = new MapWinGIS.Shape();
            int  Segments;
            bool Status;

            Status = sf.Open(MapWin.Layers[MapWin.Layers.CurrentLayer].FileName, null);
            if (Status == false)
            {
                gErrorMsg = sf.get_ErrorMsg(sf.LastErrorCode);
                Error.SetErrorMsg(gErrorMsg);
                MapWinUtility.Logger.Dbg(gErrorMsg);
                return(false);
            }

            if (System.IO.File.Exists(ExportToSFPath))
            {
                try
                {
                    DataManagement.DeleteShapefile(ref ExportToSFPath);
                }
                catch
                {
                    gErrorMsg = "The destination file already exists, but could not be deleted. Please check to make sure the file isn't in use.";
                    Error.SetErrorMsg(gErrorMsg);
                    MapWinUtility.Logger.Dbg(gErrorMsg);
                    return(false);
                }
            }

            Status = tollSF.CreateNew(ExportToSFPath, sf.ShapefileType);

            if (Status == false)
            {
                gErrorMsg = tollSF.get_ErrorMsg(tollSF.LastErrorCode);
                Error.SetErrorMsg(gErrorMsg);
                MapWinUtility.Logger.Dbg(gErrorMsg);
                return(false);
            }

            try
            {
                tollSF.Projection = sf.Projection;
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine(e.ToString());
            }

            Status = tollSF.StartEditingShapes(true, null);
            if (Status == false)
            {
                gErrorMsg = tollSF.get_ErrorMsg(tollSF.LastErrorCode);
                Error.SetErrorMsg(gErrorMsg);
                MapWinUtility.Logger.Dbg(gErrorMsg);
                return(false);
            }
            fld.Name  = "MWShapeID";
            fld.Type  = MapWinGIS.FieldType.INTEGER_FIELD;
            fld.Width = 12;
            Segments  = 0;

            // Chris M -- This is already opened above, why open
            // it again here?
            // sf.Open(MapWin.Layers[MapWin.Layers.CurrentLayer].FileName, null);

            for (int j = 0; j <= sf.NumFields - 1; j++)
            {
                tollSF.EditInsertField(sf.get_Field(j), ref j, null);
            }
            MapWin.View.MapCursor = MapWinGIS.tkCursor.crsrWait;
            try
            {
                for (int i = 0; i <= MapWin.View.SelectedShapes.NumSelected - 1; i++)
                {
                    seg    = sf.get_Shape(MapWin.View.SelectedShapes[i].ShapeIndex);
                    Status = tollSF.EditInsertShape(seg, ref Segments);
                    if (Status == false)
                    {
                        gErrorMsg = tollSF.get_ErrorMsg(tollSF.LastErrorCode);
                        Error.SetErrorMsg(gErrorMsg);
                        MapWinUtility.Logger.Dbg(gErrorMsg);
                        return(false);
                    }
                    for (int h = 0; h <= sf.NumFields - 1; h++)
                    {
                        tollSF.EditCellValue(h, i, sf.get_CellValue(h, MapWin.View.SelectedShapes[i].ShapeIndex));
                    }
                    Segments = Segments + 1;
                }
                sf.Close();
                tollSF.StopEditingShapes(true, true, null);
            }
            catch (Exception ex)
            {
                gErrorMsg = ex.Message;
                Error.SetErrorMsg(gErrorMsg);
                MapWinUtility.Logger.Dbg(gErrorMsg);
            }
            MapWin.View.MapCursor = MapWinGIS.tkCursor.crsrArrow;
            tollSF.Close();
            if (AddToMap)
            {
                MapWin.View.LockMap();
                MapWindow.Interfaces.Layer thelayer;
                thelayer = MapWin.Layers.Add(ExportToSFPath, System.IO.Path.GetFileNameWithoutExtension(ExportToSFPath), true);
                thelayer.ClearLabels();
                MapWin.View.UnlockMap();
            }
            MapWinUtility.Logger.Dbg("Finished ExportSelectedMWViewShapes");
            return(true);
        }
        /// <summary>
        /// Removes portions of the lineSF that fall within the erase polygon
        /// </summary>
        /// <param name="lineSF">The shapefile of lines to be erased.</param>
        /// <param name="erasePoly">The polygon to be used for erasing portion of the line shapefile.</param>
        /// <param name="resultSF">The resulting line shapefile with portions removed.</param>
        /// <param name="CopyAttributes">Indicates whether to copy attributes</param>
        /// <returns>False if an error was encountered, true otherwise.</returns>
        public static bool EraseLineSFWithPoly(ref MapWinGIS.Shapefile lineSF, ref MapWinGIS.Shape erasePoly, ref MapWinGIS.Shapefile resultSF, bool CopyAttributes)
        {
            MapWinUtility.Logger.Dbg("EraseLineSFWithPoly(lineSF: " + Macro.ParamName(lineSF) + ",\n" +
                                     "                    erasePoly: " + Macro.ParamName(erasePoly) + ",\n" +
                                     "                    resultSF: " + Macro.ParamName(resultSF) + ",\n" +
                                     "                    CopyAttributes: " + CopyAttributes.ToString() + ")");
            if (lineSF == null || erasePoly == null || resultSF == null)
            {
                gErrorMsg = "One of the input parameters is null.";
                Error.SetErrorMsg(gErrorMsg);
                Debug.WriteLine(gErrorMsg);
                MapWinUtility.Logger.Dbg(gErrorMsg);
                return(false);
            }

            if (CopyAttributes)
            {
                string          tmpName;
                MapWinGIS.Field tmpField, currField;
                for (int f = 0; f <= lineSF.NumFields - 1; f++)
                {
                    tmpField      = new MapWinGIS.Field();
                    currField     = lineSF.get_Field(f);
                    tmpName       = currField.Name;
                    tmpField.Name = tmpName;

                    tmpField.Width     = currField.Width;
                    tmpField.Type      = currField.Type;
                    tmpField.Precision = currField.Precision;
                    tmpField.Key       = currField.Key;
                    resultSF.EditInsertField(tmpField, ref f, null);
                }
            }

            int shpIndex = 0;
            int numLines = lineSF.NumShapes;

            for (int i = 0; i <= numLines - 1; i++)
            {
                MapWinGIS.Shape currLine = new MapWinGIS.ShapeClass();
                currLine.Create(lineSF.ShapefileType);
                currLine = lineSF.get_Shape(i);

                MapWinGIS.Shape lineEnvelope = new MapWinGIS.ShapeClass();
                lineEnvelope.Create(MapWinGIS.ShpfileType.SHP_POLYGON);
                //create lineExtents' points out of the line extent points
                MapWinGIS.Point lTop, rTop, rBottom, lBottom;
                lTop      = new MapWinGIS.PointClass();
                lTop.x    = currLine.Extents.xMin;
                lTop.y    = currLine.Extents.yMax;
                rTop      = new MapWinGIS.PointClass();
                rTop.x    = currLine.Extents.xMax;
                rTop.y    = currLine.Extents.yMax;
                rBottom   = new MapWinGIS.PointClass();
                rBottom.x = currLine.Extents.xMax;
                rBottom.y = currLine.Extents.yMin;
                lBottom   = new MapWinGIS.PointClass();
                lBottom.x = currLine.Extents.xMin;
                lBottom.y = currLine.Extents.yMin;
                //now add the extent points to the new polygon shape: lineEnvelope
                int ptIndex = 0;
                lineEnvelope.InsertPoint(lTop, ref ptIndex);
                ptIndex++;
                lineEnvelope.InsertPoint(rTop, ref ptIndex);
                ptIndex++;
                lineEnvelope.InsertPoint(rBottom, ref ptIndex);
                ptIndex++;
                lineEnvelope.InsertPoint(lBottom, ref ptIndex);
                ptIndex++;
                lineEnvelope.InsertPoint(lTop, ref ptIndex);
                //remove COM points from memory
                while (Marshal.ReleaseComObject(lTop) != 0)
                {
                    ;
                }
                while (Marshal.ReleaseComObject(rTop) != 0)
                {
                    ;
                }
                while (Marshal.ReleaseComObject(rBottom) != 0)
                {
                    ;
                }
                while (Marshal.ReleaseComObject(lBottom) != 0)
                {
                    ;
                }

                //Check if line extents and polygon extents overlap
                if (Globals.CheckBounds(ref lineEnvelope, ref erasePoly))
                {
                    //make the envelope polygon slightly larger
                    MapWinGIS.Shape lgEnvelope = new MapWinGIS.ShapeClass();
                    lgEnvelope.Create(MapWinGIS.ShpfileType.SHP_POLYGON);
                    SpatialOperations.BufferPolygon(ref lineEnvelope, 0.5, Enumerations.Buffer_HoleTreatment.Ignore, Enumerations.Buffer_CapStyle.Pointed, out lgEnvelope);
                    //take the difference of the envelope polygon with the erase polygon.
                    MapWinGIS.Shape diff = new MapWinGIS.ShapeClass();
                    diff.Create(MapWinGIS.ShpfileType.SHP_POLYGON);
                    diff = SpatialOperations.Difference(lgEnvelope, erasePoly);
                    if (diff.numPoints > 0)
                    {
                        //the difference shape represents the line envelope
                        //minus the area of the erase polygon.
                        MapWinGIS.Shapefile inputLine = new MapWinGIS.ShapefileClass();
                        string tempPath = System.IO.Path.GetTempPath() + "tempInputLine.shp";
                        //CDM 8/4/2006 inputLine.CreateNew(tempPath, lineSF.ShapefileType);
                        Globals.PrepareResultSF(ref tempPath, ref inputLine, lineSF.ShapefileType);
                        shpIndex = 0;
                        inputLine.EditInsertShape(currLine, ref shpIndex);

                        int numParts = diff.NumParts;
                        if (numParts == 0)
                        {
                            numParts = 1;
                        }

                        if (numParts > 1)
                        {
                            //separate and test each part individually
                            MapWinGIS.Shape[] diffParts = new MapWinGIS.Shape[numParts];
                            Globals.SeparateParts(ref diff, out diffParts);
                            for (int j = 0; j <= numParts - 1; j++)
                            {
                                //don't check inside of holes
                                if (Globals.IsClockwise(ref diffParts[j]))
                                {
                                    MapWinGIS.Shapefile tempLineResult = new MapWinGIS.ShapefileClass();
                                    string tempLineFile = System.IO.Path.GetTempPath() + "tempLines.shp";
                                    DataManagement.DeleteShapefile(ref tempLineFile);
                                    //CDM 8/4/2006 tempLineResult.CreateNew(tempLineFile, lineSF.ShapefileType);
                                    Globals.PrepareResultSF(ref tempLineFile, ref tempLineResult, lineSF.ShapefileType);
                                    tempLineResult.StartEditingShapes(true, null);

                                    SpatialOperations.ClipShapesWithPolygon(ref inputLine, ref diffParts[j], out tempLineResult, false);

                                    int numResults = tempLineResult.NumShapes;
                                    if (numResults > 0)
                                    {
                                        //add results to the final result file.
                                        for (int k = 0; k <= numResults - 1; k++)
                                        {
                                            shpIndex = resultSF.NumShapes;
                                            resultSF.EditInsertShape(tempLineResult.get_Shape(k), ref shpIndex);
                                            if (CopyAttributes)
                                            {
                                                for (int f = 0; f <= lineSF.NumFields - 1; f++)
                                                {
                                                    bool tmpbool = resultSF.EditCellValue(f, shpIndex, lineSF.get_CellValue(f, i));
                                                }
                                            }
                                        }
                                    }                    //clipping successful
                                }                        //done checking islands
                            }                            //done looping through parts of the difference shape
                        }
                        else
                        {
                            MapWinGIS.Shapefile tempLineResult = new MapWinGIS.ShapefileClass();
                            string tempLineFile = System.IO.Path.GetTempPath() + "tempLines.shp";
                            DataManagement.DeleteShapefile(ref tempLineFile);
                            //CDM 8/4/2006 tempLineResult.CreateNew(tempLineFile, lineSF.ShapefileType);
                            Globals.PrepareResultSF(ref tempLineFile, ref tempLineResult, lineSF.ShapefileType);

                            tempLineResult.StartEditingShapes(true, null);

                            SpatialOperations.ClipShapesWithPolygon(ref inputLine, ref diff, out tempLineResult, false);

                            int numResults = tempLineResult.NumShapes;
                            if (numResults > 0)
                            {
                                //add results to the final result file.
                                for (int k = 0; k <= numResults - 1; k++)
                                {
                                    shpIndex = resultSF.NumShapes;
                                    resultSF.EditInsertShape(tempLineResult.get_Shape(k), ref shpIndex);
                                    if (CopyAttributes)
                                    {
                                        for (int f = 0; f <= lineSF.NumFields - 1; f++)
                                        {
                                            bool tmpbool = resultSF.EditCellValue(f, shpIndex, lineSF.get_CellValue(f, i));
                                        }
                                    }
                                }
                            }    //clipping successful
                        }
                    }            //difference operation successful
                }                //bounds overlapped
                else
                {
                    shpIndex = resultSF.NumShapes;
                    resultSF.EditInsertShape(currLine, ref shpIndex);
                    if (CopyAttributes)
                    {
                        for (int f = 0; f <= lineSF.NumFields - 1; f++)
                        {
                            bool tmpbool = resultSF.EditCellValue(f, shpIndex, lineSF.get_CellValue(f, i));
                        }
                    }
                }
            }            //end of looping through lines in the input shapefile
            MapWinUtility.Logger.Dbg("Finished EraseLineSFWithPoly");
            return(true);
        }
        /// <summary>
        /// Returns the portions of the polygons in polySF that lie within polygon as a
        /// new shapefile of polygons: resultPolySF.
        /// </summary>
        /// <param name="polySF">The shapefile of polygons that are to be clipped.</param>
        /// <param name="polygon">The polygon used for clipping.</param>
        /// <param name="resultPolySF">The result shapefile for the resulting polygons to be saved (in-memory).</param>
        /// <param name="copyAttributes">True if copying attrs</param>
        /// <returns>False if an error was encountered, true otherwise.</returns>
        public static bool ClipPolygonSFWithPolygon(ref MapWinGIS.Shapefile polySF, ref MapWinGIS.Shape polygon, out MapWinGIS.Shapefile resultPolySF, bool copyAttributes)
        {
            MapWinUtility.Logger.Dbg("ClipPolygonSFWithPolygon(polySF: " + Macro.ParamName(polySF) + ",\n" +
                                     "                         polygon: " + Macro.ParamName(polygon) + ",\n" +
                                     "                         resultPolySF: out,\n" +
                                     "                         copyAttributes: " + copyAttributes.ToString() + "\n");

            MapWinGIS.Shapefile   resultSF = new MapWinGIS.ShapefileClass();
            MapWinGIS.ShpfileType sfType   = polySF.ShapefileType;
            string tempPath = System.IO.Path.GetTempPath() + "resultSF.shp";

            DataManagement.DeleteShapefile(ref tempPath);
            string tmpName;

            Globals.PrepareResultSF(ref tempPath, ref resultSF, sfType, copyAttributes);

            if (copyAttributes)
            {
                MapWinGIS.Field tmpField, currField;
                for (int f = 0; f <= polySF.NumFields - 1; f++)
                {
                    tmpField  = new MapWinGIS.Field();
                    currField = polySF.get_Field(f);
                    tmpName   = currField.Name;
                    if (tmpName.Contains("MWShapeID"))
                    {
                        tmpField.Name = "Last_" + tmpName;
                    }
                    else
                    {
                        tmpField.Name = tmpName;
                    }
                    tmpField.Width     = currField.Width;
                    tmpField.Type      = currField.Type;
                    tmpField.Precision = currField.Precision;
                    tmpField.Key       = currField.Key;
                    resultSF.EditInsertField(tmpField, ref f, null);
                }
            }

            int shapeIndex = 0;            //insert new shapes at the beginning of the shapefile

            if (polySF.NumShapes != 0 && polygon.numPoints != 0 && (sfType == MapWinGIS.ShpfileType.SHP_POLYGON || sfType == MapWinGIS.ShpfileType.SHP_POLYGONM || sfType == MapWinGIS.ShpfileType.SHP_POLYGONZ))
            {
                MapWinGIS.Shape resultShape     = new MapWinGIS.ShapeClass();
                int             numShapes       = polySF.NumShapes;
                bool            boundsIntersect = false;

                for (int i = 0; i <= numShapes - 1; i++)
                {
                    MapWinGIS.Shape currPoly = new MapWinGIS.ShapeClass();
                    currPoly = polySF.get_Shape(i);
                    //check to see if bounds intersect before sending shape to GPC clip function
                    boundsIntersect = Globals.CheckBounds(ref currPoly, ref polygon);

                    if (boundsIntersect == true)
                    {
                        //find the shape resulting intersection
                        resultShape = SpatialOperations.Intersection(polySF.get_Shape(i), polygon);
                        if (resultShape.numPoints != 0)
                        {
                            //save the new shape to the result shapefile
                            if (resultSF.EditInsertShape(resultShape, ref shapeIndex) == false)
                            {
                                gErrorMsg = "Problem inserting shape: " + resultSF.get_ErrorMsg(resultSF.LastErrorCode);
                                Debug.WriteLine(gErrorMsg);
                                MapWinGeoProc.Error.SetErrorMsg(gErrorMsg);
                                resultPolySF = resultSF;
                                return(false);
                            }
                            if (copyAttributes)
                            {
                                for (int f = 0; f <= polySF.NumFields - 1; f++)
                                {
                                    bool tmpbool = resultSF.EditCellValue(f, shapeIndex, polySF.get_CellValue(f, i));
                                }
                            }
                        }
                    }
                }
            }
            resultPolySF = resultSF;
            return(true);
        }
        /// <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();
        }
        /// <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>
        /// Creates a new grid containing data from the input grid that
        /// falls within the polygon boundary.
        /// </summary>
        /// <param name="inputGF">Full path to the input grid file.</param>
        /// <param name="poly">The 2D polygon used for clipping the input grid.</param>
        /// <param name="resultGF">Full path to where the resulting grid will be saved.</param>
        /// <param name="clipToExtents">True if clipping to polygon extents rather than actual polygon shape.</param>
        /// <returns>True if clipping was successful, false if an error occurs.</returns>
        public static bool ClipGridWithPolygon(ref string inputGF, ref MapWinGIS.Shape poly, ref string resultGF, bool clipToExtents)
        {
            MapWinUtility.Logger.Dbg("ClipGridWithPolygon(inputGF: " + inputGF + ",\n" +
                                     "                    poly: " + Macro.ParamName(poly) + ",\n" +
                                     "                    resultGF: " + resultGF + ",\n" +
                                     "                    clipToExtents: " + clipToExtents.ToString());
            Error.ClearErrorLog();
            //			System.Diagnostics.PerformanceCounter ramCounter;
            //			ramCounter = new PerformanceCounter("Memory", "Available Bytes");
            //			float availableRAM = ramCounter.NextValue();
            bool inRAM = true;

            //open grid to get info and traverse through points
            MapWinGIS.Grid grid = new MapWinGIS.GridClass();

            //check memory availability
            //			availableRAM = ramCounter.NextValue();//amount of RAM in bytes
            //			Debug.WriteLine("available RAM: " + availableRAM.ToString() + " bytes");

            //			System.IO.FileInfo fileInfo = new FileInfo(inputGF);
            //			long fileSize = fileInfo.Length; //size of file in bytes
            //			Debug.WriteLine("file size: " + fileSize.ToString() + " bytes");
            //			if(fileSize*2 < availableRAM)
            //			{//go ahead and load grid into memory
            //				inRAM = true;
            //			}
            //			else
            //			{
            //				inRAM = false;
            //			}
            if (grid.Open(inputGF, MapWinGIS.GridDataType.UnknownDataType, inRAM, MapWinGIS.GridFileType.UseExtension, null) == false)
            {
                gErrorMsg = "Error occurred while trying to open grid: " + grid.get_ErrorMsg(grid.LastErrorCode);
                Error.SetErrorMsg(gErrorMsg);
                Debug.WriteLine(gErrorMsg);
                MapWinUtility.Logger.Dbg(gErrorMsg);
                return(false);
            }

            int    numCols    = grid.Header.NumberCols;
            int    numRows    = grid.Header.NumberRows;
            double cellWidth  = grid.Header.dX;
            double cellHeight = grid.Header.dY;
            double xllCenter  = grid.Header.XllCenter;
            double yllCenter  = grid.Header.YllCenter;
            //now calculate the UNCOMPRESSED grid file size:
            long inputGFSize = numCols * numRows * 8;

            //find the grid extents
            double minX, maxX, minY, maxY;

            minX = xllCenter - (cellWidth / 2);
            maxX = xllCenter + (cellWidth * (numCols - 1)) + (cellWidth / 2);
            minY = yllCenter - (cellHeight / 2);
            maxY = yllCenter + (cellHeight * (numRows - 1)) + (cellHeight / 2);

            //see if grid and poly extents cross:
            double polyMinX = poly.Extents.xMin;
            double polyMaxX = poly.Extents.xMax;
            double polyMinY = poly.Extents.yMin;
            double polyMaxY = poly.Extents.yMax;

            bool boundsIntersect = Globals.CheckBounds(minX, maxX, minY, maxY, polyMinX, polyMaxX, polyMinY, polyMaxY);

            if (boundsIntersect == false)
            {
                grid.Close();
                gErrorMsg = "Polygon and Grid boundaries do not overlap.";
                Error.SetErrorMsg(gErrorMsg);
                Debug.WriteLine(gErrorMsg);
                MapWinUtility.Logger.Dbg(gErrorMsg);
                return(false);
            }

            double newXll, newYll, firstXPt, firstYPt;
            int    newNumCols, newNumRows, firstCol, firstRow;

            //check if polygon extents are completely inside of grid extents
            if ((polyMinX >= minX && polyMinX <= maxX) && (polyMaxX >= minX && polyMaxX <= maxX) &&
                (polyMinY >= minY && polyMinY <= maxY) && (polyMaxY >= minY && polyMaxY <= maxY))
            {
                Debug.WriteLine("Poly extents are inside of grid extents.");
                minX = polyMinX;
                minY = polyMinY;
                maxX = polyMaxX;
                maxY = polyMaxY;

                //Find the new number of cols, rows, Xll and Yll values.
                int lastCol, lastRow;
                Globals.ProjToCell(minX, maxY, out firstCol, out firstRow, xllCenter, yllCenter, cellWidth, cellHeight, numRows);
                Globals.ProjToCell(maxX, minY, out lastCol, out lastRow, xllCenter, yllCenter, cellWidth, cellHeight, numRows);
                newNumCols = (lastCol - firstCol) + 1;
                newNumRows = (lastRow - firstRow) + 1;
                Debug.WriteLine("New numRows = " + newNumRows + " New numCols = " + newNumCols);
                Globals.CellToProj(firstCol, lastRow, out newXll, out newYll, xllCenter, yllCenter, cellWidth, cellHeight, numRows);
                Globals.CellToProj(firstCol, firstRow, out firstXPt, out firstYPt, xllCenter, yllCenter, cellWidth, cellHeight, numRows);
            }

            //check if grid extents are completely inside of polygon extents
            //note: there is really no purpose in this, as the new grid is the same
            //as the orgiginal grid....but we'll do it anyway.
            else if ((minX >= polyMinX && minX <= polyMaxX) && (maxX >= polyMinX && maxX <= polyMaxX) &&
                     (minY >= polyMinY && minY <= polyMaxY) && (maxY >= polyMinY && maxY <= polyMaxY))
            {
                Debug.WriteLine("Grid extents are inside of polygon extents.");
                //keep min and max values the same....no need to change them.
                newNumCols = numCols;
                newNumRows = numRows;
                newXll     = xllCenter;
                newYll     = yllCenter;
                firstCol   = 0;
                firstRow   = 0;
                Globals.CellToProj(0, 0, out firstXPt, out firstYPt, xllCenter, yllCenter, cellWidth, cellHeight, numRows);
            }
            else             //part of polygon lies outside of the grid, find intersecting boundary shape
            {
                Debug.WriteLine("Grid extents and polygon extents overlap.");
                //create a new shape out of the grid extents
                MapWinGIS.Shape gridEnvelope = new MapWinGIS.ShapeClass();
                gridEnvelope.Create(MapWinGIS.ShpfileType.SHP_POLYGON);
                MapWinGIS.Point pt = new MapWinGIS.PointClass();
                pt.x = minX;
                pt.y = maxY;
                int ptIndex = 0;
                gridEnvelope.InsertPoint(pt, ref ptIndex);
                pt      = new MapWinGIS.PointClass();
                pt.x    = maxX;
                pt.y    = maxY;
                ptIndex = 1;
                gridEnvelope.InsertPoint(pt, ref ptIndex);
                pt      = new MapWinGIS.PointClass();
                pt.x    = maxX;
                pt.y    = minY;
                ptIndex = 2;
                gridEnvelope.InsertPoint(pt, ref ptIndex);
                pt      = new MapWinGIS.PointClass();
                pt.x    = minX;
                pt.y    = minY;
                ptIndex = 3;
                gridEnvelope.InsertPoint(pt, ref ptIndex);
                pt      = new MapWinGIS.PointClass();
                pt.x    = minX;
                pt.y    = maxY;
                ptIndex = 4;
                gridEnvelope.InsertPoint(pt, ref ptIndex);

                //create the final bounding envelope which is
                //the intersection of the polygon and grid envelope:
                MapWinGIS.Shape envelope = new MapWinGIS.ShapeClass();
                envelope.Create(MapWinGIS.ShpfileType.SHP_POLYGON);
                envelope = SpatialOperations.Intersection(gridEnvelope, poly);
                if (envelope.numPoints == 0)
                {
                    gErrorMsg = "Problem creating the bounding envelope. Aborting ClipGrid().";
                    Error.SetErrorMsg(gErrorMsg);
                    Debug.WriteLine(gErrorMsg);
                    MapWinUtility.Logger.Dbg(gErrorMsg);
                    return(false);
                }

                //calculate how many rows and columns will exist within the new grid
                //that is: how many rows/cols fit within the bounding envelope.
                minX = envelope.Extents.xMin;
                minY = envelope.Extents.yMin;
                maxX = envelope.Extents.xMax;
                maxY = envelope.Extents.yMax;

                newNumCols = (int)(((maxX - minX) / cellWidth) + 0.5);
                newNumRows = (int)(((maxY - minY) / cellHeight) + 0.5);
                newXll     = minX + (cellWidth / 2);
                newYll     = minY + (cellHeight / 2);
                firstXPt   = newXll;
                firstYPt   = newYll + (cellHeight * (newNumRows - 1));
                Globals.ProjToCell(firstXPt, firstYPt, out firstCol, out firstRow, xllCenter, yllCenter, cellWidth, cellHeight, numRows);

                //done using COM objects, release them
                while (Marshal.ReleaseComObject(pt) != 0)
                {
                    ;
                }
                pt = null;
                while (Marshal.ReleaseComObject(gridEnvelope) != 0)
                {
                    ;
                }
                gridEnvelope = null;
                while (Marshal.ReleaseComObject(envelope) != 0)
                {
                    ;
                }
                envelope = null;
            }

            // Chris M 12/13/2006 for BugZilla 377
            // Below code:
            // The grid header cannot be copied right across like that! The first line creates
            // a new grid header; the second line deletes the newly created grid header and
            // copies a reference to the original grid's header. Both grids then are using
            // the same header; and when the last lines set the XllCenter and YllCenter,
            // BOTH grids are updated with that information! A classic example of pointers gone wrong.
            //MapWinGIS.GridHeader resultHeader = new MapWinGIS.GridHeaderClass();
            //resultHeader = grid.Header;
            //resultHeader.NodataValue = grid.Header.NodataValue;
            //resultHeader.NumberCols = newNumCols;
            //resultHeader.NumberRows = newNumRows;
            //resultHeader.XllCenter = newXll;
            //resultHeader.YllCenter = newYll;
            // The right way to do it:
            MapWinGIS.GridHeader resultHeader = new MapWinGIS.GridHeaderClass();
            resultHeader.CopyFrom(grid.Header);
            // Not really needed due to CopyFrom: resultHeader.NodataValue = grid.Header.NodataValue;
            resultHeader.NumberCols = newNumCols;
            resultHeader.NumberRows = newNumRows;
            resultHeader.XllCenter  = newXll;
            resultHeader.YllCenter  = newYll;
            // Not really needed due to CopyFrom: resultHeader.dX = grid.Header.dX;
            // Not really needed due to CopyFrom: resultHeader.dY = grid.Header.dY;
            // Not really needed due to CopyFrom: resultHeader.Projection = grid.Header.Projection;

            //create the new grid object
            MapWinGIS.Grid resultGrid = new MapWinGIS.GridClass();
            DataManagement.DeleteGrid(ref resultGF);

            //check memory availability
            //			availableRAM = ramCounter.NextValue();//amount of RAM in bytes
            //			Debug.WriteLine("available RAM: " + availableRAM.ToString() + " bytes");

            long resultGFSize = newNumCols * newNumRows * 8;             //projected size of grid in bytes

            //			if(resultGFSize * 2 < availableRAM)
            //			{//go ahead and load grid into memory
            //				inRAM = true;
            //			}
            //			else
            //			{
            //				inRAM = false;
            //			}

            if (resultGrid.CreateNew(resultGF, resultHeader, grid.DataType, grid.Header.NodataValue, inRAM, MapWinGIS.GridFileType.UseExtension, null) == false)
            {
                gErrorMsg = "Problem creating the result grid: " + resultGrid.get_ErrorMsg(resultGrid.LastErrorCode);
                Debug.WriteLine(gErrorMsg);
                Error.SetErrorMsg(gErrorMsg);
                MapWinUtility.Logger.Dbg(gErrorMsg);
                return(false);
            }
            //close the grids, we need to use the wrapper class now due to memory issues
            resultGrid.Save(resultGF, MapWinGIS.GridFileType.UseExtension, null);
            resultGrid.Close();
            while (Marshal.ReleaseComObject(resultGrid) != 0)
            {
                ;
            }
            resultGrid = null;
            grid.Close();
            while (Marshal.ReleaseComObject(grid) != 0)
            {
                ;
            }
            grid = null;

            //fill the result grid with values from the original grid
            try
            {
                Debug.WriteLine("newNumRows = " + newNumRows + " newNumCols = " + newNumCols);

                int rowClearCount = Globals.DetermineRowClearCount(newNumRows, newNumCols);

                Debug.WriteLine("Clearing COM resources every " + rowClearCount + " rows.");

                if (FillGrid(ref inputGF, ref resultGF, ref poly, newNumRows, newNumCols, rowClearCount, firstCol, firstRow, firstXPt, firstYPt, clipToExtents) == false)
                {
                    MapWinUtility.Logger.Dbg("Error running FillGrid\n");
                    return(false);
                }
            }            //end of try block
            catch (Exception e)
            {
                gErrorMsg = e.Message + e.ToString();
                Debug.WriteLine(gErrorMsg);
                Error.SetErrorMsg(gErrorMsg);
                MapWinUtility.Logger.Dbg(gErrorMsg);
                return(false);
            }


            //NOTE: The need for trimGrid has been removed from this function.
            //It will always return the smallest possible grid because we
            //build it based on the intersection boundary.

            DataManagement.CopyGridLegend(inputGF, resultGF);
            MapWinUtility.Logger.Dbg("Finished ClipGridWithPolygon");
            return(true);
        }