/// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="tile">TerrainTile to be cached.</param>
 public TerrainTileCacheEntry(TerrainTile tile)
 {
     m_terrainTile = tile;
 }
        /// <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 (!higherResSub.IsOn)
                    {
                        continue;
                    }
                    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);
        }