/// <summary> /// Creates a new Feature that has a geometry that is the union between this feature and the specified feature. /// This also copies the attributes that are shared between this featureset and the /// specified destination featureset, and adds this feature to the destination featureset. /// </summary> /// <param name="self">This feature</param> /// <param name="other">The other feature to compare to.</param> /// <param name="destinationFeatureSet">The featureset to add the new feature to.</param> /// <param name="joinType">Clarifies how the attributes should be handled during the union</param> /// <returns>A new feature that is the geometric symmetric difference between this feature and the specified feature.</returns> public static IFeature Union(this IFeature self, IFeature other, IFeatureSet destinationFeatureSet, FieldJoinType joinType) { IFeature f = Union(self, other.Geometry); if (f != null) { UpdateFields(self, other, f, destinationFeatureSet, joinType); } return(f); }
/// <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(); } for (int i = 0; i < self.Features.Count; i++) { IFeature selfFeature = self.Features[i]; List <IFeature> potentialOthers = other.Select(selfFeature.Geometry.EnvelopeInternal.ToExtent()); foreach (IFeature otherFeature in potentialOthers) { selfFeature.Intersection(otherFeature, result, joinType); } pm.CurrentValue = i; } pm.Reset(); } else if (joinType == FieldJoinType.LocalOnly) { if (!self.AttributesPopulated) { self.FillAttributes(); } result = new FeatureSet(); result.CopyTableSchema(self); result.FeatureType = self.FeatureType; if (other.Features != null && other.Features.Count > 0) { pm = new ProgressMeter(progHandler, "Calculating Union", other.Features.Count); IFeature union = other.Features[0]; for (int i = 1; i < other.Features.Count; i++) { union = union.Union(other.Features[i].Geometry); pm.CurrentValue = i; } pm.Reset(); pm = new ProgressMeter(progHandler, "Calculating Intersections", self.NumRows()); Extent otherEnvelope = union.Geometry.EnvelopeInternal.ToExtent(); 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(); } } else if (joinType == FieldJoinType.ForeignOnly) { if (!other.AttributesPopulated) { other.FillAttributes(); } result = new FeatureSet(); result.CopyTableSchema(other); result.FeatureType = other.FeatureType; if (self.Features != null && self.Features.Count > 0) { pm = new ProgressMeter(progHandler, "Calculating Union", self.Features.Count); IFeature union = self.Features[0]; for (int i = 1; i < self.Features.Count; i++) { union = union.Union(self.Features[i].Geometry); pm.CurrentValue = i; } pm.Reset(); if (other.Features != null) { pm = new ProgressMeter(progHandler, "Calculating Intersection", other.Features.Count); for (int i = 0; i < other.Features.Count; i++) { other.Features[i].Intersection(union, result, FieldJoinType.LocalOnly); pm.CurrentValue = i; } } pm.Reset(); } } return(result); }
/// <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; }
// This handles the slightly complex business of attribute outputs. private static void UpdateFields(IFeature self, IFeature other, IFeature result, IFeatureSet destinationFeatureSet, FieldJoinType joinType) { if (destinationFeatureSet.FeatureType != result.FeatureType) { return; } destinationFeatureSet.Features.Add(result); if (joinType == FieldJoinType.None) { return; } if (joinType == FieldJoinType.All) { // This overly complex mess is concerned with preventing duplicate field names. // This assumes that numbers were appended when duplicates occured, and will // repeat the process here to establish one set of string names and values. Dictionary <string, object> mappings = new Dictionary <string, object>(); foreach (DataColumn dc in self.ParentFeatureSet.DataTable.Columns) { string name = dc.ColumnName; int i = 1; while (mappings.ContainsKey(name)) { name = dc.ColumnName + i; i++; } mappings.Add(name, self.DataRow[dc.ColumnName]); } foreach (DataColumn dc in other.ParentFeatureSet.DataTable.Columns) { string name = dc.ColumnName; int i = 1; while (mappings.ContainsKey(name)) { name = dc.ColumnName + i; i++; } mappings.Add(name, other.DataRow[dc.ColumnName]); } foreach (KeyValuePair <string, object> pair in mappings) { if (!result.DataRow.Table.Columns.Contains(pair.Key)) { result.DataRow.Table.Columns.Add(pair.Key); } result.DataRow[pair.Key] = pair.Value; } } if (joinType == FieldJoinType.LocalOnly) { foreach (DataColumn dc in destinationFeatureSet.DataTable.Columns) { if (self.DataRow.Table.Columns.Contains(dc.ColumnName)) { result.DataRow[dc.ColumnName] = self.DataRow[dc.ColumnName]; } } } if (joinType == FieldJoinType.ForeignOnly) { foreach (DataColumn dc in destinationFeatureSet.DataTable.Columns) { if (other.DataRow[dc.ColumnName] != null) { result.DataRow[dc.ColumnName] = self.DataRow[dc.ColumnName]; } } } }
/// <summary> /// Creates a new Feature that has a geometry that is the union between this feature and the specified feature. /// This also copies the attributes that are shared between this featureset and the /// specified destination featureset, and adds this feature to the destination featureset. /// </summary> /// <param name="self">This feature</param> /// <param name="other">The other feature to compare to.</param> /// <param name="destinationFeatureSet">The featureset to add the new feature to.</param> /// <param name="joinType">Clarifies how the attributes should be handled during the union</param> /// <returns>A new feature that is the geometric symmetric difference between this feature and the specified feature.</returns> public static IFeature Union(this IFeature self, IFeature other, IFeatureSet destinationFeatureSet, FieldJoinType joinType) { IFeature f = Union(self, other); if (f != null) { UpdateFields(self, other, f, destinationFeatureSet, joinType); } return f; }
/// <summary> /// Creates a new Feature that has a geometry that is the symmetric difference between this feature and the specified feature. /// This also copies the attributes that are shared between this featureset and the /// specified destination featureset, and adds this feature to the destination featureset. /// </summary> /// <param name="self">This feature</param> /// <param name="other">The other feature to compare to.</param> /// <param name="destinationFeatureSet">The featureset to add the new feature to.</param> /// <param name="joinType">This clarifies the overall join strategy being used with regards to attribute fields.</param> /// <returns>A new feature that is the geometric symmetric difference between this feature and the specified feature.</returns> public static IFeature SymmetricDifference(this IFeature self, IFeature other, IFeatureSet destinationFeatureSet, FieldJoinType joinType) { IFeature f = SymmetricDifference(self, other); if (f != null) { UpdateFields(self, other, f, destinationFeatureSet, joinType); } return f; }
// This handles the slightly complex business of attribute outputs. private static void UpdateFields(IFeature self, IFeature other, IFeature result, IFeatureSet destinationFeatureSet, FieldJoinType joinType) { if (destinationFeatureSet.FeatureType != result.FeatureType) return; destinationFeatureSet.Features.Add(result); if (joinType == FieldJoinType.None) return; if (joinType == FieldJoinType.All) { // This overly complex mess is concerned with preventing duplicate field names. // This assumes that numbers were appended when duplicates occured, and will // repeat the process here to establish one set of string names and values. Dictionary<string, object> mappings = new Dictionary<string, object>(); foreach (DataColumn dc in self.ParentFeatureSet.DataTable.Columns) { string name = dc.ColumnName; int i = 1; while (mappings.ContainsKey(name)) { name = dc.ColumnName + i; i++; } mappings.Add(name, self.DataRow[dc.ColumnName]); } foreach (DataColumn dc in other.ParentFeatureSet.DataTable.Columns) { string name = dc.ColumnName; int i = 1; while (mappings.ContainsKey(name)) { name = dc.ColumnName + i; i++; } mappings.Add(name, other.DataRow[dc.ColumnName]); } foreach (KeyValuePair<string, object> pair in mappings) { if (!result.DataRow.Table.Columns.Contains(pair.Key)) { result.DataRow.Table.Columns.Add(pair.Key); } result.DataRow[pair.Key] = pair.Value; } } if (joinType == FieldJoinType.LocalOnly) { foreach (DataColumn dc in destinationFeatureSet.DataTable.Columns) { if (self.DataRow.Table.Columns.Contains(dc.ColumnName)) { result.DataRow[dc.ColumnName] = self.DataRow[dc.ColumnName]; } } } if (joinType == FieldJoinType.ForeignOnly) { foreach (DataColumn dc in destinationFeatureSet.DataTable.Columns) { if (other.DataRow[dc.ColumnName] != null) { result.DataRow[dc.ColumnName] = self.DataRow[dc.ColumnName]; } } } }
/// <summary> /// Creates a new Feature that has a geometry that is the symmetric difference between this feature and the specified feature. /// This also copies the attributes that are shared between this featureset and the /// specified destination featureset, and adds this feature to the destination featureset. /// </summary> /// <param name="self">This feature</param> /// <param name="other">The other feature to compare to.</param> /// <param name="destinationFeatureSet">The featureset to add the new feature to.</param> /// <param name="joinType">This clarifies the overall join strategy being used with regards to attribute fields.</param> /// <returns>A new feature that is the geometric symmetric difference between this feature and the specified feature.</returns> public static IFeature SymmetricDifference(this IFeature self, IFeature other, IFeatureSet destinationFeatureSet, FieldJoinType joinType) { IFeature f = SymmetricDifference(self, other); if (f != null) { UpdateFields(self, other, f, destinationFeatureSet, joinType); } return(f); }
/// <summary> /// Creates a new Feature that has a geometry that is the intersection between this feature and the specified feature. /// This also copies the attributes that are shared between this featureset and the /// specified destination featureset, and adds this feature to the destination featureset. /// </summary> /// <param name="self">This feature</param> /// <param name="other">The other feature to compare to.</param> /// <param name="destinationFeatureSet">The featureset to add the new feature to.</param> /// <param name="joinType">This clarifies the overall join strategy being used with regards to attribute fields.</param> /// <returns>A new feature that is the geometric intersection between this feature and the specified feature.</returns> public static IFeature Intersection(this IFeature self, IFeature other, IFeatureSet destinationFeatureSet, FieldJoinType joinType) { IFeature f = Intersection(self, other); if (f != null) { UpdateFields(self, other, f, destinationFeatureSet, joinType); } return(f); }