MapControlEx.cs 112 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733
  1. using DevExpress.Export.Xl;
  2. using DevExpress.Internal;
  3. using DevExpress.Map;
  4. using DevExpress.Map.Native;
  5. using DevExpress.Utils;
  6. using DevExpress.Utils.Helpers;
  7. using DevExpress.Utils.Svg;
  8. using DevExpress.XtraBars;
  9. using DevExpress.XtraGrid;
  10. using DevExpress.XtraGrid.Columns;
  11. using DevExpress.XtraGrid.Views.Grid;
  12. using DevExpress.XtraMap;
  13. using DevExpress.XtraMap.ItemEditor;
  14. using DevExpress.XtraPrinting;
  15. using DxHelper;
  16. using System;
  17. using System.Collections.Generic;
  18. using System.ComponentModel.DataAnnotations;
  19. using System.Configuration;
  20. using System.Data.Common;
  21. using System.Data.Entity.Core.Metadata.Edm;
  22. using System.Data.SQLite;
  23. using System.Drawing;
  24. using System.Drawing.Imaging;
  25. using System.IO;
  26. using System.Linq;
  27. using System.Reflection;
  28. using System.Security.Policy;
  29. using System.Text;
  30. using System.Threading;
  31. using System.Windows.Forms;
  32. using XdCxRhDW.App;
  33. using XdCxRhDW.Entity;
  34. using XdCxRhDW.Repostory;
  35. public enum GoogleMapType
  36. {
  37. /// <summary>
  38. /// 卫星地图
  39. /// </summary>
  40. Sat = 47626774,
  41. /// <summary>
  42. /// 地形图
  43. /// </summary>
  44. Landform = 370833361,
  45. /// <summary>
  46. /// 混合地图
  47. /// </summary>
  48. Mix = 1024577166,
  49. /// <summary>
  50. /// 普通地图
  51. /// </summary>
  52. Normal = 1818940751
  53. }
  54. /// <summary>
  55. /// MapControl扩展类,封装了常用的非业务基础功能.
  56. /// 内置了4个图层,ImageTileLayer、DrawLayer、FixedDrawLayer、PosLayer.
  57. /// 必须首先调用UseDefalutOptions函数
  58. /// </summary>
  59. public static class MapControlEx
  60. {
  61. class InnerData
  62. {
  63. internal GeoPoint _mapMenuGeoPoint;
  64. internal Dictionary<int, MapItem> _clusterCache = new Dictionary<int, MapItem>();
  65. internal Dictionary<PosData, MapItem> _dataCache = new Dictionary<PosData, MapItem>();
  66. internal BarManager barM;
  67. internal PopupMenu mapMenu;
  68. internal PopupMenu posMenu;
  69. internal PopupMenu rectMenu;
  70. internal Action<(double starLon, double startLat, double centerLon, double centerLat,
  71. double endLon, double endLat, double lonRange, double latRange)> mOnRectChanged;
  72. internal Action<(double Lon, double Lat)> onClickChanged;
  73. internal MapItemStorage mMapStorage;
  74. internal MapItemStorage mMapStorageFixed;
  75. internal MapPolyline distinctPath;
  76. internal MapDot hoverPoint;
  77. internal ToolTipControllerShowEventArgs hoverTip;
  78. internal ToolTipController mapToolTip;
  79. internal MapItemStorage posStorge;
  80. internal MapRectangle rangeItem;
  81. internal MapDot dotItem = new MapDot() { Tag = "DrawRect" };
  82. internal bool drawingRect = false;
  83. internal bool mouseLeftDown = false;
  84. internal (double starLon, double startLat, double centerLon, double centerLat,
  85. double endLon, double endLat, double lonRange, double latRange)
  86. CurrentRect;
  87. internal MapDot preSelectedItem;
  88. }
  89. private static GoogleMapType mMapType = GoogleMapType.Normal;
  90. private static List<MapControl> listMapCtrl = new List<MapControl>();
  91. private const int _dotSize = 8;
  92. private const int _selectedDotSize = 12;
  93. /// <summary>
  94. /// <para>设置地图通用属性并创建4个Layer.</para>
  95. /// <para>ImageLayer:绘制地图瓦片</para>
  96. /// <para>DrawLayer:地图绘制图层,右键可以擦除</para>
  97. /// <para>FixedDrawLayer:地图绘制层,右键无法擦除</para>
  98. /// <para>PosLayer:定位点绘制专用图层</para>
  99. /// </summary>
  100. /// <param name="ctrl"></param>
  101. /// <returns></returns>
  102. public static MapControl UseDefalutOptions(this MapControl ctrl)
  103. {
  104. if (ctrl.Tag != null) return ctrl;
  105. var barM = new BarManager();
  106. barM.BeginInit();
  107. barM.Form = ctrl;
  108. var mapMeun = new PopupMenu() { Manager = barM };
  109. var posMenu = new PopupMenu() { Manager = barM };
  110. var rectMenu = new PopupMenu() { Manager = barM };
  111. barM.EndInit();
  112. listMapCtrl.Add(ctrl);
  113. var innerData = new InnerData();
  114. innerData.barM = barM;
  115. innerData.mapMenu = mapMeun;
  116. innerData.posMenu = posMenu;
  117. innerData.rectMenu = rectMenu;
  118. innerData.mapToolTip = new ToolTipController();
  119. innerData.mapToolTip.InitialDelay = 10;
  120. innerData.mapToolTip.KeepWhileHovered = true;
  121. innerData.mapToolTip.ReshowDelay = 10;
  122. innerData.mapToolTip.ShowBeak = true;
  123. innerData.mapToolTip.ToolTipAnchor = DevExpress.Utils.ToolTipAnchor.Cursor;
  124. innerData.mapToolTip.ToolTipType = ToolTipType.SuperTip;
  125. ctrl.Tag = innerData;
  126. ctrl.ToolTipController = innerData.mapToolTip;
  127. ctrl.ToolTipController.BeforeShow += (sender, e) =>
  128. {
  129. if (e.SelectedObject == null) return;
  130. SuperToolTip superToolTip = new SuperToolTip();
  131. if (innerData.posMenu.Visible || innerData.mapMenu.Visible || innerData.rectMenu.Visible)
  132. {
  133. e.SuperTip = null;
  134. e.ToolTip = null;
  135. return;
  136. }
  137. if (e.SelectedObject.ToString() == ItemsEditorPanelAction.AddRectangle.ToString())
  138. {
  139. e.ToolTip = "绘制矩形";
  140. return;
  141. }
  142. else if (e.SelectedObject is MapDot mapDot)
  143. {
  144. if (mapDot == null) return;
  145. var posItem = mapDot.Tag as PosData;
  146. if (mapDot == null || posItem == null) return;
  147. if (posItem.ClusterCount == 1)
  148. {
  149. var props = posItem.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
  150. var list = new List<(int Index, string Name, string Format, object Value)>();
  151. foreach (var prop in props)
  152. {
  153. var attrToolTip = prop.GetCustomAttribute<ToolTipAttribute>();
  154. if (attrToolTip == null) continue;
  155. string toolTipFormat = attrToolTip.Format;
  156. var val = prop.GetValue(posItem);
  157. string displayName = prop.Name;
  158. var attrDisplay = prop.GetCustomAttribute<DisplayAttribute>();
  159. if (attrDisplay != null && !string.IsNullOrWhiteSpace(attrDisplay.Name))
  160. displayName = attrDisplay.Name;
  161. int index = attrToolTip.Index;
  162. list.Add((index, displayName, toolTipFormat, val));
  163. }
  164. list = list.OrderBy(p => p.Index).ToList();
  165. foreach ((int Index, string Name, string Format, object val) in list)
  166. {
  167. string f = null;
  168. if (val is DateTime)
  169. {
  170. f = "yyyy-MM-dd HH:mm:ss";
  171. }
  172. else if (val is float || val is double || val is decimal)
  173. {
  174. f = "f4";
  175. }
  176. if (!string.IsNullOrWhiteSpace(Format))
  177. f = Format;
  178. string valStr = "";
  179. if (val is null)
  180. valStr = "--";
  181. else if (!string.IsNullOrWhiteSpace(f))
  182. valStr = ((dynamic)val).ToString(f);
  183. else if (val.GetType().IsEnum)
  184. {
  185. var field = val.GetType().GetField(Enum.GetName(val.GetType(), val));
  186. var attr = field.GetCustomAttribute<DisplayAttribute>();
  187. if (attr != null && !string.IsNullOrWhiteSpace(attr.Name))
  188. {
  189. valStr = attr.Name;
  190. }
  191. else
  192. {
  193. valStr = val.ToString();
  194. }
  195. }
  196. else
  197. valStr = val.ToString();
  198. ToolTipItem tipItem = new ToolTipItem();
  199. tipItem.Text = $"{Name}:{valStr}";
  200. superToolTip.Items.Add(tipItem);
  201. }
  202. }
  203. else
  204. {
  205. ToolTipItem tipItem = new ToolTipItem();
  206. tipItem.Text = $"当前位置附近有{posItem.ClusterCount}个定位点,放大可查看";
  207. superToolTip.Items.Add(tipItem);
  208. }
  209. e.SuperTip = superToolTip;
  210. }
  211. else if (e.SelectedObject is MapCustomElement ele)
  212. {
  213. if (ele.Tag.GetType() == typeof(string)) return;
  214. var find = innerData.mMapStorageFixed.Items.Where(p => (p is MapCustomElement pp) && p != ele && pp.Location.Equals(ele.Location));
  215. StringBuilder sb = new StringBuilder();
  216. sb.Append(((object[])ele.Tag)[1]);
  217. foreach (var item in find)
  218. {
  219. sb.Append("\r\n");
  220. sb.Append("-------------------");
  221. sb.Append("\r\n");
  222. sb.Append(((object[])item.Tag)[1]);
  223. }
  224. ele.ToolTipPattern = sb.ToString();
  225. }
  226. };
  227. ctrl.MouseDown += (sender, e) =>
  228. {
  229. if (e.Button == MouseButtons.Right)
  230. {
  231. var hitInfo = ctrl.CalcHitInfo(e.Location);
  232. if (hitInfo.InMapRectangle && innerData.rangeItem != null)
  233. {
  234. rectMenu?.ShowPopup(Cursor.Position);
  235. }
  236. else if (hitInfo.InMapDot && hitInfo.MapDot.Tag is PosData)
  237. {
  238. var selectPos = (PosData)hitInfo.MapDot.Tag;
  239. if (!selectPos.Selected)
  240. {
  241. selectPos.Selected = true;
  242. ctrl.UpdatePosItem(selectPos);
  243. }
  244. if (selectPos.ClusterCount == 1)
  245. {
  246. posMenu?.ShowPopup(Cursor.Position);//选中了原始MapItem
  247. }
  248. else
  249. {
  250. //选中了聚合后的MapItem
  251. }
  252. }
  253. else
  254. {
  255. var geoPoint = ctrl.ScreenPointToCoordPoint(e.Location) as GeoPoint;
  256. innerData._mapMenuGeoPoint = geoPoint;
  257. innerData.mapMenu?.ShowPopup(Cursor.Position);
  258. }
  259. }
  260. else
  261. {
  262. innerData.mouseLeftDown = true;
  263. innerData.barM.CloseMenus();
  264. var hitInfo = ctrl.CalcHitInfo(e.Location);
  265. if (hitInfo.InMapDot && hitInfo.MapDot.Tag is PosData)
  266. {
  267. var selectPos = hitInfo.MapDot.Tag as PosData;
  268. if (!selectPos.Selected)
  269. {
  270. selectPos.Selected = true;
  271. ctrl.UpdatePosItem(selectPos);
  272. }
  273. }
  274. }
  275. };
  276. ctrl.MouseUp += (sender, e) =>
  277. {
  278. innerData.mouseLeftDown = false;
  279. };
  280. //中心点、缩放级别
  281. ctrl.MinZoomLevel = 2;
  282. ctrl.ZoomLevel = 5;
  283. ctrl.MaxZoomLevel = 14;
  284. ctrl.CenterPoint = new GeoPoint(18, 110);
  285. //禁用多余特效
  286. ctrl.EnableDelayedScrolling = true;
  287. ctrl.RenderMode = RenderMode.DirectX;
  288. ctrl.EnableAnimation = false;
  289. ctrl.EnableRotation = false;
  290. //ctrl.ShowSearchPanel = false;
  291. ctrl.SearchPanelOptions.Visible = false;
  292. ctrl.SelectionMode = ElementSelectionMode.Single;//只能单选图层上的元素
  293. ((GeoMapCoordinateSystem)ctrl.CoordinateSystem).CircularScrollingMode = CircularScrollingMode.TilesAndVectorItems;
  294. //地图下方导航栏
  295. ctrl.NavigationPanelOptions.Height = 35;
  296. ctrl.NavigationPanelOptions.BackgroundStyle.Fill = Color.Transparent;
  297. ctrl.NavigationPanelOptions.ShowScrollButtons = false;
  298. ctrl.NavigationPanelOptions.ShowZoomTrackbar = false;
  299. ctrl.NavigationPanelOptions.ShowCoordinates = true;
  300. ctrl.NavigationPanelOptions.ShowKilometersScale = false;
  301. ctrl.NavigationPanelOptions.ShowMilesScale = false;
  302. ctrl.NavigationPanelOptions.CoordinatesStyle.Font = new Font("微软雅黑", 10F);
  303. ctrl.NavigationPanelOptions.ScaleStyle.Font = new Font("微软雅黑", 10F);
  304. // Create ImageTileLayer
  305. ImageLayer layer = new ImageLayer() { Name = "ImageTileLayer" };
  306. ctrl.Layers.Add(layer);
  307. //地图绘制加载(标点、测距、框选等元素载体图层).用来绘制可擦除的元素
  308. var layerDraw = new VectorItemsLayer() { Name = "DrawLayer" };
  309. var drawDataStorage = new MapItemStorage();
  310. layerDraw.Data = drawDataStorage;
  311. ctrl.Layers.Add(layerDraw);
  312. innerData.mMapStorage = drawDataStorage;
  313. //绘制图层,不可手动擦除,一般用来绘制卫星、参考站等固定元素
  314. var layerDrawFixed = new VectorItemsLayer() { Name = "FixedDrawLayer" };
  315. var drawDataStorageFixed = new MapItemStorage();
  316. layerDrawFixed.Data = drawDataStorageFixed;
  317. ctrl.Layers.Add(layerDrawFixed);
  318. innerData.mMapStorageFixed = drawDataStorageFixed;
  319. //定位点专用PosLayer
  320. var layerPos = new VectorItemsLayer() { Name = "PosLayer" };
  321. layerPos.ToolTipPattern = " ";//随便给一个,不然不会显示定位点的tooltip
  322. layerPos.AllowEditItems = true;
  323. layerPos.EnableHighlighting = false;
  324. layerPos.EnableSelection = false;
  325. ctrl.Layers.Add(layerPos);
  326. var posStorge = new MapItemStorage();
  327. layerPos.Data = posStorge;
  328. innerData.posStorge = posStorge;
  329. return ctrl;
  330. }
  331. /// <summary>
  332. /// 在定位点上增加右键菜单
  333. /// </summary>
  334. /// <param name="ctrl"></param>
  335. /// <param name="caption"></param>
  336. /// <param name="img"></param>
  337. /// <param name="action">一个回调,参数为选中的定位点</param>
  338. /// <param name="showCondition"></param>
  339. /// <returns></returns>
  340. public static MapControl AddPosMenu<T>(this MapControl ctrl, string caption, SvgImage img, Action<T> action, Func<T, bool> showCondition = null)
  341. {
  342. var btnCustom = new BarButtonItem() { Caption = caption };
  343. btnCustom.ImageOptions.SvgImage = img;
  344. btnCustom.Tag = ctrl;
  345. var innerData = ctrl.Tag as InnerData;
  346. btnCustom.ItemClick += (sender, e) =>
  347. {
  348. action((T)innerData.preSelectedItem.Tag);
  349. };
  350. innerData.barM.BeginInit();
  351. innerData.barM.Items.Add(btnCustom);
  352. innerData.posMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnCustom));
  353. innerData.barM.EndInit();
  354. innerData.posMenu.BeforePopup += (sender, e) =>
  355. {
  356. if (showCondition == null)
  357. btnCustom.Visibility = BarItemVisibility.Always;
  358. else
  359. {
  360. bool showBtn = showCondition((T)innerData.preSelectedItem.Tag);
  361. if (showBtn)
  362. btnCustom.Visibility = BarItemVisibility.Always;
  363. else
  364. btnCustom.Visibility = BarItemVisibility.Never;
  365. }
  366. };
  367. return ctrl;
  368. }
  369. /// <summary>
  370. /// 将GridControl单行元素右键菜单挂载到地图定位点右键菜单上(实验)
  371. /// </summary>
  372. /// <typeparam name="T"></typeparam>
  373. /// <param name="grid"></param>
  374. /// <param name="mapCtrl"></param>
  375. /// <returns></returns>
  376. public static GridControl MountRowMenuToMapPos<T>(this GridControl grid, MapControl mapCtrl)
  377. {
  378. var data = grid.Tag as GridControlEx.GridTag;
  379. data.RowButtonsItems.ForEach(t => mapCtrl.AddPosMenu<T>(t));
  380. return grid;
  381. }
  382. /// <summary>
  383. /// 将GridControl多行选择菜单挂载到地图框选区域右键菜单上(实验)
  384. /// </summary>
  385. /// <param name="grid"></param>
  386. /// <param name="mapCtrl"></param>
  387. /// <returns></returns>
  388. public static GridControl MountMultRowMenuToMapRegion(this GridControl grid, MapControl mapCtrl)
  389. {
  390. return grid;
  391. }
  392. /// <summary>
  393. /// 在定位点上增加右键菜单
  394. /// </summary>
  395. /// <param name="ctrl"></param>
  396. /// <param name="btn">右键菜单</param>
  397. /// <returns></returns>
  398. public static MapControl AddPosMenu<T>(this MapControl ctrl, BarButtonItem btn)
  399. {
  400. if (ctrl.Tag == null)
  401. ctrl.UseDefalutOptions();
  402. var innerData = ctrl.Tag as InnerData;
  403. innerData.barM.BeginInit();
  404. var btnNew = new BarButtonItem()
  405. {
  406. Tag = btn.Tag,
  407. Caption = btn.Caption,
  408. };
  409. btnNew.ItemClick += (ItemClickEventHandler)btn.Events()[btn.Caption];
  410. btnNew.ImageOptions.SvgImage = btn.ImageOptions.SvgImage;
  411. innerData.barM.Items.Add(btnNew);
  412. innerData.posMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnNew));
  413. innerData.barM.EndInit();
  414. innerData.posMenu.BeforePopup += (sender, e) =>
  415. {
  416. if (btnNew.Tag != null && btnNew.Tag is Func<bool> showCondition)
  417. {
  418. if (showCondition())
  419. btnNew.Visibility = BarItemVisibility.Always;
  420. else
  421. btnNew.Visibility = BarItemVisibility.Never;
  422. }
  423. };
  424. return ctrl;
  425. }
  426. /// <summary>
  427. /// 在地图上增加右键菜单
  428. /// </summary>
  429. /// <param name="ctrl"></param>
  430. /// <param name="caption"></param>
  431. /// <param name="img"></param>
  432. /// <param name="action">一个回调,参数为点击位置的经纬度</param>
  433. /// <returns></returns>
  434. public static MapControl AddMapMenu(this MapControl ctrl, string caption, SvgImage img, Action<double, double> action)
  435. {
  436. var btnCustom = new BarButtonItem() { Caption = caption, Name = caption };
  437. btnCustom.ImageOptions.SvgImage = img;
  438. btnCustom.Tag = ctrl;
  439. var innerData = ctrl.Tag as InnerData;
  440. btnCustom.ItemClick += (sender, e) =>
  441. {
  442. action(innerData._mapMenuGeoPoint.Longitude, innerData._mapMenuGeoPoint.Latitude);
  443. };
  444. innerData.barM.BeginInit();
  445. innerData.barM.Items.Add(btnCustom);
  446. innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnCustom));
  447. innerData.barM.EndInit();
  448. return ctrl;
  449. }
  450. /// <summary>
  451. /// 在框选矩形上增加右键菜单
  452. /// </summary>
  453. /// <param name="ctrl"></param>
  454. /// <param name="caption"></param>
  455. /// <param name="img"></param>
  456. /// <param name="action">一个回调,参数为框选的定位点</param>
  457. /// <param name="resetMapEdior"></param>
  458. /// <returns></returns>
  459. public static MapControl AddRectMenu<T>(this MapControl ctrl, string caption, SvgImage img, Action<IEnumerable<T>> action, bool resetMapEdior = true) where T : PosData, new()
  460. {
  461. var btnCustom = new BarButtonItem() { Caption = caption };
  462. btnCustom.ImageOptions.SvgImage = img;
  463. btnCustom.Tag = ctrl;
  464. btnCustom.ItemClick += (sender, e) =>
  465. {
  466. var data = ctrl.GetRectPosItem<T>();
  467. action(data);
  468. if (resetMapEdior)
  469. {
  470. ctrl.MapEditor.SetTransformMode(MapItemTransform.None);
  471. }
  472. };
  473. var innerData = ctrl.Tag as InnerData;
  474. innerData.barM.BeginInit();
  475. innerData.barM.Items.Add(btnCustom);
  476. innerData.rectMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnCustom));
  477. innerData.barM.EndInit();
  478. return ctrl;
  479. }
  480. /// <summary>
  481. /// 重新设置定位数据
  482. /// </summary>
  483. /// <typeparam name="T"></typeparam>
  484. /// <param name="ctrl"></param>
  485. /// <param name="items">数据源(指定null或空集合可以清空已有数据)</param>
  486. /// <param name="clearDrawLayer">是否清除DrawLayer上临时绘制的内容</param>
  487. public static void SetPosDataSource<T>(this MapControl ctrl, IEnumerable<T> items, bool clearDrawLayer = true) where T : PosData, new()
  488. {
  489. var innerData = ctrl.Tag as InnerData;
  490. innerData._dataCache.Clear();
  491. if (clearDrawLayer)
  492. ctrl.ClearDrawObj();
  493. innerData.posStorge.Items.Clear();
  494. if (items == null || !items.Any())
  495. {
  496. ctrl.Refresh();
  497. return;
  498. }
  499. List<MapDot> list = new List<MapDot>();
  500. for (int i = 0; i < items.Count(); i++)
  501. {
  502. var p = items.ElementAt(i);
  503. if (p.PosLon > 180) continue;
  504. var mapItem = new MapDot()
  505. {
  506. EnableHighlighting = DefaultBoolean.False,
  507. EnableSelection = DefaultBoolean.False,
  508. CanMove = false,
  509. Visible = p.Visible,
  510. IsHitTestVisible = true,
  511. StrokeWidth = 2,
  512. Fill = ColorHelper.IsHtmlColor(p.ColorKey) ? ColorTranslator.FromHtml(p.ColorKey) : ColorHelper.GetColor(p.ColorKey),
  513. Size = _dotSize,
  514. Tag = items.ElementAt(i),
  515. Location = new GeoPoint(p.PosLat, p.PosLon)
  516. };
  517. list.Add(mapItem);
  518. innerData._dataCache.Add(p, mapItem);
  519. }
  520. innerData.posStorge.Items.AddRange(list);
  521. }
  522. /// <summary>
  523. /// 定位图层数据源添加一个定位点
  524. /// </summary>
  525. /// <typeparam name="T"></typeparam>
  526. /// <param name="ctrl"></param>
  527. /// <param name="item"></param>
  528. public static void AddPosItem<T>(this MapControl ctrl, T item) where T : PosData, new()
  529. {
  530. if (item.PosLon > 180) return;
  531. var innerData = ctrl.Tag as InnerData;
  532. var mapItem = new MapDot()
  533. {
  534. EnableHighlighting = DefaultBoolean.True,
  535. EnableSelection = DefaultBoolean.False,
  536. CanMove = false,
  537. Visible = item.Visible,
  538. IsHitTestVisible = true,
  539. Fill = ColorHelper.IsHtmlColor(item.ColorKey) ? ColorTranslator.FromHtml(item.ColorKey) : ColorHelper.GetColor(item.ColorKey),
  540. Size = _dotSize,
  541. Tag = item,
  542. Location = new GeoPoint(item.PosLat, item.PosLon)
  543. };
  544. innerData._dataCache.Add(item, mapItem);
  545. innerData.posStorge.Items.Add(mapItem);
  546. }
  547. /// <summary>
  548. /// 定位图层数据源删除定位点
  549. /// </summary>
  550. /// <typeparam name="T"></typeparam>
  551. /// <param name="ctrl"></param>
  552. /// <param name="data"></param>
  553. public static void DelPosItem<T>(this MapControl ctrl, IEnumerable<T> data) where T : PosData, new()
  554. {
  555. if (data == null || !data.Any()) return;
  556. foreach (var item in data)
  557. {
  558. ctrl.DelPosItem(item);
  559. }
  560. ctrl.Refresh();
  561. }
  562. /// <summary>
  563. /// 定位图层数据源删除定位点
  564. /// </summary>
  565. /// <typeparam name="T"></typeparam>
  566. /// <param name="ctrl"></param>
  567. /// <param name="item"></param>
  568. public static void DelPosItem<T>(this MapControl ctrl, T item) where T : PosData, new()
  569. {
  570. if (item == null) return;
  571. var innerData = ctrl.Tag as InnerData;
  572. var key = innerData._dataCache.Keys.Where(p => p.ID == item.ID).FirstOrDefault();
  573. if (key != null)
  574. {
  575. innerData.posStorge.Items.Remove(innerData._dataCache[key]);
  576. innerData._dataCache.Remove(key);
  577. }
  578. ctrl.Refresh();
  579. }
  580. /// <summary>
  581. /// 定位图层数据源删除定位点
  582. /// </summary>
  583. /// <typeparam name="T"></typeparam>
  584. /// <param name="ctrl"></param>
  585. /// <param name="predicate"></param>
  586. public static void DelPosItem<T>(this MapControl ctrl, Func<T, bool> predicate) where T : PosData, new()
  587. {
  588. var innerData = ctrl.Tag as InnerData;
  589. List<PosData> keys = new List<PosData>();
  590. foreach (var item in innerData._dataCache.Keys)
  591. {
  592. if (predicate((T)item))
  593. keys.Add(item);
  594. }
  595. foreach (var item in keys)
  596. {
  597. ctrl.DelPosItem(item);
  598. }
  599. ctrl.Refresh();
  600. }
  601. /// <summary>
  602. /// 更新定位数据(可以更新可见性、颜色、经纬度、选中状态)
  603. /// </summary>
  604. /// <typeparam name="T"></typeparam>
  605. /// <param name="ctrl"></param>
  606. /// <param name="item"></param>
  607. /// <param name="setCenter">是否将这个点设置到地图中心显示</param>
  608. public static void UpdatePosItem<T>(this MapControl ctrl, T item, bool setCenter = false) where T : PosData, new()
  609. {
  610. if (item == null) return;
  611. var innerData = ctrl.Tag as InnerData;
  612. var key = innerData._dataCache.Keys.Where(p => p.ID == item.ID).FirstOrDefault();
  613. if (key != null)
  614. {
  615. var mapDot = innerData._dataCache[key] as MapDot;
  616. mapDot.Visible = item.Visible;//外部修改了可见性
  617. mapDot.Fill = ColorHelper.IsHtmlColor(item.ColorKey) ? ColorTranslator.FromHtml(item.ColorKey) : ColorHelper.GetColor(item.ColorKey);//外部修改了颜色
  618. mapDot.Location = new GeoPoint(item.PosLat, item.PosLon);//外部修改了位置
  619. if (mapDot.Size != (item.Selected ? _selectedDotSize : _dotSize))//外部修改了选中状态
  620. {
  621. mapDot.Size = item.Selected ? _selectedDotSize : _dotSize;
  622. mapDot.StrokeWidth = item.Selected ? 0 : 2;
  623. if (item.ClusterCount > 1)
  624. {
  625. if (innerData._clusterCache.TryGetValue(item.ClusterKey, out MapItem clusterItem))
  626. {
  627. (clusterItem as MapDot).Size = item.Selected ? _selectedDotSize : _dotSize;
  628. }
  629. }
  630. if (mapDot.ClusteredItems.Any())
  631. (mapDot.ClusteredItems[0] as MapDot).Size = _selectedDotSize;
  632. if (item.Selected)
  633. {
  634. //让选中的Item在上层
  635. var idx = innerData.posStorge.Items.IndexOf(mapDot);
  636. innerData.posStorge.Items.Swap(idx, innerData.posStorge.Items.Count - 1);
  637. //需要将上次选中的点设置为未选中
  638. if (innerData.preSelectedItem != null)
  639. {
  640. innerData.preSelectedItem.Size = _dotSize;
  641. (innerData.preSelectedItem.Tag as PosData).Selected = false;
  642. innerData.preSelectedItem.StrokeWidth = 2;
  643. if ((innerData.preSelectedItem.Tag as PosData).ClusterCount > 1)
  644. {
  645. if (innerData._clusterCache.TryGetValue((innerData.preSelectedItem.Tag as PosData).ClusterKey, out MapItem clusterItem))
  646. {
  647. (clusterItem as MapDot).Size = _dotSize + 2;
  648. }
  649. }
  650. }
  651. innerData.preSelectedItem = mapDot;
  652. }
  653. }
  654. if (setCenter && item.Visible)
  655. ctrl.SetCenterPoint(item.PosLon, item.PosLat, false);
  656. }
  657. }
  658. /// <summary>
  659. /// 更新定位数据(可以更新可见性、颜色、经纬度)
  660. /// </summary>
  661. /// <typeparam name="T"></typeparam>
  662. /// <param name="ctrl"></param>
  663. /// <param name="items"></param>
  664. public static void UpdatePosItem<T>(this MapControl ctrl, IEnumerable<T> items) where T : PosData, new()
  665. {
  666. if (items == null || !items.Any()) return;
  667. var innerData = ctrl.Tag as InnerData;
  668. foreach (var item in items)
  669. {
  670. var key = innerData._dataCache.Keys.Where(p => p.ID == item.ID).FirstOrDefault();
  671. if (key != null)
  672. {
  673. var mapDot = innerData._dataCache[key] as MapDot;
  674. mapDot.Visible = item.Visible;//外部修改了可见性
  675. mapDot.Fill = ColorHelper.IsHtmlColor(item.ColorKey) ? ColorTranslator.FromHtml(item.ColorKey) : ColorHelper.GetColor(item.ColorKey);//外部修改了颜色
  676. mapDot.Location = new GeoPoint(item.PosLat, item.PosLon);//外部修改了位置
  677. }
  678. }
  679. }
  680. /// <summary>
  681. /// 设置地图中心点
  682. /// </summary>
  683. /// <param name="ctrl"></param>
  684. /// <param name="lon"></param>
  685. /// <param name="lat"></param>
  686. /// <param name="animated">是否显示动画</param>
  687. /// <returns></returns>
  688. public static MapControl SetCenterPoint(this MapControl ctrl, double lon, double lat, bool animated = false)
  689. {
  690. ctrl.SetCenterPoint(new GeoPoint(lat, lon), animated);
  691. return ctrl;
  692. }
  693. /// <summary>
  694. /// 地图上添加图片
  695. /// </summary>
  696. /// <param name="ctrl"></param>
  697. /// <param name="tag"></param>
  698. /// <param name="imgLat"></param>
  699. /// <param name="imgLon"></param>
  700. /// <param name="img"></param>
  701. /// <param name="toolTip"></param>
  702. public static void DrawFixedImg(this MapControl ctrl, string tag, double imgLat, double imgLon, Image img, string toolTip = "")
  703. {
  704. var innerData = ctrl.Tag as InnerData;
  705. var item = new MapCustomElement() { Tag = new object[] { tag, toolTip } };
  706. item.UseAnimation = false;
  707. item.BackgroundDrawingMode = ElementState.None;
  708. item.Location = new GeoPoint(imgLat, imgLon);
  709. item.Image = img;
  710. item.ToolTipPattern = toolTip;
  711. innerData.mMapStorageFixed.Items.Add(item);
  712. }
  713. /// <summary>
  714. /// 地图上添加指定大小图片
  715. /// </summary>
  716. /// <param name="ctrl"></param>
  717. /// <param name="tag"></param>
  718. /// <param name="imgLat"></param>
  719. /// <param name="imgLon"></param>
  720. /// <param name="img"></param>
  721. /// <param name="toolTip"></param>
  722. public static void DrawFixedImg(this MapControl ctrl, string tag, double imgLat, double imgLon, SvgImage img, string toolTip = "")
  723. {
  724. var innerData = ctrl.Tag as InnerData;
  725. var item = new MapCustomElement() { Tag = new object[] { tag, toolTip } };
  726. item.UseAnimation = false;
  727. item.BackgroundDrawingMode = ElementState.None;
  728. item.Location = new GeoPoint(imgLat, imgLon);
  729. item.SvgImage = img;
  730. item.CanMove = false;
  731. item.EnableHighlighting = DefaultBoolean.False;
  732. item.EnableSelection = DefaultBoolean.False;
  733. item.ToolTipPattern = toolTip;
  734. innerData.mMapStorageFixed.Items.Add(item);
  735. }
  736. public static void DelFixedImg(this MapControl ctrl, string tag)
  737. {
  738. var innerData = ctrl.Tag as InnerData;
  739. var delItems = innerData.mMapStorageFixed.Items.ToList().FindAll(p => ((object[])p.Tag)[0].ToString() == tag);
  740. foreach (var item in delItems)
  741. {
  742. innerData.mMapStorageFixed.Items.Remove(item);
  743. }
  744. }
  745. /// <summary>
  746. /// 获取当前矩形框选的定位点
  747. /// </summary>
  748. /// <param name="ctrl"></param>
  749. /// <returns></returns>
  750. public static IEnumerable<T> GetRectPosItem<T>(this MapControl ctrl) where T : PosData, new()
  751. {
  752. var innerData = ctrl.Tag as InnerData;
  753. if (innerData.CurrentRect == default) return new List<T>();
  754. var rect = ctrl.GetCurrentRect();
  755. double startLon = rect.starLon;
  756. double startLat = rect.startLat;
  757. double endLon = rect.endLon;
  758. double endLat = rect.endLat;
  759. var temp = innerData._dataCache.Keys.Where(p => p.InRectangle(startLon, startLat, endLon, endLat));
  760. var res = temp.Select(p => (T)p);
  761. return res;
  762. }
  763. /// <summary>
  764. /// 使用本地DB文件图源
  765. /// </summary>
  766. /// <param name="ctrl"></param>
  767. /// <returns></returns>
  768. public static MapControl UseLocalDb(this MapControl ctrl)
  769. {
  770. bool localGmdbDataEnable = false;//本地Data.Gmdb是否可用,可用时读取本地瓦片,否则执行Http请求资源
  771. var files = Directory.GetFiles(Application.StartupPath, "Data.gmdb", SearchOption.AllDirectories);
  772. if (files.Length > 0)
  773. {
  774. try
  775. {
  776. string conStr = string.Format("Data Source=\"{0}\";Page Size=32768", files[0]);
  777. var con = new SQLiteConnection(conStr);
  778. con.Open();
  779. con.Close();
  780. localGmdbDataEnable = true;
  781. }
  782. catch (Exception ex)
  783. {
  784. Console.Error.WriteLine(ex.Message);
  785. }
  786. }
  787. if (localGmdbDataEnable)
  788. {
  789. var provider = new ImageTileDataProvider();//地图瓦片提供者
  790. provider.TileSource = new ImageTileSource();//地图瓦片数据源接口实现
  791. ctrl.GetImageLayer().DataProvider = provider;
  792. }
  793. return ctrl;
  794. }
  795. /// <summary>
  796. /// 使用WMTS图源
  797. /// </summary>
  798. /// <param name="ctrl"></param>
  799. /// <param name="url">such as http://192.168.100.63:58089</param>
  800. /// <param name="source"></param>
  801. /// <param name="layerType"></param>
  802. /// <returns></returns>
  803. public static MapControl UseWMTS(this MapControl ctrl, string url, EnumWmtsSource source, EnumMapLayerType layerType)
  804. {
  805. var provider = new HttpMapDataProvider();
  806. var tileSource = provider.TileSource as HttpTileSource;
  807. tileSource.HttpServerAddr = url;
  808. tileSource.WmtsSource = source;
  809. tileSource.LayerType = layerType;
  810. ctrl.GetImageLayer().DataProvider = provider;
  811. ctrl.MinZoomLevel = 3;
  812. ctrl.MaxZoomLevel = 20;
  813. return ctrl;
  814. }
  815. /// <summary>
  816. /// 使用WMS图源
  817. /// </summary>
  818. /// <param name="ctrl"></param>
  819. /// <param name="url"></param>
  820. /// <param name="layerName"></param>
  821. /// <returns></returns>
  822. public static MapControl UseWMS(this MapControl ctrl, string url, string layerName)
  823. {
  824. if (ctrl is null)
  825. {
  826. throw new ArgumentNullException(nameof(ctrl));
  827. }
  828. if (string.IsNullOrEmpty(url))
  829. {
  830. throw new ArgumentException($"“{nameof(url)}”不能为 null 或空。", nameof(url));
  831. }
  832. if (layerName is null)
  833. {
  834. throw new ArgumentNullException(nameof(layerName));
  835. }
  836. var provider = new WmsDataProvider();//地图瓦片提供者
  837. provider.ServerUri = url;
  838. if (!string.IsNullOrWhiteSpace(layerName))
  839. provider.ActiveLayerName = layerName;
  840. provider.CustomParameters.Add("format", "image/JPEG");
  841. // provider.CustomParameters.Add("srs", "EPSG:4326");
  842. var cs = (GeoMapCoordinateSystem)ctrl.CoordinateSystem;
  843. cs.Projection = new EPSG4326Projection();
  844. //provider.ResponseCapabilities += (sender, e) =>
  845. //{
  846. // if (string.IsNullOrWhiteSpace(layerName))
  847. // provider.ActiveLayerName = e.Layers[0].Name;
  848. //};
  849. ctrl.GetImageLayer().DataProvider = provider;
  850. return ctrl;
  851. }
  852. /// <summary>
  853. /// 定位点使用内置聚合器
  854. /// </summary>
  855. /// <param name="ctrl"></param>
  856. /// <returns></returns>
  857. public static MapControl UseCluster(this MapControl ctrl)
  858. {
  859. var innerData = ctrl.Tag as InnerData;
  860. innerData.posStorge.Clusterer = new PosClusterer(ctrl);//定位点聚合器
  861. return ctrl;
  862. }
  863. /// <summary>
  864. /// 为地图添加右键测距功能
  865. /// </summary>
  866. /// <returns></returns>
  867. public static MapControl UseDistanceLine(this MapControl ctrl)
  868. {
  869. var btnDistance = new BarButtonItem() { Caption = "测距" };
  870. btnDistance.ImageOptions.SvgImage = SvgHelper.CreateDistanceLine();
  871. btnDistance.Tag = ctrl;
  872. btnDistance.ItemClick += DistanceLine_ItemClick;
  873. var innerData = ctrl.Tag as InnerData;
  874. innerData.barM.BeginInit();
  875. innerData.barM.Items.Add(btnDistance);
  876. innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnDistance));
  877. innerData.barM.EndInit();
  878. return ctrl;
  879. }
  880. /// <summary>
  881. /// 使用航迹
  882. /// </summary>
  883. /// <param name="ctrl"></param>
  884. /// <param name="onClickChanged">点击事件返回当前经纬度</param>
  885. /// <returns></returns>
  886. public static MapControl UseHJ(this MapControl ctrl, Action<(double Lon, double Lat)> onClickChanged = null)
  887. {
  888. var btnHJ = new BarButtonItem() { Caption = "航迹" };
  889. btnHJ.ImageOptions.SvgImage = SvgHelper.CreateMarkDot();
  890. btnHJ.Tag = ctrl;
  891. var innerData = ctrl.Tag as InnerData;
  892. innerData.onClickChanged = onClickChanged;
  893. btnHJ.ItemClick += (sender, e) =>
  894. {
  895. ctrl.MapEditor.SetEditMode();
  896. ctrl.MouseClick += AddHJPoint;
  897. ctrl.DoubleClick += (sender1, e1) =>
  898. {
  899. ctrl.MouseClick -= AddHJPoint;
  900. };
  901. };
  902. innerData.barM.BeginInit();
  903. innerData.barM.Items.Add(btnHJ);
  904. innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnHJ));
  905. innerData.barM.EndInit();
  906. return ctrl;
  907. }
  908. /// <summary>
  909. /// 添加航迹点
  910. /// </summary>
  911. /// <typeparam name="T"></typeparam>
  912. /// <param name="ctrl"></param>
  913. /// <param name="item"></param>
  914. public static void AddHJPosItem<T>(this MapControl ctrl, T item) where T : PosData, new()
  915. {
  916. if (item.PosLon > 180) return;
  917. var innerData = ctrl.Tag as InnerData;
  918. var mapItem = new MapDot()
  919. {
  920. EnableHighlighting = DefaultBoolean.True,
  921. EnableSelection = DefaultBoolean.False,
  922. CanMove = false,
  923. Visible = item.Visible,
  924. IsHitTestVisible = true,
  925. Fill = ColorHelper.IsHtmlColor(item.ColorKey) ? ColorTranslator.FromHtml(item.ColorKey) : ColorHelper.GetColor(item.ColorKey),
  926. Size = _dotSize,
  927. Tag = item,
  928. Location = new GeoPoint(item.PosLat, item.PosLon),
  929. ToolTipPattern = "dd"
  930. };
  931. innerData.mMapStorage.Items.Add(mapItem);
  932. }
  933. private static void AddHJPoint(object sender, MouseEventArgs e)
  934. {
  935. var innerData = (sender as MapControl).Tag as InnerData;
  936. var ctrl = sender as MapControl;
  937. var geoPoint = ctrl.ScreenPointToCoordPoint(e.Location) as GeoPoint;
  938. innerData.onClickChanged?.Invoke((geoPoint.Longitude, geoPoint.Latitude));
  939. }
  940. /// <summary>
  941. /// 为地图添加右键标点功能
  942. /// </summary>
  943. /// <param name="ctrl"></param>
  944. /// <returns></returns>
  945. public static MapControl UseMarkDot(this MapControl ctrl)
  946. {
  947. var btnMarkDot = new BarButtonItem() { Caption = "标点" };
  948. btnMarkDot.ImageOptions.SvgImage = SvgHelper.CreateMarkDot();
  949. btnMarkDot.Tag = ctrl;
  950. btnMarkDot.ItemClick += MarkDot_ItemClick;
  951. var innerData = ctrl.Tag as InnerData;
  952. innerData.barM.BeginInit();
  953. innerData.barM.Items.Add(btnMarkDot);
  954. innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnMarkDot));
  955. innerData.barM.EndInit();
  956. return ctrl;
  957. }
  958. /// <summary>
  959. /// 为地图添加清除功能
  960. /// </summary>
  961. /// <param name="ctrl"></param>
  962. /// <returns></returns>
  963. public static MapControl UseClearAll(this MapControl ctrl)
  964. {
  965. var btnClearAll = new BarButtonItem() { Caption = "清除" };
  966. btnClearAll.ImageOptions.SvgImage = SvgHelper.CreateClear();
  967. btnClearAll.Tag = ctrl;
  968. btnClearAll.ItemClick += (sender, e) => ctrl.ClearDrawObj();
  969. var innerData = ctrl.Tag as InnerData;
  970. innerData.barM.BeginInit();
  971. innerData.barM.Items.Add(btnClearAll);
  972. innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnClearAll));
  973. innerData.barM.EndInit();
  974. return ctrl;
  975. }
  976. /// <summary>
  977. /// 为地图添加导出图片功能
  978. /// </summary>
  979. /// <param name="ctrl"></param>
  980. /// <returns></returns>
  981. public static MapControl UseExportImg(this MapControl ctrl)
  982. {
  983. var btnExportImg = new BarButtonItem() { Caption = "导出图片" };
  984. btnExportImg.ImageOptions.SvgImage = SvgHelper.CreateExportImg();
  985. btnExportImg.Tag = ctrl;
  986. btnExportImg.ItemClick += ExportImg_ItemClick;
  987. var innerData = ctrl.Tag as InnerData;
  988. innerData.barM.BeginInit();
  989. innerData.barM.Items.Add(btnExportImg);
  990. innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnExportImg));
  991. innerData.barM.EndInit();
  992. return ctrl;
  993. }
  994. /// <summary>
  995. /// 为地图添加导出图片功能
  996. /// </summary>
  997. /// <param name="ctrl"></param>
  998. /// <param name="exportHeader"></param>
  999. /// <returns></returns>
  1000. public static MapControl UseExportCsv(this MapControl ctrl, bool exportHeader = true)
  1001. {
  1002. var innerData = ctrl.Tag as InnerData;
  1003. var btnExportCsv = new BarButtonItem() { Caption = "导出Csv" };
  1004. btnExportCsv.ImageOptions.SvgImage = SvgHelper.CreateExportCsv();
  1005. btnExportCsv.Tag = ctrl;
  1006. btnExportCsv.ItemClick += (sender, e) =>
  1007. {
  1008. if (!innerData._dataCache.Any()) return;
  1009. bool exportSigTime = false;
  1010. Dictionary<string, string> cellFormats = new Dictionary<string, string>();//单元格的format
  1011. var props = innerData._dataCache.Keys.GetType().GetGenericArguments().First().GetProperties(BindingFlags.Public | BindingFlags.Instance);
  1012. List<(int ColumnIndex, PropertyInfo Prop, string Header)> listPorps = new List<(int, PropertyInfo, string)>();
  1013. foreach (var prop in props)
  1014. {
  1015. ExportCellAttribute attrExport = prop.GetCustomAttribute<ExportCellAttribute>();
  1016. if (attrExport == null) continue;
  1017. if (prop.Name == nameof(PosData.SigTime))
  1018. exportSigTime = true;
  1019. if (!string.IsNullOrWhiteSpace(attrExport.Format))
  1020. {
  1021. cellFormats.Add(prop.Name, attrExport.Format);
  1022. }
  1023. if (attrExport.ColumnIndex == -1)
  1024. attrExport.ColumnIndex = 10000;
  1025. var attrDisplay = prop.GetCustomAttribute<DisplayAttribute>();
  1026. if (attrDisplay != null && !string.IsNullOrWhiteSpace(attrDisplay.Name))
  1027. listPorps.Add((attrExport.ColumnIndex, prop, attrDisplay.Name));
  1028. else
  1029. listPorps.Add((attrExport.ColumnIndex, prop, prop.Name));
  1030. }
  1031. listPorps = listPorps.OrderBy(p => p.ColumnIndex).ToList();
  1032. using (var dialog = new SaveFileDialog())
  1033. {
  1034. dialog.Filter = "CSV文件|*.csv";
  1035. dialog.AddExtension = true;
  1036. dialog.FileName = $"Pos{DateTime.Now:yyyyMMddHHmmss}.csv";
  1037. if (dialog.ShowDialog() == DialogResult.OK)
  1038. {
  1039. var list = innerData._dataCache.Keys as IEnumerable<PosData>;
  1040. if (exportSigTime)
  1041. list = list.OrderByDescending(p => p.SigTime);//如果导出了SigTime,则自动按照SigTime降序排列后导出
  1042. StreamWriter sw = new StreamWriter(dialog.FileName, false, new UTF8Encoding(true));//utf8-bom
  1043. if (exportHeader)
  1044. {
  1045. foreach (var prop in listPorps)
  1046. {
  1047. sw.Write($"{prop.Header},");
  1048. }
  1049. sw.WriteLine();
  1050. }
  1051. WaitHelper.ShowOverlayForm(ctrl);
  1052. long count = list.Count() * listPorps.Count;
  1053. int idx = 1;
  1054. foreach (var item in list)
  1055. {
  1056. foreach (var prop in listPorps)
  1057. {
  1058. WaitHelper.UpdateOverlyText($"{idx * 100 / count}%");
  1059. var value = prop.Prop.GetValue(item);
  1060. string str = null;
  1061. if (cellFormats.ContainsKey(prop.Prop.Name))
  1062. {
  1063. str = ((dynamic)value).ToString(cellFormats[prop.Prop.Name]);
  1064. }
  1065. else
  1066. {
  1067. if (value is DateTime)
  1068. str = $"{(DateTime)value:yyyy-MM-dd HH:mm:ss}";
  1069. else if (value is float || value is double || value is decimal)
  1070. {
  1071. dynamic valD = value;
  1072. str = ((dynamic)value).ToString("f4");
  1073. }
  1074. }
  1075. sw.Write($"{str},");
  1076. idx++;
  1077. }
  1078. sw.WriteLine();
  1079. }
  1080. sw.Close();
  1081. WaitHelper.CloseOverlayForm();
  1082. }
  1083. }
  1084. GC.Collect();
  1085. };
  1086. innerData.barM.BeginInit();
  1087. innerData.barM.Items.Add(btnExportCsv);
  1088. innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnExportCsv));
  1089. innerData.barM.EndInit();
  1090. return ctrl;
  1091. }
  1092. /// <summary>
  1093. /// 为地图添加导出Excel数据功能
  1094. /// </summary>
  1095. /// <param name="ctrl"></param>
  1096. /// <param name="exportHeader">是否导出列头</param>
  1097. /// <returns></returns>
  1098. public static MapControl UseExportXlsx(this MapControl ctrl, bool exportHeader = true)
  1099. {
  1100. Action action = () =>
  1101. {
  1102. var btnExportXlsx = new BarButtonItem() { Caption = "导出Excel" };
  1103. btnExportXlsx.ImageOptions.SvgImage = SvgHelper.CreateExportXlsx();
  1104. var innerData = ctrl.Tag as InnerData;
  1105. innerData.barM.BeginInit();
  1106. innerData.barM.Items.Add(btnExportXlsx);
  1107. innerData.mapMenu.LinksPersistInfo.Add(new LinkPersistInfo(btnExportXlsx));
  1108. innerData.barM.EndInit();
  1109. btnExportXlsx.ItemClick += (sender, e) =>
  1110. {
  1111. if (!innerData._dataCache.Any()) return;
  1112. GridControl gc = new GridControl();
  1113. GridView view = new GridView();
  1114. view.GridControl = gc;
  1115. gc.MainView = view;
  1116. gc.ViewCollection.Add(view);
  1117. view.OptionsPrint.ShowPrintExportProgress = false;
  1118. bool exportSigTime = false;
  1119. Dictionary<string, string> cellFormats = new Dictionary<string, string>();//单元格的format
  1120. var props = innerData._dataCache.Keys.GetType().GetGenericArguments().First().GetProperties(BindingFlags.Public | BindingFlags.Instance);
  1121. foreach (var prop in props)
  1122. {
  1123. ExportCellAttribute attrExport = prop.GetCustomAttribute<ExportCellAttribute>();
  1124. if (attrExport == null) continue;
  1125. if (prop.Name == nameof(PosData.SigTime))
  1126. exportSigTime = true;
  1127. if (!string.IsNullOrWhiteSpace(attrExport.Format))
  1128. {
  1129. cellFormats.Add(prop.Name, attrExport.Format);
  1130. }
  1131. var col = new GridColumn();
  1132. col.FieldName = prop.Name;
  1133. col.Visible = true;
  1134. var attr = prop.GetCustomAttribute<DisplayAttribute>();
  1135. if (attr != null && !string.IsNullOrWhiteSpace(attr.Name))
  1136. col.Caption = attr.Name;
  1137. else
  1138. col.Caption = prop.Name;
  1139. if (attrExport.ColumnIndex >= 0)
  1140. col.VisibleIndex = attrExport.ColumnIndex;
  1141. view.Columns.Add(col);
  1142. }
  1143. gc.Visible = false;
  1144. gc.Parent = ctrl.Parent;
  1145. using (var dialog = new SaveFileDialog())
  1146. {
  1147. dialog.Filter = "Excel文件|*.xlsx";
  1148. dialog.AddExtension = true;
  1149. dialog.FileName = $"Pos{DateTime.Now:yyyyMMddHHmmss}.xlsx";
  1150. if (dialog.ShowDialog() == DialogResult.OK)
  1151. {
  1152. var list = innerData._dataCache.Keys.ToList();
  1153. if (exportSigTime)
  1154. list = list.OrderByDescending(p => p.SigTime).ToList();//如果导出了SigTime,则自动按照SigTime降序排列后导出
  1155. gc.DataSource = list;
  1156. gc.Visible = true;
  1157. var exportType = DevExpress.Export.ExportSettings.DefaultExportType;
  1158. var options = new XlsxExportOptionsEx();
  1159. WaitHelper.ShowOverlayForm(ctrl);
  1160. options.ExportProgress += arg =>
  1161. {
  1162. WaitHelper.UpdateOverlyText($"{arg.ProgressPercentage}%");
  1163. if (arg.ProgressPercentage >= 100)
  1164. {
  1165. WaitHelper.CloseOverlayForm();
  1166. }
  1167. };
  1168. view.OptionsPrint.PrintHeader = exportHeader;
  1169. options.CustomizeCell += arg =>
  1170. {
  1171. arg.Handled = true;
  1172. var aligmentCenter = new XlCellAlignment()
  1173. {
  1174. HorizontalAlignment = XlHorizontalAlignment.Center,
  1175. VerticalAlignment = XlVerticalAlignment.Center
  1176. };
  1177. var aligmentLeft = new XlCellAlignment()
  1178. {
  1179. HorizontalAlignment = XlHorizontalAlignment.Left,
  1180. VerticalAlignment = XlVerticalAlignment.Center
  1181. };
  1182. if (arg.Value is bool)
  1183. {
  1184. arg.Formatting.Alignment = aligmentCenter;
  1185. arg.Value = ((bool)arg.Value) ? "☑" : "☐";
  1186. }
  1187. if (arg.Value is DateTime)
  1188. {
  1189. arg.Formatting.Alignment = aligmentLeft;
  1190. arg.Formatting.FormatType = FormatType.DateTime;
  1191. arg.Formatting.FormatString = "yyyy-MM-dd HH:mm:ss";
  1192. }
  1193. else if (arg.Value is float || arg.Value is double || arg.Value is decimal)
  1194. {
  1195. arg.Formatting.Alignment = aligmentLeft;
  1196. arg.Formatting.FormatType = FormatType.Numeric;
  1197. arg.Formatting.FormatString = "f4";
  1198. }
  1199. if (cellFormats.ContainsKey(arg.ColumnFieldName))
  1200. {
  1201. arg.Formatting.FormatString = cellFormats[arg.ColumnFieldName];
  1202. }
  1203. };
  1204. view.OptionsPrint.ShowPrintExportProgress = false;
  1205. DevExpress.Export.ExportSettings.DefaultExportType = DevExpress.Export.ExportType.DataAware;
  1206. gc.ExportToXlsx(dialog.FileName, options);
  1207. DevExpress.Export.ExportSettings.DefaultExportType = exportType;
  1208. gc.Visible = false;
  1209. }
  1210. }
  1211. gc.Parent = null;
  1212. gc.Dispose();
  1213. GC.Collect();
  1214. };
  1215. };
  1216. if (ctrl.Parent == null)
  1217. {
  1218. ctrl.ParentChanged += (sender, e) => action();
  1219. }
  1220. else
  1221. {
  1222. action();
  1223. }
  1224. return ctrl;
  1225. }
  1226. /// <summary>
  1227. /// 为地图添加矩形框选区域功能
  1228. /// </summary>
  1229. /// <returns></returns>
  1230. public static MapControl UseDrawRect(this MapControl ctrl, Action<(double starLon, double startLat, double centerLon, double centerLat,
  1231. double endLon, double endLat, double lonRange, double latRange)> onRectChanged = null)
  1232. {
  1233. var innerData = ctrl.Tag as InnerData;
  1234. innerData.mOnRectChanged = onRectChanged;
  1235. ctrl.MapEditor.ShowEditorPanel = true;
  1236. ctrl.MapEditor.PanelOptions.ShowAddCalloutButton = false;
  1237. ctrl.MapEditor.PanelOptions.ShowAddCustomElementButton = false;
  1238. ctrl.MapEditor.PanelOptions.ShowAddDotButton = false;
  1239. ctrl.MapEditor.PanelOptions.ShowAddEllipseButton = false;
  1240. ctrl.MapEditor.PanelOptions.ShowAddLineButton = false;
  1241. ctrl.MapEditor.PanelOptions.ShowAddPathButton = false;
  1242. ctrl.MapEditor.PanelOptions.ShowAddPolylineButton = false;
  1243. ctrl.MapEditor.PanelOptions.ShowAddPushpinButton = false;
  1244. ctrl.MapEditor.PanelOptions.ShowAddSplineButton = false;
  1245. ctrl.MapEditor.PanelOptions.ShowEditModeButton = false;
  1246. ctrl.MapEditor.PanelOptions.ShowTransformModeButton = false;
  1247. ctrl.MapEditor.PanelOptions.ShowUndoRedoButtons = false;
  1248. ctrl.MouseMove += DrawRect_MouseMove;
  1249. ctrl.MapEditor.MapItemCreating += (sender, e) =>
  1250. {
  1251. if (!innerData.mouseLeftDown)
  1252. {
  1253. e.Cancel = true;
  1254. return;
  1255. }
  1256. if (!(e.Item is MapRectangle)) return;
  1257. var items = innerData.mMapStorage.Items.ToList().FindAll(p => p.Tag != null && p.Tag.ToString() == "DrawRect");
  1258. ctrl.MapEditor.RemoveItems(items);
  1259. var item = e.Item as MapRectangle;
  1260. item.Tag = "DrawRect";
  1261. item.CanMove = false;
  1262. item.CanResize = false;
  1263. item.EnableSelection = DefaultBoolean.False;
  1264. item.EnableHighlighting = DefaultBoolean.True;
  1265. innerData.rangeItem = item;
  1266. if (innerData.rangeItem.Height == 0 && innerData.rangeItem.Width == 0)
  1267. {
  1268. innerData.rangeItem.Height = 5;
  1269. innerData.rangeItem.Width = 5;
  1270. }
  1271. item.Fill = Color.FromArgb(50, Color.FromArgb(23, 107, 209));
  1272. item.Stroke = Color.FromArgb(23, 107, 209);
  1273. item.StrokeWidth = 1;
  1274. innerData.dotItem.Fill = Color.Red;
  1275. innerData.dotItem.Size = 6;
  1276. innerData.dotItem.Location = innerData.rangeItem.GetCenter();
  1277. innerData.mMapStorage.Items.Add(innerData.rangeItem);
  1278. innerData.mMapStorage.Items.Add(innerData.dotItem);
  1279. DrawRect_MouseMove(ctrl, null);
  1280. var layer = ctrl.Layers.Find(p => p.Name == "");
  1281. if (layer != null) ctrl.Layers.Remove(layer);
  1282. };
  1283. ctrl.MapEditor.MapItemEdited += (sender, e) =>
  1284. {
  1285. innerData.drawingRect = e.Action == MapEditorAction.Create;
  1286. };
  1287. return ctrl;
  1288. }
  1289. /// <summary>
  1290. /// 绘制矩形
  1291. /// </summary>
  1292. /// <param name="ctrl"></param>
  1293. /// <param name="startLon"></param>
  1294. /// <param name="startLat"></param>
  1295. /// <param name="endLon"></param>
  1296. /// <param name="endLat"></param>
  1297. /// <param name="recCallback"></param>
  1298. public static void DrawRect(this MapControl ctrl, double startLon, double startLat, double endLon, double endLat, bool recCallback = false)
  1299. {
  1300. var innerData = ctrl.Tag as InnerData;
  1301. if (innerData.rangeItem != null)
  1302. innerData.mMapStorage.Items.Remove(innerData.rangeItem);
  1303. if (innerData.dotItem != null)
  1304. innerData.mMapStorage.Items.Remove(innerData.dotItem);
  1305. double centerLon = (startLon + endLon) / 2;
  1306. double centerLat = (startLat + endLat) / 2;
  1307. var size = BoundingRectItemHelper.CalculateRectangleSize(ctrl.CoordinateSystem,
  1308. new GeoPoint(startLat, startLon),
  1309. new GeoPoint(endLat, endLon));
  1310. innerData.dotItem.Location = new GeoPoint(centerLat, centerLon);
  1311. innerData.dotItem.Fill = Color.Red;
  1312. innerData.dotItem.Size = 8;
  1313. var rect = new MapRectangle()
  1314. {
  1315. CanMove = false,
  1316. CanResize = false,
  1317. EnableSelection = DefaultBoolean.False,
  1318. EnableHighlighting = DefaultBoolean.True,
  1319. Tag = "DrawRect",
  1320. Width = size.Width,
  1321. Height = size.Height,
  1322. Location = new GeoPoint(startLat, startLon),
  1323. Fill = Color.FromArgb(50, Color.FromArgb(23, 107, 209)),
  1324. Stroke = Color.FromArgb(23, 107, 209),
  1325. StrokeWidth = 1
  1326. };
  1327. innerData.rangeItem = rect;
  1328. innerData.CurrentRect = (startLon, startLat, centerLon, centerLat, endLon, endLat, (endLon - startLon) / 2, (endLat - startLat) / 2);
  1329. innerData.mMapStorage.Items.Add(innerData.rangeItem);
  1330. innerData.mMapStorage.Items.Add(innerData.dotItem);
  1331. if (recCallback)
  1332. innerData.mOnRectChanged?.Invoke(ctrl.GetCurrentRect());
  1333. }
  1334. public static void DrawDtoPonit(this MapControl ctrl, string title, IEnumerable<(double lon, double lat)> lines)
  1335. {
  1336. string identify = "DrawPoint_";
  1337. if (lines == null) return;
  1338. lines = lines.Where(p => p.lon >= -180 && p.lon <= 180);
  1339. if (!lines.Any()) return;
  1340. var innerData = ctrl.Tag as InnerData;
  1341. int size = 4;
  1342. List<MapDot> list = new List<MapDot>();
  1343. var color = ColorHelper.GetColor(title);
  1344. for (int i = 0; i < lines.Count(); i++)
  1345. {
  1346. var p = lines.ElementAt(i);
  1347. if (double.IsNaN(p.lat) || double.IsNaN(p.lon)) continue;
  1348. var mapItem = new MapDot()
  1349. {
  1350. EnableHighlighting = DefaultBoolean.False,
  1351. EnableSelection = DefaultBoolean.False,
  1352. CanMove = false,
  1353. CanResize = false,
  1354. StrokeWidth = 2,
  1355. Visible = true,
  1356. IsHitTestVisible = true,
  1357. Fill = color,
  1358. Size = size,
  1359. Tag = $"{identify}{title}{lines.ElementAt(i).lon}",
  1360. Location = new GeoPoint(p.lat, p.lon),
  1361. ToolTipPattern = $"{title}",
  1362. };
  1363. list.Add(mapItem);
  1364. }
  1365. if (!list.Any()) return;
  1366. innerData.mMapStorage.Items.AddRange(list);
  1367. }
  1368. public static void DrawDtoLine(this MapControl ctrl, string title, IEnumerable<(double lon, double lat)> lines)
  1369. {
  1370. if (lines == null || !lines.Any()) return;
  1371. var innerData = ctrl.Tag as InnerData;
  1372. var polyLine = new MapPolyline()
  1373. {
  1374. EnableSelection = DefaultBoolean.False,
  1375. EnableHighlighting = DefaultBoolean.False,
  1376. Stroke = ColorHelper.GetColor(title),
  1377. StrokeWidth = 4,
  1378. IsGeodesic = true,
  1379. CanResize = false,
  1380. CanEdit = false,
  1381. CanRotate = false,
  1382. IsHitTestVisible = true,
  1383. CanMove = false,
  1384. Tag = $"DrawDtoLine_{title}",
  1385. ToolTipPattern = $"{title}",
  1386. };
  1387. foreach (var item in lines)
  1388. {
  1389. if (double.IsNaN(item.lat) || double.IsNaN(item.lon)) continue;
  1390. polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
  1391. }
  1392. if (!polyLine.Points.Any()) return;
  1393. innerData.mMapStorage.Items.Add(polyLine);
  1394. }
  1395. public static void DrawGdopLine(this MapControl ctrl, IEnumerable<(string wcKm, double lon, double lat)> lines)
  1396. {
  1397. if (lines == null || !lines.Any()) return;
  1398. var innerData = ctrl.Tag as InnerData;
  1399. var wcKm = lines.First().wcKm;
  1400. var polyLine = new MapPolyline()
  1401. {
  1402. Stroke = ColorHelper.GetColor(wcKm),
  1403. StrokeWidth = 2,
  1404. IsGeodesic = true,
  1405. CanResize = false,
  1406. CanEdit = false,
  1407. CanRotate = false,
  1408. IsHitTestVisible = true,
  1409. CanMove = false,
  1410. Tag = $"DrawGdopLine_{wcKm}",
  1411. };
  1412. polyLine.TitleOptions.Pattern = wcKm;
  1413. foreach (var item in lines)
  1414. {
  1415. if (double.IsNaN(item.lat) || double.IsNaN(item.lon)) continue;
  1416. polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
  1417. }
  1418. if (!polyLine.Points.Any()) return;
  1419. innerData.mMapStorage.Items.Add(polyLine);
  1420. }
  1421. /// <summary>
  1422. /// 绘制线
  1423. /// </summary>
  1424. /// <param name="ctrl"></param>
  1425. /// <param name="title"></param>
  1426. /// <param name="lines"></param>
  1427. /// <param name="isClear">是否清除上次绘制</param>
  1428. public static void DrawCXLine(this MapControl ctrl, string title, IEnumerable<(double lon, double lat)> lines, bool isClear = true)
  1429. {
  1430. string identify = "DrawCXLine_";
  1431. if (lines == null || !lines.Any()) return;
  1432. var innerData = ctrl.Tag as InnerData;
  1433. if (isClear)
  1434. {
  1435. var mapItem = innerData.mMapStorage.Items.Find(m => m.Tag.ToString().StartsWith(identify));
  1436. if (mapItem != null)
  1437. {
  1438. innerData.mMapStorage.Items.Remove(mapItem);
  1439. }
  1440. }
  1441. var polyLine = new MapPolyline()
  1442. {
  1443. Stroke = Color.Red,
  1444. StrokeWidth = 2,
  1445. CanMove = false,
  1446. Visible = true,
  1447. IsHitTestVisible = true,
  1448. Tag = $"{identify}{title}",
  1449. ToolTipPattern = title,
  1450. };
  1451. foreach (var item in lines)
  1452. {
  1453. if (double.IsNaN(item.lat) || double.IsNaN(item.lon)) continue;
  1454. polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
  1455. }
  1456. if (!polyLine.Points.Any()) return;
  1457. innerData.mMapStorage.Items.Add(polyLine);
  1458. }
  1459. public static void DrawErrEllipse(this MapControl ctrl, double r1, double r2, IEnumerable<(double lon, double lat)> lines)
  1460. {
  1461. if (lines == null || !lines.Any()) return;
  1462. var innerData = ctrl.Tag as InnerData;
  1463. //innerData.mMapStorage.Items.Clear();
  1464. var polyLine = new MapPolyline()
  1465. {
  1466. Stroke = Color.Red,
  1467. StrokeWidth = 2,
  1468. IsGeodesic = true,
  1469. CanResize = false,
  1470. CanEdit = false,
  1471. CanRotate = false,
  1472. IsHitTestVisible = true,
  1473. CanMove = false,
  1474. Tag = $"DrawErrEllipse",
  1475. };
  1476. //polyLine.ToolTipPattern = $"长轴:{r1:f1}km\r\n短轴:{r2:f1}km";
  1477. foreach (var item in lines)
  1478. {
  1479. if (double.IsNaN(item.lat) || double.IsNaN(item.lon)) continue;
  1480. polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
  1481. }
  1482. if (!polyLine.Points.Any()) return;
  1483. innerData.mMapStorage.Items.Add(polyLine);
  1484. var callout = new DevExpress.XtraMap.MapCallout()
  1485. {
  1486. Text = $"R1={r1:f1}km\r\nR2={r2:f1}km",
  1487. Location = polyLine.Points.First(),
  1488. CanMove = false,
  1489. IsHitTestVisible = false,
  1490. };
  1491. innerData.mMapStorage.Items.Add(callout);
  1492. }
  1493. /// <summary>
  1494. /// 绘制GDOP多条线 两个点绘制一个线段 1和2一个线段 3和4一个线段
  1495. /// </summary>
  1496. /// <param name="ctrl"></param>
  1497. /// <param name="wcKm"></param>
  1498. /// <param name="dots"></param>
  1499. /// <param name="patterncount"></param>
  1500. public static void DrawGdopLineTwo(this MapControl ctrl, string wcKm, IEnumerable<(double lon, double lat)> dots, int patterncount)
  1501. {
  1502. if (dots == null || !dots.Any()) return;
  1503. string identify = "DrawGdopLine_";
  1504. var innerData = ctrl.Tag as InnerData;
  1505. //多条线 两个点绘制一个线段 1和2一个线段 3和4一个线段
  1506. List<MapPolyline> polylines = new List<MapPolyline>();
  1507. int index = 0;
  1508. int count = dots.Count();
  1509. MapPolyline polyLine = null;
  1510. foreach (var item in dots)
  1511. {
  1512. if (index % 2 == 0)
  1513. {
  1514. if (polyLine != null)//添加线段
  1515. {
  1516. polylines.Add(polyLine);
  1517. }
  1518. polyLine = new MapPolyline()
  1519. {
  1520. Stroke = ColorHelper.GetColor(wcKm),
  1521. EnableHighlighting = DefaultBoolean.False,
  1522. EnableSelection = DefaultBoolean.False,
  1523. StrokeWidth = 4,
  1524. IsGeodesic = true,
  1525. CanResize = false,
  1526. CanEdit = false,
  1527. CanRotate = false,
  1528. IsHitTestVisible = true,
  1529. CanMove = false,
  1530. Tag = $"{identify}{wcKm}",
  1531. ToolTipPattern = wcKm,
  1532. };
  1533. }
  1534. polyLine.Points.Add(new GeoPoint(item.lat, item.lon));
  1535. if (patterncount == index)//提示公里信息
  1536. {
  1537. polyLine.TitleOptions.Pattern = wcKm;
  1538. }
  1539. index++;
  1540. if (index == count)//添加最后一个线段
  1541. {
  1542. polylines.Add(polyLine);
  1543. }
  1544. }
  1545. if (!polyLine.Points.Any()) return;
  1546. innerData.mMapStorage.Items.AddRange(polylines);
  1547. }
  1548. /// <summary>
  1549. /// 绘制半径圆
  1550. /// </summary>
  1551. /// <param name="ctrl"></param>
  1552. /// <param name="lat"></param>
  1553. /// <param name="lon"></param>
  1554. /// <param name="radius"></param>
  1555. public static void DrawRadiusRound(this MapControl ctrl, double lat, double lon, int radius)
  1556. {
  1557. var innerData = ctrl.Tag as InnerData;
  1558. try
  1559. {
  1560. if (radius <= 0)
  1561. return;
  1562. CoordPointCollection latLngs = new CoordPointCollection();
  1563. MyLatLng centerLatLng = new MyLatLng(lon, lat);
  1564. // 0 - 360度 寻找半径为radius,圆心为centerP的圆上点的经纬度
  1565. for (int i = 0; i < 360; i++)
  1566. {
  1567. //获取目标经纬度
  1568. MyLatLng tempLatLng = getMyLatLng(centerLatLng, radius, i);
  1569. //将自定义的经纬度类 转换成 标准经纬度类
  1570. CoordPoint p = new GeoPoint(tempLatLng.m_Latitude, tempLatLng.m_Longitude);
  1571. latLngs.Add(p);
  1572. }
  1573. //安全性检查
  1574. if (latLngs.Count < 20)
  1575. {
  1576. return;
  1577. }
  1578. //通过绘制多边形的方式绘制圆
  1579. MapPolygon gpol = new MapPolygon();
  1580. gpol.Points = latLngs;
  1581. gpol.Stroke = Color.Red;
  1582. gpol.Fill = Color.FromArgb(50, Color.Red);
  1583. gpol.IsHitTestVisible = true;
  1584. innerData.mMapStorageFixed.Items.Add(gpol);
  1585. }
  1586. catch (Exception)
  1587. {
  1588. //Dialog.Error(ex);
  1589. }
  1590. }
  1591. /// <summary>
  1592. /// 度 转换成 弧度
  1593. /// </summary>
  1594. /// <param name="degrees"></param>
  1595. /// <returns></returns>
  1596. public static double DegreesToRadians(double degrees)
  1597. {
  1598. const double degToRadFactor = Math.PI / 180;
  1599. return degrees * degToRadFactor;
  1600. }
  1601. /// <summary>
  1602. /// 计算两个点之间的距离
  1603. /// </summary>
  1604. /// <param name="startlon">开始经度</param>
  1605. /// <param name="startlat">开始纬度</param>
  1606. /// <param name="endlon">结束经度</param>
  1607. /// <param name="endlat">结束纬度</param>
  1608. /// <returns></returns>
  1609. public static double CalcLineKm(double startlon, double startlat, double endlon, double endlat)
  1610. {
  1611. GeoPoint startPoint = new GeoPoint() { Longitude = startlon, Latitude = startlat };
  1612. GeoPoint endPoint = new GeoPoint() { Longitude = endlon, Latitude = endlat };
  1613. double result = 0;
  1614. MapSize sizeInKm = new SphericalMercatorProjection().GeoToKilometersSize(startPoint, new MapSize(Math.Abs(startPoint.Longitude - endPoint.Longitude), Math.Abs(startPoint.Latitude - endPoint.Latitude)));
  1615. result = Math.Sqrt(sizeInKm.Width * sizeInKm.Width + sizeInKm.Height * sizeInKm.Height);
  1616. return result;
  1617. }
  1618. /// <summary>
  1619. /// 计算方向线坐标
  1620. /// </summary>
  1621. /// <param name="lon">经度</param>
  1622. /// <param name="lat">纬度</param>
  1623. /// <param name="deg"> 艏向角 角度制</param>
  1624. /// <param name="dis">长度 m</param>
  1625. /// <returns></returns>
  1626. public static (double, double) CalcSituation(double lon, double lat, double deg, double dis)
  1627. {
  1628. double arc = 6371.393 * 1000; //地球平均半径
  1629. double rad = deg * (Math.PI / 180); //角度转弧度
  1630. double c_lng = lon + dis * Math.Sin(rad) / (arc * Math.Cos(lat) * 2 * Math.PI / 360);
  1631. double c_lat = lat + dis * Math.Cos(rad) / (arc * 2 * Math.PI / 360);
  1632. return (c_lng, c_lat); //方向上的另一点坐标
  1633. }
  1634. /**
  1635. * 求B点经纬度
  1636. * @param A 已知点的经纬度,
  1637. * @param distance AB两地的距离 单位km
  1638. * @param angle AB连线与正北方向的夹角(0~360)
  1639. * @return B点的经纬度
  1640. */
  1641. private static MyLatLng getMyLatLng(MyLatLng A, double distance, double angle)
  1642. {
  1643. double dx = distance * 1000 * Math.Sin(DegreesToRadians(angle));
  1644. double dy = distance * 1000 * Math.Cos(DegreesToRadians(angle));
  1645. double bjd = (dx / A.Ed + A.m_RadLo) * 180 / Math.PI;
  1646. double bwd = (dy / A.Ec + A.m_RadLa) * 180 / Math.PI;
  1647. return new MyLatLng(bjd, bwd);
  1648. }
  1649. public static void ClearRect(this MapControl ctrl)
  1650. {
  1651. var innerDate = ctrl.Tag as InnerData;
  1652. if (innerDate.rangeItem != null)
  1653. innerDate.mMapStorage.Items.Remove(innerDate.rangeItem);
  1654. if (innerDate.dotItem != null)
  1655. innerDate.mMapStorage.Items.Remove(innerDate.dotItem);
  1656. }
  1657. /// <summary>
  1658. /// 获取地图框选的范围信息(可能为null)
  1659. /// </summary>
  1660. /// <param name="ctrl"></param>
  1661. /// <returns></returns>
  1662. public static (double starLon, double startLat, double centerLon, double centerLat,
  1663. double endLon, double endLat, double lonRange, double latRange) GetCurrentRect(this MapControl ctrl)
  1664. {
  1665. var innerData = ctrl.Tag as InnerData;
  1666. return innerData.CurrentRect;
  1667. }
  1668. /// <summary>
  1669. /// 获取地图瓦片图层
  1670. /// </summary>
  1671. /// <param name="ctrl"></param>
  1672. /// <returns></returns>
  1673. public static ImageLayer GetImageLayer(this MapControl ctrl)
  1674. {
  1675. if (ctrl.Layers == null) return null;
  1676. return (ImageLayer)ctrl.Layers["ImageTileLayer"];
  1677. }
  1678. /// <summary>
  1679. /// 获取地图绘制图层
  1680. /// </summary>
  1681. /// <param name="ctrl"></param>
  1682. /// <returns></returns>
  1683. public static VectorItemsLayer GetDrawLayer(this MapControl ctrl)
  1684. {
  1685. return (VectorItemsLayer)ctrl.Layers["DrawLayer"];
  1686. }
  1687. /// <summary>
  1688. /// 获取地图绘制图层
  1689. /// </summary>
  1690. /// <param name="ctrl"></param>
  1691. /// <returns></returns>
  1692. public static VectorItemsLayer GetPosLayer(this MapControl ctrl)
  1693. {
  1694. return (VectorItemsLayer)ctrl.Layers["PosLayer"];
  1695. }
  1696. /// <summary>
  1697. /// 获取地图绘制图层的数据仓库
  1698. /// </summary>
  1699. /// <param name="ctrl"></param>
  1700. /// <returns></returns>
  1701. public static MapItemStorage GetDrawStorage(this MapControl ctrl)
  1702. {
  1703. var innerData = ctrl.Tag as InnerData;
  1704. return innerData.mMapStorage;
  1705. }
  1706. /// <summary>
  1707. /// 设置地图类型.默认为Normal
  1708. /// 该方法为所有MapControl实例设置地图类型
  1709. /// </summary>
  1710. /// <param name="mapType"></param>
  1711. public static void SetMapType(GoogleMapType mapType)
  1712. {
  1713. mMapType = mapType;
  1714. listMapCtrl.ForEach(t =>
  1715. {
  1716. if (t.GetImageLayer() == null) return;
  1717. var provider = t.GetImageLayer().DataProvider as MapTileDataProviderBase;
  1718. provider?.ClearCache();
  1719. t.Refresh();
  1720. });
  1721. }
  1722. #region private
  1723. private static void DrawRect_MouseMove(object sender, MouseEventArgs e)
  1724. {
  1725. var innerData = (sender as MapControl).Tag as InnerData;
  1726. if (!innerData.drawingRect) return;
  1727. innerData.dotItem.Location = innerData.rangeItem.GetCenter();
  1728. var startLon = Math.Round(innerData.rangeItem.Location.GetX(), 3);
  1729. var startLat = Math.Round(innerData.rangeItem.Location.GetY(), 3);
  1730. if (startLon >= 180)
  1731. {
  1732. startLon -= 360;
  1733. }
  1734. if (startLon <= -180)
  1735. {
  1736. startLon += 360;
  1737. }
  1738. var center = innerData.rangeItem.GetCenter();
  1739. var centerLon = Math.Round(center.GetX(), 3);
  1740. if (centerLon >= 180)
  1741. {
  1742. centerLon -= 360;
  1743. }
  1744. if (centerLon <= -180)
  1745. {
  1746. centerLon += 360;
  1747. }
  1748. var centerLat = Math.Round(center.GetY(), 3);
  1749. double endLon;
  1750. if (centerLon < 0 && startLon > 0)
  1751. endLon = startLon + 2 * (centerLon + 360 - startLon);
  1752. else
  1753. endLon = startLon + 2 * (centerLon - startLon);
  1754. var endLat = startLat + 2 * (centerLat - startLat);
  1755. var StartLon = Math.Min(startLon, endLon);
  1756. var StartLat = Math.Min(startLat, endLat);
  1757. var CenterLon = centerLon;
  1758. var CenterLat = centerLat;
  1759. var EndLon = Math.Max(startLon, endLon);
  1760. var EndLat = Math.Max(startLat, endLat);
  1761. double centerLonNew = CenterLon % 360;
  1762. CenterLon = centerLonNew;
  1763. //double LonRange = Math.Round((EndLon - StartLon) / 2, 3);
  1764. //double LatRange = Math.Round((EndLat - StartLat) / 2, 3);
  1765. double LonRange = Math.Round((EndLon - StartLon), 3);
  1766. double LatRange = Math.Round((EndLat - StartLat), 3);
  1767. if (LonRange >= 360)
  1768. {
  1769. }
  1770. innerData.CurrentRect = (StartLon, StartLat, CenterLon, CenterLat, EndLon, EndLat, LonRange, LatRange);
  1771. innerData.mOnRectChanged?.Invoke(innerData.CurrentRect);
  1772. }
  1773. private static void ExportImg_ItemClick(object sender, ItemClickEventArgs e)
  1774. {
  1775. var ctrl = e.Item.Tag as MapControl;
  1776. using (var dialog = new SaveFileDialog())
  1777. {
  1778. dialog.Filter = "PNG图片|*.png";
  1779. dialog.AddExtension = true;
  1780. dialog.FileName = $"Map{DateTime.Now:yyyyMMddHHmmss}.png";
  1781. if (dialog.ShowDialog() == DialogResult.OK)
  1782. {
  1783. ctrl.ExportToImage(dialog.FileName, ImageFormat.Png);
  1784. }
  1785. }
  1786. }
  1787. private static void ExportCsv_ItemClick(object sender, ItemClickEventArgs e)
  1788. {
  1789. var ctrl = e.Item.Tag as MapControl;
  1790. using (var dialog = new SaveFileDialog())
  1791. {
  1792. dialog.Filter = "CSV文件|*.csv";
  1793. dialog.AddExtension = true;
  1794. dialog.FileName = $"Pos{DateTime.Now:yyyyMMddHHmmss}.xlsx";
  1795. if (dialog.ShowDialog() == DialogResult.OK)
  1796. {
  1797. ctrl.ExportToXlsx(dialog.FileName);
  1798. }
  1799. }
  1800. }
  1801. private static void ClearDrawObj(this MapControl ctrl)
  1802. {
  1803. ctrl.Invoke(new Action(() =>
  1804. {
  1805. try
  1806. {
  1807. var innerData = ctrl.Tag as InnerData;
  1808. ctrl.MapEditor.SetTransformMode(MapItemTransform.None);
  1809. innerData.drawingRect = false;
  1810. innerData.CurrentRect = (0, 0, 0, 0, 0, 0, 0, 0);
  1811. innerData.rangeItem = null;
  1812. if (innerData.mMapStorage != null && innerData.mMapStorage.Items.Any())
  1813. {
  1814. innerData.mMapStorage.Items.Clear();
  1815. }
  1816. }
  1817. catch (Exception)
  1818. {
  1819. }
  1820. }));
  1821. }
  1822. private static void DistanceLine_ItemClick(object sender, ItemClickEventArgs e)
  1823. {
  1824. var ctrl = e.Item.Tag as MapControl;
  1825. var innerData = ctrl.Tag as InnerData;
  1826. ctrl.MapEditor.SetEditMode();
  1827. var items = innerData.mMapStorage.Items.ToArray();
  1828. foreach (var item in items)
  1829. {
  1830. if (item.Tag != null && item.Tag.ToString() == "DrawDistanceLine")
  1831. innerData.mMapStorage.Items.Remove(item);
  1832. }
  1833. if (innerData.distinctPath != null)
  1834. {
  1835. innerData.distinctPath.Points.Clear();
  1836. }
  1837. innerData.distinctPath = new MapPolyline()
  1838. {
  1839. Stroke = Color.FromArgb(127, 255, 0, 199),
  1840. StrokeWidth = 2,
  1841. IsGeodesic = true,
  1842. CanResize = false,
  1843. CanEdit = false,
  1844. CanRotate = false,
  1845. IsHitTestVisible = false,
  1846. CanMove = true,
  1847. Tag = "DrawDistanceLine"
  1848. };
  1849. innerData.mMapStorage.Items.Add(innerData.distinctPath);
  1850. innerData.hoverPoint = new MapDot() { CanResize = false, CanMove = false, IsHitTestVisible = false, Tag = "DrawDistanceLine", Size = 8 };
  1851. innerData.hoverPoint.Fill = ColorHelper.GetColor(innerData.hoverPoint.Tag.ToString());
  1852. innerData.mMapStorage.Items.Add(innerData.hoverPoint);
  1853. innerData.hoverTip = CreateHoverTip();
  1854. ctrl.MouseClick += AddDistinctPoint;
  1855. ctrl.MouseMove += MovingDistinct;
  1856. ctrl.MouseLeave += MapControl_MouseLeave;
  1857. ctrl.MouseEnter += MapControl_MouseEnter;
  1858. ctrl.DoubleClick += EndDistinct;
  1859. }
  1860. private static void MarkDot_ItemClick(object sender, ItemClickEventArgs e)
  1861. {
  1862. var ctrl = e.Item.Tag as MapControl;
  1863. ctrl.MapEditor.SetTransformMode(MapItemTransform.None);
  1864. var innerData = ctrl.Tag as InnerData;
  1865. innerData.drawingRect = false;
  1866. using (var frm = new MapEditPointView())
  1867. {
  1868. if (frm.ShowDialog() != DialogResult.OK) return;
  1869. var locPoint = new GeoPoint(frm.Lat, frm.Lon);
  1870. MapCustomElement cusItem = new MapCustomElement()
  1871. {
  1872. Location = locPoint,
  1873. UseAnimation = true,
  1874. CanMove = false,
  1875. EnableHighlighting = DefaultBoolean.True,
  1876. EnableSelection = DefaultBoolean.False,
  1877. Text = "",
  1878. ToolTipPattern = $"{frm.Caption}",
  1879. SvgImage = SvgHelper.CreatePentagram("#F12233", 24, 24),
  1880. TextAlignment = DevExpress.XtraMap.TextAlignment.BottomCenter,
  1881. Tag = "DrawMarkDot"
  1882. };
  1883. innerData.mMapStorage.Items.Add(cusItem);
  1884. }
  1885. }
  1886. private static ToolTipControllerShowEventArgs CreateHoverTip()
  1887. {
  1888. ToolTipTitleItem titleItem1 = new ToolTipTitleItem() { Text = $"0千米" };
  1889. titleItem1.Appearance.ForeColor = SystemColors.GrayText;
  1890. titleItem1.Appearance.Font = new Font(AppearanceObject.DefaultFont.FontFamily, 12, FontStyle.Bold);
  1891. SuperToolTip superToolTip = new SuperToolTip();
  1892. superToolTip.Items.Add(titleItem1);
  1893. ToolTipSeparatorItem sepItem = new ToolTipSeparatorItem();
  1894. superToolTip.Items.Add(sepItem);
  1895. ToolTipItem textItem = new ToolTipItem() { Text = "单击添加测距点,双击结束测距" };
  1896. superToolTip.Items.Add(textItem);
  1897. ToolTipControllerShowEventArgs arg = new ToolTipControllerShowEventArgs();
  1898. arg.ShowBeak = true;
  1899. arg.SuperTip = superToolTip;
  1900. return arg;
  1901. }
  1902. private static void MapControl_MouseEnter(object sender, EventArgs e)
  1903. {
  1904. var innerData = (sender as MapControl).Tag as InnerData;
  1905. innerData.hoverPoint.Visible = true;
  1906. }
  1907. private static void MapControl_MouseLeave(object sender, EventArgs e)
  1908. {
  1909. var innerData = (sender as MapControl).Tag as InnerData;
  1910. innerData.hoverPoint.Visible = false;
  1911. }
  1912. private static void AddDistinctPoint(object sender, MouseEventArgs e)
  1913. {
  1914. var innerData = (sender as MapControl).Tag as InnerData;
  1915. var ctrl = sender as MapControl;
  1916. MapCallout disItem = new MapCallout { IsHitTestVisible = false, CanMove = false };
  1917. disItem.Location = ctrl.ScreenPointToCoordPoint(e.Location);
  1918. disItem.Text = $"{CalcLineKm(innerData):F2}千米";
  1919. disItem.Tag = "DrawDistanceLine";
  1920. innerData.mMapStorage.Items.Add(disItem);
  1921. innerData.distinctPath.Points.Add(innerData.hoverPoint.Location);
  1922. innerData.hoverPoint = new MapDot() { CanResize = false, CanMove = false, IsHitTestVisible = false, Tag = "DrawDistanceLine", Size = 8 };
  1923. innerData.hoverPoint.Location = ctrl.ScreenPointToCoordPoint(e.Location);
  1924. innerData.hoverPoint.Fill = ColorHelper.GetColor(innerData.hoverPoint.Tag.ToString());
  1925. innerData.mMapStorage.Items.Add(innerData.hoverPoint);
  1926. innerData.distinctPath.Points.Add(innerData.hoverPoint.Location);
  1927. }
  1928. private static void MovingDistinct(object sender, MouseEventArgs e)
  1929. {
  1930. var innerData = (sender as MapControl).Tag as InnerData;
  1931. var ctrl = sender as MapControl;
  1932. var itemPoint = ctrl.ScreenPointToCoordPoint(e.Location);
  1933. innerData.hoverPoint.Location = itemPoint;
  1934. if (innerData.distinctPath.Points.Count > 0)
  1935. {
  1936. ctrl.MapEditor.SetEditMode();
  1937. innerData.distinctPath.Points[innerData.distinctPath.Points.Count - 1] = itemPoint;
  1938. (innerData.hoverTip.SuperTip.Items[0] as ToolTipTitleItem).Text = $"{CalcLineKm(innerData):F2}千米";
  1939. innerData.mapToolTip.ShowHint(innerData.hoverTip, ctrl.PointToScreen(e.Location));
  1940. }
  1941. }
  1942. private static double CalcLineKm(InnerData data)
  1943. {
  1944. double result = 0;
  1945. if (data.distinctPath.Points.Count < 2) return result;
  1946. for (int i = 0; i < data.distinctPath.Points.Count - 1; i++)
  1947. {
  1948. var startPoint = data.distinctPath.Points[i] as GeoPoint;
  1949. var endPoint = data.distinctPath.Points[i + 1] as GeoPoint;
  1950. MapSize sizeInKm = new SphericalMercatorProjection().GeoToKilometersSize(startPoint, new MapSize(Math.Abs(startPoint.Longitude - endPoint.Longitude), Math.Abs(startPoint.Latitude - endPoint.Latitude)));
  1951. double partlength = Math.Sqrt(sizeInKm.Width * sizeInKm.Width + sizeInKm.Height * sizeInKm.Height);
  1952. result += partlength;
  1953. }
  1954. return result;
  1955. }
  1956. public static void ClearMap(this MapControl ctrl)
  1957. {
  1958. var innerData = ctrl.Tag as InnerData;
  1959. innerData.CurrentRect = (0, 0, 0, 0, 0, 0, 0, 0);
  1960. innerData.mMapStorage?.Items.Clear();
  1961. }
  1962. private static void EndDistinct(object sender, EventArgs e)
  1963. {
  1964. var ctrl = sender as MapControl;
  1965. var innerData = ctrl.Tag as InnerData;
  1966. innerData.mapToolTip.HideHint();
  1967. ctrl.MouseClick -= AddDistinctPoint;
  1968. ctrl.MouseMove -= MovingDistinct;
  1969. ctrl.DoubleClick -= EndDistinct;
  1970. ctrl.MouseLeave -= MapControl_MouseLeave;
  1971. ctrl.MouseEnter -= MapControl_MouseEnter;
  1972. }
  1973. class MapEditPointView : DevExpress.XtraEditors.XtraForm
  1974. {
  1975. private System.ComponentModel.IContainer components = null;
  1976. private DevExpress.XtraLayout.LayoutControl layoutControl1;
  1977. private DevExpress.XtraLayout.LayoutControlGroup Root;
  1978. private DevExpress.XtraLayout.LayoutControlItem layoutControlItem1;
  1979. private DevExpress.XtraLayout.EmptySpaceItem emptySpaceItem1;
  1980. private DevExpress.XtraLayout.LayoutControlItem layoutControlItem2;
  1981. private DevExpress.XtraEditors.ButtonEdit txtLon;
  1982. private DevExpress.XtraEditors.ButtonEdit txtLat;
  1983. private DevExpress.XtraEditors.TextEdit txtCaption;
  1984. private DevExpress.XtraLayout.LayoutControlItem layoutControlItem5;
  1985. private DevExpress.XtraEditors.SimpleButton btnCancel;
  1986. private DevExpress.XtraEditors.SimpleButton btnOk;
  1987. private DevExpress.XtraLayout.LayoutControlItem layoutControlItem3;
  1988. private DevExpress.XtraLayout.LayoutControlItem layoutControlItem6;
  1989. private DevExpress.XtraEditors.DXErrorProvider.DXErrorProvider dxErrorProvider1;
  1990. private DevExpress.XtraLayout.EmptySpaceItem emptySpaceItem2;
  1991. private void InitializeComponent()
  1992. {
  1993. this.components = new System.ComponentModel.Container();
  1994. DevExpress.XtraEditors.Controls.EditorButtonImageOptions editorButtonImageOptions1 = new DevExpress.XtraEditors.Controls.EditorButtonImageOptions();
  1995. DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject1 = new DevExpress.Utils.SerializableAppearanceObject();
  1996. DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject2 = new DevExpress.Utils.SerializableAppearanceObject();
  1997. DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject3 = new DevExpress.Utils.SerializableAppearanceObject();
  1998. DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject4 = new DevExpress.Utils.SerializableAppearanceObject();
  1999. DevExpress.XtraEditors.Controls.EditorButtonImageOptions editorButtonImageOptions2 = new DevExpress.XtraEditors.Controls.EditorButtonImageOptions();
  2000. DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject5 = new DevExpress.Utils.SerializableAppearanceObject();
  2001. DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject6 = new DevExpress.Utils.SerializableAppearanceObject();
  2002. DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject7 = new DevExpress.Utils.SerializableAppearanceObject();
  2003. DevExpress.Utils.SerializableAppearanceObject serializableAppearanceObject8 = new DevExpress.Utils.SerializableAppearanceObject();
  2004. this.layoutControl1 = new DevExpress.XtraLayout.LayoutControl();
  2005. this.txtCaption = new DevExpress.XtraEditors.TextEdit();
  2006. this.txtLon = new DevExpress.XtraEditors.ButtonEdit();
  2007. this.txtLat = new DevExpress.XtraEditors.ButtonEdit();
  2008. this.Root = new DevExpress.XtraLayout.LayoutControlGroup();
  2009. this.layoutControlItem1 = new DevExpress.XtraLayout.LayoutControlItem();
  2010. this.emptySpaceItem1 = new DevExpress.XtraLayout.EmptySpaceItem();
  2011. this.layoutControlItem2 = new DevExpress.XtraLayout.LayoutControlItem();
  2012. this.layoutControlItem5 = new DevExpress.XtraLayout.LayoutControlItem();
  2013. this.btnOk = new DevExpress.XtraEditors.SimpleButton();
  2014. this.layoutControlItem3 = new DevExpress.XtraLayout.LayoutControlItem();
  2015. this.btnCancel = new DevExpress.XtraEditors.SimpleButton();
  2016. this.layoutControlItem6 = new DevExpress.XtraLayout.LayoutControlItem();
  2017. this.dxErrorProvider1 = new DevExpress.XtraEditors.DXErrorProvider.DXErrorProvider(this.components);
  2018. this.emptySpaceItem2 = new DevExpress.XtraLayout.EmptySpaceItem();
  2019. ((System.ComponentModel.ISupportInitialize)(this.layoutControl1)).BeginInit();
  2020. this.layoutControl1.SuspendLayout();
  2021. ((System.ComponentModel.ISupportInitialize)(this.txtCaption.Properties)).BeginInit();
  2022. ((System.ComponentModel.ISupportInitialize)(this.txtLon.Properties)).BeginInit();
  2023. ((System.ComponentModel.ISupportInitialize)(this.txtLat.Properties)).BeginInit();
  2024. ((System.ComponentModel.ISupportInitialize)(this.Root)).BeginInit();
  2025. ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem1)).BeginInit();
  2026. ((System.ComponentModel.ISupportInitialize)(this.emptySpaceItem1)).BeginInit();
  2027. ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem2)).BeginInit();
  2028. ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem5)).BeginInit();
  2029. ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem3)).BeginInit();
  2030. ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem6)).BeginInit();
  2031. ((System.ComponentModel.ISupportInitialize)(this.dxErrorProvider1)).BeginInit();
  2032. ((System.ComponentModel.ISupportInitialize)(this.emptySpaceItem2)).BeginInit();
  2033. this.SuspendLayout();
  2034. //
  2035. // layoutControl1
  2036. //
  2037. this.layoutControl1.Controls.Add(this.btnCancel);
  2038. this.layoutControl1.Controls.Add(this.btnOk);
  2039. this.layoutControl1.Controls.Add(this.txtCaption);
  2040. this.layoutControl1.Controls.Add(this.txtLon);
  2041. this.layoutControl1.Controls.Add(this.txtLat);
  2042. this.layoutControl1.Dock = System.Windows.Forms.DockStyle.Fill;
  2043. this.layoutControl1.Location = new System.Drawing.Point(0, 0);
  2044. this.layoutControl1.Name = "layoutControl1";
  2045. this.layoutControl1.OptionsCustomizationForm.DesignTimeCustomizationFormPositionAndSize = new System.Drawing.Rectangle(689, 0, 650, 400);
  2046. this.layoutControl1.Root = this.Root;
  2047. this.layoutControl1.Size = new System.Drawing.Size(272, 208);
  2048. this.layoutControl1.TabIndex = 0;
  2049. this.layoutControl1.Text = "layoutControl1";
  2050. //
  2051. // txtCaption
  2052. //
  2053. this.txtCaption.Location = new System.Drawing.Point(12, 29);
  2054. this.txtCaption.Name = "txtCaption";
  2055. this.txtCaption.Properties.Appearance.Options.UseTextOptions = true;
  2056. this.txtCaption.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Near;
  2057. this.txtCaption.Properties.AutoHeight = false;
  2058. this.txtCaption.Properties.MaxLength = 30;
  2059. this.txtCaption.Size = new System.Drawing.Size(248, 22);
  2060. this.txtCaption.StyleController = this.layoutControl1;
  2061. this.txtCaption.TabIndex = 9;
  2062. //
  2063. // txtLon
  2064. //
  2065. this.txtLon.Location = new System.Drawing.Point(12, 80);
  2066. this.txtLon.Name = "txtLon";
  2067. this.txtLon.Properties.Appearance.Options.UseTextOptions = true;
  2068. this.txtLon.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Near;
  2069. this.txtLon.Properties.AutoHeight = false;
  2070. this.txtLon.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] {
  2071. 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)});
  2072. this.txtLon.Size = new System.Drawing.Size(248, 22);
  2073. this.txtLon.StyleController = this.layoutControl1;
  2074. this.txtLon.TabIndex = 4;
  2075. //
  2076. // txtLat
  2077. //
  2078. this.txtLat.Location = new System.Drawing.Point(12, 131);
  2079. this.txtLat.Name = "txtLat";
  2080. this.txtLat.Properties.Appearance.Options.UseTextOptions = true;
  2081. this.txtLat.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Near;
  2082. this.txtLat.Properties.AutoHeight = false;
  2083. this.txtLat.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] {
  2084. 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)});
  2085. this.txtLat.Size = new System.Drawing.Size(248, 22);
  2086. this.txtLat.StyleController = this.layoutControl1;
  2087. this.txtLat.TabIndex = 5;
  2088. //
  2089. // Root
  2090. //
  2091. this.Root.EnableIndentsWithoutBorders = DevExpress.Utils.DefaultBoolean.True;
  2092. this.Root.GroupBordersVisible = false;
  2093. this.Root.Items.AddRange(new DevExpress.XtraLayout.BaseLayoutItem[] {
  2094. this.layoutControlItem1,
  2095. this.emptySpaceItem1,
  2096. this.layoutControlItem5,
  2097. this.layoutControlItem2,
  2098. this.layoutControlItem3,
  2099. this.layoutControlItem6,
  2100. this.emptySpaceItem2});
  2101. this.Root.Name = "Root";
  2102. this.Root.Size = new System.Drawing.Size(272, 208);
  2103. this.Root.TextVisible = false;
  2104. //
  2105. // layoutControlItem1
  2106. //
  2107. this.layoutControlItem1.Control = this.txtLon;
  2108. this.layoutControlItem1.Location = new System.Drawing.Point(0, 43);
  2109. this.layoutControlItem1.MaxSize = new System.Drawing.Size(0, 51);
  2110. this.layoutControlItem1.MinSize = new System.Drawing.Size(54, 51);
  2111. this.layoutControlItem1.Name = "layoutControlItem1";
  2112. this.layoutControlItem1.Padding = new DevExpress.XtraLayout.Utils.Padding(2, 2, 10, 2);
  2113. this.layoutControlItem1.Size = new System.Drawing.Size(252, 51);
  2114. this.layoutControlItem1.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
  2115. this.layoutControlItem1.Text = "经度";
  2116. this.layoutControlItem1.TextLocation = DevExpress.Utils.Locations.Top;
  2117. this.layoutControlItem1.TextSize = new System.Drawing.Size(24, 14);
  2118. //
  2119. // emptySpaceItem1
  2120. //
  2121. this.emptySpaceItem1.AllowHotTrack = false;
  2122. this.emptySpaceItem1.Location = new System.Drawing.Point(0, 162);
  2123. this.emptySpaceItem1.MaxSize = new System.Drawing.Size(0, 26);
  2124. this.emptySpaceItem1.MinSize = new System.Drawing.Size(104, 26);
  2125. this.emptySpaceItem1.Name = "emptySpaceItem1";
  2126. this.emptySpaceItem1.Size = new System.Drawing.Size(113, 26);
  2127. this.emptySpaceItem1.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
  2128. this.emptySpaceItem1.TextSize = new System.Drawing.Size(0, 0);
  2129. //
  2130. // layoutControlItem2
  2131. //
  2132. this.layoutControlItem2.Control = this.txtLat;
  2133. this.layoutControlItem2.Location = new System.Drawing.Point(0, 94);
  2134. this.layoutControlItem2.MaxSize = new System.Drawing.Size(0, 51);
  2135. this.layoutControlItem2.MinSize = new System.Drawing.Size(54, 51);
  2136. this.layoutControlItem2.Name = "layoutControlItem2";
  2137. this.layoutControlItem2.Padding = new DevExpress.XtraLayout.Utils.Padding(2, 2, 10, 2);
  2138. this.layoutControlItem2.Size = new System.Drawing.Size(252, 51);
  2139. this.layoutControlItem2.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
  2140. this.layoutControlItem2.Text = "纬度";
  2141. this.layoutControlItem2.TextLocation = DevExpress.Utils.Locations.Top;
  2142. this.layoutControlItem2.TextSize = new System.Drawing.Size(24, 14);
  2143. //
  2144. // layoutControlItem5
  2145. //
  2146. this.layoutControlItem5.Control = this.txtCaption;
  2147. this.layoutControlItem5.Location = new System.Drawing.Point(0, 0);
  2148. this.layoutControlItem5.MaxSize = new System.Drawing.Size(0, 43);
  2149. this.layoutControlItem5.MinSize = new System.Drawing.Size(54, 43);
  2150. this.layoutControlItem5.Name = "layoutControlItem5";
  2151. this.layoutControlItem5.Size = new System.Drawing.Size(252, 43);
  2152. this.layoutControlItem5.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
  2153. this.layoutControlItem5.Text = "标题";
  2154. this.layoutControlItem5.TextLocation = DevExpress.Utils.Locations.Top;
  2155. this.layoutControlItem5.TextSize = new System.Drawing.Size(24, 14);
  2156. //
  2157. // btnOk
  2158. //
  2159. this.btnOk.Location = new System.Drawing.Point(125, 174);
  2160. this.btnOk.Name = "btnOk";
  2161. this.btnOk.Size = new System.Drawing.Size(65, 22);
  2162. this.btnOk.StyleController = this.layoutControl1;
  2163. this.btnOk.TabIndex = 10;
  2164. this.btnOk.Text = "确定";
  2165. this.btnOk.Click += new System.EventHandler(this.btnOk_Click);
  2166. //
  2167. // layoutControlItem3
  2168. //
  2169. this.layoutControlItem3.Control = this.btnOk;
  2170. this.layoutControlItem3.Location = new System.Drawing.Point(113, 162);
  2171. this.layoutControlItem3.MaxSize = new System.Drawing.Size(69, 26);
  2172. this.layoutControlItem3.MinSize = new System.Drawing.Size(69, 26);
  2173. this.layoutControlItem3.Name = "layoutControlItem3";
  2174. this.layoutControlItem3.Size = new System.Drawing.Size(69, 26);
  2175. this.layoutControlItem3.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
  2176. this.layoutControlItem3.TextSize = new System.Drawing.Size(0, 0);
  2177. this.layoutControlItem3.TextVisible = false;
  2178. //
  2179. // btnCancel
  2180. //
  2181. this.btnCancel.Location = new System.Drawing.Point(194, 174);
  2182. this.btnCancel.Name = "btnCancel";
  2183. this.btnCancel.Size = new System.Drawing.Size(66, 22);
  2184. this.btnCancel.StyleController = this.layoutControl1;
  2185. this.btnCancel.TabIndex = 11;
  2186. this.btnCancel.Text = "取消";
  2187. this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
  2188. //
  2189. // layoutControlItem6
  2190. //
  2191. this.layoutControlItem6.Control = this.btnCancel;
  2192. this.layoutControlItem6.Location = new System.Drawing.Point(182, 162);
  2193. this.layoutControlItem6.MaxSize = new System.Drawing.Size(70, 26);
  2194. this.layoutControlItem6.MinSize = new System.Drawing.Size(70, 26);
  2195. this.layoutControlItem6.Name = "layoutControlItem6";
  2196. this.layoutControlItem6.Size = new System.Drawing.Size(70, 26);
  2197. this.layoutControlItem6.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
  2198. this.layoutControlItem6.TextSize = new System.Drawing.Size(0, 0);
  2199. this.layoutControlItem6.TextVisible = false;
  2200. //
  2201. // dxErrorProvider1
  2202. //
  2203. this.dxErrorProvider1.ContainerControl = this;
  2204. //
  2205. // emptySpaceItem2
  2206. //
  2207. this.emptySpaceItem2.AllowHotTrack = false;
  2208. this.emptySpaceItem2.Location = new System.Drawing.Point(0, 145);
  2209. this.emptySpaceItem2.MinSize = new System.Drawing.Size(104, 1);
  2210. this.emptySpaceItem2.Name = "emptySpaceItem2";
  2211. this.emptySpaceItem2.Size = new System.Drawing.Size(252, 17);
  2212. this.emptySpaceItem2.SizeConstraintsType = DevExpress.XtraLayout.SizeConstraintsType.Custom;
  2213. this.emptySpaceItem2.TextSize = new System.Drawing.Size(0, 0);
  2214. //
  2215. // MapEditPointView
  2216. //
  2217. this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F);
  2218. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
  2219. this.ClientSize = new System.Drawing.Size(272, 208);
  2220. this.Controls.Add(this.layoutControl1);
  2221. this.IconOptions.ShowIcon = false;
  2222. this.MaximizeBox = false;
  2223. this.MinimizeBox = false;
  2224. this.Name = "MapEditPointView";
  2225. this.ShowInTaskbar = false;
  2226. this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
  2227. this.Text = "标点";
  2228. ((System.ComponentModel.ISupportInitialize)(this.layoutControl1)).EndInit();
  2229. this.layoutControl1.ResumeLayout(false);
  2230. ((System.ComponentModel.ISupportInitialize)(this.txtCaption.Properties)).EndInit();
  2231. ((System.ComponentModel.ISupportInitialize)(this.txtLon.Properties)).EndInit();
  2232. ((System.ComponentModel.ISupportInitialize)(this.txtLat.Properties)).EndInit();
  2233. ((System.ComponentModel.ISupportInitialize)(this.Root)).EndInit();
  2234. ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem1)).EndInit();
  2235. ((System.ComponentModel.ISupportInitialize)(this.emptySpaceItem1)).EndInit();
  2236. ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem2)).EndInit();
  2237. ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem5)).EndInit();
  2238. ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem3)).EndInit();
  2239. ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem6)).EndInit();
  2240. ((System.ComponentModel.ISupportInitialize)(this.dxErrorProvider1)).EndInit();
  2241. ((System.ComponentModel.ISupportInitialize)(this.emptySpaceItem2)).EndInit();
  2242. this.ResumeLayout(false);
  2243. }
  2244. protected override void Dispose(bool disposing)
  2245. {
  2246. if (disposing && (components != null))
  2247. {
  2248. components.Dispose();
  2249. }
  2250. base.Dispose(disposing);
  2251. }
  2252. public MapEditPointView()
  2253. {
  2254. InitializeComponent();
  2255. }
  2256. public string Caption
  2257. {
  2258. get
  2259. {
  2260. return txtCaption.Text.Trim();
  2261. }
  2262. set
  2263. {
  2264. txtCaption.Text = value;
  2265. }
  2266. }
  2267. public double Lon
  2268. {
  2269. get
  2270. {
  2271. return double.Parse(txtLon.Text.Trim());
  2272. }
  2273. set
  2274. {
  2275. txtLon.Text = value.ToString();
  2276. }
  2277. }
  2278. public double Lat
  2279. {
  2280. get
  2281. {
  2282. return double.Parse(txtLat.Text.Trim());
  2283. }
  2284. set
  2285. {
  2286. txtLat.Text = value.ToString();
  2287. }
  2288. }
  2289. private void btnOk_Click(object sender, EventArgs e)
  2290. {
  2291. dxErrorProvider1.ClearErrors();
  2292. double lon, lat;
  2293. if (!double.TryParse(txtLon.Text, out lon))
  2294. {
  2295. dxErrorProvider1.SetError(txtLon, "请设置正确的经度");
  2296. return;
  2297. }
  2298. if (!double.TryParse(txtLat.Text, out lat))
  2299. {
  2300. dxErrorProvider1.SetError(txtLat, "请设置正确的纬度");
  2301. return;
  2302. }
  2303. if (lon < -180 || lon > 180)
  2304. {
  2305. dxErrorProvider1.SetError(txtLon, "经度范围[-180,180]");
  2306. return;
  2307. }
  2308. if (lat < -90 || lat > 90)
  2309. {
  2310. dxErrorProvider1.SetError(txtLat, "纬度范围[-90,90]");
  2311. return;
  2312. }
  2313. this.DialogResult = DialogResult.OK;
  2314. }
  2315. private void btnCancel_Click(object sender, EventArgs e)
  2316. {
  2317. this.DialogResult = DialogResult.Cancel;
  2318. }
  2319. }
  2320. #endregion
  2321. #region 半径圆
  2322. public class MyLatLng
  2323. {
  2324. public double Rc = 6378137; //赤道半径
  2325. public double Rj = 6356725; //极半径
  2326. public double m_LoDeg, m_LoMin, m_LoSec;
  2327. public double m_LaDeg, m_LaMin, m_LaSec;
  2328. public double m_Longitude, m_Latitude;
  2329. public double m_RadLo, m_RadLa;
  2330. public double Ec;
  2331. public double Ed;
  2332. public MyLatLng(double longitude, double latitude)
  2333. {
  2334. m_LoDeg = (int)longitude;
  2335. m_LoMin = (int)((longitude - m_LoDeg) * 60);
  2336. m_LoSec = (longitude - m_LoDeg - m_LoMin / 60) * 3600;
  2337. m_LaDeg = (int)latitude;
  2338. m_LaMin = (int)((latitude - m_LaDeg) * 60);
  2339. m_LaSec = (latitude - m_LaDeg - m_LaMin / 60) * 3600;
  2340. m_Longitude = longitude;
  2341. m_Latitude = latitude;
  2342. m_RadLo = longitude * Math.PI / 180;
  2343. m_RadLa = latitude * Math.PI / 180;
  2344. Ec = Rj + (Rc - Rj) * (90 - m_Latitude) / 90;
  2345. Ed = Ec * Math.Cos(m_RadLa);
  2346. }
  2347. }
  2348. #endregion
  2349. #region ImageLayer数据源接口实现(本地和Http接口)
  2350. class ImageTileSource : IImageTileSource
  2351. {
  2352. SQLiteConnection con;
  2353. public ImageTileSource()
  2354. {
  2355. var files = Directory.GetFiles(Application.StartupPath, "Data.gmdb", SearchOption.AllDirectories);
  2356. if (files.Length > 0)
  2357. {
  2358. try
  2359. {
  2360. conStr = string.Format(conStr, files[0]);
  2361. con = new SQLiteConnection(conStr);
  2362. con.Open();
  2363. }
  2364. catch
  2365. {
  2366. conStr = null;
  2367. Console.WriteLine("Data.gmdb文件读取出错!");
  2368. }
  2369. }
  2370. else
  2371. {
  2372. conStr = null;
  2373. }
  2374. }
  2375. public string Name => "GMap地图瓦片";
  2376. public bool CanDisposeSourceImage => true;
  2377. public Image GetImage(int x, int y, int level, Size size)
  2378. {
  2379. var data = QueryTile(x, y, level, 0);
  2380. if (data == null) return null;
  2381. return Image.FromStream(new MemoryStream(data));
  2382. }
  2383. 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})";
  2384. string conStr = "Data Source=\"{0}\";Page Size=32768";
  2385. byte[] QueryTile(int x, int y, int zoom, int type)
  2386. {
  2387. if (conStr == null) return null;
  2388. type = (int)mMapType;
  2389. if (type == 0) type = 1818940751;
  2390. using (DbCommand com = con.CreateCommand())
  2391. {
  2392. com.CommandText = string.Format(QuerySql, x, y, zoom, type);
  2393. using (DbDataReader rd = com.ExecuteReader(System.Data.CommandBehavior.SequentialAccess))
  2394. {
  2395. if (rd.Read())
  2396. {
  2397. long length = rd.GetBytes(0, 0, null, 0, 0);
  2398. byte[] tile = new byte[length];
  2399. rd.GetBytes(0, 0, tile, 0, tile.Length);
  2400. return tile;
  2401. }
  2402. }
  2403. }
  2404. return null;
  2405. }
  2406. }
  2407. class HttpMapDataProvider : MapDataProviderBase
  2408. {
  2409. public HttpMapDataProvider()
  2410. {
  2411. TileSource = new HttpTileSource(this);
  2412. }
  2413. public override MapSize GetMapSizeInPixels(double zoomLevel)
  2414. {
  2415. double imageSize;
  2416. imageSize = HttpTileSource.CalculateTotalImageSize(zoomLevel);
  2417. return new MapSize(imageSize, imageSize);
  2418. }
  2419. protected override Size BaseSizeInPixels
  2420. {
  2421. get { return new Size(Convert.ToInt32(HttpTileSource.tileSize * 2), Convert.ToInt32(HttpTileSource.tileSize * 2)); }
  2422. }
  2423. }
  2424. class HttpTileSource : MapTileSourceBase
  2425. {
  2426. public const int tileSize = 256;
  2427. public const int maxZoomLevel = 14;
  2428. public string HttpServerAddr { get; set; }
  2429. public EnumWmtsSource WmtsSource { get; set; }
  2430. public EnumMapLayerType LayerType { get; set; }
  2431. public GoogleMapType MapType { get; set; } = GoogleMapType.Normal;
  2432. internal static double CalculateTotalImageSize(double zoomLevel)
  2433. {
  2434. if (zoomLevel < 1.0)
  2435. return zoomLevel * tileSize * 2;
  2436. return Math.Pow(2.0, zoomLevel) * tileSize;
  2437. }
  2438. public HttpTileSource(ICacheOptionsProvider cacheOptionsProvider) :
  2439. base((int)CalculateTotalImageSize(maxZoomLevel), (int)CalculateTotalImageSize(maxZoomLevel), tileSize, tileSize, cacheOptionsProvider)
  2440. {
  2441. }
  2442. public override Uri GetTileByZoomLevel(int zoomLevel, int tilePositionX, int tilePositionY)
  2443. {
  2444. if (string.IsNullOrWhiteSpace(HttpServerAddr)) return null;
  2445. try
  2446. {
  2447. if (zoomLevel <= maxZoomLevel)
  2448. {
  2449. string imgUrl = string.Empty;
  2450. // imgUrl = $"{HttpServerAddr}/{(int)MapType}/{zoomLevel}/{tilePositionX}/{tilePositionY}";
  2451. string layerName;
  2452. if (WmtsSource == EnumWmtsSource.SJZX)
  2453. {
  2454. if (LayerType == EnumMapLayerType.SatMap)
  2455. layerName = "satellite";
  2456. else
  2457. layerName = "electron";
  2458. imgUrl = $"{HttpServerAddr}?lyr={layerName}&x={tilePositionX}&y={tilePositionY}&z={zoomLevel}";
  2459. }
  2460. else
  2461. {
  2462. if (LayerType == EnumMapLayerType.SatMap)
  2463. layerName = "NaturalEarthII";
  2464. else if (LayerType == EnumMapLayerType.RoadMap)
  2465. layerName = "roadmap-final";
  2466. else
  2467. layerName = "overlay-final";
  2468. imgUrl = $"{HttpServerAddr}/{layerName}/{zoomLevel}/{tilePositionX}/{tilePositionY}.jpg";
  2469. }
  2470. if (AppConst.Debug)
  2471. {
  2472. Serilog.Log.Information(imgUrl);
  2473. }
  2474. //string imgUrl = string.Format("http://192.168.0.214:58089/{0}/{1}/{2}/{3}", (int)GoogleMapType.Normal, zoomLevel, tilePositionX, tilePositionY);
  2475. Uri u = new Uri(imgUrl);
  2476. return u;
  2477. }
  2478. return null;
  2479. }
  2480. catch
  2481. {
  2482. Console.WriteLine($"加载地图数据出错,无法连接到{HttpServerAddr}");
  2483. return null;
  2484. }
  2485. }
  2486. }
  2487. #endregion
  2488. //定位点聚合器
  2489. class PosClusterer : IClusterer
  2490. {
  2491. private MapControl ctrl;
  2492. private IMapDataAdapter owner;
  2493. private MapViewport preViewPoint;
  2494. private DebounceDispatcher dispatcher = new DebounceDispatcher();
  2495. public bool IsBusy { get; private set; }
  2496. public MapItemCollection Items { get; private set; }
  2497. public PosClusterer(MapControl ctrl)
  2498. {
  2499. this.ctrl = ctrl;
  2500. }
  2501. public void SetOwner(IMapDataAdapter owner)
  2502. {
  2503. this.owner = owner;
  2504. Items = new MapItemCollection(owner);
  2505. }
  2506. public void Clusterize(IEnumerable<MapItem> sourceItems, MapViewport viewport, bool sourceChanged)
  2507. {
  2508. IsBusy = true;
  2509. if (sourceChanged)
  2510. DoClusterize(sourceItems, viewport, sourceChanged);
  2511. else
  2512. dispatcher.Debounce(100, () => DoClusterize(sourceItems, viewport, sourceChanged));
  2513. }
  2514. private void DoClusterize(IEnumerable<MapItem> sourceItems, MapViewport viewport, bool sourceChanged)
  2515. {
  2516. if (preViewPoint == null)
  2517. {
  2518. preViewPoint = viewport;
  2519. return;
  2520. }
  2521. if (!sourceChanged && preViewPoint.ZoomLevel == viewport.ZoomLevel)//地图移动或者MapControl大小发生了改变时直接操作Items避免闪烁
  2522. {
  2523. preViewPoint = viewport;
  2524. }
  2525. else//地图进行了缩放
  2526. {
  2527. Items.Clear();
  2528. var cache = new Dictionary<int, List<MapItem>>();
  2529. foreach (MapDot item in sourceItems)
  2530. {
  2531. var point = ctrl.CoordPointToScreenPoint(item.Location);
  2532. int pointX = (int)point.X;
  2533. int pointY = (int)point.Y;
  2534. bool visible = true;
  2535. if (pointX <= _dotSize || pointX > ctrl.Width - _dotSize)
  2536. visible = false;
  2537. else if (pointY <= _dotSize || pointY > ctrl.Height - _dotSize)
  2538. visible = false;
  2539. pointX /= (_dotSize * 2);
  2540. pointY /= (_dotSize * 2);
  2541. var key = pointX << 16 | pointY;
  2542. if (!visible)
  2543. key = -key;
  2544. if (!cache.ContainsKey(key))
  2545. cache.Add(key, new List<MapItem>());
  2546. cache[key].Add(item);
  2547. }
  2548. var innerData = ctrl.Tag as InnerData;
  2549. innerData._clusterCache.Clear();
  2550. LinkedList<MapItem> temp = new LinkedList<MapItem>();
  2551. foreach (var kv in cache)
  2552. {
  2553. var firstDot = kv.Value[0] as MapDot;
  2554. var firstObj = firstDot.Tag as PosData;
  2555. firstDot.Size = kv.Value.Count > 1 ? _dotSize + 2 : _dotSize;
  2556. firstObj.ClusterCount = kv.Value.Count;
  2557. firstObj.ClusterKey = kv.Key;
  2558. innerData._clusterCache.Add(kv.Key, firstDot);
  2559. temp.AddLast(firstDot);
  2560. }
  2561. Items.AddRange(temp);
  2562. cache.Clear();
  2563. preViewPoint = viewport;
  2564. owner.OnClustered();
  2565. }
  2566. this.IsBusy = false;
  2567. }
  2568. //计算多个坐标的中心位置
  2569. public GeoPoint GetCenterPointFromListOfCoordinates(List<MapItem> geoCoordinateList)
  2570. {
  2571. int total = geoCoordinateList.Count;
  2572. double lat = 0, lon = 0;
  2573. foreach (MapDot g in geoCoordinateList)
  2574. {
  2575. lat += (g.Location as GeoPoint).Latitude * Math.PI / 180;
  2576. lon += (g.Location as GeoPoint).Longitude * Math.PI / 180;
  2577. }
  2578. lat /= total;
  2579. lon /= total;
  2580. return new GeoPoint(lat * 180 / Math.PI, lon * 180 / Math.PI);
  2581. }
  2582. }
  2583. }