Creating a custom projected coordinate system


Summary
This topic shows how to create a custom projected coordinate system (PCS) and manipulate the projection parameters.


About creating a custom projected coordinate system

The components of a PCS, such as the projection, linear unit, and geographic coordinate system (GCS) are objects. All support ISpatialReference2 and ISpatialReferenceFactory. When defining a custom PCS, use the predefined objects available in the various esriSR* enumerations.
You can access the majority of the properties and methods through the IProjectedCoordinateSystem2 interface; although, additional properties are available in IProjectedCoordinateSystem3 and IProjectedCoordinateSystem4.
The IProjectedCoordinateSystemEdit contains the Define method, which allows you to define a custom PCS. To access the hundreds of predefined PCSs, ISpatialReferenceFactory has the CreateProjectedCoordinateSystem method. The predefined PCSs are listed in the esriSRProjCSType, esriSRProjCS2Type, esriSRProjCS3Type, and esriSRProjCS4Type enumerations.
The IProjectedCoordinateSystemEdit interface provides you with the Define method to create your PCS object based on parameters, such as Name, GeographicCoordinateSystem, projectedUnit, Projection, and if necessary, projection Parameters. See the following code example:
[C#]
private IProjectedCoordinateSystem CreateProjectedCoordinateSystem()
{

    // Set up the SpatialReferenceEnvironment.
    // SpatialReferenceEnvironment is a singleton object and needs to use the Activator class.
    Type factoryType = Type.GetTypeFromProgID(
        "esriGeometry.SpatialReferenceEnvironment");
    System.Object obj = Activator.CreateInstance(factoryType);
    ISpatialReferenceFactory3 spatialReferenceFactory = obj as
        ISpatialReferenceFactory3;

    // Create a projection, GeographicCoordinateSystem, and unit using the factory.
    IProjectionGEN projection = spatialReferenceFactory.CreateProjection((int)
        esriSRProjectionType.esriSRProjection_Sinusoidal)as IProjectionGEN;
    IGeographicCoordinateSystem geographicCoordinateSystem =
        spatialReferenceFactory.CreateGeographicCoordinateSystem((int)
        esriSRGeoCSType.esriSRGeoCS_WGS1984);
    ILinearUnit unit = spatialReferenceFactory.CreateUnit((int)
        esriSRUnitType.esriSRUnit_Meter)as ILinearUnit;

    // Get the default parameters from the projection.
    IParameter[] parameters = projection.GetDefaultParameters();

    // Create a PCS using the Define method.
    IProjectedCoordinateSystemEdit projectedCoordinateSystemEdit = new
        ProjectedCoordinateSystemClass();
    object name = "Newfoundland";
    object alias = "NF_LAB";
    object abbreviation = "NF";
    object remarks = "Most Eastern Province in Canada";
    object usage = "When making maps of Newfoundland";
    object geographicCoordinateSystemObject = geographicCoordinateSystem as object;
    object unitObject = unit as object;
    object projectionObject = projection as object;
    object parametersObject = parameters as object;


    projectedCoordinateSystemEdit.Define(ref name, ref alias, ref abbreviation, ref
        remarks, ref usage, ref geographicCoordinateSystemObject, ref unitObject,
        ref projectionObject, ref parametersObject);
    return projectedCoordinateSystemEdit as IProjectedCoordinateSystem;
}
[VB.NET]
Private Function CreateProjectedCoordinateSystem() As IProjectedCoordinateSystem
    
    
    ' Set up the SpatialReferenceEnvironment.
    ' SpatialReferenceEnvironment is a singleton object and needs to use the Activator class.
    Dim factoryType As Type = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment")
    Dim spatialReferenceFactory As ISpatialReferenceFactory3 = CType(Activator.CreateInstance(factoryType), ISpatialReferenceFactory3)
    
    ' Create a projection, GeographicCoordinateSystem, and unit using the factory.
    Dim projection As IProjectionGEN = TryCast(spatialReferenceFactory.CreateProjection(CInt(esriSRProjectionType.esriSRProjection_Sinusoidal)), IProjectionGEN)
    Dim geographicCoordinateSystem As IGeographicCoordinateSystem = spatialReferenceFactory.CreateGeographicCoordinateSystem(CInt(esriSRGeoCSType.esriSRGeoCS_WGS1984))
    Dim unit As ILinearUnit = TryCast(spatialReferenceFactory.CreateUnit(CInt(esriSRUnitType.esriSRUnit_Meter)), ILinearUnit)
    
    ' Get the default parameters from the projection.
    Dim parameters As IParameter() = projection.GetDefaultParameters()
    
    ' Create a PCS using the Define method.
    Dim projectedCoordinateSystemEdit As IProjectedCoordinateSystemEdit = New ProjectedCoordinateSystemClass()
    Dim Name As Object = "Newfoundland"
    Dim [Alias] As Object = "NF_LAB"
    Dim abbreviation As Object = "NF"
    Dim remarks As Object = "Most Eastern Province in Canada"
    Dim usage As Object = "When making maps of Newfoundland"
    Dim geographicCoordinateSystemObject As Object = TryCast(geographicCoordinateSystem, Object)
    Dim unitObject As Object = TryCast(unit, Object)
    Dim projectionObject As Object = TryCast(projection, Object)
    Dim parametersObject As Object = TryCast(parameters, Object)
    
    ' Note: Alias is a reserved keyword in VB .NET. To use it as a variable name, encase it in brackets [ ].
    
    projectedCoordinateSystemEdit.Define(Name, [Alias], abbreviation, remarks, usage, geographicCoordinateSystemObject, unitObject, projectionObject, parametersObject)
    Return TryCast(projectedCoordinateSystemEdit, IProjectedCoordinateSystem)
    
    
End Function

Parameter requirements

Parameters are required by both PCSs and geographic (datum) transformations. For example, to define a Lambert Azimuthal Equal Area PCS, only the central meridian and latitude of origin parameters are required by the mathematical algorithm that performs the projection.
The IParameter interface has an index and a value. The value is self-explanatory. The index refers to the internal array that holds the parameters for a PCS or a geographic transformation. The ISpatialReferenceFactory can be used to create parameters. 
The following code example shows how to use the CreateParameter method and the esriSR_ParameterType enumeration. The SpatialReferenceFactory provides default values for each type of parameter, which can easily be changed.
[C#]
private void PrintParameter()
{
    // Set up the SpatialReferenceEnvironment.
    // SpatialReferenceEnvironment is a singleton object and needs to use the Activator class.
    Type t = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");
    System.Object obj = Activator.CreateInstance(t);
    ISpatialReferenceFactory3 spatialReferenceFactory = obj as
        ISpatialReferenceFactory3;

    IParameter parameter = spatialReferenceFactory.CreateParameter((int)
        esriSRParameterType.esriSRParameter_LatitudeOfOrigin);

    System.Windows.Forms.MessageBox.Show(parameter.Name);
    System.Windows.Forms.MessageBox.Show(parameter.Index.ToString());
    System.Windows.Forms.MessageBox.Show(parameter.Value.ToString());
    parameter.Value = 45;
    System.Windows.Forms.MessageBox.Show(parameter.Value.ToString());
}
[VB.NET]
Private Sub PrintParameter()
    
    ' Set up the SpatialReferenceEnvironment.
    ' SpatialReferenceEnvironment is a singleton object and needs to use the Activator class.
    
    Dim t As Type = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment")
    Dim obj As System.Object = Activator.CreateInstance(t)
    Dim spatialReferenceFactory As ESRI.ArcGIS.Geometry.ISpatialReferenceFactory3 = obj
    
    Dim parameter As IParameter = spatialReferenceFactory.CreateParameter(CInt(esriSRParameterType.esriSRParameter_LatitudeOfOrigin))
    System.Windows.Forms.MessageBox.Show(parameter.Name)
    System.Windows.Forms.MessageBox.Show(parameter.Index.ToString())
    System.Windows.Forms.MessageBox.Show(parameter.Value.ToString())
    parameter.Value = 45
    System.Windows.Forms.MessageBox.Show(parameter.Value.ToString())
    
End Sub
The following code example shows how to get the parameters from a PCS. It assumes that the projected coordinate is already defined. These parameters are passed to the client by reference, then it is possible to modify the value of the parameters directly. If modification is done, call the Changed method on the ProjectedCoordinateSystem.
[C#]
private void PrintParameters(IProjectedCoordinateSystem4GEN
    projectedCoordinateSystem)
{

    // Create an array of IParameters with 16 elements.
    IParameter[] parameters = new IParameter[16];

    // Get the parameters.
    projectedCoordinateSystem.GetParameters(ref parameters);

    // Iterate through the array of parameters. 
    for (int i = 0; i < parameters.Length; i++)
    {
        IParameter currentParameter = parameters[i];

        if (currentParameter != null)
        {
            System.Windows.Forms.MessageBox.Show(currentParameter.Name + ", " +
                currentParameter.Index + ", " + currentParameter.Value);
        }

    }

}
[VB.NET]
Private Sub PrintParameters(ByVal projectedCoordinateSystem As IProjectedCoordinateSystem4GEN)
    
    ' Create an array of IParameters with 16 elements.
    Dim parameters As IParameter() = New IParameter(15) {}
    
    ' Get the parameters.
    projectedCoordinateSystem.GetParameters(parameters)
    
    ' Iterate through the array of parameters.
    For i As Integer = 0 To parameters.Length - 1
        
        Dim currentParameter As IParameter = parameters(i)
        
        If Not currentParameter Is Nothing Then
            System.Windows.Forms.MessageBox.Show(currentParameter.Name & ", " & currentParameter.Index & ", " & currentParameter.Value)
        End If
        
    Next i
    
End Sub
The following code example shows how to change a parameter using the same variables:
[C#]
private void SetParameter(IProjectedCoordinateSystem4GEN projectedCoordinateSystem)
{

    // Create an array of IParameters with 16 elements.
    IParameter[] parameters = new IParameter[16];

    // Get the parameters.
    projectedCoordinateSystem.GetParameters(ref parameters);

    // Get the Central Meridian Parameter, you know that it is the third element (remember, arrays are 0-based).
    // A safer and more intuitive way would be to use the following methods:
    // IProjectedCoordinateSystem4GEN.get_CentralMeridian; or to set it
    // IProjectedCoordinateSystem4GEN.set_CentralMeridian.
    IParameter centralMeridian = parameters[2];

    // Set the new value. 
    centralMeridian.Value = 123;

    // Tell the PCS that it has changed. 
    projectedCoordinateSystem.Changed();

}
[VB.NET]
Private Sub SetParameter(ByVal projectedCoordinateSystem As IProjectedCoordinateSystem4GEN)
    
    ' Create an array of IParameters with 16 elements.
    Dim parameters As IParameter() = New IParameter(15) {}
    
    ' Get the parameters.
    projectedCoordinateSystem.GetParameters(parameters)
    
    ' Get the Central Meridian Parameter, you know that it is the third element (remember, arrays are 0-based).
    ' A safer and more intuitive way would be to use the following methods:
    ' IProjectedCoordinateSystem4GEN.get_CentralMeridian; or to set it
    ' IProjectedCoordinateSystem4GEN.set_CentralMeridian.
    Dim centralMeridian As IParameter = parameters(2)
    
    ' Set the new value.
    centralMeridian.Value = 123
    
    ' Tell the PCS that it has changed.
    projectedCoordinateSystem.Changed()
    
End Sub
The following code example uses the GetDefaultParameters method on the IProjection interface to retrieve a set of the required parameters for a projection. Set values and create a PCS using these parameters, then make a call to IProjectedCoordinateSystem4GEN.GetParameters to verify that the parameters have been set.
[C#]
private void SetProjectionParameters()
{

    // Set up the SpatialReferenceEnvironment.
    // SpatialReferenceEnvironment is a singleton object and needs to use the Activator class.
    Type t = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");
    System.Object obj = Activator.CreateInstance(t);
    ISpatialReferenceFactory3 spatialReferenceFactory = obj as
        ISpatialReferenceFactory3;

    // Create a projection, GeographicCoordinateSystem, and unit using the factory.
    IProjectionGEN projection = spatialReferenceFactory.CreateProjection((int)
        esriSRProjectionType.esriSRProjection_Sinusoidal)as IProjectionGEN;
    IGeographicCoordinateSystem geographicCoordinateSystem =
        spatialReferenceFactory.CreateGeographicCoordinateSystem((int)
        esriSRGeoCSType.esriSRGeoCS_WGS1984);
    ILinearUnit unit = spatialReferenceFactory.CreateUnit((int)
        esriSRUnitType.esriSRUnit_Meter)as ILinearUnit;

    // Get the default parameters from the projection.
    IParameter[] parameters = projection.GetDefaultParameters();

    // Iterate through the parameters and print their name and value.
    for (int i = 0; i < parameters.Length; i++)
    {

        IParameter currentParameter = parameters[i];

        if (currentParameter != null)
        {
            System.Windows.Forms.MessageBox.Show(currentParameter.Name + ", " +
                currentParameter.Index + ", " + currentParameter.Value);
        }

    }

    // Reset one of the parameter values.
    IParameter parameter = parameters[2];
    parameter.Value = 45;

    // Create a PCS using the Define method.
    IProjectedCoordinateSystemEdit projectedCoordinateSystemEdit = new
        ProjectedCoordinateSystemClass();
    object name = "Newfoundland";
    object alias = "NF_LAB";
    object abbreviation = "NF";
    object remarks = "Most Eastern Province in Canada";
    object usage = "When making maps of Newfoundland";
    object geographicCoordinateSystemObject = geographicCoordinateSystem as object;
    object unitObject = unit as object;
    object projectionObject = projection as object;
    object parametersObject = parameters as object;

    projectedCoordinateSystemEdit.Define(ref name, ref alias, ref abbreviation, ref
        remarks, ref usage, ref geographicCoordinateSystemObject, ref unitObject,
        ref projectionObject, ref parametersObject);

    IProjectedCoordinateSystem4GEN projectedCoordinateSystem =
        projectedCoordinateSystemEdit as IProjectedCoordinateSystem4GEN;

    // Get the parameters from your new PCS and verify that the parameter
    // value was changed.
    // Create an array of IParameters with 16 elements.
    IParameter[] newParameters = new IParameter[16];

    // Get the parameters.
    projectedCoordinateSystem.GetParameters(ref newParameters);

    // Iterate through the parameters and print their name and value.
    for (int i = 0; i < newParameters.Length; i++)
    {

        IParameter currentNewParameter = newParameters[i];

        if (currentNewParameter != null)
        {
            System.Windows.Forms.MessageBox.Show(currentNewParameter.Name + ", " +
                currentNewParameter.Index + ", " + currentNewParameter.Value);
        }

    }

}
[VB.NET]
Private Sub SetProjectionParameters()
    
    ' Create a factory by setting up the SpatialReferenceEnvironment.
    ' SpatialReferenceEnvironment is a singleton object and needs to use the Activator class.
    
    Dim t As Type = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment")
    Dim obj As System.Object = Activator.CreateInstance(t)
    Dim spatialReferenceFactory As ESRI.ArcGIS.Geometry.ISpatialReferenceFactory3 = obj
    
    ' Create a projection, GeographicCoordinateSystem, and unit using the factory.
    Dim projection As IProjectionGEN = TryCast(spatialReferenceFactory.CreateProjection(CInt(esriSRProjectionType.esriSRProjection_Sinusoidal)), IProjectionGEN)
    Dim geographicCoordinateSystem As IGeographicCoordinateSystem = spatialReferenceFactory.CreateGeographicCoordinateSystem(CInt(esriSRGeoCSType.esriSRGeoCS_WGS1984))
    Dim unit As ILinearUnit = TryCast(spatialReferenceFactory.CreateUnit(CInt(esriSRUnitType.esriSRUnit_Meter)), ILinearUnit)
    
    ' Get the default parameters from the projection.
    Dim parameters As IParameter() = projection.GetDefaultParameters()
    
    ' Iterate through the parameters and print their name and value.
    For i As Integer = 0 To parameters.Length - 1
        
        Dim currentParameter As IParameter = parameters(i)
        
        If Not currentParameter Is Nothing Then
            System.Windows.Forms.MessageBox.Show(currentParameter.Name & ", " & currentParameter.Index & ", " & currentParameter.Value)
        End If
        
    Next i
    
    ' Change one of the parameter values.
    Dim parameter As IParameter = parameters(2)
    parameter.Value = 45
    
    ' Create a PCS using the Define method.
    Dim projectedCoordinateSystemEdit As IProjectedCoordinateSystemEdit = New ProjectedCoordinateSystemClass()
    Dim Name As Object = "Newfoundland"
    Dim [Alias] As Object = "NF_LAB"
    Dim abbreviation As Object = "NF"
    Dim remarks As Object = "Most Eastern Province in Canada"
    Dim usage As Object = "When making maps of Newfoundland"
    Dim geographicCoordinateSystemObject As Object = TryCast(geographicCoordinateSystem, Object)
    Dim unitObject As Object = TryCast(unit, Object)
    Dim projectionObject As Object = TryCast(projection, Object)
    Dim parametersObject As Object = TryCast(parameters, Object)
    projectedCoordinateSystemEdit.Define(Name, [Alias], abbreviation, remarks, usage, geographicCoordinateSystemObject, unitObject, projectionObject, parametersObject)
    Dim projectedCoordinateSystem As IProjectedCoordinateSystem4GEN = TryCast(projectedCoordinateSystemEdit, IProjectedCoordinateSystem4GEN)
    
    ' Get the parameters from your new PCS and verify that the parameter
    ' value was changed.
    ' Create an array of IParameters with 16 elements.
    Dim newParameters As IParameter() = New IParameter(15) {}
    
    ' Get the parameters.
    projectedCoordinateSystem.GetParameters(newParameters)
    
    ' Iterate through the parameters and print their name and value.
    For i As Integer = 0 To newParameters.Length - 1
        
        Dim currentNewParameter As IParameter = newParameters(i)
        
        If Not currentNewParameter Is Nothing Then
            System.Windows.Forms.MessageBox.Show(currentNewParameter.Name & ", " & currentNewParameter.Index & ", " & currentNewParameter.Value)
        End If
        
    Next i
    
End Sub


See Also:

Constructing a high- or low-precision spatial reference




To use the code in this topic, reference the following assemblies in your Visual Studio project. In the code files, you will need using (C#) or Imports (VB .NET) directives for the corresponding namespaces (given in parenthesis below if different from the assembly name):
Development licensing Deployment licensing
ArcGIS for Desktop Basic ArcGIS for Desktop Basic
ArcGIS for Desktop Standard ArcGIS for Desktop Standard
ArcGIS for Desktop Advanced ArcGIS for Desktop Advanced
Engine Developer Kit Engine