/// <summary>
        /// Convert region geography from one coordinate system to
        /// another coordinate system.
        /// </summary>
        /// <param name="regionGeography">Region geography that should be converted.</param>
        /// <param name="fromCoordinateSystem">From coordinate system.</param>
        /// <param name="toCoordinateSystem">To coordinate system.</param>
        /// <returns>Region geography with coordinates according to toCoordinateSystem</returns>
        public virtual WebRegionGeography GetConvertedRegionGeography(WebRegionGeography regionGeography,
                                                                      WebCoordinateSystem fromCoordinateSystem,
                                                                      WebCoordinateSystem toCoordinateSystem)
        {
            WebRegionGeography toRegionGeography;

            toRegionGeography = regionGeography;
            toRegionGeography.MultiPolygon = GetConvertedMultiPolygon(regionGeography.MultiPolygon,
                                                                      fromCoordinateSystem,
                                                                      toCoordinateSystem);
            toRegionGeography.BoundingBox = toRegionGeography.MultiPolygon.GetBoundingBox();
            return(toRegionGeography);
        }
        /// <summary>
        /// Test if point is located inside region.
        /// Currently only two dimensions are handled.
        /// </summary>
        /// <param name="regionGeography">This region geography.</param>
        /// <param name="context">Web service request context.</param>
        /// <param name="coordinateSystem">Coordinate system used in region.</param>
        /// <param name='point'>Point.</param>
        /// <returns>True if point is located inside region.</returns>
        public static Boolean IsPointInsideGeography(this WebRegionGeography regionGeography,
                                                     WebServiceContext context,
                                                     WebCoordinateSystem coordinateSystem,
                                                     WebPoint point)
        {
            SqlGeography geographyMultiPolygon, geographyPoint;

            if (regionGeography.BoundingBox.IsPointInside(point))
            {
                geographyPoint        = point.GetGeography();
                geographyMultiPolygon = regionGeography.GetMultiPolygonGeography(context, coordinateSystem);
                return(geographyMultiPolygon.STIntersects(geographyPoint).Value);
            }
            else
            {
                // Species observation can not be inside region
                // since it is not inside the regions bounding box.
                return(false);
            }
        }
        /// <summary>
        /// Get a SqlGeometry instance with same information as
        /// property MultiPolygon in provided WebRegionGeography.
        /// </summary>
        /// <param name="regionGeography">This region geography.</param>
        /// <param name="context">Web service request context.</param>
        /// <param name="coordinateSystem">Coordinate system used in region.</param>
        /// <returns>
        /// A SqlGeometry instance with same information as
        /// property MultiPolygon in provided WebRegionGeography.
        /// </returns>
        private static SqlGeometry GetMultiPolygonGeometry(this WebRegionGeography regionGeography,
                                                           WebServiceContext context,
                                                           WebCoordinateSystem coordinateSystem)
        {
            SqlGeometry geometryMultiPolygon;
            String      cacheKey;

            // Get cached information.
            cacheKey = "RegionSqlGeometry:" +
                       regionGeography.Id +
                       ":CoordinateSystem:" +
                       coordinateSystem.GetWkt();
            geometryMultiPolygon = (SqlGeometry)context.GetCachedObject(cacheKey);

            if (geometryMultiPolygon.IsNull())
            {
                geometryMultiPolygon = regionGeography.MultiPolygon.GetGeometry();

                // Add information to cache.
                context.AddCachedObject(cacheKey, geometryMultiPolygon, new TimeSpan(1, 0, 0), CacheItemPriority.BelowNormal);
            }

            return(geometryMultiPolygon);
        }