GMap.NET开发技巧- 开发可以根据地图放大缩小而缩放的图元
2013-06-03 17:31 GPS视频平台产品经理 阅读(4166) 评论(2) 编辑 收藏 举报在GMap.NET 当中,我们可以自定义Marker,进行画圆形、矩形和多边形等操作,这个功能在GPS软件中很重要,需要基于此功能设置区域,就是我们常说的电子围栏。但是很多人做的时候,是基于窗口像素来进行画图操作,这样会造成画图的时候,严重失真,因为同一个像素长度,在不同的Zoom比例尺下,换算成地图距离是不一样的。这样会造成画出来的电子围栏非常不准确,再次打开地图重新加载的时候,围栏可能变大或者变小。
所以我们在保存图元的时候,例如保存一个圆,需要一个圆心和半径,半径需要保存的不是像素长度,而是地图距离,然后再加载图元的时候,在图元渲染函数里,将距离根据当前地图的Zoom值换算成像素长度,这样图元就可以根据不同的Zoom而缩放了。
如下是圆形Marker的源码:
namespace GpsNET.Marker { [Serializable] public class GMapMarkerCircle : GMapMarker, ISerializable { /// <summary> /// 距离,单位为米 /// </summary> public int Radius; /// <summary> /// specifies how the outline is painted /// </summary> [NonSerialized] public Pen Stroke = new Pen(Color.FromArgb(155, Color.MidnightBlue)); /// <summary> /// background color /// </summary> [NonSerialized] public Brush Fill = new SolidBrush(Color.FromArgb(155, Color.AliceBlue)); /// <summary> /// is filled /// </summary> public bool IsFilled = true ; public GMapMarkerCircle(PointLatLng p, int _raidus) : base (p) { Radius = _raidus; // 100m IsHitTestVisible = false ; } public override void OnRender(Graphics g) { //将距离转换成像素长度 int R = ( int )((Radius) / Overlay.Control.MapProvider.Projection.GetGroundResolution(( int )Overlay.Control.Zoom, Position.Lat)) * 2; if (IsFilled) { g.FillEllipse(Fill, new System.Drawing.Rectangle(LocalPosition.X - R / 2, LocalPosition.Y - R / 2, R, R)); } g.DrawEllipse(Stroke, new System.Drawing.Rectangle(LocalPosition.X - R / 2, LocalPosition.Y - R / 2, R, R)); } public override void Dispose() { if (Stroke != null ) { Stroke.Dispose(); Stroke = null ; } if (Fill != null ) { Fill.Dispose(); Fill = null ; } base .Dispose(); } #region ISerializable Members void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { base .GetObjectData(info, context); // TODO: Radius, IsFilled } protected GMapMarkerCircle(SerializationInfo info, StreamingContext context) : base (info, context) { // TODO: Radius, IsFilled } #endregion } } |
这样我们在MouseMove事件中,需要不断的换算出当前点和初始点之间的地图距离,然后生成图元,就随着鼠标移动,而画出不同大小的圆了。
if (MapClickAction == MAP_ACTION_ENCLOSURE_CIRCLE && e.Button == MouseButtons.Left) { //在鼠标移动的时候,画矩形选择框 int w = e.X - originX; int h = e.Y - originY; tempOverlay.Markers.Clear(); //擦出掉以前的marker //换算成以米为单位的距离 int radius = ( int )distanceByMeter(lastPosition, latLng); lastCircleMarker = new GMapMarkerCircle(lastPosition, radius); tempOverlay.Markers.Add(lastCircleMarker); } |
我的微信号: jt808_com 添加微信
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
· 全程使用 AI 从 0 到 1 写了个小工具