using DevExpress.Export.Xl;
using DevExpress.Map;
using DevExpress.Map.Native;
using DevExpress.Utils;
using DevExpress.Utils.Helpers;
using DevExpress.Utils.Svg;
using DevExpress.XtraBars;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraMap;
using DevExpress.XtraMap.ItemEditor;
using DevExpress.XtraPrinting;
using DxHelper;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Common;
using System.Data.SQLite;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using XdCxRhDW.Entity;
public enum GoogleMapType
{
///
/// 卫星地图
///
Sat = 47626774,
///
/// 地形图
///
Landform = 370833361,
///
/// 混合地图
///
Mix = 1024577166,
///
/// 普通地图
///
Normal = 1818940751
}
///
/// MapControl扩展类,封装了常用的非业务基础功能.
/// 内置了3个图层DrawLayer、FixedDrawLayer、PosLayer.
/// 必须首先调用UseDefalutOptions函数
///
public static class MapControlEx
{
class InnerData
{
internal GeoPoint _mapMenuGeoPoint;
internal Dictionary _clusterCache = new Dictionary();
internal Dictionary _dataCache = new Dictionary();
internal BarManager barM;
internal PopupMenu mapMenu;
internal PopupMenu posMenu;
internal PopupMenu rectMenu;
internal Action<(double starLon, double startLat, double centerLon, double centerLat,
double endLon, double endLat, double lonRange, double latRange)> mOnRectChanged;
internal Action<(double Lon, double Lat)> onClickChanged;
internal MapItemStorage mMapStorage;
internal MapItemStorage mMapStorageFixed;
internal MapPolyline distinctPath;
internal MapDot hoverPoint;
internal ToolTipControllerShowEventArgs hoverTip;
internal ToolTipController mapToolTip;
internal MapItemStorage posStorge;
internal MapItemStorage trackStorge;//航迹专用
internal MapRectangle rangeItem;
internal MapDot dotItem = new MapDot() { Tag = "DrawRect" };
internal bool drawingRect = false;
internal bool mouseLeftDown = false;
internal (double starLon, double startLat, double centerLon, double centerLat,
double endLon, double endLat, double lonRange, double latRange)
CurrentRect;
internal MapDot preSelectedItem;
}
private static GoogleMapType mMapType = GoogleMapType.Normal;
private static List listMapCtrl = new List();
private const int _dotSize = 8;
private const int _selectedDotSize = 18;
///
/// 设置地图通用属性并创建4个Layer.
/// ImageLayer:绘制地图瓦片
/// DrawLayer:地图绘制图层,右键可以擦除
/// FixedDrawLayer:地图绘制层,右键无法擦除
/// PosLayer:定位点绘制专用图层
///
///
///
public static MapControl UseDefalutOptions(this MapControl ctrl)
{
if (ctrl.Tag != null) return ctrl;
var barM = new BarManager();
barM.BeginInit();
barM.Form = ctrl;
var mapMeun = new PopupMenu() { Manager = barM };
var posMenu = new PopupMenu() { Manager = barM };
var rectMenu = new PopupMenu() { Manager = barM };
barM.EndInit();
listMapCtrl.Add(ctrl);
var innerData = new InnerData();
innerData.barM = barM;
innerData.mapMenu = mapMeun;
innerData.posMenu = posMenu;
innerData.rectMenu = rectMenu;
innerData.mapToolTip = new ToolTipController();
innerData.mapToolTip.InitialDelay = 10;
innerData.mapToolTip.KeepWhileHovered = true;
innerData.mapToolTip.ReshowDelay = 10;
innerData.mapToolTip.ShowBeak = true;
innerData.mapToolTip.ToolTipAnchor = DevExpress.Utils.ToolTipAnchor.Cursor;
innerData.mapToolTip.ToolTipType = ToolTipType.SuperTip;
ctrl.Tag = innerData;
MapOverlay overlay = new MapOverlay()
{
Alignment = ContentAlignment.BottomLeft,
JoiningOrientation = Orientation.Horizontal,
Margin = new Padding(5, 0, 0, 5),
Padding = new Padding(0),
};
//overlay.BackgroundStyle.Fill = Color.Transparent;
ctrl.Overlays.Add(overlay);
ctrl.ToolTipController = innerData.mapToolTip;
ctrl.ToolTipController.BeforeShow += (sender, e) =>
{
if (e.SelectedObject == null) return;
if (e.SelectedObject is MapPolyline line)
{
if (line.Layer != ctrl.GetDrawLayer())
{
e.SuperTip = null;
e.ToolTip = null;
return;
}
}
SuperToolTip superToolTip = new SuperToolTip();
if (innerData.posMenu.Visible || innerData.mapMenu.Visible || innerData.rectMenu.Visible)
{
e.SuperTip = null;
e.ToolTip = null;
return;
}
if (e.SelectedObject.ToString() == ItemsEditorPanelAction.AddRectangle.ToString())
{
e.ToolTip = "绘制矩形";
return;
}
else if (e.SelectedObject is MapDot mapDot)
{
if (mapDot == null) return;
var posItem = mapDot.Tag as PosData;
if (mapDot == null || posItem == null) return;
if (posItem.ClusterCount == 1)
{
var props = posItem.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
var list = new List<(int Index, string Name, string Format, object Value)>();
foreach (var prop in props)
{
var attrToolTip = prop.GetCustomAttribute();
if (attrToolTip == null) continue;
string toolTipFormat = attrToolTip.Format;
var val = prop.GetValue(posItem);
string displayName = prop.Name;
var attrDisplay = prop.GetCustomAttribute();
if (attrDisplay != null && !string.IsNullOrWhiteSpace(attrDisplay.Name))
displayName = attrDisplay.Name;
int index = attrToolTip.Index;
list.Add((index, displayName, toolTipFormat, val));
}
list = list.OrderBy(p => p.Index).ToList();
foreach ((int Index, string Name, string Format, object val) in list)
{
string f = null;
if (val is DateTime)
{
f = "yyyy-MM-dd HH:mm:ss";
}
else if (val is float || val is double || val is decimal)
{
f = "f4";
}
if (!string.IsNullOrWhiteSpace(Format))
f = Format;
string valStr = "";
if (val is null)
valStr = "--";
else if (!string.IsNullOrWhiteSpace(f))
valStr = ((dynamic)val).ToString(f);
else if (val.GetType().IsEnum)
{
var field = val.GetType().GetField(Enum.GetName(val.GetType(), val));
var attr = field.GetCustomAttribute();
if (attr != null && !string.IsNullOrWhiteSpace(attr.Name))
{
valStr = attr.Name;
}
else
{
valStr = val.ToString();
}
}
else
valStr = val.ToString();
ToolTipItem tipItem = new ToolTipItem();
tipItem.Text = $"{Name}:{valStr}";
superToolTip.Items.Add(tipItem);
}
}
else
{
ToolTipItem tipItem = new ToolTipItem();
tipItem.Text = $"当前位置附近有{posItem.ClusterCount}个定位点,放大可查看";
superToolTip.Items.Add(tipItem);
}
e.SuperTip = superToolTip;
}
else if (e.SelectedObject is MapCustomElement ele)
{
if (ele.Tag.GetType() == typeof(string)) return;
var find = innerData.mMapStorageFixed.Items.Where(p => (p is MapCustomElement pp) && p != ele && pp.Location.Equals(ele.Location));
StringBuilder sb = new StringBuilder();
sb.Append(((object[])ele.Tag)[1]);
foreach (var item in find)
{
sb.Append("\r\n");
sb.Append("-------------------");
sb.Append("\r\n");
sb.Append(((object[])item.Tag).Last());
}
ele.ToolTipPattern = sb.ToString();
}
};
ctrl.MouseMove += (sender, e) =>
{
overlay.Items.Clear();
var geo = (GeoPoint)ctrl.ScreenPointToCoordPoint(e.Location);
string ee = "E";
string nn = "N";
if (geo.Longitude < 0)
{
geo.Longitude *= -1;
ee = "W";
}
if (geo.Latitude < 0)
{
geo.Latitude *= -1;
nn = "S";
}
MapOverlayTextItem item = new MapOverlayTextItem()
{
Alignment = ContentAlignment.BottomLeft,
Text = $"{geo.Longitude:f2}°{ee} {geo.Latitude:f2}°{nn}"
};
//item.TextStyle.TextColor = Color.FromArgb(128, 128, 128);
item.TextStyle.Font = new Font("微软雅黑", 11F);
overlay.Items.Add(item);
};
ctrl.MouseDown += (sender, e) =>
{
if (e.Button == MouseButtons.Right)
{
var hitInfo = ctrl.CalcHitInfo(e.Location);
if (hitInfo.InMapRectangle && innerData.rangeItem != null)
{
rectMenu?.ShowPopup(Cursor.Position);
}
else if (hitInfo.InMapDot && hitInfo.MapDot.Tag is PosData)
{
var selectPos = (PosData)hitInfo.MapDot.Tag;
if (!selectPos.Selected)
{
selectPos.Selected = true;
ctrl.UpdatePosItem(selectPos);
}
if (selectPos.ClusterCount == 1)
{
posMenu?.ShowPopup(Cursor.Position);//选中了原始MapItem
}
else
{
//选中了聚合后的MapItem
}
}
else
{
var geoPoint = ctrl.ScreenPointToCoordPoint(e.Location) as GeoPoint;
innerData._mapMenuGeoPoint = geoPoint;
innerData.mapMenu?.ShowPopup(Cursor.Position);
}
}
else
{
innerData.mouseLeftDown = true;
innerData.barM.CloseMenus();
var hitInfo = ctrl.CalcHitInfo(e.Location);
if (hitInfo.InMapDot && hitInfo.MapDot.Tag is PosData)
{
var selectPos = hitInfo.MapDot.Tag as PosData;
if (!selectPos.Selected)
{
selectPos.Selected = true;
ctrl.UpdatePosItem(selectPos);
}
}
}
};
ctrl.MouseUp += (sender, e) =>
{
innerData.mouseLeftDown = false;
};
//中心点、缩放级别
ctrl.MinZoomLevel = 2;
ctrl.ZoomLevel = 5;
ctrl.MaxZoomLevel = 14;
ctrl.CenterPoint = new GeoPoint(18, 110);
//禁用多余特效
ctrl.EnableDelayedScrolling = true;
ctrl.RenderMode = RenderMode.DirectX;
ctrl.EnableAnimation = false;
ctrl.EnableRotation = false;
//ctrl.ShowSearchPanel = false;
ctrl.SearchPanelOptions.Visible = false;
ctrl.SelectionMode = ElementSelectionMode.Single;//只能单选图层上的元素
((GeoMapCoordinateSystem)ctrl.CoordinateSystem).CircularScrollingMode = CircularScrollingMode.TilesAndVectorItems;
//地图下方导航栏
ctrl.NavigationPanelOptions.Visible = false;
//ctrl.NavigationPanelOptions.Height = 35;
//ctrl.NavigationPanelOptions.BackgroundStyle.Fill = Color.Transparent;
//ctrl.NavigationPanelOptions.ShowScrollButtons = false;
//ctrl.NavigationPanelOptions.ShowZoomTrackbar = false;
//ctrl.NavigationPanelOptions.ShowCoordinates = true;
//ctrl.NavigationPanelOptions.ShowKilometersScale = false;
//ctrl.NavigationPanelOptions.ShowMilesScale = false;
//ctrl.NavigationPanelOptions.CoordinatesStyle.Font = new Font("微软雅黑", 12F);
//ctrl.NavigationPanelOptions.CoordinatesStyle.TextColor = Color.FromArgb(80, 80, 80);
//ctrl.NavigationPanelOptions.ScaleStyle.Font = new Font("微软雅黑", 10F);
//地图绘制加载(标点、测距、框选等元素载体图层).用来绘制可擦除的元素
var layerDraw = new VectorItemsLayer() { Name = "DrawLayer" };
var drawDataStorage = new MapItemStorage();
layerDraw.Data = drawDataStorage;
ctrl.Layers.Add(layerDraw);
innerData.mMapStorage = drawDataStorage;
//绘制图层,不可手动擦除,一般用来绘制卫星、参考站等固定元素
var layerDrawFixed = new VectorItemsLayer() { Name = "FixedDrawLayer" };
var drawDataStorageFixed = new MapItemStorage();
layerDrawFixed.Data = drawDataStorageFixed;
ctrl.Layers.Add(layerDrawFixed);
innerData.mMapStorageFixed = drawDataStorageFixed;
//定位点专用PosLayer
var layerPos = new VectorItemsLayer() { Name = "PosLayer" };
layerPos.ToolTipPattern = " ";//随便给一个,不然不会显示定位点的tooltip
layerPos.AllowEditItems = true;
layerPos.EnableHighlighting = false;
layerPos.EnableSelection = false;
ctrl.Layers.Add(layerPos);
var posStorge = new MapItemStorage();
layerPos.Data = posStorge;
innerData.posStorge = posStorge;
return ctrl;
}
///
/// 在定位点上增加右键菜单
///
///
///
///
/// 一个回调,参数为选中的定位点
///
///
public static MapControl AddPosMenu(this MapControl ctrl, string caption, SvgImage img, Action action, Func showCondition = null)
{
var btnCustom = new BarButtonItem() { Caption = caption };
btnCustom.ImageOptions.SvgImage = img;
btnCustom.Tag = ctrl;
var innerData = ctrl.Tag as InnerData;
btnCustom.ItemClick += (sender, e) =>
{
action((T)innerData.preSelectedItem.Tag);
};
innerData.barM.BeginInit();
innerData.barM.Items.Add(btnCustom);
innerData.posMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnCustom));
innerData.barM.EndInit();
innerData.posMenu.BeforePopup += (sender, e) =>
{
if (showCondition == null)
btnCustom.Visibility = BarItemVisibility.Always;
else
{
bool showBtn = showCondition((T)innerData.preSelectedItem.Tag);
if (showBtn)
btnCustom.Visibility = BarItemVisibility.Always;
else
btnCustom.Visibility = BarItemVisibility.Never;
}
};
return ctrl;
}
///
/// 将GridControl单行元素右键菜单挂载到地图定位点右键菜单上(实验)
///
///
///
///
///
public static GridControl MountRowMenuToMapPos(this GridControl grid, MapControl mapCtrl)
where T : PosData
{
mapCtrl.PosSelectedChanged(t =>
{
var view = grid.MainView as GridView;
view.ClearSelection();
for (int i = 0; i < view.RowCount; i++)
{
if ((view.GetRow(i) as T).ID == t.ID)
{
view.FocusedRowHandle = i;
view.SelectRow(i);
break;
}
}
});
var data = grid.Tag as GridControlEx.GridTag;
data.RowButtonsItems.ForEach(t => mapCtrl.AddPosMenu(t));
return grid;
}
///
/// 将GridControl多行选择菜单挂载到地图框选区域右键菜单上(实验)
///
///
///
///
public static GridControl MountMultRowMenuToMapRegion(this GridControl grid, MapControl mapCtrl)
{
return grid;
}
///
/// 在定位点上增加右键菜单
///
///
/// 右键菜单
///
public static MapControl AddPosMenu(this MapControl ctrl, BarButtonItem btn)
{
if (ctrl.Tag == null)
ctrl.UseDefalutOptions();
var innerData = ctrl.Tag as InnerData;
innerData.barM.BeginInit();
var btnNew = new BarButtonItem()
{
Tag = btn.Tag,
Caption = btn.Caption,
};
btnNew.ItemClick += (ItemClickEventHandler)btn.Events()[btn.Caption];
btnNew.ImageOptions.SvgImage = btn.ImageOptions.SvgImage;
innerData.barM.Items.Add(btnNew);
innerData.posMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnNew));
innerData.barM.EndInit();
innerData.posMenu.BeforePopup += (sender, e) =>
{
if (btnNew.Tag != null && btnNew.Tag is Func showCondition)
{
if (showCondition())
btnNew.Visibility = BarItemVisibility.Always;
else
btnNew.Visibility = BarItemVisibility.Never;
}
};
return ctrl;
}
///
/// 在地图上增加右键菜单
///
///
///
///
/// 一个回调,参数为点击位置的经纬度
///
public static MapControl AddMapMenu(this MapControl ctrl, string caption, SvgImage img, Action action)
{
var btnCustom = new BarButtonItem() { Caption = caption, Name = caption };
btnCustom.ImageOptions.SvgImage = img;
btnCustom.Tag = ctrl;
var innerData = ctrl.Tag as InnerData;
btnCustom.ItemClick += (sender, e) =>
{
action(innerData._mapMenuGeoPoint.Longitude, innerData._mapMenuGeoPoint.Latitude);
};
innerData.barM.BeginInit();
innerData.barM.Items.Add(btnCustom);
innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnCustom));
innerData.barM.EndInit();
return ctrl;
}
///
/// 在框选矩形上增加右键菜单
///
///
///
///
/// 一个回调,参数为框选的定位点
///
///
public static MapControl AddRectMenu(this MapControl ctrl, string caption, SvgImage img, Action> action, bool resetMapEdior = true) where T : PosData, new()
{
var btnCustom = new BarButtonItem() { Caption = caption };
btnCustom.ImageOptions.SvgImage = img;
btnCustom.Tag = ctrl;
btnCustom.ItemClick += (sender, e) =>
{
var data = ctrl.GetRectPosItem();
ctrl.ClearRect();
action(data);
if (resetMapEdior)
{
ctrl.MapEditor.SetTransformMode(MapItemTransform.None);
}
};
var innerData = ctrl.Tag as InnerData;
innerData.barM.BeginInit();
innerData.barM.Items.Add(btnCustom);
innerData.rectMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnCustom));
innerData.barM.EndInit();
return ctrl;
}
public static MapControl PosSelectedChanged(this MapControl ctrl, Action action)
{
ctrl.MapItemClick += (sender, e) =>
{
if (e.Item.Tag is T val)
{
action(val);
}
};
return ctrl;
}
///
/// 重新设置定位数据
///
///
///
/// 数据源(指定null或空集合可以清空已有数据)
/// 是否清除DrawLayer上临时绘制的内容
public static void SetPosDataSource(this MapControl ctrl, IEnumerable items, bool clearDrawLayer = true) where T : PosData, new()
{
var innerData = ctrl.Tag as InnerData;
innerData._dataCache.Clear();
if (clearDrawLayer)
ctrl.ClearDrawObj();
innerData.posStorge.Items.Clear();
if (items == null || !items.Any())
{
ctrl.Refresh();
return;
}
List list = new List();
for (int i = 0; i < items.Count(); i++)
{
var p = items.ElementAt(i);
if (p.PosLon > 180) continue;
var mapItem = new MapDot()
{
EnableHighlighting = DefaultBoolean.False,
EnableSelection = DefaultBoolean.False,
CanMove = false,
Visible = p.Visible,
IsHitTestVisible = true,
StrokeWidth = 2,
Fill = ColorHelper.IsHtmlColor(p.ColorKey) ? ColorTranslator.FromHtml(p.ColorKey) : ColorHelper.GetColor(p.ColorKey),
Size = _dotSize,
Tag = items.ElementAt(i),
Location = new GeoPoint(p.PosLat, p.PosLon)
};
list.Add(mapItem);
innerData._dataCache.Add(p, mapItem);
}
innerData.posStorge.Items.AddRange(list);
}
///
/// 定位图层数据源添加一个定位点(如果需要一次性添加很多个点,请使用AddPosItems)
///
///
///
///
public static void AddPosItem(this MapControl ctrl, T item) where T : PosData, new()
{
if (item.PosLon > 180) return;
var innerData = ctrl.Tag as InnerData;
var mapItem = new MapDot()
{
EnableHighlighting = DefaultBoolean.True,
EnableSelection = DefaultBoolean.False,
CanMove = false,
Visible = item.Visible,
IsHitTestVisible = true,
Fill = ColorHelper.IsHtmlColor(item.ColorKey) ? ColorTranslator.FromHtml(item.ColorKey) : ColorHelper.GetColor(item.ColorKey),
Size = _dotSize,
Tag = item,
Location = new GeoPoint(item.PosLat, item.PosLon)
};
if (!innerData._dataCache.ContainsKey(item))
{
innerData._dataCache.Add(item, mapItem);
innerData.posStorge.Items.Add(mapItem);
}
}
///
/// 定位图层数据源添加多个定位点
///
///
///
///
public static void AddPosItems(this MapControl ctrl, IEnumerable items) where T : PosData, new()
{
var innerData = ctrl.Tag as InnerData;
List list = new List();
foreach (var item in items)
{
if (item.PosLon > 180) return;
var mapItem = new MapDot()
{
EnableHighlighting = DefaultBoolean.True,
EnableSelection = DefaultBoolean.False,
CanMove = false,
Visible = item.Visible,
IsHitTestVisible = true,
Fill = ColorHelper.IsHtmlColor(item.ColorKey) ? ColorTranslator.FromHtml(item.ColorKey) : ColorHelper.GetColor(item.ColorKey),
Size = _dotSize,
Tag = item,
Location = new GeoPoint(item.PosLat, item.PosLon)
};
list.Add(mapItem);
innerData._dataCache.Add(item, mapItem);
}
innerData.posStorge.Items.AddRange(list);
}
///
/// 定位图层数据源删除定位点
///
///
///
///
public static void DelPosItem(this MapControl ctrl, IEnumerable data) where T : PosData, new()
{
if (data == null || !data.Any()) return;
foreach (var item in data)
{
ctrl.DelPosItem(item, false);
}
ctrl.Refresh();
}
///
/// 定位图层数据源删除定位点
///
///
///
///
///
public static void DelPosItem(this MapControl ctrl, T item, bool refreshCtrl = true) where T : PosData, new()
{
if (item == null) return;
var innerData = ctrl.Tag as InnerData;
var key = innerData._dataCache.Keys.Where(p => p.ID == item.ID).FirstOrDefault();
if (key != null)
{
innerData.posStorge.Items.Remove(innerData._dataCache[key]);
innerData._dataCache.Remove(key);
}
if (refreshCtrl)
ctrl.Refresh();
}
///
/// 定位图层数据源删除定位点
///
///
///
///
public static void DelPosItem(this MapControl ctrl, Func predicate) where T : PosData, new()
{
var innerData = ctrl.Tag as InnerData;
List keys = new List();
foreach (var item in innerData._dataCache.Keys)
{
if (predicate((T)item))
keys.Add(item);
}
foreach (var item in keys)
{
ctrl.DelPosItem(item, false);
}
ctrl.Refresh();
}
///
/// 更新定位数据(可以更新可见性、颜色、经纬度、选中状态)
///
///
///
///
/// 是否将这个点设置到地图中心显示
public static void UpdatePosItem(this MapControl ctrl, T item, bool setCenter = false) where T : PosData, new()
{
if (item == null || item.PosLon == 999 || item.PosLat == 999) return;
var innerData = ctrl.Tag as InnerData;
var key = innerData._dataCache.Keys.Where(p => p.ID == item.ID).FirstOrDefault();
if (key != null)
{
var mapDot = innerData._dataCache[key] as MapDot;
mapDot.Visible = item.Visible;//外部修改了可见性
mapDot.Fill = ColorHelper.IsHtmlColor(item.ColorKey) ? ColorTranslator.FromHtml(item.ColorKey) : ColorHelper.GetColor(item.ColorKey);//外部修改了颜色
mapDot.Location = new GeoPoint(item.PosLat, item.PosLon);//外部修改了位置
if (mapDot.Size != (item.Selected ? _selectedDotSize : _dotSize))//外部修改了选中状态
{
mapDot.Size = item.Selected ? _selectedDotSize : _dotSize;
mapDot.StrokeWidth = item.Selected ? 0 : 2;
if (item.ClusterCount > 1)
{
if (innerData._clusterCache.TryGetValue(item.ClusterKey, out MapItem clusterItem))
{
(clusterItem as MapDot).Size = item.Selected ? _selectedDotSize : _dotSize;
}
}
if (mapDot.ClusteredItems.Any())
(mapDot.ClusteredItems[0] as MapDot).Size = _selectedDotSize;
if (item.Selected)
{
//让选中的Item在上层
var idx = innerData.posStorge.Items.IndexOf(mapDot);
innerData.posStorge.Items.Swap(idx, innerData.posStorge.Items.Count - 1);
//需要将上次选中的点设置为未选中
if (innerData.preSelectedItem != null)
{
innerData.preSelectedItem.Size = _dotSize;
(innerData.preSelectedItem.Tag as PosData).Selected = false;
innerData.preSelectedItem.StrokeWidth = 2;
if ((innerData.preSelectedItem.Tag as PosData).ClusterCount > 1)
{
if (innerData._clusterCache.TryGetValue((innerData.preSelectedItem.Tag as PosData).ClusterKey, out MapItem clusterItem))
{
(clusterItem as MapDot).Size = _dotSize + 2;
}
}
}
innerData.preSelectedItem = mapDot;
}
}
if (setCenter && item.Visible)
ctrl.SetCenterPoint(item.PosLon, item.PosLat, false);
}
}
///
/// 更新定位数据(可以更新可见性、颜色、经纬度)
///
///
///
///
public static void UpdatePosItem(this MapControl ctrl, IEnumerable items) where T : PosData, new()
{
if (items == null || !items.Any()) return;
var innerData = ctrl.Tag as InnerData;
foreach (var item in items)
{
var key = innerData._dataCache.Keys.Where(p => p.ID == item.ID).FirstOrDefault();
if (key != null)
{
var mapDot = innerData._dataCache[key] as MapDot;
mapDot.Visible = item.Visible;//外部修改了可见性
mapDot.Fill = ColorHelper.IsHtmlColor(item.ColorKey) ? ColorTranslator.FromHtml(item.ColorKey) : ColorHelper.GetColor(item.ColorKey);//外部修改了颜色
mapDot.Location = new GeoPoint(item.PosLat, item.PosLon);//外部修改了位置
}
}
}
///
/// 设置地图中心点
///
///
///
///
/// 是否显示动画
///
public static MapControl SetCenterPoint(this MapControl ctrl, double lon, double lat, bool animated = false)
{
ctrl.SetCenterPoint(new GeoPoint(lat, lon), animated);
return ctrl;
}
///
/// 地图上添加图片
///
///
///
///
///
///
///
///
public static void DrawFixedImg(this MapControl ctrl, string tag, string id, double imgLat, double imgLon, Image img, string toolTip = "")
{
var innerData = ctrl.Tag as InnerData;
var item = new MapCustomElement() { Tag = new object[] { tag, id, toolTip } };
item.UseAnimation = false;
item.BackgroundDrawingMode = ElementState.None;
item.Location = new GeoPoint(imgLat, imgLon);
item.Image = img;
item.ToolTipPattern = toolTip;
innerData.mMapStorageFixed.Items.Add(item);
}
///
/// 地图上添加指定大小图片
///
///
///
///
///
///
///
///
public static void DrawFixedImg(this MapControl ctrl, string tag, string id, double imgLat, double imgLon, SvgImage img, string toolTip = "")
{
var innerData = ctrl.Tag as InnerData;
var item = new MapCustomElement() { Tag = new object[] { tag, id, toolTip } };
item.UseAnimation = false;
item.BackgroundDrawingMode = ElementState.None;
item.Location = new GeoPoint(imgLat, imgLon);
item.SvgImage = img;
item.CanMove = false;
item.EnableHighlighting = DefaultBoolean.False;
item.EnableSelection = DefaultBoolean.False;
item.ToolTipPattern = toolTip;
innerData.mMapStorageFixed.Items.Add(item);
}
///
///
///
///
///
///
///
///
public static bool ExistFixedImg(this MapControl ctrl, string id, double imgLat, double imgLon)
{
var innerData = ctrl.Tag as InnerData;
return innerData.mMapStorageFixed.Items.Any(p => (p is MapCustomElement ele)
&& (ele.Tag as object[])[1].ToString() == id
&& (ele.Location as GeoPoint).Longitude == imgLon
&& (ele.Location as GeoPoint).Latitude == imgLat);
}
public static void DelFixedImg(this MapControl ctrl, string tag)
{
var innerData = ctrl.Tag as InnerData;
var delItems = innerData.mMapStorageFixed.Items.ToList().FindAll(p => ((object[])p.Tag)[0].ToString() == tag);
foreach (var item in delItems)
{
innerData.mMapStorageFixed.Items.Remove(item);
}
}
///
/// 获取当前矩形框选的定位点
///
///
///
public static IEnumerable GetRectPosItem(this MapControl ctrl) where T : PosData, new()
{
var innerData = ctrl.Tag as InnerData;
if (innerData.CurrentRect == default) return new List();
var rect = ctrl.GetCurrentRect();
double startLon = rect.starLon;
double startLat = rect.startLat;
double endLon = rect.endLon;
double endLat = rect.endLat;
var temp = innerData._dataCache.Keys.Where(p => p.InRectangle(startLon, startLat, endLon, endLat));
var res = temp.Select(p => (T)p);
return res;
}
///
/// 使用本地DB文件图源
///
///
///
public static MapControl UseLocalDb(this MapControl ctrl)
{
bool localGmdbDataEnable = false;//本地Data.Gmdb是否可用,可用时读取本地瓦片,否则执行Http请求资源
var files = Directory.GetFiles(Application.StartupPath, "Data.gmdb", SearchOption.AllDirectories);
if (files.Length > 0)
{
try
{
string conStr = string.Format("Data Source=\"{0}\";Page Size=32768", files[0]);
var con = new SQLiteConnection(conStr);
con.Open();
con.Close();
localGmdbDataEnable = true;
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
}
if (localGmdbDataEnable)
{
RemoveWmtsLyaer(ctrl);
ImageLayer layer = new ImageLayer() { Name = "WMTS:Local" };
ctrl.Layers.Add(layer);
var provider = new ImageTileDataProvider();//地图瓦片提供者
provider.TileSource = new ImageTileSource();//地图瓦片数据源接口实现
layer.DataProvider = provider;
}
return ctrl;
}
private static void RemoveWmtsLyaer(MapControl ctrl)
{
var layers = ctrl.Layers.Where(p => p.Name.StartsWith("WMTS:")).ToList();
foreach (var item in layers)
{
ctrl.Layers.Remove(item);
}
}
///
/// 使用WMTS图源
///
///
/// such as http://192.168.100.63:58089
///
///
///
public static MapControl UseWMTS(this MapControl ctrl, string url, EnumWmtsSource source, EnumMapLayerType layerType)
{
RemoveWmtsLyaer(ctrl);
if (source == EnumWmtsSource.SJZX)
{
if (layerType.HasFlag(EnumMapLayerType.SatMap))
{
var provider = new HttpMapDataProvider();
var tileSource = provider.TileSource as HttpTileSource;
tileSource.HttpServerAddr = url;
tileSource.WmtsSource = source;
tileSource.LayerType = layerType;
tileSource.LayerName = "satellite";
ImageLayer satelliteImageLayer = new ImageLayer()
{
Name = "WMTS:SJZX-SatMap"
};
ctrl.Layers.Add(satelliteImageLayer);
satelliteImageLayer.DataProvider = provider;
}
if (layerType.HasFlag(EnumMapLayerType.RoadMap) || layerType.HasFlag(EnumMapLayerType.XZQH_Map))
{
var provider = new HttpMapDataProvider();
var tileSource = provider.TileSource as HttpTileSource;
tileSource.HttpServerAddr = url;
tileSource.WmtsSource = source;
tileSource.LayerType = layerType;
tileSource.LayerName = "electron";
ImageLayer electronImageLayer = new ImageLayer()
{
Name = "WMTS:SJZX-Electron"
};
ctrl.Layers.Add(electronImageLayer);
electronImageLayer.DataProvider = provider;
}
}
else
{
if (layerType.HasFlag(EnumMapLayerType.SatMap))
{
var provider = new HttpMapDataProvider();
var tileSource = provider.TileSource as HttpTileSource;
tileSource.HttpServerAddr = url;
tileSource.WmtsSource = source;
tileSource.LayerType = layerType;
tileSource.LayerName = "NaturalEarthII";
ImageLayer naturalEarthIIImageLayer = new ImageLayer()
{
Name = "WMTS:ZCJ-NaturalEarthII"
};
ctrl.Layers.Add(naturalEarthIIImageLayer);
naturalEarthIIImageLayer.DataProvider = provider;
}
if (layerType.HasFlag(EnumMapLayerType.RoadMap))
{
var provider = new HttpMapDataProvider();
var tileSource = provider.TileSource as HttpTileSource;
tileSource.HttpServerAddr = url;
tileSource.WmtsSource = source;
tileSource.LayerType = layerType;
tileSource.LayerName = "roadmap-final";
ImageLayer roadmapIImageLayer = new ImageLayer()
{
Name = "WMTS:ZCJ-Roadmap"
};
ctrl.Layers.Add(roadmapIImageLayer);
roadmapIImageLayer.DataProvider = provider;
}
if (layerType.HasFlag(EnumMapLayerType.XZQH_Map))
{
var provider = new HttpMapDataProvider();
var tileSource = provider.TileSource as HttpTileSource;
tileSource.HttpServerAddr = url;
tileSource.WmtsSource = source;
tileSource.LayerType = layerType;
tileSource.LayerName = "overlay-final";
ImageLayer overlayImageLayer = new ImageLayer()
{
Name = "WMTS:ZCJ-Overlay"
};
ctrl.Layers.Add(overlayImageLayer);
overlayImageLayer.DataProvider = provider;
}
}
ctrl.MinZoomLevel = 3;
ctrl.MaxZoomLevel = 20;
return ctrl;
}
///
/// 使用WMS图源
///
///
///
///
///
public static MapControl UseWMS(this MapControl ctrl, string url, string layerName)
{
if (ctrl is null)
{
throw new ArgumentNullException(nameof(ctrl));
}
if (string.IsNullOrEmpty(url))
{
throw new ArgumentException($"“{nameof(url)}”不能为 null 或空。", nameof(url));
}
if (layerName is null)
{
throw new ArgumentNullException(nameof(layerName));
}
RemoveWmtsLyaer(ctrl);
var provider = new WmsDataProvider();//地图瓦片提供者
provider.ServerUri = url;
if (!string.IsNullOrWhiteSpace(layerName))
provider.ActiveLayerName = layerName;
provider.CustomParameters.Add("format", "image/JPEG");
// provider.CustomParameters.Add("srs", "EPSG:4326");
var cs = (GeoMapCoordinateSystem)ctrl.CoordinateSystem;
cs.Projection = new EPSG4326Projection();
//provider.ResponseCapabilities += (sender, e) =>
//{
// if (string.IsNullOrWhiteSpace(layerName))
// provider.ActiveLayerName = e.Layers[0].Name;
//};
ImageLayer layer = new ImageLayer() { Name = "WMTS:Wms" };
layer.DataProvider = provider;
ctrl.Layers.Add(layer);
return ctrl;
}
///
/// 定位点使用内置聚合器
///
///
///
public static MapControl UseCluster(this MapControl ctrl)
{
var innerData = ctrl.Tag as InnerData;
innerData.posStorge.Clusterer = new PosClusterer(ctrl);//定位点聚合器
return ctrl;
}
///
/// 为地图添加右键测距功能
///
///
public static MapControl UseDistanceLine(this MapControl ctrl)
{
var btnDistance = new BarButtonItem() { Caption = "测距" };
btnDistance.ImageOptions.SvgImage = SvgHelper.CreateDistanceLine();
btnDistance.Tag = ctrl;
btnDistance.ItemClick += DistanceLine_ItemClick;
var innerData = ctrl.Tag as InnerData;
innerData.barM.BeginInit();
innerData.barM.Items.Add(btnDistance);
innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnDistance));
innerData.barM.EndInit();
return ctrl;
}
///
/// 使用航迹
///
///
/// 点击事件返回当前经纬度
///
public static MapControl UseHJ(this MapControl ctrl, Action<(double Lon, double Lat)> onClickChanged = null)
{
var btnHJ = new BarButtonItem() { Caption = "航迹" };
btnHJ.ImageOptions.SvgImage = SvgHelper.CreateMarkDot();
btnHJ.Tag = ctrl;
var innerData = ctrl.Tag as InnerData;
innerData.onClickChanged = onClickChanged;
btnHJ.ItemClick += (sender, e) =>
{
ctrl.MapEditor.SetEditMode();
ctrl.MouseClick += AddHJPoint;
ctrl.DoubleClick += (sender1, e1) =>
{
ctrl.MouseClick -= AddHJPoint;
};
};
innerData.barM.BeginInit();
innerData.barM.Items.Add(btnHJ);
innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnHJ));
innerData.barM.EndInit();
return ctrl;
}
///
/// 添加航迹点
///
///
///
///
public static void AddHJPosItem(this MapControl ctrl, T item) where T : PosData, new()
{
if (item.PosLon > 180) return;
var innerData = ctrl.Tag as InnerData;
var mapItem = new MapDot()
{
EnableHighlighting = DefaultBoolean.True,
EnableSelection = DefaultBoolean.False,
CanMove = false,
Visible = item.Visible,
IsHitTestVisible = true,
Fill = ColorHelper.IsHtmlColor(item.ColorKey) ? ColorTranslator.FromHtml(item.ColorKey) : ColorHelper.GetColor(item.ColorKey),
Size = _dotSize,
Tag = item,
Location = new GeoPoint(item.PosLat, item.PosLon),
ToolTipPattern = "dd"
};
innerData.mMapStorage.Items.Add(mapItem);
}
private static void AddHJPoint(object sender, MouseEventArgs e)
{
var innerData = (sender as MapControl).Tag as InnerData;
var ctrl = sender as MapControl;
var geoPoint = ctrl.ScreenPointToCoordPoint(e.Location) as GeoPoint;
innerData.onClickChanged?.Invoke((geoPoint.Longitude, geoPoint.Latitude));
}
///
/// 为地图添加右键标点功能
///
///
///
public static MapControl UseMarkDot(this MapControl ctrl)
{
var btnMarkDot = new BarButtonItem() { Caption = "标点" };
btnMarkDot.ImageOptions.SvgImage = SvgHelper.CreateMarkDot();
btnMarkDot.Tag = ctrl;
btnMarkDot.ItemClick += MarkDot_ItemClick;
var innerData = ctrl.Tag as InnerData;
innerData.barM.BeginInit();
innerData.barM.Items.Add(btnMarkDot);
innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnMarkDot));
innerData.barM.EndInit();
return ctrl;
}
///
/// 显示目标轨迹
///
///
///
public static MapControl UseTrack(this MapControl ctrl)
{
var innerData = ctrl.Tag as InnerData;
//航迹线图层
var trackLayer = new VectorItemsLayer() { Name = "TrackLayer" };
var trackStorage = new MapItemStorage();
trackLayer.Data = trackStorage;
ctrl.Layers.Add(trackLayer);
innerData.trackStorge = trackStorage;
var btnMarkDot = new BarButtonItem() { Caption = "目标轨迹" };
btnMarkDot.ImageOptions.SvgImage = SvgHelper.CreateTrack();
btnMarkDot.Tag = ctrl;
btnMarkDot.ItemClick += ShowTrack_ItemClick;
innerData.barM.BeginInit();
innerData.barM.Items.Add(btnMarkDot);
innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnMarkDot));
innerData.barM.EndInit();
return ctrl;
}
///
/// 为地图添加清除功能
///
///
///
public static MapControl UseClearAll(this MapControl ctrl)
{
var btnClearAll = new BarButtonItem() { Caption = "清除" };
btnClearAll.ImageOptions.SvgImage = SvgHelper.CreateClear();
btnClearAll.Tag = ctrl;
btnClearAll.ItemClick += (sender, e) => ctrl.ClearDrawObj();
var innerData = ctrl.Tag as InnerData;
innerData.barM.BeginInit();
innerData.barM.Items.Add(btnClearAll);
innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnClearAll));
innerData.barM.EndInit();
return ctrl;
}
///
/// 为地图添加导出图片功能
///
///
///
public static MapControl UseExportImg(this MapControl ctrl)
{
var btnExportImg = new BarButtonItem() { Caption = "导出图片" };
btnExportImg.ImageOptions.SvgImage = SvgHelper.CreateExportImg();
btnExportImg.Tag = ctrl;
btnExportImg.ItemClick += ExportImg_ItemClick;
var innerData = ctrl.Tag as InnerData;
innerData.barM.BeginInit();
innerData.barM.Items.Add(btnExportImg);
innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnExportImg));
innerData.barM.EndInit();
return ctrl;
}
///
/// 为地图添加导出图片功能
///
///
///
///
public static MapControl UseExportCsv(this MapControl ctrl, bool exportHeader = true)
{
var innerData = ctrl.Tag as InnerData;
var btnExportCsv = new BarButtonItem() { Caption = "导出Csv" };
btnExportCsv.ImageOptions.SvgImage = SvgHelper.CreateExportCsv();
btnExportCsv.Tag = ctrl;
btnExportCsv.ItemClick += (sender, e) =>
{
if (!innerData._dataCache.Any()) return;
bool exportSigTime = false;
Dictionary cellFormats = new Dictionary();//单元格的format
var props = innerData._dataCache.Keys.GetType().GetGenericArguments().First().GetProperties(BindingFlags.Public | BindingFlags.Instance);
List<(int ColumnIndex, PropertyInfo Prop, string Header)> listPorps = new List<(int, PropertyInfo, string)>();
foreach (var prop in props)
{
ExportCellAttribute attrExport = prop.GetCustomAttribute();
if (attrExport == null) continue;
if (prop.Name == nameof(PosData.SigTime))
exportSigTime = true;
if (!string.IsNullOrWhiteSpace(attrExport.Format))
{
cellFormats.Add(prop.Name, attrExport.Format);
}
if (attrExport.ColumnIndex == -1)
attrExport.ColumnIndex = 10000;
var attrDisplay = prop.GetCustomAttribute();
if (attrDisplay != null && !string.IsNullOrWhiteSpace(attrDisplay.Name))
listPorps.Add((attrExport.ColumnIndex, prop, attrDisplay.Name));
else
listPorps.Add((attrExport.ColumnIndex, prop, prop.Name));
}
listPorps = listPorps.OrderBy(p => p.ColumnIndex).ToList();
using (var dialog = new SaveFileDialog())
{
dialog.Filter = "CSV文件|*.csv";
dialog.AddExtension = true;
dialog.FileName = $"Pos{DateTime.Now:yyyyMMddHHmmss}.csv";
if (dialog.ShowDialog() == DialogResult.OK)
{
var list = innerData._dataCache.Keys as IEnumerable;
if (exportSigTime)
list = list.OrderByDescending(p => p.SigTime);//如果导出了SigTime,则自动按照SigTime降序排列后导出
StreamWriter sw = new StreamWriter(dialog.FileName, false, new UTF8Encoding(true));//utf8-bom
if (exportHeader)
{
foreach (var prop in listPorps)
{
sw.Write($"{prop.Header},");
}
sw.WriteLine();
}
WaitHelper.ShowOverlayForm(ctrl);
long count = list.Count() * listPorps.Count;
int idx = 1;
foreach (var item in list)
{
foreach (var prop in listPorps)
{
WaitHelper.UpdateOverlyText($"{idx * 100 / count}%");
var value = prop.Prop.GetValue(item);
string str = null;
if (cellFormats.ContainsKey(prop.Prop.Name))
{
str = ((dynamic)value).ToString(cellFormats[prop.Prop.Name]);
}
else
{
if (value is DateTime)
str = $"{(DateTime)value:yyyy-MM-dd HH:mm:ss}";
else if (value is float || value is double || value is decimal)
{
dynamic valD = value;
str = ((dynamic)value).ToString("f4");
}
}
sw.Write($"{str},");
idx++;
}
sw.WriteLine();
}
sw.Close();
WaitHelper.CloseOverlayForm();
}
}
GC.Collect();
};
innerData.barM.BeginInit();
innerData.barM.Items.Add(btnExportCsv);
innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnExportCsv));
innerData.barM.EndInit();
return ctrl;
}
///
/// 为地图添加导出Excel数据功能
///
///
/// 是否导出列头
///
public static MapControl UseExportXlsx(this MapControl ctrl, bool exportHeader = true)
{
Action action = () =>
{
var btnExportXlsx = new BarButtonItem() { Caption = "导出Excel" };
btnExportXlsx.ImageOptions.SvgImage = SvgHelper.CreateExportXlsx();
var innerData = ctrl.Tag as InnerData;
innerData.barM.BeginInit();
innerData.barM.Items.Add(btnExportXlsx);
innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnExportXlsx));
innerData.barM.EndInit();
btnExportXlsx.ItemClick += (sender, e) =>
{
if (!innerData._dataCache.Any()) return;
GridControl gc = new GridControl();
GridView view = new GridView();
view.GridControl = gc;
gc.MainView = view;
gc.ViewCollection.Add(view);
view.OptionsPrint.ShowPrintExportProgress = false;
bool exportSigTime = false;
Dictionary cellFormats = new Dictionary();//单元格的format
var props = innerData._dataCache.Keys.GetType().GetGenericArguments().First().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in props)
{
ExportCellAttribute attrExport = prop.GetCustomAttribute();
if (attrExport == null) continue;
if (prop.Name == nameof(PosData.SigTime))
exportSigTime = true;
if (!string.IsNullOrWhiteSpace(attrExport.Format))
{
cellFormats.Add(prop.Name, attrExport.Format);
}
var col = new GridColumn();
col.FieldName = prop.Name;
col.Visible = true;
var attr = prop.GetCustomAttribute();
if (attr != null && !string.IsNullOrWhiteSpace(attr.Name))
col.Caption = attr.Name;
else
col.Caption = prop.Name;
if (attrExport.ColumnIndex >= 0)
col.VisibleIndex = attrExport.ColumnIndex;
view.Columns.Add(col);
}
gc.Visible = false;
gc.Parent = ctrl.Parent;
gc.Width = view.Columns.Count * 120;
using (var dialog = new SaveFileDialog())
{
dialog.Filter = "Excel文件|*.xlsx";
dialog.AddExtension = true;
dialog.FileName = $"Pos{DateTime.Now:yyyyMMddHHmmss}.xlsx";
if (dialog.ShowDialog() == DialogResult.OK)
{
var list = innerData._dataCache.Keys.ToList();
if (exportSigTime)
list = list.OrderByDescending(p => p.SigTime).ToList();//如果导出了SigTime,则自动按照SigTime降序排列后导出
gc.DataSource = list;
gc.Visible = true;
var exportType = DevExpress.Export.ExportSettings.DefaultExportType;
var options = new XlsxExportOptionsEx();
WaitHelper.ShowOverlayForm(ctrl);
options.ExportProgress += arg =>
{
WaitHelper.UpdateOverlyText($"{arg.ProgressPercentage}%");
if (arg.ProgressPercentage >= 100)
{
WaitHelper.CloseOverlayForm();
}
};
view.OptionsPrint.PrintHeader = exportHeader;
options.CustomizeCell += arg =>
{
arg.Handled = true;
var aligmentCenter = new XlCellAlignment()
{
HorizontalAlignment = XlHorizontalAlignment.Center,
VerticalAlignment = XlVerticalAlignment.Center
};
var aligmentLeft = new XlCellAlignment()
{
HorizontalAlignment = XlHorizontalAlignment.Left,
VerticalAlignment = XlVerticalAlignment.Center
};
if (arg.Value is bool)
{
arg.Formatting.Alignment = aligmentCenter;
arg.Value = ((bool)arg.Value) ? "☑" : "☐";
}
if (arg.Value is DateTime)
{
arg.Formatting.Alignment = aligmentLeft;
arg.Formatting.FormatType = FormatType.DateTime;
arg.Formatting.FormatString = "yyyy-MM-dd HH:mm:ss";
}
else if (arg.Value is float || arg.Value is double || arg.Value is decimal)
{
arg.Formatting.Alignment = aligmentLeft;
arg.Formatting.FormatType = FormatType.Numeric;
arg.Formatting.FormatString = "f4";
}
if (cellFormats.ContainsKey(arg.ColumnFieldName))
{
arg.Formatting.FormatString = cellFormats[arg.ColumnFieldName];
}
};
view.OptionsPrint.ShowPrintExportProgress = false;
DevExpress.Export.ExportSettings.DefaultExportType = DevExpress.Export.ExportType.DataAware;
gc.ExportToXlsx(dialog.FileName, options);
DevExpress.Export.ExportSettings.DefaultExportType = exportType;
gc.Visible = false;
}
}
gc.Parent = null;
gc.Dispose();
GC.Collect();
};
};
if (ctrl.Parent == null)
{
ctrl.ParentChanged += (sender, e) => action();
}
else
{
action();
}
return ctrl;
}
///
/// 为地图添加矩形框选区域功能
///
///
public static MapControl UseDrawRect(this MapControl ctrl, Action<(double starLon, double startLat, double centerLon, double centerLat,
double endLon, double endLat, double lonRange, double latRange)> onRectChanged = null)
{
var innerData = ctrl.Tag as InnerData;
innerData.mOnRectChanged = onRectChanged;
ctrl.MapEditor.ShowEditorPanel = true;
ctrl.MapEditor.PanelOptions.ShowAddCalloutButton = false;
ctrl.MapEditor.PanelOptions.ShowAddCustomElementButton = false;
ctrl.MapEditor.PanelOptions.ShowAddDotButton = false;
ctrl.MapEditor.PanelOptions.ShowAddEllipseButton = false;
ctrl.MapEditor.PanelOptions.ShowAddLineButton = false;
ctrl.MapEditor.PanelOptions.ShowAddPathButton = false;
ctrl.MapEditor.PanelOptions.ShowAddPolylineButton = false;
ctrl.MapEditor.PanelOptions.ShowAddPushpinButton = false;
ctrl.MapEditor.PanelOptions.ShowAddSplineButton = false;
ctrl.MapEditor.PanelOptions.ShowEditModeButton = false;
ctrl.MapEditor.PanelOptions.ShowTransformModeButton = false;
ctrl.MapEditor.PanelOptions.ShowUndoRedoButtons = false;
ctrl.MouseMove += DrawRect_MouseMove;
ctrl.MapEditor.MapItemCreating += (sender, e) =>
{
if (!innerData.mouseLeftDown)
{
e.Cancel = true;
return;
}
if (!(e.Item is MapRectangle)) return;
var items = innerData.mMapStorage.Items.ToList().FindAll(p => p.Tag != null && p.Tag.ToString() == "DrawRect");
ctrl.MapEditor.RemoveItems(items);
var item = e.Item as MapRectangle;
item.Tag = "DrawRect";
item.CanMove = false;
item.CanResize = false;
item.EnableSelection = DefaultBoolean.False;
item.EnableHighlighting = DefaultBoolean.True;
innerData.rangeItem = item;
if (innerData.rangeItem.Height == 0 && innerData.rangeItem.Width == 0)
{
innerData.rangeItem.Height = 5;
innerData.rangeItem.Width = 5;
}
item.Fill = Color.FromArgb(50, Color.FromArgb(23, 107, 209));
item.Stroke = Color.FromArgb(23, 107, 209);
item.StrokeWidth = 1;
innerData.dotItem.Fill = Color.Red;
innerData.dotItem.Size = 6;
innerData.dotItem.Location = innerData.rangeItem.GetCenter();
innerData.mMapStorage.Items.Add(innerData.rangeItem);
innerData.mMapStorage.Items.Add(innerData.dotItem);
DrawRect_MouseMove(ctrl, null);
var layer = ctrl.Layers.Find(p => p.Name == "");
if (layer != null) ctrl.Layers.Remove(layer);
};
ctrl.MapEditor.MapItemEdited += (sender, e) =>
{
innerData.drawingRect = e.Action == MapEditorAction.Create;
};
return ctrl;
}
///
/// 绘制矩形
///
///
///
///
///
///
///
public static void DrawRect(this MapControl ctrl, double startLon, double startLat, double endLon, double endLat, bool recCallback = false)
{
var innerData = ctrl.Tag as InnerData;
if (innerData.rangeItem != null)
innerData.mMapStorage.Items.Remove(innerData.rangeItem);
if (innerData.dotItem != null)
innerData.mMapStorage.Items.Remove(innerData.dotItem);
double centerLon = (startLon + endLon) / 2;
double centerLat = (startLat + endLat) / 2;
var size = BoundingRectItemHelper.CalculateRectangleSize(ctrl.CoordinateSystem,
new GeoPoint(startLat, startLon),
new GeoPoint(endLat, endLon));
innerData.dotItem.Location = new GeoPoint(centerLat, centerLon);
innerData.dotItem.Fill = Color.Red;
innerData.dotItem.Size = 8;
var rect = new MapRectangle()
{
CanMove = false,
CanResize = false,
EnableSelection = DefaultBoolean.False,
EnableHighlighting = DefaultBoolean.True,
Tag = "DrawRect",
Width = size.Width,
Height = size.Height,
Location = new GeoPoint(startLat, startLon),
Fill = Color.FromArgb(50, Color.FromArgb(23, 107, 209)),
Stroke = Color.FromArgb(23, 107, 209),
StrokeWidth = 1
};
innerData.rangeItem = rect;
innerData.CurrentRect = (startLon, startLat, centerLon, centerLat, endLon, endLat, (endLon - startLon) / 2, (endLat - startLat) / 2);
innerData.mMapStorage.Items.Add(innerData.rangeItem);
innerData.mMapStorage.Items.Add(innerData.dotItem);
if (recCallback)
innerData.mOnRectChanged?.Invoke(ctrl.GetCurrentRect());
}
public static void DrawDtoPonit(this MapControl ctrl, string title, IEnumerable<(double lon, double lat)> lines)
{
string identify = "DrawPoint_";
if (lines == null) return;
lines = lines.Where(p => p.lon >= -180 && p.lon <= 180);
if (!lines.Any()) return;
var innerData = ctrl.Tag as InnerData;
int size = 4;
List list = new List();
var color = ColorHelper.GetColor(title);
for (int i = 0; i < lines.Count(); i++)
{
var p = lines.ElementAt(i);
if (double.IsNaN(p.lat) || double.IsNaN(p.lon)) continue;
var mapItem = new MapDot()
{
EnableHighlighting = DefaultBoolean.False,
EnableSelection = DefaultBoolean.False,
CanMove = false,
CanResize = false,
StrokeWidth = 2,
Visible = true,
IsHitTestVisible = true,
Fill = color,
Size = size,
Tag = $"{identify}{title}{lines.ElementAt(i).lon}",
Location = new GeoPoint(p.lat, p.lon),
ToolTipPattern = $"{title}",
};
list.Add(mapItem);
}
if (!list.Any()) return;
innerData.mMapStorage.Items.AddRange(list);
}
public static MapPolyline GetLine(this MapControl ctrl, string title, IEnumerable<(double lon, double lat)> lines)
{
if (lines == null || !lines.Any()) return null;
var polyLine = new MapPolyline()
{
EnableSelection = DefaultBoolean.False,
EnableHighlighting = DefaultBoolean.True,
Stroke = ColorHelper.GetColor(title),
StrokeWidth = 2,
HighlightedStrokeWidth = 4,
IsGeodesic = true,
CanResize = false,
CanEdit = false,
CanRotate = false,
IsHitTestVisible = true,
CanMove = false,
Tag = $"DrawDtoLine_{title}",
ToolTipPattern = $"{title}",
};
bool isShowPattern = lines.Count() > 400;
if (isShowPattern)
{
polyLine.TitleOptions.Pattern = title;
}
foreach (var item in lines)
{
if (double.IsNaN(item.lat) || double.IsNaN(item.lon)) continue;
polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
}
if (!polyLine.Points.Any())
{
return null;
}
else
{
return polyLine;
}
}
public static MapPolyline GetLine(this MapControl ctrl, string title, IEnumerable<(double lon, double lat)> lines, bool isShowPattern = false)
{
if (lines == null || !lines.Any()) return null;
var polyLine = new MapPolyline()
{
EnableSelection = DefaultBoolean.False,
EnableHighlighting = DefaultBoolean.True,
Stroke = ColorHelper.GetColor(title),
StrokeWidth = 2,
HighlightedStrokeWidth = 4,
IsGeodesic = true,
CanResize = false,
CanEdit = false,
CanRotate = false,
IsHitTestVisible = true,
CanMove = false,
Tag = $"DrawDtoLine_{title}",
ToolTipPattern = $"{title}",
};
if (isShowPattern)
{
polyLine.TitleOptions.Pattern = title;
}
foreach (var item in lines)
{
if (double.IsNaN(item.lat) || double.IsNaN(item.lon)) continue;
polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
}
if (!polyLine.Points.Any())
{
return null;
}
else
{
return polyLine;
}
}
public static void DrawDtoLine(this MapControl ctrl, List polylines)
{
if (polylines == null || !polylines.Any()) return;
var innerData = ctrl.Tag as InnerData;
innerData.mMapStorage.Items.AddRange(polylines);
}
public static void DrawDtoLine(this MapControl ctrl, string title, IEnumerable<(double lon, double lat)> lines)
{
if (lines == null || !lines.Any()) return;
var innerData = ctrl.Tag as InnerData;
var polyLine = new MapPolyline()
{
EnableSelection = DefaultBoolean.False,
EnableHighlighting = DefaultBoolean.True,
Stroke = ColorHelper.GetColor(title),
StrokeWidth = 2,
HighlightedStrokeWidth = 4,
IsGeodesic = true,
CanResize = false,
CanEdit = false,
CanRotate = false,
IsHitTestVisible = true,
CanMove = false,
Tag = $"DrawDtoLine_{title}",
ToolTipPattern = $"{title}",
};
polyLine.TitleOptions.Pattern = title;
foreach (var item in lines)
{
if (double.IsNaN(item.lat) || double.IsNaN(item.lon)) continue;
polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
}
if (!polyLine.Points.Any()) return;
innerData.mMapStorage.Items.Add(polyLine);
}
///
/// 绘制时差多条线 两个点绘制一个线段 1和2一个线段 3和4一个线段
///
///
///
///
public static void DrawDtoLineTwo(this MapControl ctrl, string title, IEnumerable<(double lon, double lat)> dots)
{
if (dots == null || !dots.Any()) return;
string identify = $"DrawDtoLine_{title}";
var innerData = ctrl.Tag as InnerData;
//多条线 两个点绘制一个线段 1和2一个线段 3和4一个线段
List polylines = new List();
int index = 0;
int count = dots.Count();
MapPolyline polyLine = null;
foreach (var item in dots)
{
if (index % 2 == 0)
{
if (polyLine != null)//添加线段
{
polylines.Add(polyLine);
}
polyLine = new MapPolyline()
{
Stroke = ColorHelper.GetColor(identify),
EnableHighlighting = DefaultBoolean.False,
EnableSelection = DefaultBoolean.False,
StrokeWidth = 2,
HighlightedStrokeWidth = 4,
IsGeodesic = true,
CanResize = false,
CanEdit = false,
CanRotate = false,
IsHitTestVisible = true,
CanMove = false,
Tag = $"{identify}",
ToolTipPattern = title
};
}
polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
index++;
if (index == count)//添加最后一个线段
{
polylines.Add(polyLine);
}
}
if (!polyLine.Points.Any()) return;
innerData.mMapStorage.Items.AddRange(polylines);
}
public static void DrawGdopLine(this MapControl ctrl, IEnumerable<(string wcKm, double lon, double lat)> lines)
{
if (lines == null || !lines.Any()) return;
var innerData = ctrl.Tag as InnerData;
var wcKm = lines.First().wcKm;
var polyLine = new MapPolyline()
{
Stroke = ColorHelper.GetColor(wcKm),
StrokeWidth = 2,
IsGeodesic = true,
CanResize = false,
CanEdit = false,
CanRotate = false,
IsHitTestVisible = true,
CanMove = false,
Tag = $"DrawGdopLine_{wcKm}",
};
polyLine.TitleOptions.Pattern = wcKm;
foreach (var item in lines)
{
if (double.IsNaN(item.lat) || double.IsNaN(item.lon)) continue;
polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
}
if (!polyLine.Points.Any()) return;
innerData.mMapStorage.Items.Add(polyLine);
}
///
/// 绘制线
///
///
///
///
/// 是否清除上次绘制
public static void DrawCXLine(this MapControl ctrl, string title, IEnumerable<(double lon, double lat)> lines, bool isClear = true)
{
string identify = "DrawCXLine_";
if (lines == null || !lines.Any()) return;
var innerData = ctrl.Tag as InnerData;
if (isClear)
{
var mapItem = innerData.mMapStorage.Items.Find(m => m.Tag.ToString().StartsWith(identify));
if (mapItem != null)
{
innerData.mMapStorage.Items.Remove(mapItem);
}
}
var polyLine = new MapPolyline()
{
Stroke = Color.Red,
StrokeWidth = 2,
CanMove = false,
Visible = true,
IsHitTestVisible = true,
Tag = $"{identify}{title}",
ToolTipPattern = title,
};
foreach (var item in lines)
{
if (double.IsNaN(item.lat) || double.IsNaN(item.lon)) continue;
polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
}
if (!polyLine.Points.Any()) return;
innerData.mMapStorage.Items.Add(polyLine);
}
public static void DrawErrEllipse(this MapControl ctrl, double r1, double r2, IEnumerable<(double lon, double lat)> lines)
{
if (lines == null || !lines.Any()) return;
var innerData = ctrl.Tag as InnerData;
//innerData.mMapStorage.Items.Clear();
var polyLine = new MapPolyline()
{
Stroke = Color.Red,
StrokeWidth = 2,
IsGeodesic = true,
CanResize = false,
CanEdit = false,
CanRotate = false,
IsHitTestVisible = true,
CanMove = false,
Tag = $"DrawErrEllipse",
};
//polyLine.ToolTipPattern = $"长轴:{r1:f1}km\r\n短轴:{r2:f1}km";
foreach (var item in lines)
{
if (double.IsNaN(item.lat) || double.IsNaN(item.lon)) continue;
polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
}
if (!polyLine.Points.Any()) return;
innerData.mMapStorage.Items.Add(polyLine);
var callout = new DevExpress.XtraMap.MapCallout()
{
Text = $"R1={r1:f1}km\r\nR2={r2:f1}km",
Location = polyLine.Points.First(),
CanMove = false,
IsHitTestVisible = false,
};
innerData.mMapStorage.Items.Add(callout);
}
///
/// 绘制GDOP多条线 两个点绘制一个线段 1和2一个线段 3和4一个线段
///
///
///
///
///
public static void DrawGdopLineTwo(this MapControl ctrl, string wcKm, IEnumerable<(double lon, double lat)> dots, int patterncount)
{
if (dots == null || !dots.Any()) return;
string identify = "DrawGdopLine_";
var innerData = ctrl.Tag as InnerData;
//多条线 两个点绘制一个线段 1和2一个线段 3和4一个线段
List polylines = new List();
int index = 0;
int count = dots.Count();
MapPolyline polyLine = null;
foreach (var item in dots)
{
if (index % 2 == 0)
{
if (polyLine != null)//添加线段
{
polylines.Add(polyLine);
}
polyLine = new MapPolyline()
{
Stroke = ColorHelper.GetColor(wcKm),
EnableHighlighting = DefaultBoolean.False,
EnableSelection = DefaultBoolean.False,
StrokeWidth = 4,
IsGeodesic = true,
CanResize = false,
CanEdit = false,
CanRotate = false,
IsHitTestVisible = true,
CanMove = false,
Tag = $"{identify}{wcKm}",
ToolTipPattern = wcKm,
};
}
polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
if (patterncount == index)//提示公里信息
{
polyLine.TitleOptions.Pattern = wcKm;
}
index++;
if (index == count)//添加最后一个线段
{
polylines.Add(polyLine);
}
}
if (!polyLine.Points.Any()) return;
innerData.mMapStorage.Items.AddRange(polylines);
}
///
/// 绘制半径圆
///
///
///
///
///
public static void DrawRadiusRound(this MapControl ctrl, double lat, double lon, int radius)
{
var innerData = ctrl.Tag as InnerData;
try
{
if (radius <= 0)
return;
CoordPointCollection latLngs = new CoordPointCollection();
MyLatLng centerLatLng = new MyLatLng(lon, lat);
// 0 - 360度 寻找半径为radius,圆心为centerP的圆上点的经纬度
for (int i = 0; i < 360; i++)
{
//获取目标经纬度
MyLatLng tempLatLng = getMyLatLng(centerLatLng, radius, i);
//将自定义的经纬度类 转换成 标准经纬度类
CoordPoint p = new GeoPoint(tempLatLng.m_Latitude, tempLatLng.m_Longitude);
latLngs.Add(p);
}
//安全性检查
if (latLngs.Count < 20)
{
return;
}
//通过绘制多边形的方式绘制圆
MapPolygon gpol = new MapPolygon();
gpol.Points = latLngs;
gpol.Stroke = Color.Red;
gpol.Fill = Color.FromArgb(50, Color.Red);
gpol.IsHitTestVisible = true;
innerData.mMapStorageFixed.Items.Add(gpol);
}
catch (Exception)
{
//Dialog.Error(ex);
}
}
///
/// 度 转换成 弧度
///
///
///
public static double DegreesToRadians(double degrees)
{
const double degToRadFactor = Math.PI / 180;
return degrees * degToRadFactor;
}
///
/// 计算两个点之间的距离
///
/// 开始经度
/// 开始纬度
/// 结束经度
/// 结束纬度
///
public static double CalcLineKm(double startlon, double startlat, double endlon, double endlat)
{
GeoPoint startPoint = new GeoPoint() { Longitude = startlon, Latitude = startlat };
GeoPoint endPoint = new GeoPoint() { Longitude = endlon, Latitude = endlat };
double result = 0;
MapSize sizeInKm = new SphericalMercatorProjection().GeoToKilometersSize(startPoint, new MapSize(Math.Abs(startPoint.Longitude - endPoint.Longitude), Math.Abs(startPoint.Latitude - endPoint.Latitude)));
result = Math.Sqrt(sizeInKm.Width * sizeInKm.Width + sizeInKm.Height * sizeInKm.Height);
return result;
}
///
/// 计算方向线坐标
///
/// 经度
/// 纬度
/// 艏向角 角度制
/// 长度 m
///
public static (double, double) CalcSituation(double lon, double lat, double deg, double dis)
{
double rad = deg * (Math.PI / 180); //角度转弧度
double dx = dis * Math.Sin(rad);
double dy = dis * Math.Cos(rad);
MyLatLng A = new MyLatLng(lon, lat);
double bjd = (dx / A.Ed + A.m_RadLo) * 180 / Math.PI;
double bwd = (dy / A.Ec + A.m_RadLa) * 180 / Math.PI;
return (bjd, bwd);
}
/**
* 求B点经纬度
* @param A 已知点的经纬度,
* @param distance AB两地的距离 单位km
* @param angle AB连线与正北方向的夹角(0~360)
* @return B点的经纬度
*/
private static MyLatLng getMyLatLng(MyLatLng A, double distance, double angle)
{
double dx = distance * 1000 * Math.Sin(DegreesToRadians(angle));
double dy = distance * 1000 * Math.Cos(DegreesToRadians(angle));
double bjd = (dx / A.Ed + A.m_RadLo) * 180 / Math.PI;
double bwd = (dy / A.Ec + A.m_RadLa) * 180 / Math.PI;
return new MyLatLng(bjd, bwd);
}
public static void ClearRect(this MapControl ctrl)
{
var innerDate = ctrl.Tag as InnerData;
if (innerDate.rangeItem != null)
innerDate.mMapStorage.Items.Remove(innerDate.rangeItem);
if (innerDate.dotItem != null)
innerDate.mMapStorage.Items.Remove(innerDate.dotItem);
}
///
/// 获取地图框选的范围信息(可能为null)
///
///
///
public static (double starLon, double startLat, double centerLon, double centerLat,
double endLon, double endLat, double lonRange, double latRange) GetCurrentRect(this MapControl ctrl)
{
var innerData = ctrl.Tag as InnerData;
return innerData.CurrentRect;
}
///
/// 获取地图瓦片图层
///
///
///
public static List GetImageLayer(this MapControl ctrl)
{
if (ctrl.Layers == null) return null;
return ctrl.Layers.Where(p => p.Name.StartsWith("WMTS:")).Select(p => (ImageLayer)p).ToList();
}
///
/// 获取地图绘制图层
///
///
///
public static VectorItemsLayer GetDrawLayer(this MapControl ctrl)
{
return (VectorItemsLayer)ctrl.Layers["DrawLayer"];
}
///
/// 获取地图绘制图层
///
///
///
public static VectorItemsLayer GetPosLayer(this MapControl ctrl)
{
return (VectorItemsLayer)ctrl.Layers["PosLayer"];
}
///
/// 获取地图绘制图层的数据仓库
///
///
///
public static MapItemStorage GetDrawStorage(this MapControl ctrl)
{
var innerData = ctrl.Tag as InnerData;
return innerData.mMapStorage;
}
///
/// 设置本地地图类型.默认为Normal
/// 该方法为所有MapControl实例设置地图类型
///
///
public static void SetLocalMapType(GoogleMapType mapType)
{
mMapType = mapType;
listMapCtrl.ForEach(t =>
{
var localLayer = t.GetImageLayer()?.FirstOrDefault(p => p.Name == "WMTS:Local");
if (localLayer == null) return;
var provider = localLayer.DataProvider as MapTileDataProviderBase;
provider?.ClearCache();
t.Refresh();
});
}
#region private
private static void DrawRect_MouseMove(object sender, MouseEventArgs e)
{
var innerData = (sender as MapControl).Tag as InnerData;
if (!innerData.drawingRect) return;
innerData.dotItem.Location = innerData.rangeItem.GetCenter();
var startLon = Math.Round(innerData.rangeItem.Location.GetX(), 3);
var startLat = Math.Round(innerData.rangeItem.Location.GetY(), 3);
if (startLon >= 180)
{
startLon -= 360;
}
if (startLon <= -180)
{
startLon += 360;
}
var center = innerData.rangeItem.GetCenter();
var centerLon = Math.Round(center.GetX(), 3);
if (centerLon >= 180)
{
centerLon -= 360;
}
if (centerLon <= -180)
{
centerLon += 360;
}
var centerLat = Math.Round(center.GetY(), 3);
double endLon;
if (centerLon < 0 && startLon > 0)
endLon = startLon + 2 * (centerLon + 360 - startLon);
else
endLon = startLon + 2 * (centerLon - startLon);
var endLat = startLat + 2 * (centerLat - startLat);
var StartLon = Math.Min(startLon, endLon);
var StartLat = Math.Min(startLat, endLat);
var CenterLon = centerLon;
var CenterLat = centerLat;
var EndLon = Math.Max(startLon, endLon);
var EndLat = Math.Max(startLat, endLat);
double centerLonNew = CenterLon % 360;
CenterLon = centerLonNew;
//double LonRange = Math.Round((EndLon - StartLon) / 2, 3);
//double LatRange = Math.Round((EndLat - StartLat) / 2, 3);
double LonRange = Math.Round((EndLon - StartLon), 3);
double LatRange = Math.Round((EndLat - StartLat), 3);
if (LonRange >= 360)
{
}
innerData.CurrentRect = (StartLon, StartLat, CenterLon, CenterLat, EndLon, EndLat, LonRange, LatRange);
innerData.mOnRectChanged?.Invoke(innerData.CurrentRect);
}
private static void ExportImg_ItemClick(object sender, ItemClickEventArgs e)
{
var ctrl = e.Item.Tag as MapControl;
using (var dialog = new SaveFileDialog())
{
dialog.Filter = "PNG图片|*.png";
dialog.AddExtension = true;
dialog.FileName = $"Map{DateTime.Now:yyyyMMddHHmmss}.png";
if (dialog.ShowDialog() == DialogResult.OK)
{
ctrl.ExportToImage(dialog.FileName, ImageFormat.Png);
}
}
}
private static void ExportCsv_ItemClick(object sender, ItemClickEventArgs e)
{
var ctrl = e.Item.Tag as MapControl;
using (var dialog = new SaveFileDialog())
{
dialog.Filter = "CSV文件|*.csv";
dialog.AddExtension = true;
dialog.FileName = $"Pos{DateTime.Now:yyyyMMddHHmmss}.xlsx";
if (dialog.ShowDialog() == DialogResult.OK)
{
ctrl.ExportToXlsx(dialog.FileName);
}
}
}
private static void ClearDrawObj(this MapControl ctrl)
{
ctrl.Invoke(new Action(() =>
{
try
{
var innerData = ctrl.Tag as InnerData;
ctrl.MapEditor.SetTransformMode(MapItemTransform.None);
innerData.drawingRect = false;
innerData.CurrentRect = (0, 0, 0, 0, 0, 0, 0, 0);
innerData.rangeItem = null;
if (innerData.mMapStorage != null && innerData.mMapStorage.Items.Any())
{
innerData.mMapStorage.Items.Clear();
}
if (innerData.trackStorge != null)
{
innerData.trackStorge.Items.Clear();
}
}
catch (Exception)
{
}
}));
}
private static void DistanceLine_ItemClick(object sender, ItemClickEventArgs e)
{
var ctrl = e.Item.Tag as MapControl;
var innerData = ctrl.Tag as InnerData;
ctrl.MapEditor.SetEditMode();
var items = innerData.mMapStorage.Items.ToArray();
foreach (var item in items)
{
if (item.Tag != null && item.Tag.ToString() == "DrawDistanceLine")
innerData.mMapStorage.Items.Remove(item);
}
if (innerData.distinctPath != null)
{
innerData.distinctPath.Points.Clear();
}
innerData.distinctPath = new MapPolyline()
{
Stroke = Color.FromArgb(127, 255, 0, 199),
StrokeWidth = 2,
IsGeodesic = true,
CanResize = false,
CanEdit = false,
CanRotate = false,
IsHitTestVisible = false,
CanMove = true,
Tag = "DrawDistanceLine"
};
innerData.mMapStorage.Items.Add(innerData.distinctPath);
innerData.hoverPoint = new MapDot() { CanResize = false, CanMove = false, IsHitTestVisible = false, Tag = "DrawDistanceLine", Size = 8 };
innerData.hoverPoint.Fill = ColorHelper.GetColor(innerData.hoverPoint.Tag.ToString());
innerData.mMapStorage.Items.Add(innerData.hoverPoint);
innerData.hoverTip = CreateHoverTip();
ctrl.MouseClick += AddDistinctPoint;
ctrl.MouseMove += MovingDistinct;
ctrl.MouseLeave += MapControl_MouseLeave;
ctrl.MouseEnter += MapControl_MouseEnter;
ctrl.DoubleClick += EndDistinct;
}
private static void ShowTrack_ItemClick(object sender, ItemClickEventArgs e)
{
var ctrl = e.Item.Tag as MapControl;
var innerData = ctrl.Tag as InnerData;
innerData.trackStorge.Items.Clear();
var posData = innerData._dataCache.Keys.OrderBy(p => p.SigTime);
var itemList = posData.GroupBy(t => t.ColorKey);
List listLine = new List();
int w = 12;
int h = 20;
if (ctrl.ZoomLevel < 4)
{
w = 2;
h = 4;
}
else if (ctrl.ZoomLevel < 6)
{
w = 6;
h = 12;
}
else
{
w = 10;
h = 20;
}
foreach (var groupItems in itemList)
{
var targets = groupItems.ToList();
var colorKey = targets.First().ColorKey;
for (int i = 0; i < targets.Count - 1; i++)
{
var line = new MapPolyline();
line.CanEdit = false;
line.CanMove = false;
line.CanResize = false;
line.CanRotate = false;
line.EnableSelection = DefaultBoolean.False;
line.EnableHighlighting = DefaultBoolean.False;
line.IsGeodesic = true;
line.Stroke = ColorHelper.IsHtmlColor(colorKey) ? ColorTranslator.FromHtml(colorKey) : ColorHelper.GetColor(colorKey);
line.EndLineCap.Width = w;
line.EndLineCap.Length = h;
line.EndLineCap.Visible = true;
line.EndLineCap.IsFilled = false;
line.StrokeWidth = 2;
//line.EndLineCap.Length = 100;
var p1 = new GeoPoint(targets[i].PosLat, targets[i].PosLon);
var p2 = new GeoPoint(targets[i + 1].PosLat, targets[i + 1].PosLon);
line.Points.Add(p1);
line.Points.Add(p2);
listLine.Add(line);
}
}
innerData.trackStorge.Items.AddRange(listLine);
}
private static void MarkDot_ItemClick(object sender, ItemClickEventArgs e)
{
var ctrl = e.Item.Tag as MapControl;
ctrl.MapEditor.SetTransformMode(MapItemTransform.None);
var innerData = ctrl.Tag as InnerData;
innerData.drawingRect = false;
using (var frm = new MapEditPointView())
{
if (frm.ShowDialog() != DialogResult.OK) return;
var locPoint = new GeoPoint(frm.Lat, frm.Lon);
MapCustomElement cusItem = new MapCustomElement()
{
Location = locPoint,
UseAnimation = true,
CanMove = false,
EnableHighlighting = DefaultBoolean.True,
EnableSelection = DefaultBoolean.False,
Text = "",
ToolTipPattern = $"{frm.Caption}",
SvgImage = SvgHelper.CreatePentagram("#F12233", 24, 24),
TextAlignment = DevExpress.XtraMap.TextAlignment.BottomCenter,
Tag = "DrawMarkDot"
};
innerData.mMapStorage.Items.Add(cusItem);
}
}
private static ToolTipControllerShowEventArgs CreateHoverTip()
{
ToolTipTitleItem titleItem1 = new ToolTipTitleItem() { Text = $"0千米" };
titleItem1.Appearance.ForeColor = SystemColors.GrayText;
titleItem1.Appearance.Font = new Font(AppearanceObject.DefaultFont.FontFamily, 12, FontStyle.Bold);
SuperToolTip superToolTip = new SuperToolTip();
superToolTip.Items.Add(titleItem1);
ToolTipSeparatorItem sepItem = new ToolTipSeparatorItem();
superToolTip.Items.Add(sepItem);
ToolTipItem textItem = new ToolTipItem() { Text = "单击添加测距点,双击结束测距" };
superToolTip.Items.Add(textItem);
ToolTipControllerShowEventArgs arg = new ToolTipControllerShowEventArgs();
arg.ShowBeak = true;
arg.SuperTip = superToolTip;
return arg;
}
private static void MapControl_MouseEnter(object sender, EventArgs e)
{
var innerData = (sender as MapControl).Tag as InnerData;
innerData.hoverPoint.Visible = true;
}
private static void MapControl_MouseLeave(object sender, EventArgs e)
{
var innerData = (sender as MapControl).Tag as InnerData;
innerData.hoverPoint.Visible = false;
}
private static void AddDistinctPoint(object sender, MouseEventArgs e)
{
var innerData = (sender as MapControl).Tag as InnerData;
var ctrl = sender as MapControl;
MapCallout disItem = new MapCallout { IsHitTestVisible = false, CanMove = false };
disItem.Location = ctrl.ScreenPointToCoordPoint(e.Location);
disItem.Text = $"{CalcLineKm(innerData):F2}千米";
disItem.Tag = "DrawDistanceLine";
innerData.mMapStorage.Items.Add(disItem);
innerData.distinctPath.Points.Add(innerData.hoverPoint.Location);
innerData.hoverPoint = new MapDot() { CanResize = false, CanMove = false, IsHitTestVisible = false, Tag = "DrawDistanceLine", Size = 8 };
innerData.hoverPoint.Location = ctrl.ScreenPointToCoordPoint(e.Location);
innerData.hoverPoint.Fill = ColorHelper.GetColor(innerData.hoverPoint.Tag.ToString());
innerData.mMapStorage.Items.Add(innerData.hoverPoint);
innerData.distinctPath.Points.Add(innerData.hoverPoint.Location);
}
private static void MovingDistinct(object sender, MouseEventArgs e)
{
var innerData = (sender as MapControl).Tag as InnerData;
var ctrl = sender as MapControl;
var itemPoint = ctrl.ScreenPointToCoordPoint(e.Location);
innerData.hoverPoint.Location = itemPoint;
if (innerData.distinctPath.Points.Count > 0)
{
ctrl.MapEditor.SetEditMode();
innerData.distinctPath.Points[innerData.distinctPath.Points.Count - 1] = itemPoint;
(innerData.hoverTip.SuperTip.Items[0] as ToolTipTitleItem).Text = $"{CalcLineKm(innerData):F2}千米";
innerData.mapToolTip.ShowHint(innerData.hoverTip, ctrl.PointToScreen(e.Location));
}
}
private static double CalcLineKm(InnerData data)
{
double result = 0;
if (data.distinctPath.Points.Count < 2) return result;
for (int i = 0; i < data.distinctPath.Points.Count - 1; i++)
{
var startPoint = data.distinctPath.Points[i] as GeoPoint;
var endPoint = data.distinctPath.Points[i + 1] as GeoPoint;
MapSize sizeInKm = new SphericalMercatorProjection().GeoToKilometersSize(startPoint, new MapSize(Math.Abs(startPoint.Longitude - endPoint.Longitude), Math.Abs(startPoint.Latitude - endPoint.Latitude)));
double partlength = Math.Sqrt(sizeInKm.Width * sizeInKm.Width + sizeInKm.Height * sizeInKm.Height);
result += partlength;
}
return result;
}
public static void ClearMap(this MapControl ctrl)
{
var innerData = ctrl.Tag as InnerData;
innerData.CurrentRect = (0, 0, 0, 0, 0, 0, 0, 0);
innerData.mMapStorage?.Items.Clear();
}
private static void EndDistinct(object sender, EventArgs e)
{
var ctrl = sender as MapControl;
var innerData = ctrl.Tag as InnerData;
innerData.mapToolTip.HideHint();
ctrl.MouseClick -= AddDistinctPoint;
ctrl.MouseMove -= MovingDistinct;
ctrl.DoubleClick -= EndDistinct;
ctrl.MouseLeave -= MapControl_MouseLeave;
ctrl.MouseEnter -= MapControl_MouseEnter;
}
class MapEditPointView : DevExpress.XtraEditors.XtraForm
{
private System.ComponentModel.IContainer components = null;
private DevExpress.XtraLayout.LayoutControl layoutControl1;
private DevExpress.XtraLayout.LayoutControlGroup Root;
private DevExpress.XtraLayout.LayoutControlItem layoutControlItem1;
private DevExpress.XtraLayout.EmptySpaceItem emptySpaceItem1;
private DevExpress.XtraLayout.LayoutControlItem layoutControlItem2;
private DevExpress.XtraEditors.ButtonEdit txtLon;
private DevExpress.XtraEditors.ButtonEdit txtLat;
private DevExpress.XtraEditors.TextEdit txtCaption;
private DevExpress.XtraLayout.LayoutControlItem layoutControlItem5;
private DevExpress.XtraEditors.SimpleButton btnCancel;
private DevExpress.XtraEditors.SimpleButton btnOk;
private DevExpress.XtraLayout.LayoutControlItem layoutControlItem3;
private DevExpress.XtraLayout.LayoutControlItem layoutControlItem6;
private DevExpress.XtraEditors.DXErrorProvider.DXErrorProvider dxErrorProvider1;
private DevExpress.XtraLayout.EmptySpaceItem emptySpaceItem2;
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
DevExpress.XtraEditors.Controls.EditorButtonImageOptions editorButtonImageOptions1 = new DevExpress.XtraEditors.Controls.EditorButtonImageOptions();
DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject1 = new DevExpress.Utils.SerializableAppearanceObject();
DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject2 = new DevExpress.Utils.SerializableAppearanceObject();
DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject3 = new DevExpress.Utils.SerializableAppearanceObject();
DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject4 = new DevExpress.Utils.SerializableAppearanceObject();
DevExpress.XtraEditors.Controls.EditorButtonImageOptions editorButtonImageOptions2 = new DevExpress.XtraEditors.Controls.EditorButtonImageOptions();
DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject5 = new DevExpress.Utils.SerializableAppearanceObject();
DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject6 = new DevExpress.Utils.SerializableAppearanceObject();
DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject7 = new DevExpress.Utils.SerializableAppearanceObject();
DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject8 = new DevExpress.Utils.SerializableAppearanceObject();
this.layoutControl1 = new DevExpress.XtraLayout.LayoutControl();
this.txtCaption = new DevExpress.XtraEditors.TextEdit();
this.txtLon = new DevExpress.XtraEditors.ButtonEdit();
this.txtLat = new DevExpress.XtraEditors.ButtonEdit();
this.Root = new DevExpress.XtraLayout.LayoutControlGroup();
this.layoutControlItem1 = new DevExpress.XtraLayout.LayoutControlItem();
this.emptySpaceItem1 = new DevExpress.XtraLayout.EmptySpaceItem();
this.layoutControlItem2 = new DevExpress.XtraLayout.LayoutControlItem();
this.layoutControlItem5 = new DevExpress.XtraLayout.LayoutControlItem();
this.btnOk = new DevExpress.XtraEditors.SimpleButton();
this.layoutControlItem3 = new DevExpress.XtraLayout.LayoutControlItem();
this.btnCancel = new DevExpress.XtraEditors.SimpleButton();
this.layoutControlItem6 = new DevExpress.XtraLayout.LayoutControlItem();
this.dxErrorProvider1 = new DevExpress.XtraEditors.DXErrorProvider.DXErrorProvider(this.components);
this.emptySpaceItem2 = new DevExpress.XtraLayout.EmptySpaceItem();
((System.ComponentModel.ISupportInitialize)(this.layoutControl1)).BeginInit();
this.layoutControl1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.txtCaption.Properties)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.txtLon.Properties)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.txtLat.Properties)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.Root)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.layoutControlItem1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.emptySpaceItem1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.layoutControlItem2)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.layoutControlItem5)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.layoutControlItem3)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.layoutControlItem6)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.dxErrorProvider1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.emptySpaceItem2)).BeginInit();
this.SuspendLayout();
//
// layoutControl1
//
this.layoutControl1.Controls.Add(this.btnCancel);
this.layoutControl1.Controls.Add(this.btnOk);
this.layoutControl1.Controls.Add(this.txtCaption);
this.layoutControl1.Controls.Add(this.txtLon);
this.layoutControl1.Controls.Add(this.txtLat);
this.layoutControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.layoutControl1.Location = new System.Drawing.Point(0, 0);
this.layoutControl1.Name = "layoutControl1";
this.layoutControl1.OptionsCustomizationForm.DesignTimeCustomizationFormPositionAndSize = new System.Drawing.Rectangle(689, 0, 650, 400);
this.layoutControl1.Root = this.Root;
this.layoutControl1.Size = new System.Drawing.Size(272, 208);
this.layoutControl1.TabIndex = 0;
this.layoutControl1.Text = "layoutControl1";
//
// txtCaption
//
this.txtCaption.Location = new System.Drawing.Point(12, 29);
this.txtCaption.Name = "txtCaption";
this.txtCaption.Properties.Appearance.Options.UseTextOptions = true;
this.txtCaption.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Near;
this.txtCaption.Properties.AutoHeight = false;
this.txtCaption.Properties.MaxLength = 30;
this.txtCaption.Size = new System.Drawing.Size(248, 22);
this.txtCaption.StyleController = this.layoutControl1;
this.txtCaption.TabIndex = 9;
//
// txtLon
//
this.txtLon.Location = new System.Drawing.Point(12, 80);
this.txtLon.Name = "txtLon";
this.txtLon.Properties.Appearance.Options.UseTextOptions = true;
this.txtLon.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Near;
this.txtLon.Properties.AutoHeight = false;
this.txtLon.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] {
new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Glyph, "° ", -1, false, true, false, editorButtonImageOptions1, new DevExpress.Utils.KeyShortcut(System.Windows.Forms.Keys.None), serializableAppearanceObject1, serializableAppearanceObject2, serializableAppearanceObject3, serializableAppearanceObject4, "", null, null, DevExpress.Utils.ToolTipAnchor.Default)});
this.txtLon.Size = new System.Drawing.Size(248, 22);
this.txtLon.StyleController = this.layoutControl1;
this.txtLon.TabIndex = 4;
//
// txtLat
//
this.txtLat.Location = new System.Drawing.Point(12, 131);
this.txtLat.Name = "txtLat";
this.txtLat.Properties.Appearance.Options.UseTextOptions = true;
this.txtLat.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Near;
this.txtLat.Properties.AutoHeight = false;
this.txtLat.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] {
new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Glyph, "° ", -1, false, true, false, editorButtonImageOptions2, new DevExpress.Utils.KeyShortcut(System.Windows.Forms.Keys.None), serializableAppearanceObject5, serializableAppearanceObject6, serializableAppearanceObject7, serializableAppearanceObject8, "", null, null, DevExpress.Utils.ToolTipAnchor.Default)});
this.txtLat.Size = new System.Drawing.Size(248, 22);
this.txtLat.StyleController = this.layoutControl1;
this.txtLat.TabIndex = 5;
//
// Root
//
this.Root.EnableIndentsWithoutBorders = DevExpress.Utils.DefaultBoolean.True;
this.Root.GroupBordersVisible = false;
this.Root.Items.AddRange(new DevExpress.XtraLayout.BaseLayoutItem[] {
this.layoutControlItem1,
this.emptySpaceItem1,
this.layoutControlItem5,
this.layoutControlItem2,
this.layoutControlItem3,
this.layoutControlItem6,
this.emptySpaceItem2});
this.Root.Name = "Root";
this.Root.Size = new System.Drawing.Size(272, 208);
this.Root.TextVisible = false;
//
// layoutControlItem1
//
this.layoutControlItem1.Control = this.txtLon;
this.layoutControlItem1.Location = new System.Drawing.Point(0, 43);
this.layoutControlItem1.MaxSize = new System.Drawing.Size(0, 51);
this.layoutControlItem1.MinSize = new System.Drawing.Size(54, 51);
this.layoutControlItem1.Name = "layoutControlItem1";
this.layoutControlItem1.Padding = new DevExpress.XtraLayout.Utils.Padding(2, 2, 10, 2);
this.layoutControlItem1.Size = new System.Drawing.Size(252, 51);
this.layoutControlItem1.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
this.layoutControlItem1.Text = "经度";
this.layoutControlItem1.TextLocation = DevExpress.Utils.Locations.Top;
this.layoutControlItem1.TextSize = new System.Drawing.Size(24, 14);
//
// emptySpaceItem1
//
this.emptySpaceItem1.AllowHotTrack = false;
this.emptySpaceItem1.Location = new System.Drawing.Point(0, 162);
this.emptySpaceItem1.MaxSize = new System.Drawing.Size(0, 26);
this.emptySpaceItem1.MinSize = new System.Drawing.Size(104, 26);
this.emptySpaceItem1.Name = "emptySpaceItem1";
this.emptySpaceItem1.Size = new System.Drawing.Size(113, 26);
this.emptySpaceItem1.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
this.emptySpaceItem1.TextSize = new System.Drawing.Size(0, 0);
//
// layoutControlItem2
//
this.layoutControlItem2.Control = this.txtLat;
this.layoutControlItem2.Location = new System.Drawing.Point(0, 94);
this.layoutControlItem2.MaxSize = new System.Drawing.Size(0, 51);
this.layoutControlItem2.MinSize = new System.Drawing.Size(54, 51);
this.layoutControlItem2.Name = "layoutControlItem2";
this.layoutControlItem2.Padding = new DevExpress.XtraLayout.Utils.Padding(2, 2, 10, 2);
this.layoutControlItem2.Size = new System.Drawing.Size(252, 51);
this.layoutControlItem2.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
this.layoutControlItem2.Text = "纬度";
this.layoutControlItem2.TextLocation = DevExpress.Utils.Locations.Top;
this.layoutControlItem2.TextSize = new System.Drawing.Size(24, 14);
//
// layoutControlItem5
//
this.layoutControlItem5.Control = this.txtCaption;
this.layoutControlItem5.Location = new System.Drawing.Point(0, 0);
this.layoutControlItem5.MaxSize = new System.Drawing.Size(0, 43);
this.layoutControlItem5.MinSize = new System.Drawing.Size(54, 43);
this.layoutControlItem5.Name = "layoutControlItem5";
this.layoutControlItem5.Size = new System.Drawing.Size(252, 43);
this.layoutControlItem5.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
this.layoutControlItem5.Text = "标题";
this.layoutControlItem5.TextLocation = DevExpress.Utils.Locations.Top;
this.layoutControlItem5.TextSize = new System.Drawing.Size(24, 14);
//
// btnOk
//
this.btnOk.Location = new System.Drawing.Point(125, 174);
this.btnOk.Name = "btnOk";
this.btnOk.Size = new System.Drawing.Size(65, 22);
this.btnOk.StyleController = this.layoutControl1;
this.btnOk.TabIndex = 10;
this.btnOk.Text = "确定";
this.btnOk.Click += new System.EventHandler(this.btnOk_Click);
//
// layoutControlItem3
//
this.layoutControlItem3.Control = this.btnOk;
this.layoutControlItem3.Location = new System.Drawing.Point(113, 162);
this.layoutControlItem3.MaxSize = new System.Drawing.Size(69, 26);
this.layoutControlItem3.MinSize = new System.Drawing.Size(69, 26);
this.layoutControlItem3.Name = "layoutControlItem3";
this.layoutControlItem3.Size = new System.Drawing.Size(69, 26);
this.layoutControlItem3.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
this.layoutControlItem3.TextSize = new System.Drawing.Size(0, 0);
this.layoutControlItem3.TextVisible = false;
//
// btnCancel
//
this.btnCancel.Location = new System.Drawing.Point(194, 174);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(66, 22);
this.btnCancel.StyleController = this.layoutControl1;
this.btnCancel.TabIndex = 11;
this.btnCancel.Text = "取消";
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// layoutControlItem6
//
this.layoutControlItem6.Control = this.btnCancel;
this.layoutControlItem6.Location = new System.Drawing.Point(182, 162);
this.layoutControlItem6.MaxSize = new System.Drawing.Size(70, 26);
this.layoutControlItem6.MinSize = new System.Drawing.Size(70, 26);
this.layoutControlItem6.Name = "layoutControlItem6";
this.layoutControlItem6.Size = new System.Drawing.Size(70, 26);
this.layoutControlItem6.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
this.layoutControlItem6.TextSize = new System.Drawing.Size(0, 0);
this.layoutControlItem6.TextVisible = false;
//
// dxErrorProvider1
//
this.dxErrorProvider1.ContainerControl = this;
//
// emptySpaceItem2
//
this.emptySpaceItem2.AllowHotTrack = false;
this.emptySpaceItem2.Location = new System.Drawing.Point(0, 145);
this.emptySpaceItem2.MinSize = new System.Drawing.Size(104, 1);
this.emptySpaceItem2.Name = "emptySpaceItem2";
this.emptySpaceItem2.Size = new System.Drawing.Size(252, 17);
this.emptySpaceItem2.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
this.emptySpaceItem2.TextSize = new System.Drawing.Size(0, 0);
//
// MapEditPointView
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(272, 208);
this.Controls.Add(this.layoutControl1);
this.IconOptions.ShowIcon = false;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "MapEditPointView";
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "标点";
((System.ComponentModel.ISupportInitialize)(this.layoutControl1)).EndInit();
this.layoutControl1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.txtCaption.Properties)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.txtLon.Properties)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.txtLat.Properties)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.Root)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.layoutControlItem1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.emptySpaceItem1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.layoutControlItem2)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.layoutControlItem5)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.layoutControlItem3)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.layoutControlItem6)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.dxErrorProvider1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.emptySpaceItem2)).EndInit();
this.ResumeLayout(false);
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
public MapEditPointView()
{
InitializeComponent();
}
public string Caption
{
get
{
return txtCaption.Text.Trim();
}
set
{
txtCaption.Text = value;
}
}
public double Lon
{
get
{
return double.Parse(txtLon.Text.Trim());
}
set
{
txtLon.Text = value.ToString();
}
}
public double Lat
{
get
{
return double.Parse(txtLat.Text.Trim());
}
set
{
txtLat.Text = value.ToString();
}
}
private void btnOk_Click(object sender, EventArgs e)
{
dxErrorProvider1.ClearErrors();
double lon, lat;
if (!double.TryParse(txtLon.Text, out lon))
{
dxErrorProvider1.SetError(txtLon, "请设置正确的经度");
return;
}
if (!double.TryParse(txtLat.Text, out lat))
{
dxErrorProvider1.SetError(txtLat, "请设置正确的纬度");
return;
}
if (lon < -180 || lon > 180)
{
dxErrorProvider1.SetError(txtLon, "经度范围[-180,180]");
return;
}
if (lat < -90 || lat > 90)
{
dxErrorProvider1.SetError(txtLat, "纬度范围[-90,90]");
return;
}
this.DialogResult = DialogResult.OK;
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
}
}
#endregion
#region 半径圆
public class MyLatLng
{
public double Rc = 6378137; //赤道半径
public double Rj = 6356725; //极半径
public double m_LoDeg, m_LoMin, m_LoSec;
public double m_LaDeg, m_LaMin, m_LaSec;
public double m_Longitude, m_Latitude;
public double m_RadLo, m_RadLa;
public double Ec;
public double Ed;
public MyLatLng(double longitude, double latitude)
{
m_LoDeg = (int)longitude;
m_LoMin = (int)((longitude - m_LoDeg) * 60);
m_LoSec = (longitude - m_LoDeg - m_LoMin / 60) * 3600;
m_LaDeg = (int)latitude;
m_LaMin = (int)((latitude - m_LaDeg) * 60);
m_LaSec = (latitude - m_LaDeg - m_LaMin / 60) * 3600;
m_Longitude = longitude;
m_Latitude = latitude;
m_RadLo = longitude * Math.PI / 180;
m_RadLa = latitude * Math.PI / 180;
Ec = Rj + (Rc - Rj) * (90 - m_Latitude) / 90;
Ed = Ec * Math.Cos(m_RadLa);
}
}
#endregion
#region ImageLayer数据源接口实现(本地和Http接口)
class ImageTileSource : IImageTileSource
{
SQLiteConnection con;
public ImageTileSource()
{
var files = Directory.GetFiles(Application.StartupPath, "Data.gmdb", SearchOption.AllDirectories);
if (files.Length > 0)
{
try
{
conStr = string.Format(conStr, files[0]);
con = new SQLiteConnection(conStr);
con.Open();
}
catch
{
conStr = null;
Console.WriteLine("Data.gmdb文件读取出错!");
}
}
else
{
conStr = null;
}
}
public string Name => "GMap地图瓦片";
public bool CanDisposeSourceImage => true;
public Image GetImage(int x, int y, int level, Size size)
{
var data = QueryTile(x, y, level, 0);
if (data == null) return null;
return Image.FromStream(new MemoryStream(data));
}
string QuerySql = "SELECT Tile FROM main.TilesData WHERE id = (SELECT id FROM main.Tiles WHERE X={0} AND Y={1} AND Zoom={2} AND Type={3})";
string conStr = "Data Source=\"{0}\";Page Size=32768";
byte[] QueryTile(int x, int y, int zoom, int type)
{
if (conStr == null) return null;
type = (int)mMapType;
if (type == 0) type = 1818940751;
using (DbCommand com = con.CreateCommand())
{
com.CommandText = string.Format(QuerySql, x, y, zoom, type);
using (DbDataReader rd = com.ExecuteReader(System.Data.CommandBehavior.SequentialAccess))
{
if (rd.Read())
{
long length = rd.GetBytes(0, 0, null, 0, 0);
byte[] tile = new byte[length];
rd.GetBytes(0, 0, tile, 0, tile.Length);
return tile;
}
}
}
return null;
}
}
class HttpMapDataProvider : MapDataProviderBase
{
public HttpMapDataProvider()
{
TileSource = new HttpTileSource(this);
}
public override MapSize GetMapSizeInPixels(double zoomLevel)
{
double imageSize;
imageSize = HttpTileSource.CalculateTotalImageSize(zoomLevel);
return new MapSize(imageSize, imageSize);
}
protected override Size BaseSizeInPixels
{
get { return new Size(Convert.ToInt32(HttpTileSource.tileSize * 2), Convert.ToInt32(HttpTileSource.tileSize * 2)); }
}
}
class HttpTileSource : MapTileSourceBase
{
public const int tileSize = 256;
public const int maxZoomLevel = 14;
public string HttpServerAddr { get; set; }
public EnumWmtsSource WmtsSource { get; set; }
public EnumMapLayerType LayerType { get; set; }
public string LayerName { get; set; }
public GoogleMapType MapType { get; set; } = GoogleMapType.Normal;
internal static double CalculateTotalImageSize(double zoomLevel)
{
if (zoomLevel < 1.0)
return zoomLevel * tileSize * 2;
return Math.Pow(2.0, zoomLevel) * tileSize;
}
public HttpTileSource(ICacheOptionsProvider cacheOptionsProvider) :
base((int)CalculateTotalImageSize(maxZoomLevel), (int)CalculateTotalImageSize(maxZoomLevel), tileSize, tileSize, cacheOptionsProvider)
{
}
public override Uri GetTileByZoomLevel(int zoomLevel, int tilePositionX, int tilePositionY)
{
if (string.IsNullOrWhiteSpace(HttpServerAddr)) return null;
try
{
if (zoomLevel <= maxZoomLevel)
{
string imgUrl = string.Empty;
if (WmtsSource == EnumWmtsSource.SJZX)
{
imgUrl = $"{HttpServerAddr}?lyr={LayerName}&x={tilePositionX}&y={tilePositionY}&z={zoomLevel}";
}
else
{
string suffix = ".png";
if (LayerType == EnumMapLayerType.SatMap)
{
suffix = ".jpg";
}
int maxY = (int)Math.Pow(2, zoomLevel);
imgUrl = $"{HttpServerAddr}/{LayerName}/{zoomLevel}/{tilePositionX}/{maxY - tilePositionY}{suffix}";
}
//string imgUrl = string.Format("http://192.168.0.214:58089/{0}/{1}/{2}/{3}", (int)GoogleMapType.Normal, zoomLevel, tilePositionX, tilePositionY);
Uri u = new Uri(imgUrl);
return u;
}
return null;
}
catch
{
Console.WriteLine($"加载地图数据出错,无法连接到{HttpServerAddr}");
return null;
}
}
}
#endregion
//定位点聚合器
class PosClusterer : IClusterer
{
private MapControl ctrl;
private IMapDataAdapter owner;
private MapViewport preViewPoint;
private DebounceDispatcher dispatcher = new DebounceDispatcher();
public bool IsBusy { get; private set; }
public MapItemCollection Items { get; private set; }
public PosClusterer(MapControl ctrl)
{
this.ctrl = ctrl;
}
public void SetOwner(IMapDataAdapter owner)
{
this.owner = owner;
Items = new MapItemCollection(owner);
}
public void Clusterize(IEnumerable sourceItems, MapViewport viewport, bool sourceChanged)
{
IsBusy = true;
if (sourceChanged)
DoClusterize(sourceItems, viewport, sourceChanged);
else
dispatcher.Debounce(100, () => DoClusterize(sourceItems, viewport, sourceChanged));
}
private void DoClusterize(IEnumerable sourceItems, MapViewport viewport, bool sourceChanged)
{
if (preViewPoint == null)
{
preViewPoint = viewport;
return;
}
if (!sourceChanged && preViewPoint.ZoomLevel == viewport.ZoomLevel)//地图移动或者MapControl大小发生了改变时直接操作Items避免闪烁
{
preViewPoint = viewport;
}
else//地图进行了缩放
{
Items.Clear();
var cache = new Dictionary>();
foreach (MapDot item in sourceItems)
{
var point = ctrl.CoordPointToScreenPoint(item.Location);
int pointX = (int)point.X;
int pointY = (int)point.Y;
bool visible = true;
if (pointX <= _dotSize || pointX > ctrl.Width - _dotSize)
visible = false;
else if (pointY <= _dotSize || pointY > ctrl.Height - _dotSize)
visible = false;
pointX /= (_dotSize * 2);
pointY /= (_dotSize * 2);
var key = pointX << 16 | pointY;
if (!visible)
key = -key;
if (!cache.ContainsKey(key))
cache.Add(key, new List());
cache[key].Add(item);
}
var innerData = ctrl.Tag as InnerData;
innerData._clusterCache.Clear();
LinkedList temp = new LinkedList();
foreach (var kv in cache)
{
var firstDot = kv.Value[0] as MapDot;
var firstObj = firstDot.Tag as PosData;
firstDot.Size = kv.Value.Count > 1 ? _dotSize + 2 : _dotSize;
firstObj.ClusterCount = kv.Value.Count;
firstObj.ClusterKey = kv.Key;
innerData._clusterCache.Add(kv.Key, firstDot);
temp.AddLast(firstDot);
}
Items.AddRange(temp);
cache.Clear();
preViewPoint = viewport;
owner.OnClustered();
}
this.IsBusy = false;
}
//计算多个坐标的中心位置
public GeoPoint GetCenterPointFromListOfCoordinates(List geoCoordinateList)
{
int total = geoCoordinateList.Count;
double lat = 0, lon = 0;
foreach (MapDot g in geoCoordinateList)
{
lat += (g.Location as GeoPoint).Latitude * Math.PI / 180;
lon += (g.Location as GeoPoint).Longitude * Math.PI / 180;
}
lat /= total;
lon /= total;
return new GeoPoint(lat * 180 / Math.PI, lon * 180 / Math.PI);
}
}
}
class MyLatLng
{
static double Rc = 6378137;
static double Rj = 6356725;
double m_LoDeg, m_LoMin, m_LoSec;
double m_LaDeg, m_LaMin, m_LaSec;
double m_Longitude, m_Latitude;
double m_RadLo, m_RadLa;
double Ec;
double Ed;
public MyLatLng(double longitude, double latitude)
{
m_LoDeg = (int)longitude;
m_LoMin = (int)((longitude - m_LoDeg) * 60);
m_LoSec = (longitude - m_LoDeg - m_LoMin / 60) * 3600;
m_LaDeg = (int)latitude;
m_LaMin = (int)((latitude - m_LaDeg) * 60);
m_LaSec = (latitude - m_LaDeg - m_LaMin / 60) * 3600;
m_Longitude = longitude;
m_Latitude = latitude;
m_RadLo = longitude * Math.PI / 180;
m_RadLa = latitude * Math.PI / 180;
Ec = Rj + (Rc - Rj) * (90 - m_Latitude) / 90;
Ed = Ec * Math.Cos(m_RadLa);
}
}