SpatialQuerySOE_VBNet\Extension.vb
' 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. ' Imports Microsoft.VisualBasic Imports System Imports System.Runtime.InteropServices Imports System.EnterpriseServices Namespace SpatialQuerySOE_VBNet ''' <summary> ''' Implementation of the Spatial Query SOE. ''' </summary> <AutomationProxy(True), ClassInterface(ClassInterfaceType.None), Guid("3896A0F5-1028-489c-81CD-F7757D117C9E")> _ Public Class Extension Inherits ServicedComponent Implements SpatialQuerySOE.Interfaces_VBNet.IExtension, ESRI.ArcGIS.Server.IServerObjectExtension, ESRI.ArcGIS.esriSystem.IObjectConstruct, ESRI.ArcGIS.esriSystem.ILogSupport, ESRI.ArcGIS.esriSystem.IObjectActivate #Region "Member Variables" Private m_ServerObjectHelper As ESRI.ArcGIS.Server.IServerObjectHelper Private m_featureLayer As ESRI.ArcGIS.Carto.IFeatureLayer Private m_layerName As String Private m_fieldName As String Private m_log As ESRI.ArcGIS.esriSystem.ILog #End Region #Region "IServerObjectExtension Members" Public Sub Init(ByVal pSOH As ESRI.ArcGIS.Server.IServerObjectHelper) Implements ESRI.ArcGIS.Server.IServerObjectExtension.Init m_ServerObjectHelper = pSOH m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Init called") End Sub Public Sub Shutdown() Implements ESRI.ArcGIS.Server.IServerObjectExtension.Shutdown m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Shutdown called") m_ServerObjectHelper = Nothing m_featureLayer = Nothing m_log = Nothing End Sub #End Region #Region "SpatialQuerySOE.Interfaces_VBNet.IExtension Members" Public Function QueryPoint(ByVal point As ESRI.ArcGIS.Geometry.IPoint, ByVal distance As Double) As SpatialQuerySOE.Interfaces_VBNet.IResults Implements SpatialQuerySOE.Interfaces_VBNet.IExtension.QueryPoint If m_featureLayer Is Nothing Then m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: layer not found") Return Nothing End If Dim featureClass As ESRI.ArcGIS.Geodatabase.IFeatureClass = m_featureLayer.FeatureClass ' buffer the point Dim topologicalOperator As ESRI.ArcGIS.Geometry.ITopologicalOperator = CType(point, ESRI.ArcGIS.Geometry.ITopologicalOperator) Dim queryGeometry As ESRI.ArcGIS.Geometry.IGeometry = topologicalOperator.Buffer(distance) ' query the feature class Dim spatialFilter As ESRI.ArcGIS.Geodatabase.ISpatialFilter = New ESRI.ArcGIS.Geodatabase.SpatialFilter() spatialFilter.Geometry = queryGeometry spatialFilter.SpatialRel = ESRI.ArcGIS.Geodatabase.esriSpatialRelEnum.esriSpatialRelIntersects spatialFilter.GeometryField = featureClass.ShapeFieldName Dim resultsFeatureCursor As ESRI.ArcGIS.Geodatabase.IFeatureCursor = featureClass.Search(spatialFilter, True) ' loop thourgh the features, clip each geometry to the buffer ' and total areas by attribute value topologicalOperator = CType(queryGeometry, ESRI.ArcGIS.Geometry.ITopologicalOperator) Dim classFieldIndex As Integer = featureClass.FindField(m_fieldName) Dim summaryStatsDictionary As New System.Collections.Specialized.ListDictionary() ' create the symbol and graphic elements collection for the graphics Dim simpleFillSymbol As ESRI.ArcGIS.Display.ISimpleFillSymbol = createFillSymbol() Dim resultsGraphics As ESRI.ArcGIS.Carto.IGraphicElements = New ESRI.ArcGIS.Carto.GraphicElements() Dim resultsFeature As ESRI.ArcGIS.Geodatabase.IFeature resultsFeature = resultsFeatureCursor.NextFeature() Do While resultsFeature IsNot Nothing ' create the graphic Dim fillShapeElement As ESRI.ArcGIS.Carto.IFillShapeElement = TryCast(New ESRI.ArcGIS.Carto.PolygonElement, ESRI.ArcGIS.Carto.IFillShapeElement) Dim element As ESRI.ArcGIS.Carto.IElement = TryCast(fillShapeElement, ESRI.ArcGIS.Carto.IElement) ' clip the geometry Dim clippedResultsGeometry As ESRI.ArcGIS.Geometry.IGeometry = topologicalOperator.Intersect(resultsFeature.Shape, ESRI.ArcGIS.Geometry.esriGeometryDimension.esriGeometry2Dimension) element.Geometry = clippedResultsGeometry fillShapeElement.Symbol = simpleFillSymbol Dim resultsGraphicElement As ESRI.ArcGIS.Carto.IGraphicElement = TryCast(fillShapeElement, ESRI.ArcGIS.Carto.IGraphicElement) resultsGraphics.Add(resultsGraphicElement) ' get statistics and add to dictionary Dim area As ESRI.ArcGIS.Geometry.IArea = TryCast(clippedResultsGeometry, ESRI.ArcGIS.Geometry.IArea) Dim resultsClass As String = TryCast(resultsFeature.Value(classFieldIndex), String) ' If the class is already in the dictionary, add the current feature's area to the existing entry If summaryStatsDictionary.Contains(resultsClass) Then summaryStatsDictionary(resultsClass) = CDbl(summaryStatsDictionary(resultsClass)) + area.Area Else summaryStatsDictionary(resultsClass) = area.Area End If resultsFeature = resultsFeatureCursor.NextFeature() Loop ' create the summary statistics recordset Dim summaryStatsRecordSet As ESRI.ArcGIS.Geodatabase.IRecordSet = createSummaryRecordSet(summaryStatsDictionary) ' create the results object Dim results As SpatialQuerySOE.Interfaces_VBNet.IResults = New Results() results.ResultsGraphics = resultsGraphics results.SummaryStatistics = summaryStatsRecordSet Return results End Function Private Function createSummaryRecordSet(ByVal summaryStatsDictionary As System.Collections.Specialized.ListDictionary) As ESRI.ArcGIS.Geodatabase.IRecordSet ' initialize the summary statistics record set Dim summaryStatsRecordSet As ESRI.ArcGIS.Geodatabase.IRecordSet = New ESRI.ArcGIS.Geodatabase.RecordSet() Dim recordSetInit As ESRI.ArcGIS.Geodatabase.IRecordSetInit = TryCast(summaryStatsRecordSet, ESRI.ArcGIS.Geodatabase.IRecordSetInit) Dim summaryFields As ESRI.ArcGIS.Geodatabase.IFields = New ESRI.ArcGIS.Geodatabase.Fields() Dim summaryFieldsEdit As ESRI.ArcGIS.Geodatabase.IFieldsEdit = TryCast(summaryFields, ESRI.ArcGIS.Geodatabase.IFieldsEdit) summaryFieldsEdit.FieldCount_2 = 2 Dim field As ESRI.ArcGIS.Geodatabase.IField = New ESRI.ArcGIS.Geodatabase.Field() Dim fieldEdit As ESRI.ArcGIS.Geodatabase.IFieldEdit = TryCast(field, ESRI.ArcGIS.Geodatabase.IFieldEdit) fieldEdit.Name_2 = "Type" fieldEdit.Type_2 = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeString fieldEdit.Length_2 = 50 summaryFieldsEdit.Field_2(0) = field field = New ESRI.ArcGIS.Geodatabase.Field() fieldEdit = TryCast(field, ESRI.ArcGIS.Geodatabase.IFieldEdit) fieldEdit.Name_2 = "Area" fieldEdit.Type_2 = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeDouble summaryFieldsEdit.Field_2(1) = field recordSetInit.CreateTable(summaryFields) Dim cursor As ESRI.ArcGIS.Geodatabase.ICursor = recordSetInit.Insert() Dim rowBuffer As ESRI.ArcGIS.Geodatabase.IRowBuffer = recordSetInit.CreateRowBuffer() ' Copy the summary stats to the record set Dim summaryStatsEnumerator As System.Collections.IDictionaryEnumerator = summaryStatsDictionary.GetEnumerator() Do While summaryStatsEnumerator.MoveNext() rowBuffer.Value(0) = summaryStatsEnumerator.Key rowBuffer.Value(1) = summaryStatsEnumerator.Value cursor.InsertRow(rowBuffer) Loop Return summaryStatsRecordSet End Function Private Function createFillSymbol() As ESRI.ArcGIS.Display.ISimpleFillSymbol Dim simpleLineSymbol As ESRI.ArcGIS.Display.ISimpleLineSymbol = New ESRI.ArcGIS.Display.SimpleLineSymbol() Dim rgbColor As ESRI.ArcGIS.Display.IRgbColor = 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 Dim simpleFillSymbol As ESRI.ArcGIS.Display.ISimpleFillSymbol = New ESRI.ArcGIS.Display.SimpleFillSymbol() simpleFillSymbol.Outline = simpleLineSymbol simpleFillSymbol.Style = ESRI.ArcGIS.Display.esriSimpleFillStyle.esriSFSHollow Return simpleFillSymbol End Function #End Region #Region "IObjectConstruct Members" Public Overloads Sub Construct(ByVal props As ESRI.ArcGIS.esriSystem.IPropertySet) Implements ESRI.ArcGIS.esriSystem.IObjectConstruct.Construct Try m_layerName = TryCast(props.GetProperty("LayerName"), String) m_fieldName = TryCast(props.GetProperty("FieldName"), String) Catch ex As Exception m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error. Error reading properties: " & ex.Message & " " & props.Count.ToString()) Return End Try Try ' Get the map underlying the map service and the IGeoFeatureLayers contained in the map Dim mapServer As ESRI.ArcGIS.Carto.IMapServer = CType(m_ServerObjectHelper.ServerObject, ESRI.ArcGIS.Carto.IMapServer) Dim mapServerObjects As ESRI.ArcGIS.Carto.IMapServerObjects = CType(mapServer, ESRI.ArcGIS.Carto.IMapServerObjects) Dim map As ESRI.ArcGIS.Carto.IMap = mapServerObjects.Map(mapServer.DefaultMapName) Dim layerTypeID As ESRI.ArcGIS.esriSystem.UID = New ESRI.ArcGIS.esriSystem.UIDClass() layerTypeID.Value = "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}" Dim enumLayer As ESRI.ArcGIS.Carto.IEnumLayer = map.Layers(layerTypeID, True) enumLayer.Reset() ' Get the layer specified as the SOE layer m_featureLayer = TryCast(enumLayer.Next(), ESRI.ArcGIS.Carto.IFeatureLayer) Do While m_featureLayer IsNot Nothing If m_featureLayer.Name = m_layerName Then Exit Do End If m_featureLayer = TryCast(enumLayer.Next(), ESRI.ArcGIS.Carto.IFeatureLayer) Loop If m_featureLayer Is Nothing Then m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: Layer " & m_layerName & " not found.") Return End If ' Make sure the layer contains the field specified by the SOE's configuration If m_featureLayer.FeatureClass.FindField(m_fieldName) = -1 Then 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.") End If Catch ex As Exception m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: Failed to initialize extension: " & ex.Message & "::" & ex.StackTrace.Length.ToString()) End Try End Sub #End Region #Region "ILogSupport Members" Public Sub InitLogging(ByVal log As ESRI.ArcGIS.esriSystem.ILog) Implements ESRI.ArcGIS.esriSystem.ILogSupport.InitLogging m_log = log End Sub #End Region #Region "IObjectActivate Members" Private Sub IObjectActivate_Activate() Implements ESRI.ArcGIS.esriSystem.IObjectActivate.Activate m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Activate called") End Sub Private Sub Deactivate() Implements ESRI.ArcGIS.esriSystem.IObjectActivate.Deactivate m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Deactivate called") End Sub #End Region End Class End Namespace