/// <summary> /// Generates an empty featureset that has the combined fields from this featureset /// and the specified featureset. /// </summary> /// <param name="self">This featureset</param> /// <param name="other">The other featureset to combine fields with.</param> /// <returns></returns> public static IFeatureSet CombinedFields(this IFeatureSet self, IFeatureSet other) { IFeatureSet result = new FeatureSet(self.FeatureType); Dictionary<string, DataColumn> resultColumns = new Dictionary<string, DataColumn>(); foreach (DataColumn dc in self.DataTable.Columns) { string name = dc.ColumnName; int i = 1; while (resultColumns.ContainsKey(name)) { name = dc.ColumnName + i; i++; } resultColumns.Add(name, dc); } foreach (DataColumn dc in other.DataTable.Columns) { string name = dc.ColumnName; int i = 1; while (resultColumns.ContainsKey(name)) { name = dc.ColumnName + i; i++; } resultColumns.Add(name, dc); } foreach (KeyValuePair<string, DataColumn> pair in resultColumns) { result.DataTable.Columns.Add(new DataColumn(pair.Key, pair.Value.DataType)); } return result; }
/// <summary> /// Creates a new polygon featureset that is created by buffering each of the individual shapes. /// </summary> /// <param name="self">The IFeatureSet to buffer</param> /// <param name="distance">The double distance to buffer</param> /// <param name="copyAttributes">Boolean, if this is true, then the new featureset will have /// the same attributes as the original.</param> /// <returns>The newly created IFeatureSet</returns> public static IFeatureSet Buffer(this IFeatureSet self, double distance, bool copyAttributes) { // Dimension the new, output featureset. Buffered shapes are polygons, even if the // original geometry is a point or a line. IFeatureSet result = new FeatureSet(FeatureTypes.Polygon); // Cycle through the features, and buffer each one separately. foreach (IFeature original in self.Features) { // Actually calculate the buffer geometry. IFeature buffer = original.Buffer(distance); // If copyAttributes is true, then this will copy those attributes from the original. if(copyAttributes) { // Accessing the attributes should automatically load them from the datasource if // they haven't been loaded already. buffer.CopyAttributes(original); } // Add the resulting polygon to the featureset result.Features.Add(buffer); } return result; }
private void OpenLayer() { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Shapefiles|*.shp"; if (ofd.ShowDialog() != DialogResult.OK) return; FeatureSet fs = new FeatureSet(); fs.Open(ofd.FileName); geoMap1.Layers.Add(fs); FeatureSet newFeature = new FeatureSet(); newFeature.CopyTableSchema(fs); foreach(Feature f in fs.Features) { newFeature.Features.Add(f); } bool stop = true; }
/// <summary> /// The Voronoi Graph calculation creates a delaunay tesselation where /// each point is effectively converted into triangles. /// </summary> /// <param name="points">The points to use for creating the tesselation</param> /// <returns></returns> public static IFeatureSet DelaunayLines(IFeatureSet points) { double[] vertices = points.Vertex; VoronoiGraph gp = Fortune.ComputeVoronoiGraph(vertices); FeatureSet result = new FeatureSet(); foreach (VoronoiEdge edge in gp.Edges) { Coordinate c1 = edge.RightData.ToCoordinate(); Coordinate c2 = edge.LeftData.ToCoordinate(); LineString ls = new LineString(new List<Coordinate>{c1, c2}); Feature f = new Feature(ls); result.AddFeature(f); } return result; }
/// <summary> /// The Voronoi Graph calculation creates the lines that form a voronoi diagram /// </summary> /// <param name="points">The points to use for creating the tesselation</param> /// <returns></returns> public static IFeatureSet VoronoiLines(IFeatureSet points) { double[] vertices = points.Vertex; VoronoiGraph gp = Fortune.ComputeVoronoiGraph(vertices); HandleBoundaries(gp, points.Envelope); FeatureSet result = new FeatureSet(); foreach (VoronoiEdge edge in gp.Edges) { Coordinate c1 = edge.VVertexA.ToCoordinate(); Coordinate c2 = edge.VVertexB.ToCoordinate(); LineString ls = new LineString(new List<Coordinate> { c1, c2 }); Feature f = new Feature(ls); result.AddFeature(f); } return result; }
private void RemoveAndInsert() { FeatureSet cities = new FeatureSet(); FeatureSet states = new FeatureSet(); cities.Open(@"C:\dev\SampleData\HIS_Desktop\cities.shp"); states.Open(@"C:\dev\SampleData\HIS_Desktop\states.shp"); IMapFeatureLayer cityLayer = geoMap1.Layers.Add(cities); IMapFeatureLayer stateLayer = geoMap1.Layers.Add(states); geoMap1.Layers.Remove(stateLayer); geoMap1.Layers.Insert(0, stateLayer); }
/// <summary> /// Executes the ClipPolygonWithLine Operation tool programaticaly. /// Ping deleted static for external testing 01/2010 /// </summary> /// <param name="input1">The input Polygon FeatureSet.</param> /// <param name="input2">The input Polyline FeatureSet.</param> /// <param name="output">The output Polygon FeatureSet.</param> /// <param name="cancelProgressHandler">The progress handler.</param> /// <returns></returns> public bool Execute(IFeatureSet input1, IFeatureSet input2, IFeatureSet output, ICancelProgressHandler cancelProgressHandler) { //Validates the input and output data if (input1 == null || input2 == null || output == null) { return false; } if (cancelProgressHandler.Cancel) return false; IFeature polygon = input1.Features[0]; IFeature line = input2.Features[0]; IFeatureSet resultFS = new FeatureSet(FeatureTypes.Polygon); int previous = 0; if (DoClipPolygonWithLine(ref polygon, ref line, ref output) == false) { throw new SystemException(TextStrings.Exceptioninclipin); } int intFeature = output.Features.Count; for (int i = 0; i < intFeature; i++) { Polygon poly = new Polygon(output.Features[i].Coordinates); resultFS.AddFeature(poly); int current = Convert.ToInt32(Math.Round(i * 100D / intFeature)); //only update when increment in percentage if (current > previous) cancelProgressHandler.Progress("", current, current + TextStrings.progresscompleted); previous = current; } cancelProgressHandler.Progress("", 100, 100 + TextStrings.progresscompleted); resultFS.SaveAs(output.Filename, true); return true; }
/// <summary> /// Given a line that contains portion both inside and outside of the polygon, this /// function will split the polygon based only on the segments that completely bisect /// the polygon. It assumes: out->out, and in->in 2pt segments do not intersect the /// polygon, and out->in, in->out 2pt segments have only one point of intersection. /// </summary> /// <param name="insidePts">A boolean array indicating if a point is inside the polygon or not.</param> /// <param name="line">The line that intersects the polygon.</param> /// <param name="polygon">The polygon that will be split by the intersecting line.</param> /// <param name="resultSF">The shapefile that the polygon sections will be saved to.</param> /// <returns>False if errors were encountered or an assumption violated, true otherwise.</returns> private static bool Fast_ProcessPartInAndOut(ref bool[] insidePts, ref IFeature line, ref IFeature polygon, ref IFeatureSet resultSF) { int numLinePts = line.NumPoints; int numLineSegs = numLinePts - 1; int numPolyPts = polygon.NumPoints; int[] intersectsPerSeg = new int[numLineSegs]; Point[][] intersectPts = new Point[numLineSegs][]; int[][] polyIntLocs = new int[numLineSegs][]; //intersection occurs between polygon point indexed by polyIntLoc[][] and the previous point. //cut line into 2pt segments and put in new shapefile. IFeatureSet lineSegSF = new FeatureSet(); IFeature lineSegment; IList<Coordinate> coordi = line.Coordinates; Coordinate[] secCoordinate = new Coordinate[2]; for (int i = 0; i <= numLineSegs - 1; i++) { secCoordinate[0] = coordi[i]; secCoordinate[1] = coordi[i + 1]; lineSegment = new Feature(FeatureTypes.Line, secCoordinate); lineSegSF.Features.Add(lineSegment); lineSegment.Coordinates.Clear(); intersectPts[i] = new Point[numPolyPts]; polyIntLocs[i] = new int[numPolyPts]; } //find number of intersections, intersection pts, and locations for each 2pt segment int numIntersects = CalcSiDeterm(ref lineSegSF, ref polygon, ref intersectsPerSeg, ref intersectPts, ref polyIntLocs); if (numIntersects == 0) { return false; } IFeature insideLine = new Feature(); List<Coordinate> insideLineList = new List<Coordinate>(); List<Coordinate> intersectSegList; Point startIntersect = new Point(); bool startIntExists = false; bool validInsideLine = false; int insideStart = 0; int startIntPolyLoc = 0; //loop through each 2pt segment for (int i = 0; i <= numLinePts - 2; i++) { lineSegment = lineSegSF.Features[i]; int numSegIntersects = intersectsPerSeg[i]; //****************** case: inside->inside **************************************// int ptIndex; if (insidePts[i] && insidePts[i + 1]) { if (numSegIntersects == 0 && i != numLinePts - 2 && i != 0) { //add points to an inside line segment if (startIntExists) { ptIndex = 0; insideLineList.Insert(ptIndex, startIntersect.Coordinate); startIntExists = false; validInsideLine = true; insideStart = startIntPolyLoc; } if (validInsideLine) { ptIndex = insideLine.NumPoints; insideLineList.Insert(ptIndex, lineSegment.Coordinates[0]); } } else { //we do not handle multiple intersections in the fast version return false; } }//end of inside->inside //********************** case: inside->outside **************************************** else if (insidePts[i] && insidePts[i + 1] == false) { if (numSegIntersects == 0) { return false; } if (numSegIntersects == 1) { if (startIntExists) { intersectSegList = new List<Coordinate>(); ptIndex = 0; intersectSegList.Insert(ptIndex, startIntersect.Coordinate); ptIndex = 1; intersectSegList.Insert(ptIndex, lineSegment.Coordinates[0]); ptIndex = 2; intersectSegList.Insert(ptIndex, intersectPts[i][0].Coordinate); IFeature intersectSeg = new Feature(FeatureTypes.Line, intersectSegList); int firstPolyLoc = startIntPolyLoc; int lastPolyLoc = polyIntLocs[i][0] - 1; if (SectionPolygonWithLine(ref intersectSeg, ref polygon, firstPolyLoc, lastPolyLoc, ref resultSF) == false) { return false; } startIntExists = false; //we just used it up! } else if (insideLine.NumPoints != 0 && validInsideLine) { ptIndex = insideLineList.Count; insideLineList.Insert(ptIndex, lineSegment.Coordinates[0]); ptIndex++; insideLineList.Insert(ptIndex, intersectPts[i][0].Coordinate); insideLine = new Feature(FeatureTypes.Line, insideLineList); int firstPolyLoc = insideStart; int lastPolyLoc = polyIntLocs[i][0] - 1; if (SectionPolygonWithLine(ref insideLine, ref polygon, firstPolyLoc, lastPolyLoc, ref resultSF) == false) { return false; } validInsideLine = false; insideLine.Coordinates.Clear(); } } else { //we do not handle multiple intersections in the fast version return false; } } //end of inside->outside //********************** case: outside->inside *************************************** else if (insidePts[i] == false && insidePts[i + 1]) { validInsideLine = false; if (numSegIntersects == 0) { return false; } if (numSegIntersects == 1) { startIntExists = true; startIntersect = intersectPts[i][0]; startIntPolyLoc = polyIntLocs[i][0] - 1; } else { //we do not handle multiple intersections in the fast version return false; } } //************************ case: outside->outside *********************************** else if (insidePts[i] == false && insidePts[i + 1] == false) { startIntExists = false; validInsideLine = false; if (numSegIntersects == 0) { //do nothing } else { //we do not handle multiple intersections in the fast version return false; } }//end of outside->outside }//end of looping through 2pt segments return true; }
/// <summary> /// This will clip MultiPart Polygon with line. /// </summary> /// <param name="polygon">Input Polygon.</param> /// <param name="line">Input Line.</param> /// <param name="resultFile">Output Featureset.</param> /// <param name="speedOptimized">The speed optimizer.</param> /// <returns></returns> public static bool ClipMultiPartPolyWithLine(ref IFeature polygon, ref IFeature line, ref IFeatureSet resultFile, bool speedOptimized) { int numParts = polygon.NumGeometries; if (numParts == 0) numParts = 1; if (numParts > 1) { //multiple parts FixMultiPartPoly(ref polygon); IFeature[] polyParts = new IFeature[numParts]; SeparateParts(ref polygon, ref polyParts); IFeatureSet holeSF = new FeatureSet(FeatureTypes.Polygon); IFeatureSet tempResult = new FeatureSet(FeatureTypes.Polygon); IFeatureSet modPolySF = new FeatureSet(FeatureTypes.Polygon); IFeatureSet resultSF = new FeatureSet(FeatureTypes.Polygon); for (int i = 0; i <= numParts - 1; i++) { IFeature currPart = polyParts[i]; if (MapWindow.Analysis.Topology.Algorithm.CGAlgorithms.IsCounterClockwise(currPart.Coordinates) == false) { if (speedOptimized) { Fast_ClipPolygonWithLine(ref currPart, ref line, ref tempResult); } else { Accurate_ClipPolygonWithLine(ref currPart, ref line, ref tempResult); } int numResults = tempResult.Features.Count; if (numResults > 0) { for (int j = 0; j <= numResults - 1; j++) { modPolySF.Features.Add(tempResult.Features[j]); } } } else { holeSF.Features.Add(currPart); } } if (holeSF.Features.Count > 0) { ErasePolySFWithPolySF(ref modPolySF, ref holeSF, ref resultSF); } if (resultSF.Features.Count > 0) { resultFile = resultSF; return true; } resultFile = resultSF; return false; } if (speedOptimized) return Fast_ClipPolygonWithLine(ref polygon, ref line, ref resultFile); return Accurate_ClipPolygonWithLine(ref polygon, ref line, ref resultFile); }
/// <summary> /// For lines where every point lies outside the polygon, this function will /// find if any 2pt segment crosses through the polygon. If so, it will split /// the polygon into mutliple parts using the intersecting line segments. /// </summary> /// <param name="line">The line whose points are all inside the polygon.</param> /// <param name="polygon">The polygon being checked for intersection.</param> /// <param name="resultSF">The file where new polygon sections should be saved to.</param> /// <returns>False if errors were encountered, true otherwise.</returns> private static bool ProcessAllOutside(ref IFeature line, ref IFeature polygon, ref IFeatureSet resultSF) { int numLinePts = line.NumPoints; int numLineSegs = numLinePts - 1; int numPolyPts = polygon.NumPoints; int[] intersectsPerSeg = new int[numLineSegs]; Point[][] intersectPts = new Point[numLineSegs][]; int[][] polyIntLocs = new int[numLineSegs][]; //intersection occurs between polygon point indexed by polyIntLoc[][] and the previous point. //cut line into 2pt segments and put in new shapefile. //string tempPath = System.IO.Path.GetTempPath() + "tempLineSF.shp"; IFeatureSet lineSegSF = new FeatureSet(FeatureTypes.Line); // Globals.PrepareResultSF(ref tempPath, ref lineSegSF, line.ShapeType); IList<Coordinate> coordi = line.Coordinates; Coordinate[] secCoordinate = new Coordinate[2]; for (int i = 0; i <= numLineSegs - 1; i++) { secCoordinate[0] = coordi[i]; secCoordinate[1] = coordi[i + 1]; IFeature lineSegment = new Feature(FeatureTypes.Line, secCoordinate); lineSegSF.Features.Add(lineSegment); intersectPts[i] = new Point[numPolyPts]; polyIntLocs[i] = new int[numPolyPts]; } int numIntersects = CalcSiDeterm(ref lineSegSF, ref polygon, ref intersectsPerSeg, ref intersectPts, ref polyIntLocs); if (numIntersects == 0) { //entire line is outside the polygon, no splitting occurs } else { //intersections exist! Find out where. List<Coordinate> intersectSegList = new List<Coordinate>(); for (int i = 0; i <= numLineSegs - 1; i++) { int numSegIntersects = intersectsPerSeg[i]; //if there are less than 4 intersects, the line will not cross the //polygon in such a way that a new polygon section can be created. if (numSegIntersects == 0) { //do not add the segment to the result file, //this portion is not inside the polygon int c = i + 1; while (intersectsPerSeg[c] == 0 && c <= numLineSegs - 1) { c++; if (c == numLineSegs) { break; } } i = c - 1; } else { //there should always be an even # of intersects for a line of all outside pts //find the valid intersect points from our array Point[] intPts = new Point[numSegIntersects]; Point startPt = new Point(lineSegSF.Features[i].Coordinates[0]); FindAndSortValidIntersects(numSegIntersects, ref intersectPts[i], ref intPts, ref startPt, ref polyIntLocs[i]); for (int j = 0; j <= numSegIntersects - 1; j++) { int ptIndex = 0; intersectSegList.Insert(ptIndex, intPts[j].Coordinate); ptIndex = 1; intersectSegList.Insert(ptIndex, intPts[j + 1].Coordinate); IFeature intersectSeg = new Feature(FeatureTypes.Line, intersectSegList); int polyStartIndex = polyIntLocs[i][j] - 1; int polyEndIndex = polyIntLocs[i][j + 1] - 1; if (SectionPolygonWithLine(ref intersectSeg, ref polygon, polyStartIndex, polyEndIndex, ref resultSF) == false) { return false; } intersectSeg.Coordinates.Clear(); j++; }//end of looping through segment intersect points }//end of else intersects exist for 2pt segment }//end of looping through 2pt line segments }//end of else intersects exist return true; }
private IFeatureSet CreatePointFeatureset() { Random rnd = new Random(DateTime.Now.Millisecond); FeatureSet fs = new FeatureSet(FeatureTypes.Point); fs.DataTable.Columns.Add("Number", typeof(int)); fs.DataTable.Columns.Add("Letter", typeof(string)); fs.Name = "Test"; for(int i = 0; i < 10; i++) { Feature f = new Feature(new Point(NextCoordinate(rnd))); fs.Features.Add(f); f.DataRow["Number"] = i; f.DataRow["Letter"] = "Shape " + i; } return fs; }
private static IFeatureSet CreateLineFeatureSet() { Random rnd = new Random(DateTime.Now.Millisecond); FeatureSet fs = new FeatureSet(FeatureTypes.Point); fs.DataTable.Columns.Add("Number", typeof(int)); fs.DataTable.Columns.Add("Letter", typeof(string)); fs.Name = "Test"; for (int i = 0; i < 10; i++) { List<Coordinate> coords = new List<Coordinate>(); for(int j = 0; j < 10; j++) { coords.Add(NextCoordinate(rnd)); } Feature f = new Feature(new LineString(coords)); fs.Features.Add(f); f.DataRow["Number"] = i; f.DataRow["Letter"] = "Shape " + i; } return fs; }
private static IFeatureSet CreatePolygonFeatureSet() { Random rnd = new Random(DateTime.Now.Millisecond); FeatureSet fs = new FeatureSet(FeatureTypes.Point); fs.DataTable.Columns.Add("Number", typeof(int)); fs.DataTable.Columns.Add("Letter", typeof(string)); fs.Name = "Test"; for (int i = 0; i < 10; i++) { Coordinate center = NextCoordinate(rnd); List<Coordinate> shell = new List<Coordinate>(); for (int j = 0; j < 10; j++) { Coordinate c = new Coordinate(); double dx = 5*Math.Sin(Math.PI*(double) j/(double) 5); double dy = 5*Math.Cos(Math.PI*(double) j/(double) 5); c.X = center.X + dx; c.Y = center.Y + dy; shell.Add(c); } Polygon p = new Polygon(shell); Feature f = new Feature(p); fs.Features.Add(f); f.DataRow["Number"] = i; f.DataRow["Letter"] = "Shape " + i; } return fs; }
private void CreateLayers() { FeatureSet cities = new FeatureSet(); FeatureSet states = new FeatureSet(); cities.Open(@"C:\dev\SampleData\HIS_Desktop\cities.shp"); states.Open(@"C:\dev\SampleData\HIS_Desktop\states.shp"); IMapFeatureLayer cityLayer = new MapPointLayer(cities); IMapFeatureLayer stateLayer = new MapPolygonLayer(states); geoMap1.Layers.Insert(0, cityLayer); geoMap1.Layers.Insert(0, stateLayer); }
/// <summary> /// Allows for new behavior during deactivation. /// </summary> protected override void OnDeactivate() { if (_standBy) return; // Don't completely deactivate, but rather go into standby mode // where we draw only the content that we have actually locked in. _standBy = true; // base.OnDeactivate(); if(_coordinateDialog != null)_coordinateDialog.Hide(); if (_coordinates != null && _coordinates.Count > 1) { LineString ls = new LineString(_coordinates); FeatureSet fs = new FeatureSet(FeatureTypes.Line); fs.Features.Add(new Feature(ls)); MapLineLayer gll = new MapLineLayer(fs); //gll.Symbolizer.FillColor = Color.Blue; gll.Symbolizer.ScaleMode = ScaleModes.Symbolic; gll.Symbolizer.Smoothing = true; gll.MapFrame = Map.MapFrame; _tempLayer = gll; Map.MapFrame.DrawingLayers.Add(gll); // Map.MapFrame.Initialize(_tempLayer); Map.MapFrame.Invalidate(); Map.Invalidate(); } }
/// <summary> /// The Voronoi Graph calculation creates the lines that form a voronoi diagram /// </summary> /// <param name="points">The points to use for creating the tesselation</param> /// <param name="cropToExtent">The normal polygons have sharp angles that extend like stars. /// Cropping will ensure that the original featureset extent plus a small extra buffer amount /// is the outer extent of the polygons. Errors seem to occur if the exact extent is used.</param> /// <param name="progHandler">A progress handler for updating progress information</param> /// <returns></returns> public static IFeatureSet VoronoiPolygons(IFeatureSet points, bool cropToExtent, IProgressHandler progHandler) { IFeatureSet fs = new FeatureSet(); VoronoiPolygons(points, fs, cropToExtent, progHandler); return fs; }
/// <summary> /// Sections a polygon into multiple parts depending on where line crosses it and if previous sectioning has occured. /// </summary> /// <param name="line">The line that splits the polygon. First and last points are intersect points.</param> /// <param name="polygon">The polygon that is to be split by the line.</param> /// <param name="polyStart">Index to polygon segment where the first intersect point is found.</param> /// <param name="polyEnd">Index to polygon segment where last intersect point is found.</param> /// <param name="resultSF">Reference to result shapefile where new polygon sections will be saved.</param> /// <returns>False if an error occurs, true otherwise.</returns> private static bool SectionPolygonWithLine(ref IFeature line, ref IFeature polygon, int polyStart, int polyEnd, ref IFeatureSet resultSF) { int numResults = resultSF.Features.Count; bool previousSplits = false; if (numResults != 0) { previousSplits = true; } //we can now make two new polygons by splitting the original one with the line segment IFeature poly1 = new Feature(); IFeature poly2 = new Feature(); SplitPolyInTwo(ref line, ref polygon, polyStart, polyEnd, ref poly1, ref poly2); if (previousSplits == false) { int shpIndex = 0; resultSF.Features.Insert(shpIndex, poly1); shpIndex = 1; resultSF.Features.Insert(shpIndex, poly2); } else { //this polygon underwent previous splittings, check //if the new results overlay the old ones before adding to resultSF IFeatureSet test1SF = new FeatureSet(); IFeatureSet test2SF = new FeatureSet(); if (ClipPolygonSFWithPolygon(ref resultSF, ref poly1, ref test1SF, false) == false) { return false; } if (ClipPolygonSFWithPolygon(ref resultSF, ref poly2, ref test2SF, false) == false) { return false; } if (test1SF.Features.Count > 0 || test2SF.Features.Count > 0) { int numTestShapes = test1SF.Features.Count; const int insertIndex = 0; IFeature insertShape; for (int j = 0; j <= numTestShapes - 1; j++) { insertShape = test1SF.Features[j]; resultSF.Features.Insert(insertIndex, insertShape); } numTestShapes = test2SF.Features.Count; for (int j = 0; j <= numTestShapes - 1; j++) { insertShape = test2SF.Features[j]; resultSF.Features.Insert(insertIndex, insertShape); } } }//end of checking against previous splits return true; }
void cmdNew_Click(object sender, EventArgs e) { FeatureTypeDialog dlg = new FeatureTypeDialog(); if (dlg.ShowDialog() != DialogResult.OK) return; FeatureSet fs = new FeatureSet(dlg.FeatureType); if(_geoMap.Projection != null) fs.Projection = _geoMap.Projection; fs.CoordinateType = dlg.CoordinateType; fs.IndexMode = false; IMapFeatureLayer layer = _geoMap.Layers.Add(fs); layer.EditMode = true; _geoMap.Layers.SelectedLayer = layer; layer.LegendText = _geoMap.Layers.UnusedName("New Layer"); }
/// <summary> /// For lines where every point lies within the polygon, this function will /// find if any 2pt segment crosses through the polygon. If so, it will split /// the polygon into mutliple parts using the intersecting line segments. /// </summary> /// <param name="line">The line whose points are all inside the polygon.</param> /// <param name="polygon">The polygon being checked for intersection.</param> /// <param name="resultSF">The file where new polygon sections should be saved to.</param> /// <returns>False if errors were encountered, true otherwise.</returns> private static bool ProcessAllInside(ref IFeature line, ref IFeature polygon, ref IFeatureSet resultSF) { int numLinePts = line.NumPoints; int numLineSegs = numLinePts - 1; int numPolyPts = polygon.NumPoints; int[] intersectsPerSeg = new int[numLineSegs]; Point[][] intersectPts = new Point[numLineSegs][]; int[][] polyIntLocs = new int[numLineSegs][]; //intersection occurs between polygon point indexed by polyIntLoc[][] and the previous point. //cut line into 2pt segments and put in new shapefile. IFeatureSet lineSegSF = new FeatureSet(FeatureTypes.Line); IList<Coordinate> coordi = line.Coordinates; Coordinate[] secCoordinate = new Coordinate[2]; for (int i = 0; i <= numLineSegs - 1; i++) { secCoordinate[0] = coordi[i]; secCoordinate[1] = coordi[i + 1]; IFeature lineSegment = new Feature(FeatureTypes.Line, secCoordinate); lineSegSF.Features.Add(lineSegment); intersectPts[i] = new Point[numPolyPts]; polyIntLocs[i] = new int[numPolyPts]; } int numIntersects = CalcSiDeterm(ref lineSegSF, ref polygon, ref intersectsPerSeg, ref intersectPts, ref polyIntLocs); if (numIntersects == 0)//entire line is inside the polygon { //entire line is inside the polygon, no splitting occurs } else { //intersections exist! Find out where. List<Coordinate> intersectSegList = new List<Coordinate>(); for (int i = 0; i <= numLineSegs - 1; i++) { int numSegIntersects = intersectsPerSeg[i]; //if there are less than 4 intersects, the line will not cross the //polygon in such a way that a new polygon section can be created. if (numSegIntersects <= 2) { //inside lines should be ignored, we only want a portion that crosses //the polygon. int c = i + 1; while (intersectsPerSeg[c] <= 2 && c <= numLineSegs - 1) { c++; if (c == numLineSegs) { break; } } i = c - 1; } else { //there should always be an even # of intersects for a line of all inside pts //find intersecting segments that will split the polygon Point[] intPts = new Point[numSegIntersects]; Point startPt = new Point(lineSegSF.Features[i].Coordinates[0]); FindAndSortValidIntersects(numSegIntersects, ref intersectPts[i], ref intPts, ref startPt, ref polyIntLocs[i]); for (int j = 0; j <= numSegIntersects - 1; j++) { if (j == 0 || j == numSegIntersects - 1) { //Any segment formed from inside pt -> intersect pt //or intersect pt -> inside pt will NOT cross the polygon. } else { int ptIndex = 0; intersectSegList.Insert(ptIndex, intPts[j].Coordinate); ptIndex = 1; intersectSegList.Insert(ptIndex, intPts[j + 1].Coordinate); IFeature intersectSeg = new Feature(FeatureTypes.Line, intersectSegList); int polyStartIndex = polyIntLocs[i][j] - 1; int polyEndIndex = polyIntLocs[i][j + 1] - 1; if (SectionPolygonWithLine(ref intersectSeg, ref polygon, polyStartIndex, polyEndIndex, ref resultSF) == false) { return false; } intersectSeg.Coordinates.Clear(); j++; } }//end of looping through intersect pts }//end of more than 2 intersects exist }//end of looping through 2pt line segments }//end of else intersects exist return true; }
/// <summary> /// Handles the situation for exporting the layer as a new source. /// </summary> protected override void OnExportData() { ExportFeature frmExport = new ExportFeature(); frmExport.Filename = DataSet.Filename; if (frmExport.ShowDialog() != DialogResult.OK) return; if (frmExport.FeaturesIndex == 0) { DataSet.SaveAs(frmExport.Filename, true); } else if (frmExport.FeaturesIndex == 1) { FeatureSet fs = _selection.ToFeatureSet(); fs.SaveAs(frmExport.Filename, true); } else if (frmExport.FeaturesIndex == 2) { List<IFeature> features = DataSet.Select(MapFrame.Extents); FeatureSet fs = new FeatureSet(features); if (fs.Features.Count == 0) { fs.CopyTableSchema(DataSet); } fs.SaveAs(frmExport.Filename, true); } AddToMapDialog dlgAddLayer = new AddToMapDialog(); if (dlgAddLayer.ShowDialog() != DialogResult.OK) return; if (dlgAddLayer.AddLayer == false) return; IFeatureLayer newLayer = OpenFile(frmExport.Filename) as IFeatureLayer; IGroup parent = GetParentItem() as IGroup; if (parent != null) { int index = parent.IndexOf(this); if (newLayer != null) { parent.Insert(index + 1, newLayer); } } }
/// <summary> /// For faster clipping of polygons with lines. Limits the finding of intersections to /// outside->inside or inside->outside 2pt segments. Assumes only one intersections exists /// per segment, that a segment of two inside points or two outside points will not intersect /// the polygon. /// </summary> /// <param name="polygon">The polygon that will be sectioned by the line.</param> /// <param name="line">The line that will clip the polygon into multiple parts.</param> /// <param name="resultSF">The in-memory shapefile where the polygon sections will be saved.</param> /// <returns>False if errors are encountered, true otherwise.</returns> public static bool Fast_ClipPolygonWithLine(ref IFeature polygon, ref IFeature line, ref IFeatureSet resultSF) { IFeatureSet resultFile = new FeatureSet(FeatureTypes.Polygon); if (polygon != null && line != null) { //make sure we are dealing with a valid shapefile type if (polygon.FeatureType == FeatureTypes.Polygon) { //create the result shapefile if it does not already exist if (!polygon.Overlaps(line)) { resultSF = resultFile; return false; } //find if all of the line is inside, outside, or part in and out of polygon //line might intersect polygon mutliple times int numPoints = line.NumPoints; bool[] ptsInside = new bool[numPoints]; int numInside = 0; int numOutside = 0; int numParts = polygon.NumGeometries; if (numParts == 0) { numParts = 1; } Coordinate[][] polyVertArray = new Coordinate[numParts][]; ConvertPolyToVertexArray(ref polygon, ref polyVertArray); //check each point in the line to see if the entire line is either //inside of the polygon or outside of it (we know it's inside polygon bounding box). for (int i = 0; i <= numPoints - 1; i++) { Point currPt = new Point(line.Coordinates[i]); if (polygon.Covers(currPt)) { ptsInside[i] = true; numInside += 1; } else { ptsInside[i] = false; numOutside += 1; } } //case: all points are inside polygon - check for possible intersections if (numInside == numPoints) { //assume no intersections exist in fast version } //case: all points are outside of the polygon - check for possible intersections else if (numOutside == numPoints) { //assume no intersections exist in fast version } else //case: part of line is inside and part is outside - find inside segments. { if (Fast_ProcessPartInAndOut(ref ptsInside, ref line, ref polygon, ref resultFile) == false) { resultSF = resultFile; return false; } } //resultSF result file, do not save to disk. resultSF = resultFile; } else { resultSF = resultFile; return false; } } else //polygon or line is invalid { resultSF = resultFile; return false; } return true; }
/// <summary> /// Calculates a union of any features that have a common value in the specified field. /// The output will only contain the specified field. Example: Disolving a county /// shapefile based on state name to produce a single polygon shaped like the state. /// </summary> /// <param name="self">The original featureSet to disolve the features of</param> /// <param name="fieldName">The string field name to use for the disolve operation</param> /// <returns>A featureset where the geometries of features with the same attribute in the specified field have been combined.</returns> public static IFeatureSet Dissolve(this IFeatureSet self, string fieldName) { Dictionary<object, IFeature> resultFeatures = new Dictionary<object, IFeature>(); IFeatureSet result = new FeatureSet(self.FeatureType); result.DataTable.Columns.Add(fieldName, self.DataTable.Columns[fieldName].DataType); foreach (IFeature feature in self.Features) { object value = feature.DataRow[fieldName]; if(resultFeatures.ContainsKey(value)) { IFeature union = resultFeatures[value].Union(feature); union.DataRow = result.DataTable.NewRow(); union.DataRow[fieldName] = value; resultFeatures[value] = union; } else { IFeature union = feature.Copy(); union.DataRow = result.DataTable.NewRow(); union.DataRow[fieldName] = value; resultFeatures.Add(value, feature); } } foreach (IFeature feature in resultFeatures.Values) { result.Features.Add(feature); } return result; }
/// <summary> /// Given a line that contains portions both inside and outside of the polygon, this /// function will split the polygon based only on the segments that completely bisect /// the polygon. The possibility of mutliple intersections for any 2pt segment is taken /// into account. /// </summary> /// <param name="insidePts">A boolean array indicating if a point is inside the polygon or not.</param> /// <param name="line">The line that intersects the polygon.</param> /// <param name="polygon">The polygon that will be split by the intersecting line.</param> /// <param name="resultSF">The shapefile that the polygon sections will be saved to.</param> /// <returns>False if errors were encountered or an assumption violated, true otherwise.</returns> private static bool ProcessPartInAndOut(ref bool[] insidePts, ref IFeature line, ref IFeature polygon, ref IFeatureSet resultSF) { int numLinePts = line.NumPoints; int numLineSegs = numLinePts - 1; int numPolyPts = polygon.NumPoints; int[] intersectsPerSeg = new int[numLineSegs]; Point[][] intersectPts = new Point[numLineSegs][]; int[][] polyIntLocs = new int[numLineSegs][]; //intersection occurs between polygon point indexed by polyIntLoc[][] and the previous point. //cut line into 2pt segments and put in new shapefile. IFeatureSet lineSegSF = new FeatureSet(FeatureTypes.Line); IFeature lineSegment; IList<Coordinate> coordi = line.Coordinates; Coordinate[] secCoordinate = new Coordinate[2]; for (int i = 0; i <= numLineSegs - 1; i++) { secCoordinate[0] = coordi[i]; secCoordinate[1] = coordi[i + 1]; lineSegment = new Feature(FeatureTypes.Line, secCoordinate); lineSegSF.Features.Add(lineSegment); lineSegment.Coordinates.Clear(); intersectPts[i] = new Point[numPolyPts]; polyIntLocs[i] = new int[numPolyPts]; } //find number of intersections, intersection pts, and locations for each 2pt segment int numIntersects = CalcSiDeterm(ref lineSegSF, ref polygon, ref intersectsPerSeg, ref intersectPts, ref polyIntLocs); if (numIntersects == 0) { return false; } IFeature insideLine = new Feature(); List<Coordinate> insideLineList; IFeature intersectSeg; List<Coordinate> intersectSegList; Point startIntersect = new Point(); bool startIntExists = false; bool validInsideLine = false; int insideStart = 0; int startIntPolyLoc = 0; //loop through each 2pt segment for (int i = 0; i <= numLinePts - 2; i++) { insideLineList = new List<Coordinate>(); lineSegment = lineSegSF.Features[i]; int numSegIntersects = intersectsPerSeg[i]; //****************** case: inside->inside **************************************// int ptIndex; if (insidePts[i] && insidePts[i + 1]) { if (numSegIntersects == 0 && i != numLinePts - 2 && i != 0) { //add points to an inside line segment if (startIntExists) { ptIndex = 0; insideLineList.Insert(ptIndex, startIntersect.Coordinate); startIntExists = false; validInsideLine = true; insideStart = startIntPolyLoc; } if (validInsideLine) { ptIndex = insideLineList.Count; insideLineList.Insert(ptIndex, lineSegment.Coordinates[0]); } } else { //sort the intersects and their locations Point[] intPts = new Point[numSegIntersects]; Point startPt = new Point(lineSegSF.Features[i].Coordinates[0]); FindAndSortValidIntersects(numSegIntersects, ref intersectPts[i], ref intPts, ref startPt, ref polyIntLocs[i]); for (int j = 0; j <= numSegIntersects - 1; j++) { if (j == 0) { if (startIntExists) { //first intersect pt is an ending pt, it must be //combined with a starting intersect pt in order to section the polygon. intersectSegList = new List<Coordinate>(); ptIndex = 0; intersectSegList.Insert(ptIndex, startIntersect.Coordinate); ptIndex = 1; intersectSegList.Insert(ptIndex, lineSegment.Coordinates[0]); ptIndex = 2; intersectSegList.Insert(ptIndex, intPts[0].Coordinate); intersectSeg = new Feature(FeatureTypes.Line, intersectSegList); int firstPolyLoc = startIntPolyLoc; int lastPolyLoc = polyIntLocs[i][0] - 1; if (SectionPolygonWithLine(ref intersectSeg, ref polygon, firstPolyLoc, lastPolyLoc, ref resultSF) == false) { return false; } startIntExists = false; //we used it up! } else if (insideLine.NumPoints != 0 && validInsideLine) { ptIndex = insideLineList.Count; insideLineList.Insert(ptIndex, lineSegment.Coordinates[0]); ptIndex++; insideLineList.Insert(ptIndex, intPts[0].Coordinate); insideLine = new Feature(FeatureTypes.Line, insideLineList); int firstPolyLoc = insideStart; int lastPolyLoc = polyIntLocs[i][0] - 1; if (SectionPolygonWithLine(ref insideLine, ref polygon, firstPolyLoc, lastPolyLoc, ref resultSF) == false) { return false; } validInsideLine = false; insideLine.Coordinates.Clear(); } } else if (j == numSegIntersects - 1 && i != numLinePts - 2) { //last intersect pt is a starting pt, it must be //saved for later combination startIntersect = intPts[j]; startIntPolyLoc = polyIntLocs[i][j] - 1; startIntExists = true; } else if (j != 0 || j != numSegIntersects - 1) { //a full poly section is created by two intersect points intersectSegList = new List<Coordinate>(); ptIndex = intersectSegList.Count; intersectSegList.Insert(ptIndex, intPts[j].Coordinate); ptIndex++; intersectSegList.Insert(ptIndex, intPts[j + 1].Coordinate); intersectSeg = new Feature(FeatureTypes.Line, intersectSegList); int firstPolyLoc = polyIntLocs[i][j] - 1; int lastPolyLoc = polyIntLocs[i][j + 1] - 1; if (SectionPolygonWithLine(ref intersectSeg, ref polygon, firstPolyLoc, lastPolyLoc, ref resultSF) == false) { return false; } j++; } } } } //********************** case: inside->outside **************************************** else if (insidePts[i] && insidePts[i + 1] == false) { if (numSegIntersects == 0) { return false; } if (numSegIntersects == 1) { if (startIntExists) { intersectSegList = new List<Coordinate>(); ptIndex = 0; intersectSegList.Insert(ptIndex, startIntersect.Coordinate); ptIndex = 1; intersectSegList.Insert(ptIndex, lineSegment.Coordinates[0]); ptIndex = 2; intersectSegList.Insert(ptIndex, intersectPts[i][0].Coordinate); intersectSeg = new Feature(FeatureTypes.Line, intersectSegList); int firstPolyLoc = startIntPolyLoc; int lastPolyLoc = polyIntLocs[i][0] - 1; if (SectionPolygonWithLine(ref intersectSeg, ref polygon, firstPolyLoc, lastPolyLoc, ref resultSF) == false) { return false; } startIntExists = false; //we just used it up! } else if (insideLine.NumPoints != 0 && validInsideLine) { ptIndex = insideLineList.Count; insideLineList.Insert(ptIndex, lineSegment.Coordinates[0]); ptIndex++; insideLineList.Insert(ptIndex, intersectPts[i][0].Coordinate); insideLine = new Feature(FeatureTypes.Line, insideLineList); int firstPolyLoc = insideStart; int lastPolyLoc = polyIntLocs[i][0] - 1; if (SectionPolygonWithLine(ref insideLine, ref polygon, firstPolyLoc, lastPolyLoc, ref resultSF) == false) { return false; } validInsideLine = false; insideLine.Coordinates.Clear(); } } else { //sort the intersects and their locations Point[] intPts = new Point[numSegIntersects]; Point startPt = new Point(lineSegSF.Features[i].Coordinates[0]); FindAndSortValidIntersects(numSegIntersects, ref intersectPts[i], ref intPts, ref startPt, ref polyIntLocs[i]); for (int j = 0; j <= numSegIntersects - 1; j++) { if (j == 0) { if (startIntExists) { intersectSegList = new List<Coordinate>(); ptIndex = 0; intersectSegList.Insert(ptIndex, startIntersect.Coordinate); ptIndex = 1; intersectSegList.Insert(ptIndex, lineSegment.Coordinates[0]); ptIndex = 2; intersectSegList.Insert(ptIndex, intPts[0].Coordinate); intersectSeg = new Feature(FeatureTypes.Line, intersectSegList); int firstPolyLoc = startIntPolyLoc; int lastPolyLoc = polyIntLocs[i][0] - 1; if (SectionPolygonWithLine(ref intersectSeg, ref polygon, firstPolyLoc, lastPolyLoc, ref resultSF) == false) { return false; } startIntExists = false; //we just used it up! } else if (insideLine.NumPoints != 0 && validInsideLine) { ptIndex = insideLineList.Count; insideLineList.Insert(ptIndex, lineSegment.Coordinates[0]); ptIndex++; insideLineList.Insert(ptIndex, intPts[0].Coordinate); insideLine = new Feature(FeatureTypes.Line, insideLineList); int firstPolyLoc = insideStart; int lastPolyLoc = polyIntLocs[i][0] - 1; if (SectionPolygonWithLine(ref insideLine, ref polygon, firstPolyLoc, lastPolyLoc, ref resultSF) == false) { return false; } validInsideLine = false; insideLine.Coordinates.Clear(); } } else { //section the polygon with the intersecting segment //intersectSeg = new Feature(); intersectSegList = new List<Coordinate>(); ptIndex = 0; intersectSegList.Insert(ptIndex, intPts[j].Coordinate); ptIndex = 1; intersectSegList.Insert(ptIndex, intPts[j + 1].Coordinate); intersectSeg = new Feature(FeatureTypes.Line, intersectSegList); intersectSeg.Coordinates.Insert(ptIndex, intPts[j + 1].Coordinate); int firstPolyLoc = polyIntLocs[i][j] - 1; int lastPolyLoc = polyIntLocs[i][j + 1] - 1; if (SectionPolygonWithLine(ref intersectSeg, ref polygon, firstPolyLoc, lastPolyLoc, ref resultSF) == false) { return false; } j++; } } } } //********************** case: outside->inside *************************************** else if (insidePts[i] == false && insidePts[i + 1]) { validInsideLine = false; startIntExists = false; if (numSegIntersects == 0) { return false; } if (numSegIntersects == 1) { startIntExists = true; startIntersect = intersectPts[i][0]; startIntPolyLoc = polyIntLocs[i][0] - 1; } else { //sort the intersects and their locations Point[] intPts = new Point[numSegIntersects]; Point startPt = new Point(lineSegSF.Features[i].Coordinates[0]); FindAndSortValidIntersects(numSegIntersects, ref intersectPts[i], ref intPts, ref startPt, ref polyIntLocs[i]); //an odd number of intersects exist, at least one full poly section //will be created along with one hanging intersect pt. for (int j = 0; j <= numSegIntersects - 1; j++) { if (j == numSegIntersects - 1) { startIntExists = true; startIntersect = intPts[j]; startIntPolyLoc = polyIntLocs[i][j] - 1; } else { intersectSegList = new List<Coordinate>(); ptIndex = 0; intersectSegList.Insert(ptIndex, intPts[j].Coordinate); ptIndex = 1; intersectSegList.Insert(ptIndex, intPts[j + 1].Coordinate); intersectSeg = new Feature(FeatureTypes.Line, intersectSegList); int firstPolyLoc = polyIntLocs[i][j] - 1; int lastPolyLoc = polyIntLocs[i][j + 1] - 1; if (SectionPolygonWithLine(ref intersectSeg, ref polygon, firstPolyLoc, lastPolyLoc, ref resultSF) == false) { return false; } j++; } } } } //************************ case: outside->outside *********************************** else if (insidePts[i] == false && insidePts[i + 1] == false) { startIntExists = false; validInsideLine = false; if (numSegIntersects == 0) { //do nothing } else { //sort the intersects and their locations Point[] intPts = new Point[numSegIntersects]; Point startPt = new Point(lineSegSF.Features[i].Coordinates[0]); FindAndSortValidIntersects(numSegIntersects, ref intersectPts[i], ref intPts, ref startPt, ref polyIntLocs[i]); //should always be an even amount of intersections, full poly section created for (int j = 0; j <= numSegIntersects - 1; j++) { intersectSegList = new List<Coordinate>(); ptIndex = 0; intersectSegList.Insert(ptIndex, intPts[j].Coordinate); ptIndex = 1; intersectSegList.Insert(ptIndex, intPts[j + 1].Coordinate); intersectSeg = new Feature(FeatureTypes.Line, intersectSegList); int firstPolyLoc = polyIntLocs[i][j] - 1; int lastPolyLoc = polyIntLocs[i][j + 1] - 1; if (SectionPolygonWithLine(ref intersectSeg, ref polygon, firstPolyLoc, lastPolyLoc, ref resultSF) == false) { return false; } j++; } } } } return true; }
/// <summary> /// This tests each feature of the input /// </summary> /// <param name="self">This featureSet</param> /// <param name="other">The featureSet to perform intersection with</param> /// <param name="joinType">The attribute join type</param> /// <param name="progHandler">A progress handler for status messages</param> /// <returns>An IFeatureSet with the intersecting features, broken down based on the join Type</returns> public static IFeatureSet Intersection(this IFeatureSet self, IFeatureSet other, FieldJoinType joinType, IProgressHandler progHandler) { IFeatureSet result = null; ProgressMeter pm = new ProgressMeter(progHandler, "Calculating Intersection", self.Features.Count); if (joinType == FieldJoinType.All) { result = CombinedFields(self, other); // Intersection is symetric, so only consider I X J where J <= I int i=0; foreach(IFeature selfFeature in self.Features) { List<IFeature> potentialOthers = other.Select(selfFeature.Envelope); foreach (IFeature otherFeature in potentialOthers) { selfFeature.Intersection(otherFeature, result, joinType); } pm.CurrentValue = i; i++; } pm.Reset(); } if (joinType == FieldJoinType.LocalOnly) { result = new FeatureSet(); result.CopyTableSchema(self); result.FeatureType = self.FeatureType; IFeature union; pm = new ProgressMeter(progHandler, "Calculating Union", other.Features.Count); if(other.Features != null && other.Features.Count > 0) { union = other.Features[0]; for(int i = 1; i < other.Features.Count; i++) { union = union.Union(other.Features[i]); pm.CurrentValue = i; } pm.Reset(); pm = new ProgressMeter(progHandler, "Calculating Intersections", self.NumRows()); Extent otherEnvelope = new Extent(union.Envelope); for (int shp = 0; shp < self.ShapeIndices.Count; shp++) { if (!self.ShapeIndices[shp].Extent.Intersects(otherEnvelope)) continue; IFeature selfFeature = self.GetFeature(shp); selfFeature.Intersection(union, result, joinType); pm.CurrentValue = shp; } pm.Reset(); } } if (joinType == FieldJoinType.ForeignOnly) { result = new FeatureSet(); result.CopyTableSchema(other); IFeature union; if (self.Features != null && self.Features.Count > 0) { pm = new ProgressMeter(progHandler, "Calculating Union", self.Features.Count); union = self.Features[0]; for (int i = 1; i < self.Features.Count; i++) { union = union.Union(self.Features[i]); pm.CurrentValue = i; } pm.Reset(); if (other.Features != null) { pm = new ProgressMeter(progHandler, "Calculating Intersection", other.Features.Count); int j = 0; foreach (IFeature otherFeature in other.Features) { IFeature test = otherFeature.Intersection(union, result, joinType); if (test.BasicGeometry != null) { result.Features.Add(test); } pm.CurrentValue = j; j++; } } pm.Reset(); } } return result; }
/// <summary> /// As an example, choosing myFeatureLayer.SelectedFeatures.ToFeatureSet creates a new set. /// </summary> /// <returns>An in memory featureset that has not yet been saved to a file in any way.</returns> public FeatureSet ToFeatureSet() { FeatureSet fs = new FeatureSet(ToList()); // the output features will be copied. if (fs.Features.Count == 0) { if (_filter.FeatureList.Count > 0) { fs.CopyTableSchema(_filter.FeatureList[0].ParentFeatureSet); } } return fs; }
private bool ImportFieldsFromDbf() { OpenFileDialog dlg = new OpenFileDialog(); dlg.Filter = "DBase Files (*.dbf)|*.DBF"; FeatureSet fs = new FeatureSet(); FeatureSet fsTemp = new FeatureSet(); fsTemp.CopyFeatures(_featureLayer.DataSet, true); if (dlg.ShowDialog() != DialogResult.OK) return false; string shapeFilePath2 = dlg.FileName; int count = shapeFilePath2.Length; shapeFilePath2 = shapeFilePath2.Remove(count - 4, 4);//remove the extension of the file shapeFilePath2 = shapeFilePath2 + ".shp";//add fs.Open(shapeFilePath2); int noOfCol = fs.DataTable.Columns.Count; //Add all column header for (int i = 0; i < noOfCol; i++) { DataColumn dtcol = new DataColumn(fs.DataTable.Columns[i].ColumnName, fs.DataTable.Columns[i].DataType); if (fsTemp.DataTable.Columns.Contains(fs.DataTable.Columns[i].ColumnName) == false) fsTemp.DataTable.Columns.Add(dtcol); } dataGridView1.DataSource = fsTemp.DataTable; return true; }