public void ProcessRequest(HttpContext context) { uint x, y, z; //Parse request parameters if (!uint.TryParse(context.Request.Params["x"], out x)) { throw (new ArgumentException("Invalid parameter")); } if (!uint.TryParse(context.Request.Params["y"], out y)) { throw (new ArgumentException("Invalid parameter")); } if (!uint.TryParse(context.Request.Params["z"], out z)) { throw (new ArgumentException("Invalid parameter")); } // Create a bitmap of size 256x256 using (var bmp = new Bitmap(256, 256)) // get graphics from bitmap using (var graphics = Graphics.FromImage(bmp)) { // calc rect from tile key var queryWindow = TransformTools.TileToWgs(x, y, z); // build the sql string sx1 = Convert.ToString(queryWindow.Left, CultureInfo.InvariantCulture); string sy1 = Convert.ToString(queryWindow.Top, CultureInfo.InvariantCulture); string sx2 = Convert.ToString(queryWindow.Right, CultureInfo.InvariantCulture); string sy2 = Convert.ToString(queryWindow.Bottom, CultureInfo.InvariantCulture); var strSql = string.Format("SELECT Id, AsBinary(Geometry) FROM WorldGeom WHERE MBRIntersects(Geometry, BuildMbr({0}, {1}, {2}, {3}));", sx1, sy2, sx2, sy1); using (SQLiteCommand command = new SQLiteCommand(strSql, Global.cn)) using (SQLiteDataReader reader = command.ExecuteReader()) { while (reader.Read()) { int id = reader.GetInt32(0); byte[] wkb = reader[1] as byte[]; // create GDI path from wkb var path = WkbToGdi.Parse(wkb, p => TransformTools.WgsToTile(x, y, z, p)); // fill polygon var fill = new SolidBrush(Color.FromArgb(168, 0, 0, 255)); graphics.FillPath(fill, path); fill.Dispose(); // draw outline graphics.DrawPath(Pens.Black, path); } reader.Close(); } //Stream the image to the client using (var memoryStream = new System.IO.MemoryStream()) { // Saving a PNG image requires a seekable stream, first save to memory stream // http://forums.asp.net/p/975883/3646110.aspx#1291641 bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png); var buffer = memoryStream.ToArray(); context.Response.ContentType = "image/png"; context.Response.OutputStream.Write(buffer, 0, buffer.Length); } } }
public void ProcessRequest(HttpContext context) { uint x, y, z; //Parse request parameters if (!uint.TryParse(context.Request.Params["x"], out x)) { throw (new ArgumentException("Invalid parameter")); } if (!uint.TryParse(context.Request.Params["y"], out y)) { throw (new ArgumentException("Invalid parameter")); } if (!uint.TryParse(context.Request.Params["z"], out z)) { throw (new ArgumentException("Invalid parameter")); } // Create a bitmap of size 256x256 using (var bmp = new Bitmap(256, 256)) // get graphics from bitmap using (var graphics = Graphics.FromImage(bmp)) { // calc rect from tile key var queryWindow = TransformTools.TileToWgs(x, y, z); // build the sql var strSql = string.Format(CultureInfo.InvariantCulture, @"SELECT WorldGeom.Id, AsBinary(Geometry), Pop/Area as PopDens FROM WorldGeom " + @"JOIN WorldData on WorldData.Id = WorldGeom.Id " + @"WHERE MBRIntersects(Geometry, BuildMbr({0}, {1}, {2}, {3}));", queryWindow.Left, queryWindow.Top, queryWindow.Right, queryWindow.Bottom); var choropleth = new Classification <double, Color> { MinValue = 0, // lower border for classification DefaultAttribute = Color.White, // color if key hits no class Values = new SortedList <double, Color> { // the classes { 50, Color.Green }, { 100, Color.LightGreen }, { 250, Color.Yellow }, { 500, Color.Orange }, { 1000, Color.Red }, { 2500, Color.DarkRed }, { double.MaxValue, Color.Purple } } }; using (SQLiteCommand command = new SQLiteCommand(strSql, Global.cn)) using (SQLiteDataReader reader = command.ExecuteReader()) { while (reader.Read()) { int id = reader.GetInt32(0); byte[] wkb = reader[1] as byte[]; double popDens = reader.IsDBNull(2)? -1 : reader.GetDouble(2); // create GDI path from wkb var path = WkbToGdi.Parse(wkb, p => TransformTools.WgsToTile(x, y, z, p)); // fill polygon var color = choropleth.GetValue(popDens); var fill = new SolidBrush(Color.FromArgb(168, color.R, color.G, color.B)); graphics.FillPath(fill, path); fill.Dispose(); // draw outline graphics.DrawPath(Pens.Black, path); } reader.Close(); } //Stream the image to the client using (var memoryStream = new System.IO.MemoryStream()) { // Saving a PNG image requires a seekable stream, first save to memory stream // http://forums.asp.net/p/975883/3646110.aspx#1291641 bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png); var buffer = memoryStream.ToArray(); context.Response.ContentType = "image/png"; context.Response.OutputStream.Write(buffer, 0, buffer.Length); } } }
// http://msdn.microsoft.com/en-us/library/bb259689.aspx public void ProcessRequest(HttpContext context) { uint x, y, z; //Parse request parameters if (!uint.TryParse(context.Request.Params["x"], out x)) { throw (new ArgumentException("Invalid parameter")); } if (!uint.TryParse(context.Request.Params["y"], out y)) { throw (new ArgumentException("Invalid parameter")); } if (!uint.TryParse(context.Request.Params["z"], out z)) { throw (new ArgumentException("Invalid parameter")); } // Create a bitmap of size 256x256 using (var bmp = new Bitmap(256, 256)) // get graphics from bitmap using (var graphics = Graphics.FromImage(bmp)) { int symbolSize = 16; // the size of our symbol in pixel // calculate geo rect, taking the bleeding into account // = the maximum number of pixels a symbol can "bleed" into a neighbouring tile // see tile tile http://80.146.239.139/SpatialTutorial/04-TilesAndLabelsHandler.ashx?x=69&y=44&z=7 var rect = TransformTools.TileToWgs(x, y, z, symbolSize / 2); int left = (int)Math.Floor(rect.Left); int right = (int)Math.Floor(rect.Right); int top = (int)Math.Floor(rect.Top); int bottom = (int)Math.Floor(rect.Bottom); // draw text var font = new Font("Arial", symbolSize - 4); var format = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; for (double lon = left; lon <= right; lon++) { for (double lat = top; lat <= bottom; lat++) { var g1 = new System.Windows.Point(lon, lat); var g2 = new System.Windows.Point(lon + 1, lat + 1); var p1 = TransformTools.WgsToTile(x, y, z, g1); var p2 = TransformTools.WgsToTile(x, y, z, g2); graphics.DrawLine(Pens.Black, new System.Drawing.Point((int)p1.X, (int)p1.Y), new System.Drawing.Point((int)p2.X, (int)p1.Y)); graphics.DrawLine(Pens.Black, new System.Drawing.Point((int)p1.X, (int)p1.Y), new System.Drawing.Point((int)p1.X, (int)p2.Y)); if (z < 6) // no symbols for levels < 6 { continue; } // draw symbol for latitude graphics.FillEllipse(Brushes.LightGray, (int)(p1.X + p2.X) / 2 - symbolSize, (int)p1.Y - symbolSize, symbolSize * 2, symbolSize * 2); graphics.DrawEllipse(Pens.Black, (int)(p1.X + p2.X) / 2 - symbolSize, (int)p1.Y - symbolSize, symbolSize * 2, symbolSize * 2); graphics.DrawString(string.Format("{0}°", lat), font, Brushes.Black, (int)(p1.X + p2.X) / 2, (int)p1.Y, format); // draw symbol for longitude graphics.FillEllipse(Brushes.LightGray, (int)(p1.X) - symbolSize, (int)(p1.Y + p2.Y) / 2 - symbolSize, symbolSize * 2, symbolSize * 2); graphics.DrawEllipse(Pens.Black, (int)(p1.X) - symbolSize, (int)(p1.Y + p2.Y) / 2 - symbolSize, symbolSize * 2, symbolSize * 2); graphics.DrawString(string.Format("{0}°", lon), font, Brushes.Black, (int)(p1.X), (int)(p1.Y + p2.Y) / 2, format); } } font.Dispose(); //Stream the image to the client using (var memoryStream = new System.IO.MemoryStream()) { // Saving a PNG image requires a seekable stream, first save to memory stream // http://forums.asp.net/p/975883/3646110.aspx#1291641 bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png); var buffer = memoryStream.ToArray(); context.Response.ContentType = "image/png"; context.Response.OutputStream.Write(buffer, 0, buffer.Length); } } }
// http://msdn.microsoft.com/en-us/library/bb259689.aspx public void ProcessRequest(HttpContext context) { uint x, y, z; //Parse request parameters if (!uint.TryParse(context.Request.Params["x"], out x)) { throw (new ArgumentException("Invalid parameter")); } if (!uint.TryParse(context.Request.Params["y"], out y)) { throw (new ArgumentException("Invalid parameter")); } if (!uint.TryParse(context.Request.Params["z"], out z)) { throw (new ArgumentException("Invalid parameter")); } // Create a bitmap of size 256x256 using (var bmp = new Bitmap(256, 256)) // get graphics from bitmap using (var graphics = Graphics.FromImage(bmp)) { // widen stroke width based on zoom int strokeSize = (z > 15) ? 4 : (z > 10) ? 3 : (z > 5) ? 2 : 1; // calculate map scale var mapSize = 256 * Math.Pow(2, z); // size of the map in pixel double earthCircumfence = 2.0 * Math.PI * 6378137.0; // circumfence of earth var scale = mapSize / earthCircumfence; // pixel per mercator unit // Calculate the symbol sizes with 3 different scaling modes // 1 - constant scaling - radius is always 16 pixels int sz1 = (int)(16 * Math.Pow(scale, 0.0)); // 2 - linear scaling - the symbol has a size of 10000 merctor units (=meter at equator, equals sz = 10000 * scale) int sz2 = (int)(10000 * Math.Pow(scale, 1.0)); // 2 - logarithmic scaling - the size is adapted with a base size (64) and a scaling factor (0.25) int sz3 = (int)(64 * Math.Pow(scale, 0.25)); // the maximum number of pixels a symbol can "bleed" into a neighbouring tile var bleedingPixels = (Math.Max(Math.Max(sz1, sz2), sz3) + strokeSize) / 2; var rect = TransformTools.TileToWgs(x, y, z, bleedingPixels); int left = (int)Math.Floor(rect.Left); int right = (int)Math.Floor(rect.Right); int top = (int)Math.Floor(rect.Top); int bottom = (int)Math.Floor(rect.Bottom); var pen = new System.Drawing.Pen(System.Drawing.Color.Black, strokeSize); var format = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; for (int lon = left; lon <= right; lon++) { for (int lat = top; lat <= bottom; lat++) { var g1 = new System.Windows.Point(lon, lat); var g2 = new System.Windows.Point(lon + 1, lat + 1); var p1 = TransformTools.WgsToTile(x, y, z, g1); var p2 = TransformTools.WgsToTile(x, y, z, g2); graphics.DrawLine(pen, new System.Drawing.Point((int)p1.X, (int)p1.Y), new System.Drawing.Point((int)p2.X, (int)p1.Y)); graphics.DrawLine(pen, new System.Drawing.Point((int)p1.X, (int)p1.Y), new System.Drawing.Point((int)p1.X, (int)p2.Y)); if (z < 6) // no symbols for levels < 6 { continue; } int sz; Brush brush; switch ((lat + lon) % 3) // switch between the 3 size modes { case 0: sz = sz1; brush = Brushes.LightGreen; break; case 1: sz = sz2; brush = Brushes.LightYellow; break; default: sz = sz3; brush = Brushes.LightBlue; break; } graphics.FillEllipse(brush, (int)(p1.X + p2.X) / 2 - sz, (int)p1.Y - sz, sz * 2, sz * 2); graphics.FillEllipse(brush, (int)(p1.X) - sz, (int)(p1.Y + p2.Y) / 2 - sz, sz * 2, sz * 2); graphics.DrawEllipse(pen, (int)(p1.X + p2.X) / 2 - sz, (int)p1.Y - sz, sz * 2, sz * 2); graphics.DrawEllipse(pen, (int)(p1.X) - sz, (int)(p1.Y + p2.Y) / 2 - sz, sz * 2, sz * 2); if (sz > 4) { var font = new Font("Arial", sz - 4); graphics.DrawString(string.Format("{0}°", lat), font, Brushes.Black, (int)(p1.X + p2.X) / 2, (int)p1.Y, format); graphics.DrawString(string.Format("{0}°", lon), font, Brushes.Black, (int)(p1.X), (int)(p1.Y + p2.Y) / 2, format); font.Dispose(); } } } //Stream the image to the client using (var memoryStream = new System.IO.MemoryStream()) { // Saving a PNG image requires a seekable stream, first save to memory stream // http://forums.asp.net/p/975883/3646110.aspx#1291641 bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png); var buffer = memoryStream.ToArray(); context.Response.ContentType = "image/png"; context.Response.OutputStream.Write(buffer, 0, buffer.Length); } } }
// http://msdn.microsoft.com/en-us/library/bb259689.aspx public void ProcessRequest(HttpContext context) { uint x, y, z; //Parse request parameters if (!uint.TryParse(context.Request.Params["x"], out x)) { throw (new ArgumentException("Invalid parameter")); } if (!uint.TryParse(context.Request.Params["y"], out y)) { throw (new ArgumentException("Invalid parameter")); } if (!uint.TryParse(context.Request.Params["z"], out z)) { throw (new ArgumentException("Invalid parameter")); } // Create a bitmap of size 256x256 using (var bmp = new Bitmap(256, 256)) // get graphics from bitmap using (var graphics = Graphics.FromImage(bmp)) { // draw background //var brush = new LinearGradientBrush(new Point(0, 0), new Point(256, 256), // Color.LightBlue, Color.Transparent); //graphics.FillRectangle(brush, new Rectangle(0, 0, 256, 256)); //brush.Dispose(); var rect = TransformTools.TileToWgs(x, y, z); int left = (int)Math.Floor(rect.Left); int right = (int)Math.Floor(rect.Right); int top = (int)Math.Floor(rect.Top); int bottom = (int)Math.Floor(rect.Bottom); for (int lon = left; lon <= right; lon++) { for (int lat = top; lat <= bottom; lat++) { var g1 = new System.Windows.Point(lon, lat); var g2 = new System.Windows.Point(lon + 1, lat + 1); var p1 = TransformTools.WgsToTile(x, y, z, g1); var p2 = TransformTools.WgsToTile(x, y, z, g2); graphics.DrawLine(Pens.Black, new System.Drawing.Point((int)p1.X, (int)p1.Y), new System.Drawing.Point((int)p2.X, (int)p1.Y)); graphics.DrawLine(Pens.Black, new System.Drawing.Point((int)p1.X, (int)p1.Y), new System.Drawing.Point((int)p1.X, (int)p2.Y)); } } //Stream the image to the client using (var memoryStream = new System.IO.MemoryStream()) { // Saving a PNG image requires a seekable stream, first save to memory stream // http://forums.asp.net/p/975883/3646110.aspx#1291641 bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png); var buffer = memoryStream.ToArray(); context.Response.ContentType = "image/png"; context.Response.OutputStream.Write(buffer, 0, buffer.Length); } } }