给DotSpatial添加比例尺

开源的DotSpatial虽然十分强大,但是没有比例尺造成不方便。我把我实现的比例尺控件分享出来,给大家使用。记得要监听视野范围变化的事件。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DotSpatial.Data;
using System.Drawing.Drawing2D;
using DotSpatial.Topology;
using System.Drawing.Text;

namespace test
{
    public partial class MapScaleControllerView : UserControl
    {
        /// <summary>
        /// 对于当前显示设备每像素的厘米(物理长度)
        /// </summary>
        private readonly double millimeterPerPixel = 0.0;
        private readonly double pixelPerMillimeter = 0.0;
        private int iZoomLevel = 0;
        private int iScaleLineLength = 0;
        private string sDynamicScaleString;
        private List<DistancePixelModel> zoomLevels;
        private List<System.Drawing.Point> scaleLinePoints;

        public MapScaleControllerView()
        {
            InitializeComponent();
            var g = CreateGraphics();
            var millimeterLength = NativeAPI.GetDeviceCaps(g.GetHdc(), NativeAPI.HORZSIZE);
            var pixelLength = Screen.PrimaryScreen.Bounds.Width;
            g.Dispose();
            millimeterPerPixel = (double)millimeterLength / (double)pixelLength;
            pixelPerMillimeter = (double)pixelLength / (double)millimeterLength;
            Initialize();
        }

        private void Initialize()
        {
            var evtMgr = ModuleManager.GetInstance().GetEventManager();
            var distances = new List<long>() 
            {
                10,30,50,
                100,300,500,
                1000,3000,5000,
                10000,20000,30000,50000,
                100000,200000,300000,500000,
                1000000,2000000,3000000,5000000,
                10000000,30000000,50000000,
                100000000,300000000,500000000,
                1000000000,3000000000,5000000000,
            };
            var unites = new List<string>() 
            {
                "1厘米","3厘米","5厘米",
                "10厘米","30厘米","50厘米",
                "1米","3米","5米",
                "10米","20米","30米","50米",
                "100米","200米","300米","500米",
                "1公里","2公里","3公里","5公里",
                "10公里","20公里","50公里",
                "100公里","200公里","500公里",
                "1000公里","2000公里","5000公里"
            };
            evtMgr.Subscribe(EventNames.MAP_MAIN_MAP_EXTENT_CHANGED, ViewNames.MAP_MAP_SCALE_CONTROL_VIEW, OnMainMapExtentChanged);
            zoomLevels = new List<DistancePixelModel>();
            for (var i = 0; i < distances.Count; i++)
            {
                zoomLevels.Add(new DistancePixelModel()
                {
                    Distance = distances[i],
                    Level = distances.Count - i,
                    ScreenPixel = distances[i] * pixelPerMillimeter,
                    Unit = unites[i]
                });
            }
            scaleLinePoints = new List<System.Drawing.Point>();
            scaleLinePoints.Add(new System.Drawing.Point(10, 20));
            scaleLinePoints.Add(new System.Drawing.Point(10, 30));
            scaleLinePoints.Add(new System.Drawing.Point(190, 30));
            scaleLinePoints.Add(new System.Drawing.Point(190, 20));

        }

        private void SetZoomLevel(MainMapControlView mapCtrl)
        {
            var centmeterPixel = pixelPerMillimeter * 10;
            var c1 = mapCtrl.PixelToProj(new System.Drawing.Point(Convert.ToInt32(centmeterPixel), 0));
            var c2 = mapCtrl.PixelToProj(new System.Drawing.Point(Convert.ToInt32(centmeterPixel * 2), 0));
            var pc2 = new Coordinate(0, 0);
            var p1 = mapCtrl.ProjToPixel(pc2);
            var p2 = p1;
            var centmeterDistance = (c2.X - c1.X) * 1000;
            var scale = 1.0;
            foreach (var level in zoomLevels)
            {
                scale = centmeterDistance / level.Distance;
                if (scale < 1)
                {
                    iZoomLevel = level.Level;
                    sDynamicScaleString = level.Unit;
                    pc2 = new Coordinate(level.Distance / 1000, 0);
                    break;
                }
            }
            p2 = mapCtrl.ProjToPixel(pc2);
            iScaleLineLength = p2.X - p1.X + 10;
            scaleLinePoints[2] = new System.Drawing.Point(iScaleLineLength, 30);
            scaleLinePoints[3] = new System.Drawing.Point(iScaleLineLength, 20);

        }

        private void UpdateZoomLevels(MainMapControlView mapCtrl)
        {
            var zeroPixel = mapCtrl.ProjToPixel(new Coordinate(0, 0));
            var referenceCoordinate = new Coordinate(0, 0);
            var referencePixel = zeroPixel;
            foreach (var level in zoomLevels)
            {
                referenceCoordinate.X = level.Distance / 1000;
                referencePixel = mapCtrl.ProjToPixel(referenceCoordinate);
                level.MapPixel = referencePixel.X - zeroPixel.X;
            }
        }

        private void OnMainMapExtentChanged(object obj)
        {
            var mapCtrl = ModuleManager.GetInstance().GetViewManager().GetView<IMainMapControlView>() as MainMapControlView;
            var g = CreateGraphics();
            UpdateZoomLevels(mapCtrl);
            SetZoomLevel(mapCtrl);
            if (InvokeRequired)
                Invoke(new Action(() => DrawScale(g, mapCtrl)));
            else
                DrawScale(g, mapCtrl);
            g.Dispose();
        }

        private void DrawScale(Graphics g, MainMapControlView mapCtrl)
        {
            var parentRectangle = mapCtrl.RectangleToClient(RectangleToScreen(ClientRectangle));
            var path = new GraphicsPath();
            var sf = new StringFormat(StringFormatFlags.NoWrap);
            var ff = new FontFamily(GenericFontFamilies.SansSerif);

            g.Clip = new Region(ClientRectangle);
            g.DrawImage(mapCtrl.BufferedImage, -parentRectangle.Left, -parentRectangle.Top);
            g.DrawLines(new Pen(Color.Black, 2), scaleLinePoints.ToArray());
            g.DrawString(sDynamicScaleString, new Font("微软雅黑", 10), Brushes.Black, new PointF(12, 10));
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            var mapCtrl = ModuleManager.GetInstance().GetViewManager().GetView<IMainMapControlView>() as MainMapControlView;
            base.OnPaint(e);
            UpdateZoomLevels(mapCtrl);
            SetZoomLevel(mapCtrl);
            DrawScale(e.Graphics, mapCtrl);
        }

        public int CurrentZoomLevel
        {
            get { return iZoomLevel; }
        }
    }
}


转载于:https://my.oschina.net/zhtqs/blog/1509835

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值