I'm new to GIS (so I'm lost on this) and looking for a C# code sample to help me do 2 types of spatial queries. I have 2 Layers only. First layer is pipelines, which are polyline shapes so I can select multiple pipeline segments to make up an entire pipeline. Second Layer is facilities, which are point shapes.
Query 1: Select Pipeline Segments in the Pipeline Layer (Polylines) and find the facilities (in the Facility Layer) that are within a certain distance of selected Pipeline Segments.
Query 2: Select a single Facility in the Facility Layer (Point) and find the Pipeline Segments (Polylines) that are within a certain distance of the Facility Point.
I can do these queries via the ArcMap interface. I select the Source Features in the Attribute Table, then Selection Menu, Select by Location, select the "other" Layer as the Target Layer and for Spatial Selection Method I select "Target layer(s) features are within a distance of the Source layer feature". But now I need to do this in C# code for my ArcMap AddIn.
-
1key words to search "arcobjects query select distance", you should find many code examplesartwork21– artwork212015年12月01日 21:10:08 +00:00Commented Dec 1, 2015 at 21:10
-
@Dave Stuart, You should use spatail filter with arcobjects. Take a look at How to execute spatial queries and try to create some sample code and include more details in your questionFarid Cheraghi– Farid Cheraghi2015年12月02日 03:15:44 +00:00Commented Dec 2, 2015 at 3:15
-
Thanks @Farid Cher but I have searched high and low and visited that link several times. I thought my question is very clear for a GIS developer to answer with a pseudo code example.Dave Stuart– Dave Stuart2015年12月02日 15:01:34 +00:00Commented Dec 2, 2015 at 15:01
2 Answers 2
Assuming you have a handle of your query featureclass and selected feature, you can use the following code snippet:
double searchDistance = 10; //this is your buffer distance
IFeatureClass fc = ...; //Query1: this is your facility feature class
IFeature feat = ...;// Query1: this is your selected pipeline feature
ISpatialFilter spatialFilter = new SpatialFilterClass();
if (searchDistance == 0)
spatialFilter.Geometry = feat.Shape; // can be IGeometry
else
{
ITopologicalOperator topoOperator = (ITopologicalOperator)feat.ShapeCopy;
spatialFilter.Geometry = topoOperator.Buffer(searchDistance);
}
spatialFilter.GeometryField = fc.ShapeFieldName;
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
IFeatureCursor featureCursor = fc.Search(spatialFilter, true);
//loop through features in the cursor
-
Thanks Farid. I tried this a couple days ago and got some sort of result but it was not what I expected so I will have to look at it again on Monday. Thanks for the code sample though as it has helped. I mark this one UP if I can get the correct results.Dave Stuart– Dave Stuart2015年12月06日 20:23:09 +00:00Commented Dec 6, 2015 at 20:23
-
We could discuss about the issues you are facing, here!Farid Cheraghi– Farid Cheraghi2015年12月07日 01:26:02 +00:00Commented Dec 7, 2015 at 1:26
-
My code returns the same Facilities no matter what Pipeline I Select. In your code sample where would I actually use Selected Features from the Pipeline? I'm using IFeature feat = CurrentLayer.FeatureClass.GetFeature(1); to get the Set the Currently selected layer but these is no mention of the actual selected Pipeline rows. I think that is where I'm going wrong?Dave Stuart– Dave Stuart2015年12月07日 15:05:41 +00:00Commented Dec 7, 2015 at 15:05
-
I think my question was quite clear that I was selecting Pipeline features (rows in the Pipeline attribute table) and wanted to run a Spatial Query against the Facilities Layer to get the closest Facilities to those selected Pipelines. I have however figured out the solution using this post. gis.stackexchange.com/questions/112018/….Dave Stuart– Dave Stuart2015年12月09日 23:15:01 +00:00Commented Dec 9, 2015 at 23:15
This was what I did to solve the problem. Some of it might need to be explained but I think it's very clear. Thanks to brenth. https://gis.stackexchange.com/users/19213/brenth
This helped a lot! Selecting features by location based on selected feature using ArcObjects?
public void GetClosestFeatures(IEnumerable selectedFeatures) { try { var mxDocument = ArcMap.Application.Document as IMxDocument; if (mxDocument != null) { var map = mxDocument.FocusMap; var searchDistance = 1000.0; if(UI.LayerSelection.Equals("Pipeline")) { if (UI.txtRadiusToFacilities.Text != "") { searchDistance = Convert.ToDouble(UI.txtRadiusToFacilities.Text); } else { UI.txtRadiusToFacilities.Text = searchDistance.ToString(CultureInfo.InvariantCulture); } // This not 100% Accurate due to the Lattitude changing as you move north/south so if we know the lattite we can use // the MetersToDecimalDegrees function but this will do! searchDistance = Convert.ToDouble((UI.txtRadiusToFacilities.Text)) / (111.32 * 1000); } else { if (UI.txtRadiusToPipelines.Text != "") { searchDistance = Convert.ToDouble(UI.txtRadiusToPipelines.Text); } else { UI.txtRadiusToPipelines.Text = searchDistance.ToString(CultureInfo.InvariantCulture); } // This not 100% Accurate due to the Lattitude changing as you move north/south so if we know the lattite we can use // the MetersToDecimalDegrees function but this will do! searchDistance = Convert.ToDouble((UI.txtRadiusToPipelines.Text)) / (111.32 * 1000); } var cursor = GetSelectedFeatures(CurrentLayer); // Default buffer is Decimal Degrees var polygon = UnionShapes(cursor, searchDistance); // Maybe use the name in place of the CurrentLayer.Name as this is to find Facilities for the Selected Pipelines var featureLayer = Utilities.GetOppositeFeatureLayerByFeatureClassName(map, CurrentLayer.Name); var filter = CreateSpatialFilter(featureLayer.FeatureClass, polygon); var cursor2 = GetSelectedItemsByShape(featureLayer.FeatureClass, filter); // Iterate through the features, viewing (as in this case) or editing them. IFeatureClass fc = Utilities.GetOppositeFeatureLayerByFeatureClassName(map, CurrentLayer.Name).FeatureClass; IFeature feature = null; if (UI.LayerSelection.Equals("Pipeline")) { var nameFacilityNameIndex = fc.Fields.FindField(GeodatabaseFieldNames.FacilityNameFieldName); var nameFacilityTypeIndex = fc.Fields.FindField(GeodatabaseFieldNames.FacilityTypeFieldFieldName); var counter = 0; UI.lvwFacilitiesSpatialResult.Items.Clear(); try { while ((feature = cursor2.NextFeature()) != null) { //Console.WriteLine("Facility Found: {0}", feature.get_Value(nameFieldIndex)); counter++; string[] rowData = { (counter).ToString(CultureInfo.InvariantCulture), feature.get_Value(nameFacilityNameIndex).ToString(), feature.get_Value(nameFacilityTypeIndex).ToString() }; var lvItem = new ListViewItem(rowData); UI.lvwFacilitiesSpatialResult.Items.Add(lvItem); } } catch (Exception ex) { // Handle any errors that might occur on NextFeature(). MessageBox.Show(ex.Message, @"Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } else // Facility { var namePipelinenameIndex = fc.Fields.FindField(GeodatabaseFieldNames.PipelineNameFieldName); var companyNameFieldIndex = fc.Fields.FindField(GeodatabaseFieldNames.OperatorNameFieldName); var counter = 0; UI.lvwPipelinesSpatialResult.Items.Clear(); try { while ((feature = cursor2.NextFeature()) != null) { //Console.WriteLine("Facility Found: {0}", feature.get_Value(nameFieldIndex)); counter++; string[] rowData = { (counter).ToString(CultureInfo.InvariantCulture), feature.get_Value(namePipelinenameIndex).ToString(), feature.get_Value(companyNameFieldIndex).ToString() }; var lvItem = new ListViewItem(rowData); UI.lvwPipelinesSpatialResult.Items.Add(lvItem); } } catch (Exception ex) { // Handle any errors that might occur on NextFeature(). MessageBox.Show(ex.Message, @"Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } } } catch (Exception ex) { MessageBox.Show(ex.Message, @"Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } }
public static IFeatureCursor GetSelectedFeatures(IFeatureLayer featureLayer) { if (featureLayer == null) return null; IFeatureSelection fSel = (IFeatureSelection)featureLayer; ISelectionSet selSet = (ISelectionSet)fSel.SelectionSet; ICursor cursor = null; selSet.Search(null, false, out cursor); IFeatureCursor fCursor = cursor as IFeatureCursor; return fCursor; }
public static IPolygon UnionShapes(IFeatureCursor cursor, double bufferDist) { if (cursor == null) return null; IFeature pFeat = cursor.NextFeature(); if (pFeat != null) { if (pFeat.Shape is IPoint || pFeat.Shape is IPolyline) { ITopologicalOperator ptopBuffer = (ITopologicalOperator)pFeat.Shape; IPolygon pTempPoly = (IPolygon)ptopBuffer.Buffer(bufferDist); ITopologicalOperator ptopUnion = (ITopologicalOperator)pTempPoly; pFeat = cursor.NextFeature(); while (pFeat != null) { ptopBuffer = (ITopologicalOperator)pFeat.Shape; pTempPoly = (IPolygon)ptopBuffer.Buffer(bufferDist); ptopUnion = (ITopologicalOperator)ptopUnion.Union(pTempPoly); pFeat = cursor.NextFeature(); } return (IPolygon)ptopUnion; } return null; } return null; }
public static ISpatialFilter CreateSpatialFilter(IFeatureClass fc, IGeometry shape) { if (fc == null) return null; ISpatialFilter sf = new SpatialFilterClass(); sf.GeometryField = fc.ShapeFieldName; sf.Geometry = shape; sf.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; return sf; }
public static IFeatureCursor GetSelectedItemsByShape(IFeatureClass fc, ISpatialFilter filter) { try { if (filter == null) return null; if (fc == null) return null; IFeatureCursor fcursor = fc.Search(filter, true); return fcursor; } catch { return null; } }
public static ISelectionSet CursorToSelectionSet(IFeatureLayer layer, IFeatureCursor cursor) { IFeatureSelection fSel = (IFeatureSelection)layer; if (cursor != null) { IFeature feat = cursor.NextFeature(); while (feat != null) { fSel.Add(feat); feat = cursor.NextFeature(); } } return fSel.SelectionSet; }
Since I only have 2 Layers then I can do this.
public static IFeatureLayer GetOppositeFeatureLayerByFeatureClassName(IMap map, string featureClassName) { IFeatureLayer result = null; for (var i = 0; iExplore related questions
See similar questions with these tags.