ArcGIS Geocode Search service
ArcGIS_Geocode_Search_CSharp\App_Code\Utility.cs
// Copyright 2011 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.
// 

public class Utility
{
    /// <summary>
    /// Creates a spatial reference that will minimize distortion near the input point.  Ideal for operations 
    /// that will derive geometry based on that point (e.g. buffer).
    /// </summary>
    /// <param name="agsSoapPoint">Point to use as the center of the spatial reference's datum</param>
    /// <param name="geometryServerDcomProxy">Geometry service to use in creating the spatial reference</param>
    public static ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference CreateOperationSpatialReference(
        ESRI.ArcGIS.ADF.ArcGISServer.PointN agsSoapPoint,
        ESRI.ArcGIS.ADF.ArcGISServer.GeometryServerDcomProxy geometryServerDcomProxy)
    {
        // If the input point's spatial reference uses a projected coordinate system, project the point to a 
        // geographic coordinate system (WGS 1984 in this case).  We do this because the point's coordinates 
        // will be used to initialize the datum of the operation spatial reference
        if (agsSoapPoint.SpatialReference is ESRI.ArcGIS.ADF.ArcGISServer.ProjectedCoordinateSystem)
        {
            // Create an ArcGIS Server spatial reference initalized to use the WGS 1984 coordinate system
            ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference agsSoapGeographicSpatialReference =
                new ESRI.ArcGIS.ADF.ArcGISServer.GeographicCoordinateSystem();
            agsSoapGeographicSpatialReference.WKID = 4326;
            agsSoapGeographicSpatialReference.WKIDSpecified = true;

            // Place the input point in an array for the project operation
            ESRI.ArcGIS.ADF.ArcGISServer.Geometry[] agsSoapInputGeometryArray =
                new ESRI.ArcGIS.ADF.ArcGISServer.Geometry[1];
            agsSoapInputGeometryArray[0] = agsSoapPoint;

            // Execute the projection
            ESRI.ArcGIS.ADF.ArcGISServer.Geometry[] agsSoapOutputGeometryArray =
                geometryServerDcomProxy.Project(agsSoapPoint.SpatialReference, 
                agsSoapGeographicSpatialReference, true, null, null, agsSoapInputGeometryArray);

            // Retrieve the projected point from the results array
            agsSoapPoint = agsSoapOutputGeometryArray[0] as ESRI.ArcGIS.ADF.ArcGISServer.PointN;
        }

        // 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
        string hotineObliqueMercatorDefinition = @"
            PROJCS[""World_Hotine"",
            GEOGCS[""GCS_WGS_1984"",
            DATUM[""D_WGS_1984"",
            SPHEROID[""WGS_1984"",6378137.0,298.257223563]],
            PRIMEM[""Greenwich"",0.0],
            UNIT[""Degree"",0.0174532925199433]],
            PROJECTION[""Hotine_Oblique_Mercator_Two_Point_Natural_Origin""],
            PARAMETER[""False_Easting"",0.0],
            PARAMETER[""False_Northing"",0.0],
            PARAMETER[""Latitude_Of_1st_Point"",{0}],   
            PARAMETER[""Latitude_Of_2nd_Point"",{1}],
            PARAMETER[""Scale_Factor"",1.0],
            PARAMETER[""Longitude_Of_1st_Point"",{2}],
            PARAMETER[""Longitude_Of_2nd_Point"",{3}],
            PARAMETER[""Latitude_Of_Center"",{4}],
            UNIT[""Meter"",1.0]]";

        // Specify the coordinate system's datum parameters based on the projected point's coordinates
        string customHotineObliqueCylindricalMercator = string.Format(
            hotineObliqueMercatorDefinition, agsSoapPoint.Y - 1,
            agsSoapPoint.Y + 1, agsSoapPoint.X - 1,
            agsSoapPoint.X + 1, agsSoapPoint.Y);

        // Create the spatial reference
        ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference agsSoapBufferSpatialReference =
            geometryServerDcomProxy.FindSRByWKT(customHotineObliqueCylindricalMercator, null, true, true);

        return agsSoapBufferSpatialReference;
    }

