/// <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(FeatureType.Polygon); result.CopyTableSchema(self); result.Projection = self.Projection; // 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); // Add the resulting polygon to the featureset result.Features.Add(buffer); // 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); } } return result; }
/// <summary> /// Erase features from one feature set where they are intersected by another feature set. /// </summary> /// <param name="TargetFeatures">Features which will be erased in part or whole.</param> /// <param name="SourceFeatures">Features which represent areas to erase.</param> /// <param name="cancelProgressHandler">Optional parameter to report progress and cancel entire process if needed.</param> /// <returns>A point feature set with the randomly created features.</returns> public static FeatureSet EraseFeatures(IFeatureSet TargetFeatures, IFeatureSet SourceFeatures, ICancelProgressHandler cancelProgressHandler = null) { if (TargetFeatures == null || SourceFeatures == null) { return null; } //Erase features from one feature set where they are intersected by another feature set //Note: we use the ShapeIndices here rather than for each feature in featureset.features as a memory management technique. //The current version does not preserve any attribute info. //Dan Ames 2/27/2013 FeatureSet ResultFeatures = new FeatureSet(); //the resulting featureset IFeature TF, SF; //a single output feature ResultFeatures.CopyTableSchema(TargetFeatures); //set up the data table in the new feature set for (Int16 i = 0; i <= TargetFeatures.ShapeIndices.Count - 1; i++) { TF = TargetFeatures.GetFeature(i); //get the full undifferenced feature for (Int16 j = 0; j <= SourceFeatures.ShapeIndices.Count - 1; j++) { SF = SourceFeatures.GetFeature(j); if (SF.Envelope.Intersects(TF.Envelope)) { TF = TF.Difference(SF); //clip off any pieces of SF that overlap FR } if (TF == null) { //sometimes difference leaves nothing left of a feature break; } } if (TF != null) { ResultFeatures.AddFeature(TF).CopyAttributes(TargetFeatures.GetFeature(i)); //add the fully clipped feature to the results } if (cancelProgressHandler != null) { if (cancelProgressHandler.Cancel) { return null; } int progress = Convert.ToInt32(i * 100 / TargetFeatures.ShapeIndices.Count); cancelProgressHandler.Progress(String.Empty, progress, String.Empty); } } return ResultFeatures; }
/// <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(ToFeatureList()); // the output features will be copied. if (fs.Features.Count == 0) { if (_filter.FeatureList.Count > 0) { fs.CopyTableSchema(_filter.FeatureList[0].ParentFeatureSet); } } return fs; }
/// <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 symmetric, so only consider I X J where J <= I if (!self.AttributesPopulated) self.FillAttributes(); if (!other.AttributesPopulated) other.FillAttributes(); int i = 0; foreach (IFeature selfFeature in self.Features) { List<IFeature> potentialOthers = other.Select(selfFeature.Envelope.ToExtent()); foreach (IFeature otherFeature in potentialOthers) { selfFeature.Intersection(otherFeature, result, joinType); } pm.CurrentValue = i; i++; } pm.Reset(); } if (joinType == FieldJoinType.LocalOnly) { if (!self.AttributesPopulated) self.FillAttributes(); 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) { if (!other.AttributesPopulated) other.FillAttributes(); 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; }
private static IFeatureSet UnionIntersecting(IFeatureSet fs) { FeatureSet fsunion = new FeatureSet(); // This is needed or else the table won't have the columns for copying attributes. fsunion.CopyTableSchema(fs); fsunion.Projection = fs.Projection; // Create a list of all the original shapes so if we union A->B we don't also union B->A List<int> freeFeatures = fs.Features.Select((t, i) => i).ToList(); while (freeFeatures.Count > 0) { IFeature fOriginal = fs.Features[freeFeatures[0]]; // Whether this gets unioned or not, it has been handled and should not be re-done. // We also don't want to waste time unioning shapes to themselves. freeFeatures.RemoveAt(0); // This is the unioned result. Remember, we may just add the original feature if no // shapes present themselves for unioning. IFeature fResult = null; // This is the list of any shapes that get unioned with our shape. List<int> mergedList = new List<int>(); bool shapeChanged; do { shapeChanged = false; // reset this each time. foreach (int index in freeFeatures) { if (fResult == null) { if (fOriginal.Intersects(fs.Features[index])) { // If FieldJoinType is set to all, and large numbers of shapes are combined, // the attribute table will have a huge number of extra columns, since // every column will be replicated for each instance. fResult = fOriginal.Union(fs.Features[index], fsunion, FieldJoinType.LocalOnly); // if the shape changed for an index greater than 0, then the newly unioned // shape might now union with an earlier shape that we skipped before. shapeChanged = true; } } else { if (fResult.Intersects(fs.Features[index])) { // snowball unioned features. Keep adding features to the same unioned shape. fResult = fResult.Union(fs.Features[index], fsunion, FieldJoinType.LocalOnly); shapeChanged = true; } } if (shapeChanged) { // Don't modify the "freefeatures" list during a loop. Keep track until later. mergedList.Add(index); // Less double-checking happens if we break rather than finishing the loop // and then retest the whole loop because of a change early in the list. break; } } foreach (int index in mergedList) { // We don't want to add the same shape twice. freeFeatures.Remove(index); } } while (shapeChanged); // Add fResult, unless it is null, in which case add fOriginal. fsunion.Features.Add(fResult ?? fOriginal); // Union doesn't actually add to the output featureset. The featureset is only // provided to the union method to handle column manipulation if necessary. fsunion.Features.Add(fResult); } return fsunion; }
private static IFeatureSet UnionAll(IFeatureSet fs) { FeatureSet fsunion = new FeatureSet(); fsunion.CopyTableSchema(fs); fsunion.Projection = fs.Projection; IFeature f = fs.Features[0]; for (int i = 1; i < fs.Features.Count; i++) { f = f.Union(fs.Features[i], fsunion, FieldJoinType.LocalOnly); } fsunion.AddFeature(f); return fsunion; }
public void UnionFeatureSetTest() { IFeatureSet fs = FeatureSet.Open(_shapefiles + @"Topology_Test.shp"); FeatureSet fsunion = new FeatureSet(); // This is needed or else the table won't have the columns for copying attributes. fsunion.CopyTableSchema(fs); // Create a list of all the original shapes so if we union A->B we don't also union B->A var freeFeatures = fs.Features.Select((t, i) => i).ToList(); while (freeFeatures.Count > 0) { var fOriginal = fs.Features[freeFeatures[0]]; // Whether this gets unioned or not, it has been handled and should not be re-done. // We also don't want to waste time unioning shapes to themselves. freeFeatures.RemoveAt(0); // This is the unioned result. Remember, we may just add the original feature if no // shapes present themselves for unioning. IFeature fResult = null; // This is the list of any shapes that get unioned with our shape. List<int> mergedList = new List<int>(); bool shapeChanged; do { shapeChanged = false; // reset this each time. foreach (int index in freeFeatures) { if (fResult == null) { if (fOriginal.Intersects(fs.Features[index])) { // If FieldJoinType is set to all, and large numbers of shapes are combined, // the attribute table will have a huge number of extra columns, since // every column will be replicated for each instance. fResult = fOriginal.Union(fs.Features[index], fsunion, FieldJoinType.LocalOnly); // if the shape changed for an index greater than 0, then the newly unioned // shape might now union with an earlier shape that we skipped before. shapeChanged = true; } } else { if (fResult.Intersects(fs.Features[index])) { // snowball unioned features. Keep adding features to the same unioned shape. fResult = fResult.Union(fs.Features[index], fsunion, FieldJoinType.LocalOnly); shapeChanged = true; } } if (shapeChanged) { // Don't modify the "freefeatures" list during a loop. Keep track until later. mergedList.Add(index); // Less double-checking happens if we break rather than finishing the loop // and then retest the whole loop because of a change early in the list. break; } } foreach (int index in mergedList) { // We don't want to add the same shape twice. freeFeatures.Remove(index); } } while (shapeChanged); // Add fResult, unless it is null, in which case add fOriginal. fsunion.Features.Add(fResult ?? fOriginal); // Union doesn't actually add to the output featureset. The featureset is only // provided to the union method to handle column manipulation if necessary. fsunion.Features.Add(fResult); } // fsunion is in-memory until this is called. Once this is called, the extension will // be parsed to determine that a shapefile is required. The attributes and features will // be moved to variables in an appropriate shapefile class internally, and // then that class will save the features to the disk. fsunion.SaveAs(_shapefiles + @"Union_Test.shp", true); try { // cleanup File.Delete(_shapefiles + @"Union_Test.shp"); File.Delete(_shapefiles + @"Union_Test.dbf"); File.Delete(_shapefiles + @"Union_Test.shx"); } catch (IOException) { } }
/// <summary> /// Select the features in an IShapeSource /// </summary> /// <param name="sr"></param> /// <param name="filterExpression"></param> /// <param name="envelope"></param> /// <param name="startIndex"></param> /// <param name="maxCount"></param> /// <returns></returns> protected IFeatureSet Select(IShapeSource sr, string filterExpression, IEnvelope envelope, ref int startIndex, int maxCount) { var shapes = sr.GetShapes(ref startIndex, maxCount, envelope); AttributeTable at = GetAttributeTable(Filename); var result = new FeatureSet(FeatureType.Polygon); bool schemaDefined = false; foreach (var pair in shapes) { DataTable td = at.SupplyPageOfData(pair.Key, 1); if (td.Select(filterExpression).Length > 0) { if (!schemaDefined) { schemaDefined = true; result.CopyTableSchema(td); } var f = new Feature(pair.Value) {RecordNumber = pair.Key + 1, DataRow = td.Rows[0]}; result.Features.Add(f); f.UpdateEnvelope(); } } return result; }
/// <summary> /// Show the dialog for exporting data from a feature layer. /// </summary> /// <param name="e"></param> public void ExportData(IFeatureLayer e) { using (var frmExport = new ExportFeature()) { frmExport.Filename = e.DataSet.Filename; if (ShowDialog(frmExport) != DialogResult.OK) return; // Create a FeatureSet of features that the client wants exported FeatureSet fs = null; switch (frmExport.FeaturesIndex) { case 0: fs = (FeatureSet) e.DataSet; break; case 1: fs = e.Selection.ToFeatureSet(); break; case 2: var features = e.DataSet.Select(e.MapFrame.ViewExtents); fs = new FeatureSet(features) {Projection = e.Projection}; break; } if (fs.Features.Count == 0) { fs.CopyTableSchema(e.DataSet); fs.FeatureType = e.DataSet.FeatureType; } fs.SaveAs(frmExport.Filename, true); if (MessageBox.Show(Owner, "Do you want to load the shapefile?", "The layer was exported.", MessageBoxButtons.YesNo) == DialogResult.Yes) { LoadFeatureSetAsLayer(e, fs, Path.GetFileNameWithoutExtension(frmExport.Filename)); } } }
private static IFeatureSet UnionIntersecting(IFeatureSet fs) { var fsunion = new FeatureSet(); // This is needed or else the table won't have the columns for copying attributes. fsunion.CopyTableSchema(fs); fsunion.Projection = fs.Projection; // Create a list of all the original shapes so if we union A->B we don't also union B->A var freeFeatures = fs.Features.Select((t, i) => i).ToList(); while (freeFeatures.Count > 0) { var fOriginal = fs.Features[freeFeatures[0]]; // Whether this gets unioned or not, it has been handled and should not be re-done. // We also don't want to waste time unioning shapes to themselves. freeFeatures.RemoveAt(0); // This is the unioned result. Remember, we may just add the original feature if no // shapes present themselves for unioning. IFeature fResult = null; // This is the list of any shapes that get unioned with our shape. var mergedList = new List<int>(); bool shapeChanged; do { shapeChanged = false; // reset this each time. foreach (int index in freeFeatures) { var intersectSource = fResult ?? fOriginal; if (intersectSource.Intersects(fs.Features[index])) { fResult = intersectSource.Union(fs.Features[index]); shapeChanged = true; // Don't modify the "freefeatures" list during a loop. Keep track until later. mergedList.Add(index); // Less double-checking happens if we break rather than finishing the loop // and then retest the whole loop because of a change early in the list. break; } } foreach (var index in mergedList) { // We don't want to add the same shape twice. freeFeatures.Remove(index); } } while (shapeChanged); // Add fResult, unless it is null, in which case add fOriginal. fsunion.Features.Add(fResult ?? fOriginal); } return fsunion; }