用silverlight制作自己的GIS
看了笨鸟的一篇文章:
基于DeepZoom技术的Bing Maps客户端实现研究
地址:http://www.cnblogs.com/beniao/archive/2010/05/21/1740480.html
感觉大家都可以实现自己的GIS
这一篇文章会基本的讲一下如何通过silverlight实现封装自己的GIS,原理就是笨鸟那一篇文章的介绍
主要是用了silverlight的MultiScaleImage组件
<Grid x:Name="LayoutRoot" Background="White"><MultiScaleImage x:Name="msi"/>
</Grid>
下一步就要给msi加载地图源
这就要实现自己的Tile,把我自己的Tile贴出来
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Text;
using System.Collections.Generic;
namespace MyMap
{
public abstract class MySelfTileSource : MultiScaleTileSource
{
/*
imageWidth
类型:System.Int32
Deep Zoom 图像的宽度。
imageHeight
类型:System.Int32
Deep Zoom 图像的高度。
tileWidth
类型:System.Int32
Deep Zoom 图像中图块的宽度。
tileHeight
类型:System.Int32
Deep Zoom 图像中图块的高度。
tileOverlap
类型:System.Int32
Deep Zoom 图像中图块的重叠程度。*/
protected MySelfTileSource()
: base(int.MaxValue, int.MaxValue, 256, 256, 0)
{ }
/// <summary>
/// 地图的Tile映射地址
/// </summary>
public abstract string UriFormat { get; }
/// <summary>
/// 转换X,Y坐标值为地图的QuadKey参数值
/// </summary>
/// <param name="tileX"></param>
/// <param name="tileY"></param>
/// <param name="levelOfDetail"></param>
/// <returns></returns>
private static string TileXYToQuadKey(int tileX, int tileY, int levelOfDetail)
{
var quadKey = new StringBuilder();
for (int i = levelOfDetail; i > 0; i--)
{
char digit = '0';
int mask = 1 << (i - 1);
if ((tileX & mask) != 0)
{
digit++;
}
if ((tileY & mask) != 0)
{
digit++;
digit++;
}
quadKey.Append(digit);
}
return quadKey.ToString();
}
/// <summary>
/// 图层Tile算法
/// </summary>
/// <param name="tileLevel">缩放级别</param>
/// <param name="tilePositionX">X坐标</param>
/// <param name="tilePositionY">Y坐标</param>
/// <param name="tileImageLayerSources">图层源集合</param>
protected override void GetTileLayers(int tileLevel, int tilePositionX, int tilePositionY, IList<object> tileImageLayerSources)
{
int zoom = tileLevel - 8;
if (zoom > 0)
{
string QuadKey = TileXYToQuadKey(tilePositionX, tilePositionY, zoom);
string veLink = string.Format(UriFormat, new object[] { QuadKey[QuadKey.Length - 1], QuadKey });
var veUri = new Uri(veLink);
tileImageLayerSources.Add(veUri);
}
}
}
}
图块默认大小是256*256,当然你也可以改变其大小,比如自己的切图是320*320,只需要把两个256改为320就可以
以下是自己的Tile
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
namespace MyMap
{
public class BingMapsRoadTileSource : MySelfTileSource
{
string url = "";
public BingMapsRoadTileSource(string str)
{
url = str;
}
public override string UriFormat
{
get { return "http://mt{0}.google.com/vt/lyrs=m@116&hl=zh-CN&x={1}&y={2}&z={3}&s="; }// "http://khm{0}.google.com/kh/v=47&x={1}&y={2}&z={3}"; } // "http://r{0}.ortho.tiles.virtualearth.net/tiles/r{1}.png?g=203"; }
}
/// <summary>
/// 图层Tile算法
/// </summary>
/// <param name="tileLevel">缩放级别</param>
/// <param name="tilePositionX">X坐标</param>
/// <param name="tilePositionY">Y坐标</param>
/// <param name="tileImageLayerSources">图层源集合</param>
/*google 地图
protected override void GetTileLayers(int tileLevel, int tilePositionX, int tilePositionY, IList<object> tileImageLayerSources)
{
int zoom = tileLevel - 8;
if (zoom > 0)
{
string veLink = string.Format(UriFormat, tilePositionX % 4, tilePositionX, tilePositionY, zoom);
var veUri = new Uri(veLink);
tileImageLayerSources.Add(veUri);
}
}*/
//本地地图
protected override void GetTileLayers(int tileLevel, int tilePositionX, int tilePositionY, IList<object> tileImageLayerSources)
{
string weburl = url;
int zoom = tileLevel -8;
weburl += "ClientBin/map/" + zoom + "/" + tilePositionX.ToString("D2") + tilePositionY.ToString("D2") + ".png";
var veUri = new Uri(weburl);
tileImageLayerSources.Add(veUri);
}
}
}
这个Tile包含了加载google地图,加载自己本地地图的方法
接下来要实现自己的GIS就很容易了.
只要3行代码:
var xapUri = Application.Current.Host.Source;var webUri = new Uri(xapUri, "../");
msi.Source = new BingMapsRoadTileSource(webUri.ToString());
这样就能加载自己的地图了.这需要把本地地图放在ClientBin/map/0,ClientBin/map/1.........之下.
为什么放在这个目录下 这与我自己的Tile有关.
以下加载上事件
this.MouseLeftButtonDown += new MouseButtonEventHandler(MainPage_MouseLeftButtonDown);
this.MouseLeftButtonUp += new MouseButtonEventHandler(MainPage_MouseLeftButtonUp);
this.MouseWheel += new MouseWheelEventHandler(MainPage_MouseWheel);
this.MouseEnter += new MouseEventHandler(MainPage_MouseEnter);
this.MouseMove += delegate(object sender, MouseEventArgs e)
{
this.tbcrood.Text = msi.ElementToLogicalPoint(e.GetPosition(msi)).X + " " +
msi.ElementToLogicalPoint(e.GetPosition(msi)).Y + " " + msi.ViewportWidth;
//按住左键拖动
if (mouseIsDragging)
{
if (mouseFlag == "")
{
mouseFlag = "fisrtdown";
currentPosition = msi.ViewportOrigin;
dragOffset = new Point(e.GetPosition(msi).X, e.GetPosition(msi).Y);
}
var newOrigin = new Point();
newOrigin.X = currentPosition.X -
(((e.GetPosition(msi).X - dragOffset.X) / msi.ActualWidth) * msi.ViewportWidth);
newOrigin.Y = currentPosition.Y -
(((e.GetPosition(msi).Y - dragOffset.Y) / msi.ActualHeight) * msi.ViewportWidth);
msi.ViewportOrigin = newOrigin;
}
};
需要几个全局变量:
private Point currentPosition; private Point dragOffset; private bool mouseIsDragging; private string mouseFlag = "";
void MainPage_MouseEnter(object sender, MouseEventArgs e)
{
mouseIsDragging = false;
}
void MainPage_MouseWheel(object sender, MouseWheelEventArgs e)
{
Point mouseP = msi.ElementToLogicalPoint(e.GetPosition(msi));
if (e.Delta > 0)
{
msi.ZoomAboutLogicalPoint(1.1, mouseP.X, mouseP.Y);
}
if (e.Delta < 0)
{
msi.ZoomAboutLogicalPoint(0.5, mouseP.X, mouseP.Y);
}
}
void MainPage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
mouseIsDragging = false;
mouseFlag = "";
}
void MainPage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
mouseIsDragging = true;
}
如果调用google地图,只需要把BingMapsRoadTileSource 类中的google加载方式打开即可.
上面就是如何搭建自己的GIS.
下一章会介绍如何实现添加层 点.线.面等.用坐标系的处理.
附上源码:http://www.louningbo.com/download/MyMap.rar
我自己的网站下载可能比较慢.
另 怎么才能在博客源上传附件?