protected void AddToCache(TerrainTileCacheEntry ttce)
        {
            if (!m_tileCache.ContainsKey(ttce.TerrainTile.TerrainTileFilePath))
            {
                if (m_tileCache.Count >= CacheSize)
                {
                    // Remove least recently used tile
                    TerrainTileCacheEntry oldestTile = null;
                    foreach (TerrainTileCacheEntry curEntry in m_tileCache.Values)
                    {
                        if (oldestTile == null)
                        {
                            oldestTile = curEntry;
                        }
                        else
                        {
                            if (curEntry.LastAccess < oldestTile.LastAccess)
                            {
                                oldestTile = curEntry;
                            }
                        }
                    }

                    m_tileCache.Remove(oldestTile);
                }

                m_tileCache.Add(ttce.TerrainTile.TerrainTileFilePath, ttce);
            }
        }
Beispiel #2
0
 /// <summary>
 /// Get fast terrain elevation at specified location from already loaded data.
 /// Will not trigger any download or data loading from files in cache - just memory.
 /// </summary>
 /// <param name="latitude">Latitude in decimal degrees.</param>
 /// <param name="longitude">Longitude in decimal degrees.</param>
 /// <returns>Returns NaN if no tile is available in cache.</returns>
 public override float GetCachedElevationAt(double latitude, double longitude)
 {
     try
     {
         if (m_terrainTileService == null)
         {
             return(0);
         }
         // Use higher res subset if any
         if (m_higherResolutionSubsets != null)
         {
             foreach (TerrainAccessor higherResSub in m_higherResolutionSubsets)
             {
                 if (!higherResSub.IsOn)
                 {
                     continue;
                 }
                 if (latitude > higherResSub.South && latitude < higherResSub.North &&
                     longitude > higherResSub.West && longitude < higherResSub.East)
                 {
                     return(higherResSub.GetCachedElevationAt(latitude, longitude));
                 }
             }
         }
         // Look for a tile starting from higher res level, moving down the levels
         TerrainTileCacheEntry ttce = null;
         for (int targetLevel = m_terrainTileService.NumberLevels - 1; targetLevel >= 0; targetLevel--)
         {
             // File name and path for that level
             double tileSize            = m_terrainTileService.LevelZeroTileSizeDegrees * Math.Pow(0.5, targetLevel);
             int    row                 = TerrainTileService.GetRowFromLatitude(latitude, tileSize);
             int    col                 = TerrainTileService.GetColFromLongitude(longitude, tileSize);
             string terrainTileFilePath = string.Format(CultureInfo.InvariantCulture,
                                                        @"{0}\{4}\{1:D4}\{1:D4}_{2:D4}.{3}",
                                                        m_terrainTileService.TerrainTileDirectory, row, col, m_terrainTileService.FileExtension, targetLevel);
             // Look in cache
             ttce = (TerrainTileCacheEntry)m_tileCache[terrainTileFilePath];
             if (ttce != null)
             {
                 // Tile found, get elevation from it
                 ttce.LastAccess = DateTime.Now;
                 return(ttce.TerrainTile.GetElevationAt(latitude, longitude));
             }
         }
     }
     catch (Exception)
     {
     }
     // No tile found - sorry.
     return(float.NaN);
 }
        /// <summary>
        /// Get terrain elevation at specified location.
        /// </summary>
        /// <param name="latitude">Latitude in decimal degrees.</param>
        /// <param name="longitude">Longitude in decimal degrees.</param>
        /// <param name="targetSamplesPerDegree"></param>
        /// <returns>Returns 0 if the tile is not available on disk.</returns>
        public override float GetElevationAt(double latitude, double longitude, double targetSamplesPerDegree)
        {
            try
            {
                if (m_terrainTileService == null || targetSamplesPerDegree < World.Settings.MinSamplesPerDegree)
                {
                    return(0);
                }

                if (m_higherResolutionSubsets != null)
                {
                    foreach (TerrainAccessor higherResSub in m_higherResolutionSubsets)
                    {
                        if (latitude > higherResSub.South && latitude < higherResSub.North &&
                            longitude > higherResSub.West && longitude < higherResSub.East)
                        {
                            return(higherResSub.GetElevationAt(latitude, longitude, targetSamplesPerDegree));
                        }
                    }
                }

                TerrainTile           tt   = m_terrainTileService.GetTerrainTile(latitude, longitude, targetSamplesPerDegree);
                TerrainTileCacheEntry ttce = (TerrainTileCacheEntry)m_tileCache[tt.TerrainTileFilePath];
                if (ttce == null)
                {
                    ttce = new TerrainTileCacheEntry(tt);
                    AddToCache(ttce);
                }

                if (!ttce.TerrainTile.IsInitialized)
                {
                    ttce.TerrainTile.Initialize();
                }
                ttce.LastAccess = DateTime.Now;
                return(ttce.TerrainTile.GetElevationAt(latitude, longitude));
            }
            catch (Exception ex)
            {
                throw new Exception(ex.ToString());
                return(0);
            }
            return(0);
        }
        /// <summary>
        /// Builds a terrain array with specified boundaries
        /// </summary>
        /// <param name="north">North edge in decimal degrees.</param>
        /// <param name="south">South edge in decimal degrees.</param>
        /// <param name="west">West edge in decimal degrees.</param>
        /// <param name="east">East edge in decimal degrees.</param>
        /// <param name="samples"></param>
        public override TerrainTile GetElevationArray(double north, double south, double west, double east,
                                                      int samples)
        {
            TerrainTile res = null;

            if (m_higherResolutionSubsets != null)
            {
                // TODO: Support more than 1 level of higher resolution sets and allow user selections
                foreach (TerrainAccessor higherResSub in m_higherResolutionSubsets)
                {
                    if (north <= higherResSub.North && south >= higherResSub.South &&
                        west >= higherResSub.West && east <= higherResSub.East)
                    {
                        res = higherResSub.GetElevationArray(north, south, west, east, samples);
                        return(res);
                    }
                }
            }

            res                = new TerrainTile(m_terrainTileService);
            res.North          = north;
            res.South          = south;
            res.West           = west;
            res.East           = east;
            res.SamplesPerTile = samples;
            res.IsInitialized  = true;
            res.IsValid        = true;

            double samplesPerDegree    = (double)samples / (double)(north - south);
            double latrange            = Math.Abs(north - south);
            double lonrange            = Math.Abs(east - west);
            TerrainTileCacheEntry ttce = null;

            float[,] data = new float[samples, samples];

            if (samplesPerDegree < World.Settings.MinSamplesPerDegree)
            {
                res.ElevationData = data;
                return(res);
            }

            double scaleFactor = (double)1 / (samples - 1);

            for (int x = 0; x < samples; x++)
            {
                for (int y = 0; y < samples; y++)
                {
                    double curLat = north - scaleFactor * latrange * x;
                    double curLon = west + scaleFactor * lonrange * y;

                    // Wrap lat/lon to fit range 90/-90 and -180/180 (PM 2006-11-17)
                    if (curLat > 90)
                    {
                        curLat  = 90 - (curLat - 90);
                        curLon += 180;
                    }
                    if (curLat < -90)
                    {
                        curLat  = -90 - (curLat + 90);
                        curLon += 180;
                    }
                    if (curLon > 180)
                    {
                        curLon -= 360;
                    }
                    if (curLon < -180)
                    {
                        curLon += 360;
                    }

                    if (ttce == null ||
                        curLat < ttce.TerrainTile.South ||
                        curLat > ttce.TerrainTile.North ||
                        curLon < ttce.TerrainTile.West ||
                        curLon > ttce.TerrainTile.East)
                    {
                        TerrainTile tt = m_terrainTileService.GetTerrainTile(curLat, curLon, samplesPerDegree);
                        ttce = (TerrainTileCacheEntry)m_tileCache[tt.TerrainTileFilePath];
                        if (ttce == null)
                        {
                            ttce = new TerrainTileCacheEntry(tt);
                            AddToCache(ttce);
                        }
                        if (!ttce.TerrainTile.IsInitialized)
                        {
                            ttce.TerrainTile.Initialize();
                        }
                        ttce.LastAccess = DateTime.Now;
                        if (!tt.IsValid)
                        {
                            res.IsValid = false;
                        }
                    }

                    data[x, y] = ttce.TerrainTile.GetElevationAt(curLat, curLon);
                }
            }
            res.ElevationData = data;

            return(res);
        }
		/// <summary>
		/// Get terrain elevation at specified location.  
		/// </summary>
		/// <param name="latitude">Latitude in decimal degrees.</param>
		/// <param name="longitude">Longitude in decimal degrees.</param>
		/// <param name="targetSamplesPerDegree"></param>
		/// <returns>Returns 0 if the tile is not available on disk.</returns>
		public override float GetElevationAt(double latitude, double longitude, double targetSamplesPerDegree)
		{
			try
			{
				if (m_terrainTileService == null || targetSamplesPerDegree < World.Settings.MinSamplesPerDegree)
					return 0;

				if (m_higherResolutionSubsets != null)
				{
					foreach (TerrainAccessor higherResSub in m_higherResolutionSubsets)
					{
						if (latitude > higherResSub.South && latitude < higherResSub.North &&
							longitude > higherResSub.West && longitude < higherResSub.East)
						{
							return higherResSub.GetElevationAt(latitude, longitude, targetSamplesPerDegree);
						}
					}
				}

				TerrainTile tt = m_terrainTileService.GetTerrainTile(latitude, longitude, targetSamplesPerDegree);
				TerrainTileCacheEntry ttce = (TerrainTileCacheEntry)m_tileCache[tt.TerrainTileFilePath];
				if (ttce == null)
				{
					ttce = new TerrainTileCacheEntry(tt);
					AddToCache(ttce);
				}

				if (!ttce.TerrainTile.IsInitialized)
					ttce.TerrainTile.Initialize();
				ttce.LastAccess = DateTime.Now;
				return ttce.TerrainTile.GetElevationAt(latitude, longitude);
			}
			catch (Exception)
			{
			}
			return 0;
		}
		protected void AddToCache(TerrainTileCacheEntry ttce)
		{
			if (!m_tileCache.ContainsKey(ttce.TerrainTile.TerrainTileFilePath))
			{
				if (m_tileCache.Count >= CacheSize)
				{
					// Remove least recently used tile
					TerrainTileCacheEntry oldestTile = null;
					foreach (TerrainTileCacheEntry curEntry in m_tileCache.Values)
					{
						if (oldestTile == null)
							oldestTile = curEntry;
						else
						{
							if (curEntry.LastAccess < oldestTile.LastAccess)
								oldestTile = curEntry;
						}
					}

					m_tileCache.Remove(oldestTile);
				}

				m_tileCache.Add(ttce.TerrainTile.TerrainTileFilePath, ttce);
			}
		}
		/// <summary>
		/// Builds a terrain array with specified boundaries
		/// </summary>
		/// <param name="north">North edge in decimal degrees.</param>
		/// <param name="south">South edge in decimal degrees.</param>
		/// <param name="west">West edge in decimal degrees.</param>
		/// <param name="east">East edge in decimal degrees.</param>
		/// <param name="samples"></param>
		public override TerrainTile GetElevationArray(double north, double south, double west, double east,
			int samples)
		{
			TerrainTile res = null;
			
			if (m_higherResolutionSubsets != null)
			{
				// TODO: Support more than 1 level of higher resolution sets and allow user selections
				foreach (TerrainAccessor higherResSub in m_higherResolutionSubsets)
				{
					if (north <= higherResSub.North && south >= higherResSub.South &&
						west >= higherResSub.West && east <= higherResSub.East)
					{
						res = higherResSub.GetElevationArray(north, south, west, east, samples);
						return res;
					}
				}
			}

			res = new TerrainTile(m_terrainTileService);
			res.North = north;
			res.South = south;
			res.West = west;
			res.East = east;
			res.SamplesPerTile = samples;
			res.IsInitialized = true;
			res.IsValid = true;

			double samplesPerDegree = (double)samples / (double)(north - south);
			double latrange = Math.Abs(north - south);
			double lonrange = Math.Abs(east - west);
			TerrainTileCacheEntry ttce = null;

			float[,] data = new float[samples, samples];

			if(samplesPerDegree < World.Settings.MinSamplesPerDegree)
			{
				res.ElevationData = data;
				return res;
			}

			double scaleFactor = (double)1 / (samples - 1);
			for (int x = 0; x < samples; x++)
			{
				for (int y = 0; y < samples; y++)
				{
					double curLat = north - scaleFactor * latrange * x;
					double curLon = west + scaleFactor * lonrange * y;

                    // Wrap lat/lon to fit range 90/-90 and -180/180 (PM 2006-11-17)
                    if (curLat > 90)
                    {
                        curLat = 90 - (curLat - 90);
                        curLon += 180;
                    }
                    if (curLat < -90)
                    {
                        curLat = -90 - (curLat + 90);
                        curLon += 180;
                    }
                    if (curLon > 180)
                    {
                        curLon -= 360;
                    }
                    if (curLon < -180)
                    {
                        curLon += 360;
                    }

					if (ttce == null ||
						curLat < ttce.TerrainTile.South ||
						curLat > ttce.TerrainTile.North ||
						curLon < ttce.TerrainTile.West ||
						curLon > ttce.TerrainTile.East)
					{
						TerrainTile tt = m_terrainTileService.GetTerrainTile(curLat, curLon, samplesPerDegree);
						ttce = (TerrainTileCacheEntry)m_tileCache[tt.TerrainTileFilePath];
						if (ttce == null)
						{
							ttce = new TerrainTileCacheEntry(tt);
							AddToCache(ttce);
						}
						if (!ttce.TerrainTile.IsInitialized)
							ttce.TerrainTile.Initialize();
						ttce.LastAccess = DateTime.Now;
						if (!tt.IsValid)
							res.IsValid = false;
					}

					data[x, y] = ttce.TerrainTile.GetElevationAt(curLat, curLon);
				}
			}
			res.ElevationData = data;

			return res;
		}
        /// <summary>
        /// Builds a terrain array with specified boundaries
        /// </summary>
        /// <param name="north">North edge in decimal degrees.</param>
        /// <param name="south">South edge in decimal degrees.</param>
        /// <param name="west">West edge in decimal degrees.</param>
        /// <param name="east">East edge in decimal degrees.</param>
        /// <param name="samples"></param>
        public override TerrainTile GetElevationArray(float north, float south, float west, float east,
                                                      int samples)
        {
            TerrainTile res = null;

            if (m_higherResolutionSubsets != null)
            {
                // TODO: Support more than 1 level of higher resolution sets and allow user selections
                foreach (TerrainAccessor higherResSub in m_higherResolutionSubsets)
                {
                    if (north <= higherResSub.North && south >= higherResSub.South &&
                        west >= higherResSub.West && east <= higherResSub.East)
                    {
                        res = higherResSub.GetElevationArray(north, south, west, east, samples);
                        return(res);
                    }
                }
            }

            res                = new TerrainTile(m_terrainTileService);
            res.North          = north;
            res.South          = south;
            res.West           = west;
            res.East           = east;
            res.SamplesPerTile = samples;
            res.IsInitialized  = true;
            res.IsValid        = true;

            float samplesPerDegree     = (samples / (north - south));
            float latrange             = Math.Abs(north - south);
            float lonrange             = Math.Abs(east - west);
            TerrainTileCacheEntry ttce = null;

            res.ElevationData = new List <float>(samples * samples);

            if (samplesPerDegree < 3.0)
            {
                return(null);
            }

            float scaleFactor = 1.0f / (samples - 1);
            float curLat, curLon;

            for (int y = 0; y < samples; y++)
            {
                for (int x = 0; x < samples; x++)
                {
                    curLat = north - scaleFactor * latrange * x;
                    curLon = west + scaleFactor * lonrange * y;

                    if (ttce == null ||
                        curLat < ttce.TerrainTile.South ||
                        curLat > ttce.TerrainTile.North ||
                        curLon < ttce.TerrainTile.West ||
                        curLon > ttce.TerrainTile.East)
                    {
                        TerrainTile tt = m_terrainTileService.GetTerrainTile(curLat, curLon, samplesPerDegree);
                        ttce = (TerrainTileCacheEntry)m_tileCache[tt.TerrainTileFilePath];
                        if (ttce == null)
                        {
                            ttce = new TerrainTileCacheEntry(tt);
                            AddToCache(ttce);
                        }
                        if (!ttce.TerrainTile.IsInitialized)
                        {
                            ttce.TerrainTile.Initialize();
                        }
                        ttce.LastAccess = DateTime.Now;
                        if (!tt.IsValid)
                        {
                            res.IsValid = false;
                        }
                    }

                    res.ElevationData.Add(ttce.TerrainTile.GetElevationAt(curLat, curLon));
                }
            }
            return(res);
        }