SpatialQuerySOE_CSharp\Extension.cs
// Copyright 2010 ESRI // // All rights reserved under the copyright laws of the United States // and applicable international laws, treaties, and conventions. // // You may freely redistribute and use this sample code, with or // without modification, provided you include the original copyright // notice and use restrictions. // // See the use restrictions. // using System; using System.Runtime.InteropServices; using System.EnterpriseServices; namespace SpatialQuerySOE { /// <summary> /// Implementation of the Spatial Query SOE. /// </summary> [AutomationProxy(true), ClassInterface(ClassInterfaceType.None), GuidAttribute("1932805D-7266-41a2-9428-0421A5617436")] public class Extension : ServicedComponent, SpatialQuerySOE.Interfaces.IExtension, ESRI.ArcGIS.Server.IServerObjectExtension, ESRI.ArcGIS.esriSystem.IObjectConstruct, ESRI.ArcGIS.esriSystem.ILogSupport, ESRI.ArcGIS.esriSystem.IObjectActivate { #region Member Variables private ESRI.ArcGIS.Server.IServerObjectHelper m_ServerObjectHelper; private ESRI.ArcGIS.Carto.IFeatureLayer m_featureLayer; private string m_layerName; private string m_fieldName; private ESRI.ArcGIS.esriSystem.ILog m_log; #endregion #region IServerObjectExtension Members public void Init(ESRI.ArcGIS.Server.IServerObjectHelper pSOH) { m_ServerObjectHelper = pSOH; m_log.AddMessage(3,8000,"SpatialQuerySOE custom message. Init called"); } public void Shutdown() { m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Shutdown called"); m_ServerObjectHelper = null; m_featureLayer = null; m_log = null; } #endregion #region SpatialQuerySOE.Interfaces.IExtension Members public SpatialQuerySOE.Interfaces.IResults QueryPoint(ESRI.ArcGIS.Geometry.IPoint point, double distance) { if (m_featureLayer == null) { m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: layer not found"); return null; } ESRI.ArcGIS.Geodatabase.IFeatureClass featureClass = m_featureLayer.FeatureClass; // buffer the point ESRI.ArcGIS.Geometry.ITopologicalOperator topologicalOperator = (ESRI.ArcGIS.Geometry.ITopologicalOperator)point; ESRI.ArcGIS.Geometry.IGeometry queryGeometry = topologicalOperator.Buffer(distance); // query the feature class ESRI.ArcGIS.Geodatabase.ISpatialFilter spatialFilter = new ESRI.ArcGIS.Geodatabase.SpatialFilter(); spatialFilter.Geometry = queryGeometry; spatialFilter.SpatialRel = ESRI.ArcGIS.Geodatabase.esriSpatialRelEnum.esriSpatialRelIntersects; spatialFilter.GeometryField = featureClass.ShapeFieldName; ESRI.ArcGIS.Geodatabase.IFeatureCursor resultsFeatureCursor = featureClass.Search(spatialFilter, true); // loop thourgh the features, clip each geometry to the buffer // and total areas by attribute value topologicalOperator = (ESRI.ArcGIS.Geometry.ITopologicalOperator)queryGeometry; int classFieldIndex = featureClass.FindField(m_fieldName); System.Collections.Specialized.ListDictionary summaryStatsDictionary = new System.Collections.Specialized.ListDictionary(); // create the symbol and graphic elements collection for the graphics ESRI.ArcGIS.Display.ISimpleFillSymbol simpleFillSymbol = createFillSymbol(); ESRI.ArcGIS.Carto.IGraphicElements resultsGraphics = new ESRI.ArcGIS.Carto.GraphicElements(); ESRI.ArcGIS.Geodatabase.IFeature resultsFeature; while ((resultsFeature = resultsFeatureCursor.NextFeature()) != null) { // create the graphic ESRI.ArcGIS.Carto.IFillShapeElement fillShapeElement = new ESRI.ArcGIS.Carto.PolygonElement() as ESRI.ArcGIS.Carto.IFillShapeElement; ESRI.ArcGIS.Carto.IElement element = fillShapeElement as ESRI.ArcGIS.Carto.IElement; // clip the geometry ESRI.ArcGIS.Geometry.IGeometry clippedResultsGeometry = topologicalOperator.Intersect(resultsFeature.Shape, ESRI.ArcGIS.Geometry.esriGeometryDimension.esriGeometry2Dimension); element.Geometry = clippedResultsGeometry; fillShapeElement.Symbol = simpleFillSymbol; ESRI.ArcGIS.Carto.IGraphicElement resultsGraphicElement = fillShapeElement as ESRI.ArcGIS.Carto.IGraphicElement; resultsGraphics.Add(resultsGraphicElement); // get statistics and add to dictionary ESRI.ArcGIS.Geometry.IArea area = clippedResultsGeometry as ESRI.ArcGIS.Geometry.IArea; string resultsClass = resultsFeature.get_Value(classFieldIndex) as string; // If the class is already in the dictionary, add the current feature's area to the existing entry if (summaryStatsDictionary.Contains(resultsClass)) summaryStatsDictionary[resultsClass] = (double)summaryStatsDictionary[resultsClass] + area.Area; else summaryStatsDictionary[resultsClass] = area.Area; } // create the summary statistics recordset ESRI.ArcGIS.Geodatabase.IRecordSet summaryStatsRecordSet = createSummaryRecordSet(summaryStatsDictionary); // create the results object SpatialQuerySOE.Interfaces.IResults results = new Results(); results.ResultsGraphics = resultsGraphics; results.SummaryStatistics = summaryStatsRecordSet; return results; } private ESRI.ArcGIS.Geodatabase.IRecordSet createSummaryRecordSet( System.Collections.Specialized.ListDictionary summaryStatsDictionary) { // initialize the summary statistics record set ESRI.ArcGIS.Geodatabase.IRecordSet summaryStatsRecordSet = new ESRI.ArcGIS.Geodatabase.RecordSet(); ESRI.ArcGIS.Geodatabase.IRecordSetInit recordSetInit = summaryStatsRecordSet as ESRI.ArcGIS.Geodatabase.IRecordSetInit; ESRI.ArcGIS.Geodatabase.IFields summaryFields = new ESRI.ArcGIS.Geodatabase.Fields(); ESRI.ArcGIS.Geodatabase.IFieldsEdit summaryFieldsEdit = summaryFields as ESRI.ArcGIS.Geodatabase.IFieldsEdit; summaryFieldsEdit.FieldCount_2 = 2; ESRI.ArcGIS.Geodatabase.IField field = new ESRI.ArcGIS.Geodatabase.Field(); ESRI.ArcGIS.Geodatabase.IFieldEdit fieldEdit = field as ESRI.ArcGIS.Geodatabase.IFieldEdit; fieldEdit.Name_2 = "Type"; fieldEdit.Type_2 = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeString; fieldEdit.Length_2 = 50; summaryFieldsEdit.set_Field(0, field); field = new ESRI.ArcGIS.Geodatabase.Field(); fieldEdit = field as ESRI.ArcGIS.Geodatabase.IFieldEdit; fieldEdit.Name_2 = "Area"; fieldEdit.Type_2 = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeDouble; summaryFieldsEdit.set_Field(1, field); recordSetInit.CreateTable(summaryFields); ESRI.ArcGIS.Geodatabase.ICursor cursor = recordSetInit.Insert(); ESRI.ArcGIS.Geodatabase.IRowBuffer rowBuffer = recordSetInit.CreateRowBuffer(); // Copy the summary stats to the record set System.Collections.IDictionaryEnumerator summaryStatsEnumerator = summaryStatsDictionary.GetEnumerator(); while (summaryStatsEnumerator.MoveNext()) { rowBuffer.set_Value(0, summaryStatsEnumerator.Key); rowBuffer.set_Value(1, summaryStatsEnumerator.Value); cursor.InsertRow(rowBuffer); } return summaryStatsRecordSet; } private ESRI.ArcGIS.Display.ISimpleFillSymbol createFillSymbol() { ESRI.ArcGIS.Display.ISimpleLineSymbol simpleLineSymbol = new ESRI.ArcGIS.Display.SimpleLineSymbol(); ESRI.ArcGIS.Display.IRgbColor rgbColor = new ESRI.ArcGIS.Display.RgbColor(); rgbColor.Red = 0; rgbColor.Green = 255; rgbColor.Blue = 0; simpleLineSymbol.Color = rgbColor; simpleLineSymbol.Style = ESRI.ArcGIS.Display.esriSimpleLineStyle.esriSLSSolid; simpleLineSymbol.Width = 2; ESRI.ArcGIS.Display.ISimpleFillSymbol simpleFillSymbol = new ESRI.ArcGIS.Display.SimpleFillSymbol(); simpleFillSymbol.Outline = simpleLineSymbol; simpleFillSymbol.Style = ESRI.ArcGIS.Display.esriSimpleFillStyle.esriSFSHollow; return simpleFillSymbol; } #endregion #region IObjectConstruct Members public void Construct(ESRI.ArcGIS.esriSystem.IPropertySet props) { try { m_layerName = props.GetProperty("LayerName") as string; m_fieldName = props.GetProperty("FieldName") as string; } catch (Exception ex) { m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error. Error reading properties: " + ex.Message + " " + props.Count.ToString()); return; } try { // Get the map underlying the map service and the IGeoFeatureLayers contained in the map ESRI.ArcGIS.Carto.IMapServer mapServer = (ESRI.ArcGIS.Carto.IMapServer) m_ServerObjectHelper.ServerObject; ESRI.ArcGIS.Carto.IMapServerObjects mapServerObjects = (ESRI.ArcGIS.Carto.IMapServerObjects) mapServer; ESRI.ArcGIS.Carto.IMap map = mapServerObjects.get_Map(mapServer.DefaultMapName); ESRI.ArcGIS.esriSystem.UID layerTypeID = new ESRI.ArcGIS.esriSystem.UIDClass(); layerTypeID.Value = "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}"; ESRI.ArcGIS.Carto.IEnumLayer enumLayer = map.get_Layers(layerTypeID, true); enumLayer.Reset(); // Get the layer specified as the SOE layer while ((m_featureLayer = enumLayer.Next() as ESRI.ArcGIS.Carto.IFeatureLayer) != null) { if (m_featureLayer.Name == m_layerName) break; } if (m_featureLayer == null) { m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: Layer " + m_layerName + " not found."); return; } // Make sure the layer contains the field specified by the SOE's configuration if (m_featureLayer.FeatureClass.FindField(m_fieldName) == -1) m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: Field " + m_fieldName + " not found in layer " + m_layerName); else m_log.AddMessage(3, 8000, "SpatialQuerySOE successfully initialized."); } catch (Exception ex) { m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: Failed to initialize extension: " + ex.Message + "::" + ex.StackTrace.Length.ToString()); } } #endregion #region ILogSupport Members public void InitLogging(ESRI.ArcGIS.esriSystem.ILog log) { m_log = log; } #endregion #region IObjectActivate Members void ESRI.ArcGIS.esriSystem.IObjectActivate.Activate() { m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Activate called"); } void ESRI.ArcGIS.esriSystem.IObjectActivate.Deactivate() { m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Deactivate called"); } #endregion } }