    /// <summary>
    /// Creates a spatial reference that will minimize distortion near the input point.  Ideal for operations 
    /// that will derive geometry based on that point (e.g. buffer).
    /// </summary>
    /// <param name="aoPoint">Point to use as the center of the spatial reference's datum</param>
    /// <param name="geometryServer">Geometry service to use in creating the spatial reference</param>
    public static ESRI.ArcGIS.Geometry.ISpatialReference CreateOperationSpatialReference(
        ESRI.ArcGIS.Geometry.IPoint aoPoint, ESRI.ArcGIS.Server.IServerContext geometryServerContext)
    {
        ESRI.ArcGIS.Geometry.IGeometryServer geometryServer = geometryServerContext.ServerObject as
            ESRI.ArcGIS.Geometry.IGeometryServer;
        ESRI.ArcGIS.Geometry.IPoint aoGeographicPoint = null;

        // If the input point's spatial reference uses a projected coordinate system, project the point to a 
        // geographic coordinate system (WGS 1984 in this case).  We do this because the point's coordinates 
        // will be used to define the projection parameters of the operations spatial reference.
        if (aoPoint.SpatialReference is ESRI.ArcGIS.Geometry.ProjectedCoordinateSystem)
        {
            // Create an ArcGIS Server spatial reference initalized to use the WGS 1984 coordinate system
            ESRI.ArcGIS.Geometry.ISpatialReference aoGeographicSpatialReference =
                geometryServer.FindSRByWKID(null, 4326, -1, true, true);

            // Store the point in an array for passing to the project operation
            ESRI.ArcGIS.Geometry.IGeometryArray aoInputGeometryArray =
               geometryServerContext.CreateObject("esriGeometry.GeometryArray") as
               ESRI.ArcGIS.Geometry.IGeometryArray;
            aoInputGeometryArray.Add(aoPoint);

            // Create a transformation object to specify the GCS transformation
            ESRI.ArcGIS.Geometry.ISpatialReferenceFactory spatialReferenceFactory =
                (ESRI.ArcGIS.Geometry.ISpatialReferenceFactory)geometryServerContext.CreateObject("esriGeometry.SpatialReferenceEnvironment");
                
            ESRI.ArcGIS.Geometry.ITransformation aoTransformation =
                spatialReferenceFactory.CreateGeoTransformation(1188);

            // Execute the project operation
            ESRI.ArcGIS.Geometry.IGeometryArray aoOutputGeomeryArray = geometryServer.Project(
                aoPoint.SpatialReference, aoGeographicSpatialReference,
                ESRI.ArcGIS.Geometry.esriTransformDirection.esriTransformForward, aoTransformation,
                null, aoInputGeometryArray);

            // Retrieve the projected point from the operation results
            aoGeographicPoint = aoOutputGeomeryArray.get_Element(0) as ESRI.ArcGIS.Geometry.IPoint;
        }

        // 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
        string hotineObliqueMercatorDefinition = @"
            PROJCS[""World_Hotine"",
            GEOGCS[""GCS_WGS_1984"",
            DATUM[""D_WGS_1984"",
            SPHEROID[""WGS_1984"",6378137.0,298.257223563]],
            PRIMEM[""Greenwich"",0.0],
            UNIT[""Degree"",0.0174532925199433]],
            PROJECTION[""Hotine_Oblique_Mercator_Two_Point_Natural_Origin""],
            PARAMETER[""False_Easting"",0.0],
            PARAMETER[""False_Northing"",0.0],
            PARAMETER[""Latitude_Of_1st_Point"",{0}],   
            PARAMETER[""Latitude_Of_2nd_Point"",{1}],
            PARAMETER[""Scale_Factor"",1.0],
            PARAMETER[""Longitude_Of_1st_Point"",{2}],
            PARAMETER[""Longitude_Of_2nd_Point"",{3}],
            PARAMETER[""Latitude_Of_Center"",{4}],
            UNIT[""Meter"",1.0]]";

        // Specify the coordinate system's datum parameters based on the projected point's coordinates
        string customHotineObliqueCylindricalMercator = string.Format(
            hotineObliqueMercatorDefinition, aoGeographicPoint.Y - 1,
            aoGeographicPoint.Y + 1, aoGeographicPoint.X - 1,
            aoGeographicPoint.X + 1, aoGeographicPoint.Y);

        // Create the spatial reference
        ESRI.ArcGIS.Geometry.ISpatialReference aoOperationSpatialReference =
            geometryServer.FindSRByWKT(customHotineObliqueCylindricalMercator, null, true, true);

        return aoOperationSpatialReference;
    }

