PageRenderTime 39ms CodeModel.GetById 11ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/Main/src/DynamicDataDisplay.Maps/MapTileProvider.cs

#
C# | 183 lines | 149 code | 29 blank | 5 comment | 15 complexity | 9cd450606ac90cc52bcf47fe61a6dd14 MD5 | raw file
  1using System;
  2using System.Collections.Generic;
  3using System.Linq;
  4using System.Text;
  5using System.Windows;
  6using Microsoft.Research.DynamicDataDisplay.Common;
  7using System.Diagnostics;
  8
  9namespace Microsoft.Research.DynamicDataDisplay.Charts.Maps
 10{
 11	public class MapTileProvider : TileProvider
 12	{
 13		public MapTileProvider()
 14		{
 15			rect = DataRect.FromPoints(minX, minY, maxX, maxY);
 16		}
 17
 18		private double minX = -180;
 19		private double maxX = 180;
 20		private double minY = -87;
 21		private double maxY = 87;
 22		private DataRect rect;
 23
 24		public double MaxLatitude
 25		{
 26			get { return maxY; }
 27			set
 28			{
 29				maxY = value;
 30				minY = -value;
 31
 32				rect = DataRect.FromPoints(minX, minY, maxX, maxY);
 33			}
 34		}
 35
 36		private double maxShaderLatitude = 85;
 37		public double MaxShaderLatitude
 38		{
 39			get { return maxShaderLatitude; }
 40			set { maxShaderLatitude = value; }
 41		}
 42
 43		public double MinLatitude
 44		{
 45			get { return minY; }
 46		}
 47
 48		public double XSize { get { return maxX - minX; } }
 49		public double YSize { get { return maxY - minY; } }
 50
 51		public override DataRect GetTileBounds(TileIndex tile)
 52		{
 53			if (tile.Level == 0)
 54				return rect;
 55
 56			double width = GetTileWidth(tile.Level);
 57			double height = GetTileHeight(tile.Level);
 58			double x = 0 + tile.X * width;
 59			double y = /*minY*/0 + tile.Y * height;
 60
 61			DataRect bounds = new DataRect(x, y, width, height);
 62			return bounds;
 63		}
 64
 65		private bool xCycling = true;
 66		/// <summary>
 67		/// Gets or sets a value, indicating whether use cycled x coordinate.
 68		/// </summary>
 69		public bool XCycling
 70		{
 71			get { return xCycling; }
 72			set { xCycling = value; }
 73		}
 74
 75		// todo rewrite
 76		public static IEnumerable<TileIndex> GetTilesForLevel(double level)
 77		{
 78			int size = GetSideTilesCount(level) / 2;
 79			for (int x = -size; x < size; x++)
 80			{
 81				for (int y = -size; y < size; y++)
 82				{
 83					yield return new TileIndex(x, y, level);
 84				}
 85			}
 86		}
 87
 88		public static DataRect GetTileBoundsGeneric(TileIndex tile)
 89		{
 90			double width = 360.0 / Math.Pow(2, tile.Level);
 91			double height = 174.0 / Math.Pow(2, tile.Level);
 92			double x = /*minX*/0 + tile.X * width;
 93			double y = /*minY*/0 + tile.Y * height;
 94
 95			DataRect bounds = new DataRect(x, y, width, height);
 96			return bounds;
 97		}
 98
 99		public static long GetTotalTilesCount(double level)
100		{
101			long size = GetSideTilesCount(level);
102			return size * size;
103		}
104
105		public static int GetSideTilesCount(double level)
106		{
107			return (int)Math.Pow(2, level);
108		}
109
110		public double TileWidth { get { return GetTileWidth(Level); } }
111		public double TileHeight { get { return GetTileHeight(Level); } }
112
113		public override double GetTileWidth(double level)
114		{
115			return XSize / Math.Pow(2, level);
116		}
117
118		public override double GetTileHeight(double level)
119		{
120			return YSize / Math.Pow(2, level);
121		}
122
123		public override IEnumerable<TileIndex> GetTilesForRegion(DataRect region, double level)
124		{
125			var allTilesBounds = rect;
126			if (xCycling)
127				allTilesBounds = DataRect.Create(-Double.MaxValue, -MaxLatitude, Double.MaxValue, MaxLatitude);
128
129			region.Intersect(allTilesBounds);
130			//region.Intersect(new Rect(region.XMin, minY, region.Width, maxY - minY));
131			if (region.IsEmpty)
132				yield break;
133
134			checked
135			{
136				double tileWidth = TileWidth;
137				double tileHeight = TileHeight;
138
139				int minIx = (int)Math.Floor(region.XMin / tileWidth);
140				int maxIx = (int)Math.Ceiling(region.XMax / tileWidth);
141
142				int minIy = (int)Math.Floor(region.YMin / tileHeight);
143				int maxIy = (int)Math.Ceiling(region.YMax / tileHeight);
144
145				var maxSideCount = GetSideTilesCount(Level);
146
147				int maxIndex = maxSideCount / 2;
148				if (!xCycling)
149				{
150					if (maxIx > maxIndex)
151						maxIx = maxIndex;
152					if (minIx < -maxIndex)
153						minIx = -maxIndex;
154				}
155				if (maxIy > maxIndex)
156					maxIy = maxIndex;
157				if (minIy < -maxIndex)
158					minIy = -maxIndex;
159
160				if (level != 0)
161				{
162					maxIx--;
163					maxIy--;
164				}
165
166				for (int ix = minIx; ix <= maxIx; ix++)
167				{
168					for (int iy = minIy; iy <= maxIy; iy++)
169					{
170						yield return new TileIndex(ix, iy, level);
171					}
172				}
173			}
174		}
175
176		public static TileIndex NormalizeIndex(TileIndex id)
177		{
178			int actualX = id.X % GetSideTilesCount(id.Level);
179			TileIndex res = new TileIndex(actualX, id.Y, id.Level);
180			return res;
181		}
182	}
183}