• 用silverlight制作自己的GIS


    用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 = "";

    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

    我自己的网站下载可能比较慢.

    另 怎么才能在博客源上传附件?

  • 相关阅读:
    Vue脚手架runtime-only中render函数的参数为什么是h?
    Vue中的 key 属性
    TypeScript安装以及使用
    Vue浏览器调试工具VueTools安装以及使用
    VueRouter路由跳转报错:vue-router.esm.js?fe87:2100 Uncaught (in promise) NavigationDuplicated
    VSCode使用webpack指令,因为在此系统上禁止运行脚本。
    尤雨溪在 vue3.0 beta 上推荐的 no webpack 小工具 vite
    celery task异步任务
    Notepad++使用
    Django基础013--redis开发
  • 原文地址:https://www.cnblogs.com/gaibangdaxia/p/1779461.html
Copyright © 2020-2023  润新知