/// <summary>
        /// Computes the reverse transformation.
        /// </summary>
        /// <param name="coordinate">The coordinate.</param>
        /// <returns>The transformed coordinate.</returns>
        protected override GeoCoordinate ComputeReverse(String coordinate)
        {
            // source: http://en.wikipedia.org/wiki/MGRS

            if (coordinate == null)
            {
                throw new ArgumentNullException("coordinate", "The coordinate is null.");
            }

            if (!Regex.IsMatch(coordinate, "^[0-9]{1,2}[A-Z]{1,3}[0-9]{2,10}"))
            {
                throw new ArgumentException("The coordinate is not a valid MGRS string.", "coordinate");
            }

            Int32 xZoneNumber = 0, yZoneNumber = 0, columnNumber = 0, rowNumber = 0, columnMeters = 0, rowMeters = 0, precision = 0;

            // compute the main zone
            if (Regex.IsMatch(coordinate, "^[0-9]{1,2}[A-Z]{1}"))
            {
                if (Char.IsDigit(coordinate[1]))
                {
                    xZoneNumber = Int32.Parse(coordinate.Substring(0, 2));
                    yZoneNumber = _gridSigns.IndexOf(coordinate[2]);
                }
                else
                {
                    xZoneNumber = Int32.Parse(coordinate.Substring(0, 1));
                    yZoneNumber = _gridSigns.IndexOf(coordinate[1]);
                }
            }

            // compute the latitude and longitude for the main zone
            Double longitudeBase = (xZoneNumber - 1) * _zoneWidth - Constants.PI;
            Double latitudeBase  = (yZoneNumber - 2) * _zoneHeight - 80 * Constants.DegreeToRadian;

            // compute the subzone
            if (Regex.IsMatch(coordinate, "^[0-9]{1,2}[A-Z]{3}"))
            {
                if (xZoneNumber >= 10)
                {
                    columnNumber = _columnSigns.IndexOf(coordinate[3]); // compute the relative row and column
                    rowNumber    = _rowSigns.IndexOf(coordinate[4]);
                }
                else
                {
                    columnNumber = _columnSigns.IndexOf(coordinate[2]);
                    rowNumber    = _rowSigns.IndexOf(coordinate[3]);
                }
            }

            // compute metre precision
            if (Regex.IsMatch(coordinate, "^[0-9]{1,2}[A-Z]{1,3}[0-9]{2,10}"))
            {
                if (xZoneNumber >= 10)
                {
                    if ((coordinate.Length - 5) % 2 != 0)
                    {
                        throw new ArgumentException("The coordinate is not a valid MGRS string.", "coordinate");
                    }

                    precision = (coordinate.Length - 5) / 2;

                    columnMeters = Int32.Parse(coordinate.Substring(5, precision)) * Convert.ToInt32(Calculator.Pow(10, 5 - precision));
                    rowMeters    = Int32.Parse(coordinate.Substring(5 + precision, precision)) * Convert.ToInt32(Calculator.Pow(10, 5 - precision));
                }
                else
                {
                    if ((coordinate.Length - 4) % 2 != 0)
                    {
                        throw new ArgumentException("The coordinate is not a valid MGRS string.", "coordinate");
                    }

                    precision = (coordinate.Length - 4) / 2;

                    columnMeters = Int32.Parse(coordinate.Substring(4, precision)) * Convert.ToInt32(Calculator.Pow(10, 5 - precision));
                    rowMeters    = Int32.Parse(coordinate.Substring(4 + precision, precision)) * Convert.ToInt32(Calculator.Pow(10, 5 - precision));
                }
            }

            CoordinateProjection projection     = CoordinateProjectionFactory.UniversalTransverseMercatorZone(Ellipsoids.WGS1984, xZoneNumber, latitudeBase >= 0 ? EllipsoidHemisphere.North : EllipsoidHemisphere.South);
            Coordinate           coordinateBase = projection.Forward(new GeoCoordinate(latitudeBase, longitudeBase));

            // row number correction
            if (xZoneNumber % 2 == 0)
            {
                rowNumber = (rowNumber + _rowSigns.Count - 5) % _rowSigns.Count;
            }

            Int32 rowNumberBase = Convert.ToInt32(Math.Floor(coordinateBase.Y / _rowHeight));

            // compute the number inside the zone
            if (rowNumberBase / _rowSigns.Count * _rowSigns.Count + rowNumber < rowNumberBase)
            {
                rowNumber += (rowNumberBase / _rowSigns.Count + 1) * _rowSigns.Count;
            }
            else
            {
                rowNumber += rowNumberBase / _rowSigns.Count * _rowSigns.Count;
            }

            if (rowNumber >= 190) // handle overflow
            {
                rowNumber -= _rowSigns.Count;
            }

            // compute metre precision
            Double coordinateX = (columnNumber % 8 + 1) * _columnWidth + columnMeters;
            Double coordinateY = rowNumber * _rowHeight + rowMeters;

            // apply projection
            return(projection.Reverse(new Coordinate(coordinateX, coordinateY)));
        }