public override IMathTransform Inverse()
 {
     if (_inverse == null)
     {
         _inverse = new HotineObliqueMercatorProjection(_Parameters.ToProjectionParameter(), this);
     }
     return(_inverse);
 }
        public HotineObliqueMercatorProjection(IEnumerable <ProjectionParameter> parameters, HotineObliqueMercatorProjection inverse)
            : base(parameters, inverse)
        {
            Authority     = "EPSG";
            AuthorityCode = 9812;
            Name          = "Hotine_Oblique_Mercator";

            _azimuth = Degrees2Radians(_Parameters.GetParameterValue("azimuth"));
            var rectifiedGridAngle = Degrees2Radians(_Parameters.GetParameterValue("rectified_grid_angle"));


            sincos(lat_origin, out _sinP20, out _cosP20);
            var con = 1.0 - _es * Math.Pow(_sinP20, 2);
            var com = Math.Sqrt(1.0 - _es);

            _bl = Math.Sqrt(1.0 + _es * Math.Pow(_cosP20, 4.0) / (1.0 - _es));
            _al = _semiMajor * _bl * scale_factor * com / con;

            double f;

            if (Math.Abs(lat_origin) < EPSLN)
            {
                //ts = 1.0;
                _d  = 1.0;
                _el = 1.0;
                f   = 1.0;
            }
            else
            {
                var ts = tsfnz(_e, lat_origin, _sinP20);
                con = Math.Sqrt(con);
                _d  = _bl * com / (_cosP20 * con);
                if ((_d * _d - 1.0) > 0.0)
                {
                    if (lat_origin >= 0.0)
                    {
                        f = _d + Math.Sqrt(_d * _d - 1.0);
                    }
                    else
                    {
                        f = _d - Math.Sqrt(_d * _d - 1.0);
                    }
                }
                else
                {
                    f = _d;
                }
                _el = f * Math.Pow(ts, _bl);
            }

            var g    = .5 * (f - 1.0 / f);
            var gama = asinz(Math.Sin(_azimuth) / _d);

            lon_origin = lon_origin - asinz(g * Math.Tan(gama)) / _bl;

            con = Math.Abs(lat_origin);
            if ((con > EPSLN) && (Math.Abs(con - HALF_PI) > EPSLN))
            {
                sincos(gama, out _singam, out _cosgam);
                sincos(_azimuth, out _sinaz, out _cosaz);
                if (lat_origin >= 0)
                {
                    _u = (_al / _bl) * Math.Atan(Math.Sqrt(_d * _d - 1.0) / _cosaz);
                }
                else
                {
                    _u = -(_al / _bl) * Math.Atan(Math.Sqrt(_d * _d - 1.0) / _cosaz);
                }
            }
            else
            {
                throw new ArgumentException("Input data error");
            }

            sincos(rectifiedGridAngle, out _singrid, out _cosgrid);
        }