用silverlight制作自己的GIS
看了笨鸟的一篇文章:
基于DeepZoom技术的Bing Maps客户端实现研究
地址:http://www.cnblogs.com/beniao/archive/2010/05/21/1740480.html
感觉大家都可以实现自己的GIS
这一篇文章会基本的讲一下如何通过silverlight实现封装自己的GIS,原理就是笨鸟那一篇文章的介绍
主要是用了silverlight的MultiScaleImage组件
</ Grid >
下一步就要给msi加载地图源
这就要实现自己的Tile,把我自己的Tile贴出来
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.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行代码:
msi.Source = new BingMapsRoadTileSource(webUri.ToString());
这样就能加载自己的地图了.这需要把本地地图放在ClientBin/map/0,ClientBin/map/1.........之下.
为什么放在这个目录下 这与我自己的Tile有关.
以下加载上事件
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 = "";
{
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
我自己的网站下载可能比较慢.
另 怎么才能在博客源上传附件?