ArcGIS_SelectBufferTool_VBNet\App_Code\Utility.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 Public Class Utility ''' <summary> ''' Retrieves the well-known ID of a unit based on its name. These names are ''' taken from the ESRI.ArcGIS.ADF.Web.DataSources.Units enumeration. ''' </summary> ''' <param name="unitName">Name of the unit to retrieve the WKID for</param> Public Shared Function GetWkidByUnitName(ByVal unitName As String) As Integer Dim wkid As Integer = -1 Select Case unitName Case "Inches" wkid = 109009 Case "Feet" wkid = 9003 Case "Yards" wkid = 109002 Case "Miles" wkid = 9035 Case "NauticalMiles" wkid = 9030 Case "Millimeters" wkid = 109007 Case "Centimeters" wkid = 109006 Case "Meters" wkid = 9001 Case "Kilometers" wkid = 9036 Case "Decimeters" wkid = 109005 End Select Return wkid End Function ''' <summary> ''' Gets the minimum enclosing rectangle (i.e. bounding box) of the passed-in polygon ''' </summary> ''' <param name="agsSoapPolygon">Polygon to retrieve the MER for</param> Public Shared Function GetBoundingExtent(ByVal agsSoapPolygon As ESRI.ArcGIS.ADF.ArcGISServer.PolygonN) As ESRI.ArcGIS.ADF.ArcGISServer.EnvelopeN ' Instantiate an envelope with max values minimized and min values maximized Dim agsSoapBoundingBox As ESRI.ArcGIS.ADF.ArcGISServer.EnvelopeN = New ESRI.ArcGIS.ADF.ArcGISServer.EnvelopeN() agsSoapBoundingBox.XMin = Double.MaxValue agsSoapBoundingBox.XMax = Double.MinValue agsSoapBoundingBox.YMin = Double.MaxValue agsSoapBoundingBox.YMax = Double.MinValue ' Iterate through all the polygon's vertices Dim i As Integer = 0 Do While i < agsSoapPolygon.RingArray.Length Dim agsSoapRing As ESRI.ArcGIS.ADF.ArcGISServer.Ring = agsSoapPolygon.RingArray(i) Dim j As Integer = 0 Do While j < agsSoapRing.PointArray.Length ' For each vertex, expand the bounds of the minimum enclosing rectangle with the ' vertex's coordinates if they fall outside the rectangle's current bounds Dim agsSoapCurrentPoint As ESRI.ArcGIS.ADF.ArcGISServer.PointN = TryCast(agsSoapRing.PointArray(j), ESRI.ArcGIS.ADF.ArcGISServer.PointN) If agsSoapCurrentPoint.X < agsSoapBoundingBox.XMin Then agsSoapBoundingBox.XMin = agsSoapCurrentPoint.X ElseIf agsSoapCurrentPoint.X > agsSoapBoundingBox.XMax Then agsSoapBoundingBox.XMax = agsSoapCurrentPoint.X End If If agsSoapCurrentPoint.Y < agsSoapBoundingBox.YMin Then agsSoapBoundingBox.YMin = agsSoapCurrentPoint.Y ElseIf agsSoapCurrentPoint.Y > agsSoapBoundingBox.YMax Then agsSoapBoundingBox.YMax = agsSoapCurrentPoint.Y End If j += 1 Loop i += 1 Loop Return agsSoapBoundingBox End Function ''' <summary> ''' Creates a spatial reference that will minimize distortion near the input polygon. Ideal for operations ''' that will derive geometry based on that polygon (i.e. buffer). ''' </summary> ''' <param name="agsSoapPolygon">Polygon to use as the center of the spatial reference's datum</param> ''' <param name="geometryServerProxy">Geometry service to use in creating the spatial reference</param> Public Shared Function CreateOperationSpatialReference(ByVal agsSoapPolygon As ESRI.ArcGIS.ADF.ArcGISServer.PolygonN, ByVal geometryServerProxy As ESRI.ArcGIS.ADF.ArcGISServer.GeometryServerProxy) As ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference ' Get the polygon's minimum enclosing rectangle (MER) Dim agsSoapBoundingEnvelope As ESRI.ArcGIS.ADF.ArcGISServer.EnvelopeN = GetBoundingExtent(agsSoapPolygon) ' If the input polygon's spatial reference uses a projected coordinate system, project the MER to a ' geographic coordinate system (WGS 1984 in this case). We do this because the MER's coordinates ' will be used to initialize the datum of the operation spatial reference If TypeOf agsSoapPolygon.SpatialReference Is ESRI.ArcGIS.ADF.ArcGISServer.ProjectedCoordinateSystem Then ' Create an ArcGIS Server spatial reference initalized to use the WGS 1984 coordinate system Dim agsSoapGeographicSpatialReference As ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference = New ESRI.ArcGIS.ADF.ArcGISServer.GeographicCoordinateSystem() agsSoapGeographicSpatialReference.WKID = 4326 agsSoapGeographicSpatialReference.WKIDSpecified = True ' Place the input MER in an array for the project operation Dim agsSoapInputGeometryArray As ESRI.ArcGIS.ADF.ArcGISServer.Geometry() = New ESRI.ArcGIS.ADF.ArcGISServer.Geometry(0){} agsSoapInputGeometryArray(0) = agsSoapBoundingEnvelope ' Execute the projection Dim agsSoapOutputGeometryArray As ESRI.ArcGIS.ADF.ArcGISServer.Geometry() = geometryServerProxy.Project(agsSoapPolygon.SpatialReference, agsSoapGeographicSpatialReference, True, Nothing, Nothing, agsSoapInputGeometryArray) ' Retrieve the projected MER from the results array agsSoapBoundingEnvelope = TryCast(agsSoapOutputGeometryArray(0), ESRI.ArcGIS.ADF.ArcGISServer.EnvelopeN) End If ' Get the latitude (Y coordinate) at the center of the MER Dim centerLatitude As Double = agsSoapBoundingEnvelope.YMax - (agsSoapBoundingEnvelope.YMax - agsSoapBoundingEnvelope.YMin) / 2 ' Create the definition string for the operation spatial reference's coordinate system. We will use ' the Hotine Oblique Mercator coordinate system because it lends itself well to minimizing operational ' distortion anywhere on the earth Dim hotineObliqueMercatorDefinition As String = "" & ControlChars.CrLf & " PROJCS[""World_Hotine""," & ControlChars.CrLf & " GEOGCS[""GCS_WGS_1984""," & ControlChars.CrLf & " DATUM[""D_WGS_1984""," & ControlChars.CrLf & " SPHEROID[""WGS_1984"",6378137.0,298.257223563]]," & ControlChars.CrLf & " PRIMEM[""Greenwich"",0.0]," & ControlChars.CrLf & " UNIT[""Degree"",0.0174532925199433]]," & ControlChars.CrLf & " PROJECTION[""Hotine_Oblique_Mercator_Two_Point_Natural_Origin""]," & ControlChars.CrLf & " PARAMETER[""False_Easting"",0.0]," & ControlChars.CrLf & " PARAMETER[""False_Northing"",0.0]," & ControlChars.CrLf & " PARAMETER[""Latitude_Of_1st_Point"",{0}], " & ControlChars.CrLf & " PARAMETER[""Latitude_Of_2nd_Point"",{1}]," & ControlChars.CrLf & " PARAMETER[""Scale_Factor"",1.0]," & ControlChars.CrLf & " PARAMETER[""Longitude_Of_1st_Point"",{2}]," & ControlChars.CrLf & " PARAMETER[""Longitude_Of_2nd_Point"",{3}]," & ControlChars.CrLf & " PARAMETER[""Latitude_Of_Center"",{4}]," & ControlChars.CrLf & " UNIT[""Meter"",1.0]]" ' Specify the relevant coordinates of the MER for the coordinate system's datum parameters Dim customHotineObliqueCylindricalMercator As String = String.Format(hotineObliqueMercatorDefinition, agsSoapBoundingEnvelope.YMin, agsSoapBoundingEnvelope.YMax, agsSoapBoundingEnvelope.XMin, agsSoapBoundingEnvelope.XMax, centerLatitude) ' Create the spatial reference Dim agsSoapBufferSpatialReference As ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference = geometryServerProxy.FindSRByWKT(customHotineObliqueCylindricalMercator, Nothing, True, True) Return agsSoapBufferSpatialReference End Function ''' <summary> ''' Creates an ArcGIS Server simple fill symbol with a solid outline and other parameters as ''' specified ''' </summary> ''' <param name="fillColor">Fill color of the symbol</param> ''' <param name="fillStyle">Fill style of the symbol</param> ''' <param name="outlineColor">Outline color of the symbol</param> ''' <param name="outlineWidth">Outline width of the symbol</param> Public Shared Function CreateSimpleFillSymbol(ByVal fillColor As System.Drawing.Color, ByVal fillStyle As ESRI.ArcGIS.ADF.ArcGISServer.esriSimpleFillStyle, ByVal outlineColor As System.Drawing.Color, ByVal outlineWidth As Integer) As ESRI.ArcGIS.ADF.ArcGISServer.SimpleFillSymbol ' Create an ArcGIS Server color object for the fill symbol based on the passed-in color Dim agsSoapFillColor As ESRI.ArcGIS.ADF.ArcGISServer.RgbColor = New ESRI.ArcGIS.ADF.ArcGISServer.RgbColor() agsSoapFillColor.Red = fillColor.R agsSoapFillColor.Green = fillColor.G agsSoapFillColor.Blue = fillColor.B ' Create a simple fill symbol with the color and passed-in fill style Dim agsSoapSimpleFillSymbol As ESRI.ArcGIS.ADF.ArcGISServer.SimpleFillSymbol = New ESRI.ArcGIS.ADF.ArcGISServer.SimpleFillSymbol() agsSoapSimpleFillSymbol.Style = fillStyle agsSoapSimpleFillSymbol.Color = agsSoapFillColor ' Create an ArcGIS Server color object for the outline Dim agsSoapOutlineColor As ESRI.ArcGIS.ADF.ArcGISServer.RgbColor = New ESRI.ArcGIS.ADF.ArcGISServer.RgbColor() agsSoapOutlineColor.Red = outlineColor.R agsSoapOutlineColor.Green = outlineColor.G agsSoapOutlineColor.Blue = outlineColor.B ' Create a simple line symbol with the color and passed-in width Dim agsSoapBufferSimpleLineSymbol As ESRI.ArcGIS.ADF.ArcGISServer.SimpleLineSymbol = New ESRI.ArcGIS.ADF.ArcGISServer.SimpleLineSymbol() agsSoapBufferSimpleLineSymbol.Color = agsSoapOutlineColor agsSoapBufferSimpleLineSymbol.Style = ESRI.ArcGIS.ADF.ArcGISServer.esriSimpleLineStyle.esriSLSSolid agsSoapBufferSimpleLineSymbol.Width = outlineWidth ' Apply the outline to the fill symbol agsSoapSimpleFillSymbol.Outline = agsSoapBufferSimpleLineSymbol Return agsSoapSimpleFillSymbol End Function ''' <summary> ''' Selects features that intersect the passed-in geometry. ''' </summary> ''' <param name="agsMapFunctionality">The map functionality of the resource containing the layer to ''' select features from</param> ''' <param name="agsSoapIntersectGeometry">The geometry used for selecting features</param> ''' <param name="targetLayerName">The name of the layer to select features from</param> ''' <param name="selectionColor">The color to use in displaying the selected features</param> Public Shared Sub SelectIntersectingFeatures(ByVal agsMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality, ByVal agsSoapIntersectGeometry As ESRI.ArcGIS.ADF.ArcGISServer.Geometry, ByVal targetLayerName As String, ByVal selectionColor As System.Drawing.Color) ' Retrieve the index of the target layer Dim layerIDs As String() = Nothing Dim layerNames As String() = Nothing agsMapFunctionality.GetLayers(layerIDs, layerNames) Dim targetLayerIndex As Integer = 0 Dim i As Integer = 0 Do While i < layerNames.Length If layerNames(i) = targetLayerName Then targetLayerIndex = i Exit Do End If i += 1 Loop ' Get a reference to the ArcGIS Server resource underlying the map functionality Dim mapResourceBase As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceBase = agsMapFunctionality.MapResource ' Get MapLayerInfo object for the selection layer and use it to determine the name of the layer's ' geometry field. Dim agsSoapMapLayerInfoArray As ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo() = mapResourceBase.MapServerInfo.MapLayerInfos Dim agsSoapActiveMapLayerInfo As ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo = agsSoapMapLayerInfoArray(targetLayerIndex) Dim geometryFieldName As String = Nothing For Each agsSoapField As ESRI.ArcGIS.ADF.ArcGISServer.Field In agsSoapActiveMapLayerInfo.Fields.FieldArray If agsSoapField.Type = ESRI.ArcGIS.ADF.ArcGISServer.esriFieldType.esriFieldTypeGeometry Then geometryFieldName = agsSoapField.Name Exit For End If Next agsSoapField ' Initialize a spatial filter to use in selecting features that intersect the buffer Dim agsSoapSpatialFilter As ESRI.ArcGIS.ADF.ArcGISServer.SpatialFilter = New ESRI.ArcGIS.ADF.ArcGISServer.SpatialFilter() agsSoapSpatialFilter.FilterGeometry = agsSoapIntersectGeometry agsSoapSpatialFilter.GeometryFieldName = geometryFieldName agsSoapSpatialFilter.SpatialRel = ESRI.ArcGIS.ADF.ArcGISServer.esriSpatialRelEnum.esriSpatialRelIntersects ' Retrieve the layer's LayerDescription to use in specifying the layer ID for the query operation Dim agsSoapMapDescription As ESRI.ArcGIS.ADF.ArcGISServer.MapDescription = agsMapFunctionality.MapDescription Dim agsSoapLayerDescriptionArray As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription() = agsSoapMapDescription.LayerDescriptions Dim agsSoapActiveLayerDescription As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription = agsSoapLayerDescriptionArray(targetLayerIndex) ' Execute a query to retrieve the IDs of features that intersect the buffer Dim agsSoapMapServerProxy As ESRI.ArcGIS.ADF.ArcGISServer.MapServerProxy = mapResourceBase.MapServerProxy Dim selectionAgsSoapFIDSet As ESRI.ArcGIS.ADF.ArcGISServer.FIDSet = agsSoapMapServerProxy.QueryFeatureIDs(agsSoapMapDescription.Name, agsSoapActiveLayerDescription.LayerID, agsSoapSpatialFilter) ' Set the selection layer's selected features to those intersecting the buffer agsSoapActiveLayerDescription.SelectionFeatures = selectionAgsSoapFIDSet.FIDArray ' Create an ArcGIS Server color object from the passed-in color Dim selectionAgsSoapRgbColor As ESRI.ArcGIS.ADF.ArcGISServer.RgbColor = New ESRI.ArcGIS.ADF.ArcGISServer.RgbColor() selectionAgsSoapRgbColor.Red = selectionColor.R selectionAgsSoapRgbColor.Green = selectionColor.G selectionAgsSoapRgbColor.Blue = selectionColor.B ' Set the layer's selection color to the passed-in color agsSoapActiveLayerDescription.SelectionColor = selectionAgsSoapRgbColor End Sub ''' <summary> ''' Constructs a callback result that will display a javascript alert with an error message ''' based on the passed-in exception ''' </summary> ''' <param name="exception">The exception from which the error message will be derived</param> ''' <returns></returns> Public Shared Function CreateErrorCallbackResult(ByVal exception As System.Exception) As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult ' Create a callback result to display an error message Dim jsAlertErrorMessage As String = GetJavaScriptErrorString(exception) Dim alertCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsAlertErrorMessage) Return alertCallbackResult End Function ''' <summary> ''' Constructs the syntax to display a javascript alert with an error message based on the ''' passed-in exception ''' </summary> ''' <param name="exception">The exception from which the error message will be derived</param> ''' <returns></returns> Public Shared Function GetJavaScriptErrorString(ByVal exception As System.Exception) As String ' Get the website's configuration file Dim webConfig As System.Configuration.Configuration = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(System.Web.HttpContext.Current.Request.ApplicationPath) ' Get the "compilation" section of the config file Dim compilationSection As System.Web.Configuration.CompilationSection = TryCast(webConfig.GetSection("system.web/compilation"), System.Web.Configuration.CompilationSection) ' If the config file's compilation section specifies debug mode, include ' stack trace information in the error message. Otherwise, just return ' the exception message. Dim errorMessage As String = Nothing If (Not compilationSection Is Nothing) AndAlso (compilationSection.Debug) Then Dim stackTrace As String = exception.StackTrace.Replace("\", "\\") stackTrace = stackTrace.Replace(Constants.vbLf, "\n") stackTrace = stackTrace.Replace(Constants.vbCr, "\r") stackTrace = stackTrace.Replace("'", "\'") errorMessage = exception.Message.Replace("\", "\\") errorMessage = errorMessage.Replace(Constants.vbLf, "\n") errorMessage = errorMessage.Replace(Constants.vbCr, "\r") errorMessage = errorMessage.Replace("'", "\'") errorMessage = errorMessage & "\n\n" & stackTrace.Trim() Else errorMessage = exception.Message End If ' Create a callback result to display an error message Dim jsAlertException As String = "alert('" & errorMessage & "')" Return jsAlertException End Function End Class