Implemetns the Lambert Conformal Conic 2SP Projection.

The Lambert Conformal Conic projection is a standard projection for presenting maps of land areas whose East-West extent is large compared with their North-South extent. This projection is "conformal" in the sense that lines of latitude and longitude, which are perpendicular to one another on the earth's surface, are also perpendicular to one another in the projected domain.

Inheritance: MapProjection
 /// <summary>
 /// Returns the inverse of this projection.
 /// </summary>
 /// <returns>IMathTransform that is the reverse of the current projection.</returns>
 public override IMathTransform Inverse()
 {
     if (_inverse == null)
     {
         _inverse = new LambertConformalConic2SP(this._Parameters, !_isInverse);
     }
     return(_inverse);
 }
 /// <summary>
 /// Returns the inverse of this projection.
 /// </summary>
 /// <returns>IMathTransform that is the reverse of the current projection.</returns>
 public override IMathTransform Inverse()
 {
     if (_inverse == null)
     {
         _inverse = new LambertConformalConic2SP(_Parameters.ToProjectionParameter(), this);
     }
     return(_inverse);
 }
        /// <summary>
        /// Creates an instance of an Albers projection object.
        /// </summary>
        /// <remarks>
        /// <para>The parameters this projection expects are listed below.</para>
        /// <list type="table">
        /// <listheader><term>Parameter</term><description>Description</description></listheader>
        /// <item><term>latitude_of_origin</term><description>The latitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
        /// <item><term>central_meridian</term><description>The longitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
        /// <item><term>standard_parallel_1</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is nearest the pole.  Scale is true along this parallel.</description></item>
        /// <item><term>standard_parallel_2</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is furthest from the pole.  Scale is true along this parallel.</description></item>
        /// <item><term>false_easting</term><description>The easting value assigned to the false origin.</description></item>
        /// <item><term>false_northing</term><description>The northing value assigned to the false origin.</description></item>
        /// </list>
        /// </remarks>
        /// <param name="parameters">List of parameters to initialize the projection.</param>
        /// <param name="inverse">Indicates whether the projection forward (meters to degrees or degrees to meters).</param>
        protected LambertConformalConic2SP(IEnumerable <ProjectionParameter> parameters, LambertConformalConic2SP inverse)
            : base(parameters, inverse)
        {
            Name          = "Lambert_Conformal_Conic_2SP";
            Authority     = "EPSG";
            AuthorityCode = 9802;

            //Check for missing parameters
            var lat1 = Degrees2Radians(_Parameters.GetParameterValue("standard_parallel_1"));
            var lat2 = Degrees2Radians(_Parameters.GetParameterValue("standard_parallel_2"));

            double sin_po;                              /* sin value                            */
            double cos_po;                              /* cos value                            */
            double con;                                 /* temporary variable                   */
            double ms1;                                 /* small m 1                            */
            double ms2;                                 /* small m 2                            */
            double ts0;                                 /* small t 0                            */
            double ts1;                                 /* small t 1                            */
            double ts2;                                 /* small t 2                            */



            /* Standard Parallels cannot be equal and on opposite sides of the equator
            *  ------------------------------------------------------------------------*/

            if (Math.Abs(lat1 + lat2) < EPSLN)
            {
                //Debug.Assert(true,"LambertConformalConic:LambertConformalConic() - Equal Latitiudes for St. Parallels on opposite sides of equator");
                throw new ArgumentException("Equal latitudes for St. Parallels on opposite sides of equator.");
            }

            sincos(lat1, out sin_po, out cos_po);
            con = sin_po;
            ms1 = msfnz(_e, sin_po, cos_po);
            ts1 = tsfnz(_e, lat1, sin_po);
            sincos(lat2, out sin_po, out cos_po);
            ms2    = msfnz(_e, sin_po, cos_po);
            ts2    = tsfnz(_e, lat2, sin_po);
            sin_po = Math.Sin(lat_origin);
            ts0    = tsfnz(_e, lat_origin, sin_po);

            if (Math.Abs(lat1 - lat2) > EPSLN)
            {
                ns = Math.Log(ms1 / ms2) / Math.Log(ts1 / ts2);
            }
            else
            {
                ns = con;
            }
            f0 = ms1 / (ns * Math.Pow(ts1, ns));
            rh = _semiMajor * f0 * Math.Pow(ts0, ns);
        }
        private static IMathTransform CreateCoordinateOperation(IProjection projection, IEllipsoid ellipsoid, ILinearUnit unit)
        {
            List<ProjectionParameter> parameterList = new List<ProjectionParameter>(projection.NumParameters);
            for (int i = 0; i < projection.NumParameters; i++)
                parameterList.Add(projection.GetParameter(i));

            parameterList.Add(new ProjectionParameter("semi_major", ellipsoid.SemiMajorAxis));
            parameterList.Add(new ProjectionParameter("semi_minor", ellipsoid.SemiMinorAxis));
            parameterList.Add(new ProjectionParameter("unit", unit.MetersPerUnit));
            IMathTransform transform = null;
            switch (projection.ClassName.ToLower(CultureInfo.InvariantCulture).Replace(' ', '_'))
            {
                case "mercator":
                case "mercator_1sp":
                case "mercator_2sp":
                    //1SP
                    transform = new Mercator(parameterList);
                    break;
                case "transverse_mercator":
                    transform = new TransverseMercator(parameterList);
                    break;
                case "albers":
                case "albers_conic_equal_area":
                    transform = new AlbersProjection(parameterList);
                    break;
                case "krovak":
                    transform = new KrovakProjection(parameterList);
                    break;
                case "lambert_conformal_conic":
                case "lambert_conformal_conic_2sp":
                case "lambert_conic_conformal_(2sp)":
                    transform = new LambertConformalConic2SP(parameterList);
                    break;
                default:
                    throw new NotSupportedException(String.Format("Projection {0} is not supported.", projection.ClassName));
            }
            return transform;
        }
 /// <summary>
 /// Returns the inverse of this projection.
 /// </summary>
 /// <returns>IMathTransform that is the reverse of the current projection.</returns>
 public override IMathTransform Inverse()
 {
     if (_inverse==null)
         _inverse = new LambertConformalConic2SP(this._Parameters, ! _isInverse);
     return _inverse;
 }
		/// <summary>
		/// Returns the inverse of this projection.
		/// </summary>
		/// <returns>IMathTransform that is the reverse of the current projection.</returns>
		public override IMathTransform Inverse()
		{
			if (_inverse == null)
			{
			    _inverse = new LambertConformalConic2SP(_Parameters.ToProjectionParameter(), this);
			}
			return _inverse;
		}
		/// <summary>
		/// Creates an instance of an Albers projection object.
		/// </summary>
		/// <remarks>
		/// <para>The parameters this projection expects are listed below.</para>
		/// <list type="table">
		/// <listheader><term>Parameter</term><description>Description</description></listheader>
		/// <item><term>latitude_of_origin</term><description>The latitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
		/// <item><term>central_meridian</term><description>The longitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
		/// <item><term>standard_parallel_1</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is nearest the pole.  Scale is true along this parallel.</description></item>
		/// <item><term>standard_parallel_2</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is furthest from the pole.  Scale is true along this parallel.</description></item>
		/// <item><term>false_easting</term><description>The easting value assigned to the false origin.</description></item>
		/// <item><term>false_northing</term><description>The northing value assigned to the false origin.</description></item>
		/// </list>
		/// </remarks>
		/// <param name="parameters">List of parameters to initialize the projection.</param>
		/// <param name="inverse">Indicates whether the projection forward (meters to degrees or degrees to meters).</param>
		protected LambertConformalConic2SP(IEnumerable<ProjectionParameter> parameters, LambertConformalConic2SP inverse)
			: base(parameters, inverse)
		{
			Name = "Lambert_Conformal_Conic_2SP";
			Authority = "EPSG";
			AuthorityCode = 9802;
			
            //Check for missing parameters
			var lat1 = Degrees2Radians(_Parameters.GetParameterValue("standard_parallel_1"));
            var lat2 = Degrees2Radians(_Parameters.GetParameterValue("standard_parallel_2"));

			double sin_po;                  /* sin value                            */
			double cos_po;                  /* cos value                            */
			double con;                     /* temporary variable                   */
			double ms1;                     /* small m 1                            */
			double ms2;                     /* small m 2                            */
			double ts0;                     /* small t 0                            */
			double ts1;                     /* small t 1                            */
			double ts2;                     /* small t 2                            */



			/* Standard Parallels cannot be equal and on opposite sides of the equator
			------------------------------------------------------------------------*/
			if (Math.Abs(lat1+lat2) < EPSLN)
			{
				//Debug.Assert(true,"LambertConformalConic:LambertConformalConic() - Equal Latitiudes for St. Parallels on opposite sides of equator");
				throw new ArgumentException("Equal latitudes for St. Parallels on opposite sides of equator.");
			}

			sincos(lat1,out sin_po,out cos_po);
			con = sin_po;
			ms1 = msfnz(_e,sin_po,cos_po);
			ts1 = tsfnz(_e,lat1,sin_po);
			sincos(lat2,out sin_po,out cos_po);
			ms2 = msfnz(_e,sin_po,cos_po);
			ts2 = tsfnz(_e,lat2,sin_po);
			sin_po = Math.Sin(lat_origin);
			ts0 = tsfnz(_e,lat_origin,sin_po);

			if (Math.Abs(lat1 - lat2) > EPSLN)
				ns = Math.Log(ms1/ms2)/ Math.Log (ts1/ts2);
			else
				ns = con;
			f0 = ms1 / (ns * Math.Pow(ts1,ns));
			rh = _semiMajor * f0 * Math.Pow(ts0,ns);
		}