    /// <summary>
    /// Returns an ArcGIS Server LinearUnit corresponding to the passed in esriUnits enumeration
    /// </summary>
    /// <param name="unitType"></param>
    /// <returns></returns>
    public static ESRI.ArcGIS.ADF.ArcGISServer.LinearUnit ConvertUnitType(ESRI.ArcGIS.ADF.ArcGISServer.esriUnits unitType)
    {
        // Instantiate an ArcGI Server linear unit and specify its WKID (well-known identifier) based on 
        // the passed-in enumeration
        ESRI.ArcGIS.ADF.ArcGISServer.LinearUnit linearUnit = new ESRI.ArcGIS.ADF.ArcGISServer.LinearUnit();
        switch (unitType)
        {
            case ESRI.ArcGIS.ADF.ArcGISServer.esriUnits.esriCentimeters:
                linearUnit.WKID = 109006;
                break;
            case ESRI.ArcGIS.ADF.ArcGISServer.esriUnits.esriDecimalDegrees:
                linearUnit.WKID = 9102;
                break;
            case ESRI.ArcGIS.ADF.ArcGISServer.esriUnits.esriDecimeters:
                linearUnit.WKID = 109005;
                break;
            case ESRI.ArcGIS.ADF.ArcGISServer.esriUnits.esriFeet:
                linearUnit.WKID = 9003;
                break;
            case ESRI.ArcGIS.ADF.ArcGISServer.esriUnits.esriInches:
                linearUnit.WKID = 109008;
                break;
            case ESRI.ArcGIS.ADF.ArcGISServer.esriUnits.esriKilometers:
                linearUnit.WKID = 9036;
                break;
            case ESRI.ArcGIS.ADF.ArcGISServer.esriUnits.esriMeters:
                linearUnit.WKID = 9001;
                break;
            case ESRI.ArcGIS.ADF.ArcGISServer.esriUnits.esriMiles:
                linearUnit.WKID = 9035;
                break;
            case ESRI.ArcGIS.ADF.ArcGISServer.esriUnits.esriMillimeters:
                linearUnit.WKID = 109007;
                break;
            case ESRI.ArcGIS.ADF.ArcGISServer.esriUnits.esriNauticalMiles:
                linearUnit.WKID = 9030;
                break;
            case ESRI.ArcGIS.ADF.ArcGISServer.esriUnits.esriYards:
                linearUnit.WKID = 109002;
                break;
        }

        linearUnit.WKIDSpecified = true;
        return linearUnit;
    }

    /// <summary>
    /// Returns an ArcObjects IUnit corresponding to the passed in esriUnits enumeration
    /// </summary>
    /// <param name="unitType"></param>
    /// <param name="spatialReferenceEnvironment"></param>
    /// <returns></returns>
    public static ESRI.ArcGIS.Geometry.IUnit ConvertUnitType(ESRI.ArcGIS.esriSystem.esriUnits unitType,
        ESRI.ArcGIS.Geometry.SpatialReferenceEnvironment spatialReferenceEnvironment)
    {
        // Create an ArcObjects IUnit object from a well-known identifier that is determined by the
        // value of the passed-in enumeration
        ESRI.ArcGIS.Geometry.IUnit linearUnit = null;
        switch (unitType)
        {
            case ESRI.ArcGIS.esriSystem.esriUnits.esriCentimeters:
                linearUnit = spatialReferenceEnvironment.CreateUnit(109006);
                break;
            case ESRI.ArcGIS.esriSystem.esriUnits.esriDecimalDegrees:
                linearUnit = spatialReferenceEnvironment.CreateUnit(9102);
                break;
            case ESRI.ArcGIS.esriSystem.esriUnits.esriDecimeters:
                linearUnit = spatialReferenceEnvironment.CreateUnit(109005);
                break;
            case ESRI.ArcGIS.esriSystem.esriUnits.esriFeet:
                linearUnit = spatialReferenceEnvironment.CreateUnit(9003);
                break;
            case ESRI.ArcGIS.esriSystem.esriUnits.esriInches:
                linearUnit = spatialReferenceEnvironment.CreateUnit(109008);
                break;
            case ESRI.ArcGIS.esriSystem.esriUnits.esriKilometers:
                linearUnit = spatialReferenceEnvironment.CreateUnit(9036);
                break;
            case ESRI.ArcGIS.esriSystem.esriUnits.esriMeters:
                linearUnit = spatialReferenceEnvironment.CreateUnit(9001);
                break;
            case ESRI.ArcGIS.esriSystem.esriUnits.esriMiles:
                linearUnit = spatialReferenceEnvironment.CreateUnit(9035);
                break;
            case ESRI.ArcGIS.esriSystem.esriUnits.esriMillimeters:
                linearUnit = spatialReferenceEnvironment.CreateUnit(109007);
                break;
            case ESRI.ArcGIS.esriSystem.esriUnits.esriNauticalMiles:
                linearUnit = spatialReferenceEnvironment.CreateUnit(9030);
                break;
            case ESRI.ArcGIS.esriSystem.esriUnits.esriYards:
                linearUnit = spatialReferenceEnvironment.CreateUnit(109002);
                break;
        }

        return linearUnit;
    }
}