/// <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); }
/// <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); }