SampleXYSearch.cs
Copy Code
|
|
---|---|
using System; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Collections; using Miner.Interop; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.Geodatabase; namespace Miner.Samples.Search.Strategies { /// <summary> /// XY Search Strategy /// Configuration file must include these properties: /// (IMap) "Map" /// (double) "XCoord" /// (double) "YCoord" /// (double) "Distance" /// (IObjectClass) "ObjectClass" /// </summary> [ClassInterface(ClassInterfaceType.None)] [Guid("E52A4CFA-651A-46a0-BD9E-B0213BDE19AA")] [ProgId("MinerDeveloperSamples.SampleXYSearch")] public class XYSearch : IMMSearchStrategy { private string _featureLayerClassID = "{40A9E885-5533-11D0-98BE-00805F7CED21}"; private IMMRowSearchResults _results; private Hashtable _tableHash; private IMMSearchControl _searchControl; private double _xCoord; private double _yCoord; private double _distance; private IMap _map; private IObjectClass _classFilter; public XYSearch(){} // no constructor req'd. #region IMMSearchStrategy Members public IMMSearchResults Find(IMMSearchConfiguration pSearchConfig, IMMSearchControl searchControl) { _searchControl = searchControl; ExtractSettings(pSearchConfig); ExecuteFind(); if (Stopped) { return null; } else { return _results as IMMSearchResults; } } #endregion private void ExtractSettings(IMMSearchConfiguration config) { if (null == config) throw new InvalidOperationException("Null IMMSearchConfiguration; find cannot proceed."); IPropertySet properties = config.SearchParameters as IPropertySet; if (null == properties) throw new InvalidOperationException("No PropertySet in IMMSearchConfiguration; find cannot proceed."); _map = (IMap) properties.GetProperty("Map"); _xCoord = (double) properties.GetProperty("XCoord"); _yCoord = (double) properties.GetProperty("YCoord"); _distance = (double) properties.GetProperty("Distance"); _classFilter = (IObjectClass) properties.GetProperty("ObjectClass"); if (_distance < 1) { _distance = 1; } } private bool Stopped { get { if (_searchControl != null) { return _searchControl.Stopped; } else { return false; } } } private void ExecuteFind() { // todo: Use filters for map production. // We track the tables that we have visited to eliminate // duplicates. Create a hash with the number of tables // we may hit. Note that LayerCount only returns the // count of top-level layers, NOT those that are buried // under groups - thus the doubling factor here: int appxNumberOfActualLayers = _map.LayerCount * 2; _tableHash = new Hashtable(appxNumberOfActualLayers); IGeometry searchArea = BuildSearchGeometry(); IEnumLayer layers = GetFeatureLayers(); layers.Reset(); ILayer layer = layers.Next(); while (layer != null) { if (Stopped) break; if (layer.Valid) { ICursor cursor = LocateFeatures(layer, searchArea); AddCursorToResults(cursor); } layer = layers.Next(); } // no need to persist the table data; clear it out. _tableHash.Clear(); } private IGeometry BuildSearchGeometry() { IPoint center = new PointClass(); center.X = _xCoord; center.Y = _yCoord; ICircularArc circle = new CircularArcClass(); IConstructCircularArc makeCircle = circle as IConstructCircularArc; makeCircle.ConstructCircle(center, _distance, true); return circle as IGeometry; } private IEnumLayer GetFeatureLayers() { ESRI.ArcGIS.esriSystem.UID filterUID = new ESRI.ArcGIS.esriSystem.UIDClass(); filterUID.Value = _featureLayerClassID; return _map.get_Layers(filterUID, true); } private ICursor LocateFeatures(ILayer layer, IGeometry searchArea) { IFeatureClass featClass = GetFeatureClass(layer); if (featClass == null) return null; ISpatialFilter filter = new SpatialFilterClass(); filter.Geometry = searchArea.Envelope; filter.GeometryField = featClass.ShapeFieldName; filter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; filter.WhereClause += GetQueryDefinition(layer); IObjectClass oc = featClass as IObjectClass; ITable table = oc as ITable; ICursor cursor = null; // Due to grouped layers, we may be hitting the same // table twice. Check here if we have already checked // this one - we do not want to duplicate results. if (TableAlreadySearched(table)) return cursor; try { cursor = table.Search(filter, false); } catch { //notify user with a pretty msg that the search failed: Resourcer res = new Resourcer(); string msg = "Failed Table Search"; string title = "Sample XY Search"; MessageBox.Show(msg, title); } return cursor; } private bool TableAlreadySearched(ITable table) { if (!_tableHash.Contains(table)) { _tableHash.Add(table, null); return false; } else { return true; } } private void AddCursorToResults(ICursor cursor) { // simply take a cursor, and add it to the // internal _results object. if (cursor == null) return; if (_results == null) { _results = new Miner.Framework.Search.RowSearchResults(); } _results.AddCursor(cursor, false); } private string GetQueryDefinition(ILayer layer) { if (layer == null) return null; IFeatureLayerDefinition flDef = layer as IFeatureLayerDefinition; if (null == flDef) return null; string queryDef = flDef.DefinitionExpression; if (queryDef != null && queryDef.Length > 0) { queryDef = "(" + queryDef + ")"; } return queryDef; } private IFeatureClass GetFeatureClass(ILayer layer) { if (layer == null || !layer.Valid) return null; IFeatureLayer featLyr = layer as IFeatureLayer; if (featLyr == null) return null; return featLyr.FeatureClass; } } } |