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> /// 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); }