Windows desktop map tool software sharing based on GMap.NET library

0 Preface

Because the work is often related to maps, GPS coordinate conversion, GPS track viewing, etc., I often need to use some online websites and tools to view maps and locations. I learned a GMap.NET open source desktop map library and a MapDownloader map download tool based on GMap.NET by chance. So I also want to implement a map-related tool of my own, including the following functions :

  • Multiple map switching: Baidu (Baidu), Amap (AutoNavi), Tencent (Tencent), Tianditu (Tianditu), Ship, Google, Bing, OpenStreetMap, ArcGIS, Here (Nokia), etc.;
  • Coordinate picking and coordinate conversion: mutual conversion between GPS (WGS84), Mars coordinates (GCJ02), Baidu coordinates (BD09), geocoding and reverse geocoding, etc.;
  • POI query: search and save POI data through WebAPI such as Baidu Map, Gaode Map, and Tencent Map;
  • Map download and splicing: download and cache map data or splice into large maps through rectangles, polygons, administrative divisions, etc.;
  • Navigation route search and export: search and save navigation route data through WebAPI such as Baidu Map, Gaode Map, and Tencent Map;
  • Historical trajectory loading and playback: load trajectory data in different formats (csv/excel/nmea), and can playback, test, etc.;
  • Real-time trajectory display: Receive GPS information through the serial port and display it on the map;

Project address: https://github.com/luotengyuan/MyMapTools , https://gitee.com/luotengyuan/MyMapTools
program download: https://download.csdn.net/download/loutengyuan/86507941

catch_2022-12-26_17-16-41

Disclaimer: This software is only for personal study and scientific research. The copyright of the downloaded data belongs to each map service provider. The software author is not responsible for any problems caused by improper use of data by any organization or individual.

PS: Please replace your own API Key!

1 Function Introduction

1.1 Various online map switching

  • You can switch between different map providers (for example: Baidu, Gaode) or different map types (for example: ordinary maps, satellite maps, hybrid maps) according to your needs

GIF_2022-12-26_17-26-08

1.2 Latitude and longitude coordinate display

  • According to different types of latitude and longitude coordinates, the coordinates can be marked on the map for display
    GIF_2022-12-26_17-30-22

1.3 Coordinate picking function

  • Right-click on the specified point on the map, select the menu to pick the coordinates and address of the point, and you can view the coordinates and address of the point under the Coordinates and Coordinates Picking tab
    GIF_2022-12-26_18-07-41
  • Points on the map can also be queried based on coordinates and addresses
    GIF_2022-12-26_18-35-43

1.4 POI query function

  • Query POIs based on keywords, and display them on the map, and export the search results to an Excel file
    GIF_2022-12-26_17-36-04

1.5 Map download stitching

  • You can download the map of the specified area according to the drawn rectangle and polygon, and you can download the map according to the administrative division
    GIF_2022-12-26_17-38-08
    GIF_2022-12-26_17-40-41

1.6 Navigation route planning

  • Right-click on the map to select the starting point, passing point, and end point of the navigation, and click Plan Route to generate a navigation route
    GIF_2022-12-26_17-43-01
  • Navigation routes can be exported as track points
    GIF_2022-12-26_17-44-45
  • You can also export the track as a file
    GIF_2022-12-26_17-47-25
  • The file format is as follows
    insert image description here

1.7 Historical Track Loading and Playback

  • The historical track can be displayed on the map by loading csv, excel, nmea and other files
    GIF_2022-12-26_17-55-33
  • You can set the historical track as a simulated track, simulate historical data, and send the simulated information to other processes through Pipe as input for simulated GPS testing
    GIF_2022-12-26_17-58-03

1.8 Serial port receiving real-time trajectory

  • Real-time positioning information can be received according to the NMEA or other specified formats received by the serial port, and displayed on the map

GIF_2022-12-26_18-05-19

2 code implementation

2.1 GMap.NET library use

GMap.NET is a powerful, free, cross-platform, open source .NET control, which uses Google, Yahoo!, Bing, OpenStreetMap, ArcGIS, Pergo, SigPac and other route planning, geocoding and map display functions in Windows Forms and WPF environments. The following describes from downloading and installation to how to use GMap.NET.

2.1.1 Download and install

Download it from here and unzip it to get two files (GMap.NET.Core.dll and GMap.NET.WindowsForms.dll). Then add a reference to the project.
insert image description here
Add GMapControl to toolbox. In "Select Item", select the "GMap.NET.WindowsForms.dll" file to add it.
insert image description here
Install using NUGET
insert image description here

2.1.2 Add map control

Drag GMapControl to Windows Form, you can see a small cross in the center of the control. View properties, you will find some unique properties of GMap.NET. By setting these properties you can configure the behavior of the map, but not its content.
insert image description here

  • Bearing - rotates the map to the left by the specified degree
  • CanDragMap – Whether to enable right-click dragging (panning) of the map
  • EmptyTileColor – Sets the color displayed for tiles with no data
  • MarkersEnabled – Whether to display defined markers, same as PolygonsEnabled and RoutesEnabled
  • ShowTileGridLines – show gridlines
  • Zoom, MinZoom and MaxZoom - zoom levels

GMap.NET supports a variety of map sources, and defining the map source needs to be set in the code. You can add the following code in the Load event of GMapControl:

this.gMapControl1.MapProvider = OpenStreet4UMapProvider.Instance; // 设置地图源
GMaps.Instance.Mode = AccessMode.ServerAndCache; // GMap工作模式
this.gMapControl1.SetPositionByKeywords("北京"); // 地图中心位置

//使用经纬度设置地图中心
//this.gMapControl1.Position = new GMap.NET.PointLatLng(39.923518, 116.539009);

① MapProvider: Set the map source, enter GMapProviders to see all map sources supported by GMap.
insert image description here
② GMaps.Instance.Mode: GMap can obtain data from the server, local cache, server or local cache. This applies to all GMap control instances created in the application, the value only needs to be set once.
insert image description here
③ You can use keywords or latitude and longitude to set the center position of the map.
④ The map shows the result. Press and hold the right mouse button to drag the map, of course, you can also set other keys to drag.

this.gMapControl1.DragButton = MouseButtons.Left;

insert image description here

2.1.3 Adding tags

//创建一个名为“markers”的图层
GMapOverlay markers = new GMapOverlay("markers");
//创建标记,并设置位置及样式
GMapMarker marker = new GMarkerGoogle(new PointLatLng(39.923518, 116.539009), GMarkerGoogleType.blue_pushpin);
//将标记添加到图层
markers.Markers.Add(marker);
//将图层添加到地图
this.gMapControl1.Overlays.Add(markers);

① GMapOverlay: layer. Added marks, graphics, paths, etc. are all operated on layers.
② GMapMarker: GMarkerGoogle, which provides marker position (PointLatLng) and marker style. It has two overloads to use GMarkerGoogleType and Bitmap. GMap.NET also provides GMarkerCross, which is a simple cross that does not allow icons.

public GMarkerGoogle(PointLatLng p, GMarkerGoogleType type);
public GMarkerGoogle(PointLatLng p, Bitmap Bitmap);

GMapMarker can also set ToolTip.

marker.ToolTipText = "我在这里";
marker.ToolTip.Fill = new SolidBrush(Color.FromArgb(100, Color.Black));
marker.ToolTip.Foreground = Brushes.White;
marker.ToolTip.TextPadding = new Size(20, 20);

③ The map displays the result. (Find out that the small cross in the center is gone, because this can be set)
insert image description here

this.gMapControl1.ShowCenter = false; //隐藏中心十字

④ Marker click event
The marker itself does not have any event hook, and the OnMarkerClick event of GMapControl is the marker click event. In the example below, clicking on the marker will pop up a prompt box displaying the text content of the ToolTip. Of course, GMap.NET not only has click events, but also OnMarkerEnter and OnMarkerLeave.

private void gMapControl1_OnMarkerClick(GMapMarker item, MouseEventArgs e)
{
    
    
    MessageBox.Show(String.Format("Marker:{0} 被点了。", item.ToolTipText));
}

2.1.4 Adding polygons

The principle of adding polygons is the same as adding markers.

GMapOverlay polygons = new GMapOverlay("polygons");
// 多边形的顶点
List<PointLatLng> points = new List<PointLatLng>();
points.Add(new PointLatLng(39.92244, 116.3922));
points.Add(new PointLatLng(39.92280, 116.4015));
points.Add(new PointLatLng(39.91378, 116.4019));
points.Add(new PointLatLng(39.91346, 116.3926));
GMapPolygon polygon = new GMapPolygon(points, "故宫");
polygon.Fill = new SolidBrush(Color.FromArgb(50, Color.Red));
polygon.Stroke = new Pen(Color.Red, 1);
polygons.Polygons.Add(polygon);
this.gMapControl1.Overlays.Add(polygons);

Show results.
insert image description here

Copyright statement: The above content refers to the original article of huangli0, and follows the CC 4.0 BY-SA copyright agreement. For reprinting, please attach the original source link and this statement.
Link: https://blog.csdn.net/huangli0/article/details/80147243

2.2 Coordinate transformation

Coordinate transformation consists of CoordType.cs、PointLatLng.cs、CoordinateTransform.cs、PointInDiffCoord.csfour classes, their functions and codes are as follows:

CoordType.cs: Coordinate type definition
PointLatLng.cs: Longitude and latitude encapsulation class
CoordinateTransform.cs: Different coordinate transformation tool class
PointInDiffCoord.cs: Different coordinate transformation encapsulation class

  • The code of CoordType.cs is as follows:
using System;
using System.Collections.Generic;
using System.Text;

namespace GMap.NET
{
    
    
    /// <summary>
    /// 坐标系类型
    /// </summary>
    public enum CoordType
    {
    
    
        WGS84,
        GCJ02,
        BD09,
        UNKNOW
    }
}
  • PointLatLng.cs code is as follows:
namespace GMap.NET
{
    
    
   using System;
   using System.Globalization;

   /// <summary>
   /// the point of coordinates
   /// </summary>
   [Serializable]
   public struct PointLatLng
   {
    
    
      public static readonly PointLatLng Empty = new PointLatLng();
      private double lat;
      private double lng;
      private CoordType type;


      bool NotEmpty;

      public PointLatLng(double lat, double lng)
      {
    
    
         this.lat = lat;
         this.lng = lng;
         this.type = CoordType.UNKNOW;
         NotEmpty = true;
      }

      public PointLatLng(double lat, double lng, CoordType type) : this(lat, lng)
      {
    
    
          this.type = type;
      }

      /// <summary>
      /// returns true if coordinates wasn't assigned
      /// </summary>
      public bool IsEmpty
      {
    
    
         get
         {
    
    
            return !NotEmpty;
         }
      }

      public double Lat
      {
    
    
         get
         {
    
    
            return this.lat;
         }
         set
         {
    
    
            this.lat = value;
            NotEmpty = true;
         }
      }

      public double Lng
      {
    
    
         get
         {
    
    
            return this.lng;
         }
         set
         {
    
    
            this.lng = value;
            NotEmpty = true;
         }
      }

      public CoordType Type
      {
    
    
          get
          {
    
    
              return this.type;
          }
          set
          {
    
    
              this.type = value;
          }
      }

      public static PointLatLng operator +(PointLatLng pt, SizeLatLng sz)
      {
    
    
         return Add(pt, sz);
      }

      public static PointLatLng operator -(PointLatLng pt, SizeLatLng sz)
      {
    
    
         return Subtract(pt, sz);
      }

      public static SizeLatLng operator -(PointLatLng pt1, PointLatLng pt2)
      {
    
    
          return new SizeLatLng(pt1.Lat - pt2.Lat, pt2.Lng - pt1.Lng);
      }

      public static bool operator ==(PointLatLng left, PointLatLng right)
      {
    
    
         return ((left.Lng == right.Lng) && (left.Lat == right.Lat));
      }

      public static bool operator !=(PointLatLng left, PointLatLng right)
      {
    
    
         return !(left == right);
      }

      public static PointLatLng Add(PointLatLng pt, SizeLatLng sz)
      {
    
    
         return new PointLatLng(pt.Lat - sz.HeightLat, pt.Lng + sz.WidthLng);
      }

      public static PointLatLng Subtract(PointLatLng pt, SizeLatLng sz)
      {
    
    
         return new PointLatLng(pt.Lat + sz.HeightLat, pt.Lng - sz.WidthLng);
      }

      public override bool Equals(object obj)
      {
    
    
         if(!(obj is PointLatLng))
         {
    
    
            return false;
         }
         PointLatLng tf = (PointLatLng)obj;
         return (((tf.Lng == this.Lng) && (tf.Lat == this.Lat)) && tf.GetType().Equals(base.GetType()));
      }

      public void Offset(PointLatLng pos)
      {
    
    
         this.Offset(pos.Lat, pos.Lng);
      }

      public void Offset(double lat, double lng)
      {
    
    
         this.Lng += lng;
         this.Lat -= lat;
      }

      public override int GetHashCode()
      {
    
    
         return (this.Lng.GetHashCode() ^ this.Lat.GetHashCode());
      }

      public override string ToString()
      {
    
    
         return string.Format(CultureInfo.CurrentCulture, "{
    
    {Lat={0}, Lng={1}}}", this.Lat, this.Lng);
      }
   }
}

CoordinateTransform.cs code is as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GMap.NET
{
    
    
    /// <summary>
    /// 各坐标系统转换 
    /// WGS84坐标系:即地球坐标系,国际上通用的坐标系。设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系, 
    /// 谷歌地图采用的是WGS84地理坐标系(中国范围除外); 
    /// GCJ02坐标系:即火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。 
    /// 高德地图、腾讯地图、谷歌中国地图采用的是GCJ02地理坐标系; 
    /// BD09坐标系:即百度坐标系,GCJ02坐标系经加密后的坐标系; 
    /// 搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。
    /// </summary>
    public static class CoordinateTransform
    {
    
    
        /// <summary>
        /// 检查坐标是否在中国范围内
        /// </summary>
        /// <param name="lat">latitude 纬度</param>
        /// <param name="lng">longitude 经度</param>
        /// <returns></returns>
        private static bool OutOfChina(double lat, double lng)
        {
    
    
            if (lng < 72.004 || lng > 137.8347)
                return true;
            if (lat < 0.8293 || lat > 55.8271)
                return true;
            return false;
        }

        /// <summary>
        /// 火星坐标(GCJ02)转换为WGS坐标
        /// </summary>
        /// <param name="lngMars">火星坐标经度longitude</param>
        /// <param name="latMars">火星坐标纬度latitude</param>
        /// <param name="lngWgs">WGS经度</param>
        /// <param name="latWgs">WGS纬度</param>
        public static void ConvertGcj02ToWgs84(double lngMars, double latMars, out double lngWgs, out double latWgs)
        {
    
    
            lngWgs = lngMars;
            latWgs = latMars;
            double lngtry = lngMars;
            double lattry = latMars;
            ConvertWgs84ToGcj02(lngMars, latMars, out lngtry, out lattry);
            double dx = lngtry - lngMars;
            double dy = lattry - latMars;

            lngWgs = lngMars - dx;
            latWgs = latMars - dy;
        }

        /// <summary>
        /// WGS坐标转换为火星坐标(GCJ02)
        /// </summary>
        /// <param name="lngWgs">WGS经度</param>
        /// <param name="latWgs">WGS纬度</param>
        /// <param name="lngMars">火星坐标经度</param>
        /// <param name="latMars">火星坐标纬度</param>
        public static void ConvertWgs84ToGcj02(double lngWgs, double latWgs, out double lngMars, out double latMars)
        {
    
    
            lngMars = lngWgs;
            latMars = latWgs;

            const double pi = 3.14159265358979324;

            //
            // Krasovsky 1940
            //
            // a = 6378245.0, 1/f = 298.3
            // b = a * (1 - f)
            // ee = (a^2 - b^2) / a^2;
            const double a = 6378245.0;
            const double ee = 0.00669342162296594323;

            if (lngWgs < 72.004 || lngWgs > 137.8347)
                return;
            if (latWgs < 0.8293 || latWgs > 55.8271)
                return;

            double x = 0, y = 0;
            x = lngWgs - 105.0;
            y = latWgs - 35.0;

            double dLon = 300.0 + 1.0 * x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.Sqrt(Math.Abs(x));
            dLon += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0;
            dLon += (20.0 * Math.Sin(x * pi) + 40.0 * Math.Sin(x / 3.0 * pi)) * 2.0 / 3.0;
            dLon += (150.0 * Math.Sin(x / 12.0 * pi) + 300.0 * Math.Sin(x / 30.0 * pi)) * 2.0 / 3.0;

            double dLat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.Sqrt(Math.Abs(x));
            dLat += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0;
            dLat += (20.0 * Math.Sin(y * pi) + 40.0 * Math.Sin(y / 3.0 * pi)) * 2.0 / 3.0;
            dLat += (160.0 * Math.Sin(y / 12.0 * pi) + 320.0 * Math.Sin(y * pi / 30.0)) * 2.0 / 3.0;

            double radLat = latWgs / 180.0 * pi;
            double magic = Math.Sin(radLat);
            magic = 1 - ee * magic * magic;
            double sqrtMagic = Math.Sqrt(magic);
            dLon = (dLon * 180.0) / (a / sqrtMagic * Math.Cos(radLat) * pi);
            dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
            lngMars = lngWgs + dLon;
            latMars = latWgs + dLat;
        }

        /// <summary>
        /// 火星坐标(GCJ02)转换为baidu坐标
        /// </summary>
        /// <param name="lngMars"></param>
        /// <param name="latMars"></param>
        /// <param name="lngBaidu"></param>
        /// <param name="latBaidu"></param>
        public static void ConvertGcj02ToBd09(double lngMars, double latMars, out double lngBaidu, out double latBaidu)
        {
    
    
            const double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
            //const double x_pi = 3.14159265358979324;
            double x = lngMars;
            double y = latMars;
            double z = Math.Sqrt(x * x + y * y) + 0.00002 * Math.Sin(y * x_pi);
            double theta = Math.Atan2(y, x) + 0.000003 * Math.Cos(x * x_pi);
            lngBaidu = z * Math.Cos(theta) + 0.0065;
            latBaidu = z * Math.Sin(theta) + 0.006;
        }

        /// <summary>
        /// baidu坐标转换为火星坐标(GCJ02)
        /// </summary>
        /// <param name="lngBaidu"></param>
        /// <param name="latBaidu"></param>
        /// <param name="lngMars"></param>
        /// <param name="latMars"></param>
        public static void ConvertBd09ToGcj02(double lngBaidu, double latBaidu, out double lngMars, out double latMars)
        {
    
    
            const double x_pi = 3.14159265358979324 * 3000.0 / 180.0;

            double x = lngBaidu - 0.0065;
            double y = latBaidu - 0.006;
            double z = Math.Sqrt(x * x + y * y) - 0.00002 * Math.Sin(y * x_pi);
            double theta = Math.Atan2(y, x) - 0.000003 * Math.Cos(x * x_pi);
            lngMars = z * Math.Cos(theta);
            latMars = z * Math.Sin(theta);
        }

        /// <summary>
        /// WGS坐标转换为baidu坐标
        /// </summary>
        /// <param name="lngWgs"></param>
        /// <param name="latWgs"></param>
        /// <param name="lngBaidu"></param>
        /// <param name="latBaidu"></param>
        public static void ConvertWgs84ToBd09(double lngWgs, double latWgs, out double lngBaidu, out double latBaidu)
        {
    
    
            double lng;
            double lat;
            ConvertWgs84ToGcj02(lngWgs, latWgs, out lng, out lat);
            ConvertGcj02ToBd09(lng, lat, out lngBaidu, out latBaidu);
        }

        /// <summary>
        /// baidu坐标转换为WGS坐标
        /// </summary>
        /// <param name="lngBaidu"></param>
        /// <param name="latBaidu"></param>
        /// <param name="lngWgs"></param>
        /// <param name="latWgs"></param>
        public static void ConvertBd09ToWgs84(double lngBaidu, double latBaidu,out double lngWgs, out double latWgs)
        {
    
    
            double lng;
            double lat;
            ConvertBd09ToGcj02(lngBaidu, latBaidu, out lng, out lat);
            ConvertGcj02ToWgs84(lng, lat, out lngWgs, out latWgs);
        }
    }
}

PointInDiffCoord.cs code is as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GMap.NET;
using GMapPositionFix;

namespace GMapCommonType
{
    
    
    public class PointInDiffCoord
    {
    
    
        private PointLatLng wgs84; 
        public PointLatLng WGS84
        {
    
    
            get
            {
    
    
                double lon, lat;
                if (CoordType == CoordType.WGS84)
                {
    
    
                    return wgs84;
                }
                else if (CoordType == CoordType.GCJ02)
                {
    
    
                    if (wgs84 == PointLatLng.Empty)
                    {
    
    
                        CoordinateTransform.ConvertGcj02ToWgs84(gcj02.Lng, gcj02.Lat, out lon, out lat);
                        wgs84.Lat = lat;
                        wgs84.Lng = lon;
                    }
                    return wgs84;
                }
                else if (CoordType == CoordType.BD09)
                {
    
    
                    if (wgs84 == PointLatLng.Empty)
                    {
    
    
                        CoordinateTransform.ConvertBd09ToWgs84(bd09.Lng, bd09.Lat, out lon, out lat);
                        wgs84.Lat = lat;
                        wgs84.Lng = lon;
                    }
                    return wgs84;
                }
                else
                {
    
    
                    return PointLatLng.Empty;
                }
            }
        }
        private PointLatLng gcj02;
        public PointLatLng GCJ02
        {
    
    
            get
            {
    
    
                double lon, lat;
                if (CoordType == CoordType.WGS84)
                {
    
    
                    if (gcj02 == PointLatLng.Empty)
                    {
    
    
                        CoordinateTransform.ConvertWgs84ToGcj02(wgs84.Lng, wgs84.Lat, out lon, out lat);
                        gcj02.Lat = lat;
                        gcj02.Lng = lon;
                    }
                    return gcj02;
                }
                else if (CoordType == CoordType.GCJ02)
                {
    
    
                    return gcj02;
                }
                else if (CoordType == CoordType.BD09)
                {
    
    
                    if (gcj02 == PointLatLng.Empty)
                    {
    
    
                        CoordinateTransform.ConvertBd09ToGcj02(bd09.Lng, bd09.Lat, out lon, out lat);
                        gcj02.Lat = lat;
                        gcj02.Lng = lon;
                    }
                    return gcj02;
                }
                else
                {
    
    
                    return PointLatLng.Empty;
                }
            }
        }
        private PointLatLng bd09;
        public PointLatLng BD09
        {
    
    
            get
            {
    
    
                double lon, lat;
                if (CoordType == CoordType.WGS84)
                {
    
    
                    if (bd09 == PointLatLng.Empty)
                    {
    
    
                        CoordinateTransform.ConvertWgs84ToBd09(wgs84.Lng, wgs84.Lat, out lon, out lat);
                        bd09.Lat = lat;
                        bd09.Lng = lon;
                    }
                    return bd09;
                }
                else if (CoordType == CoordType.GCJ02)
                {
    
    
                    if (bd09 == PointLatLng.Empty)
                    {
    
    
                        CoordinateTransform.ConvertGcj02ToBd09(gcj02.Lng, gcj02.Lat, out lon, out lat);
                        bd09.Lat = lat;
                        bd09.Lng = lon;
                    }
                    return bd09;
                }
                else if (CoordType == CoordType.BD09)
                {
    
    
                    return bd09;
                }
                else
                {
    
    
                    return PointLatLng.Empty;
                }
            }
        }
        public CoordType CoordType;
        public PointInDiffCoord()
        {
    
    
            wgs84 = PointLatLng.Empty;
            gcj02 = PointLatLng.Empty;
            bd09 = PointLatLng.Empty;
            CoordType = CoordType.UNKNOW;
        }

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="p"></param>
        public PointInDiffCoord(PointLatLng p)
        {
    
    
            if (p.Type == CoordType.WGS84)
            {
    
    
                wgs84 = p;
                gcj02 = PointLatLng.Empty;
                bd09 = PointLatLng.Empty;
                CoordType = CoordType.WGS84;
            }
            else if (p.Type == CoordType.GCJ02)
            {
    
    
                wgs84 = PointLatLng.Empty;
                gcj02 = p;
                bd09 = PointLatLng.Empty;
                CoordType = CoordType.GCJ02;
            }
            else if (p.Type == CoordType.BD09)
            {
    
    
                wgs84 = PointLatLng.Empty;
                gcj02 = PointLatLng.Empty;
                bd09 = p;
                CoordType = CoordType.BD09;
            }
            else
            {
    
    
                wgs84 = PointLatLng.Empty;
                gcj02 = PointLatLng.Empty;
                bd09 = PointLatLng.Empty;
                CoordType = CoordType.UNKNOW;
            }
        }

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="lat"></param>
        /// <param name="lon"></param>
        public PointInDiffCoord(double lat, double lon)
            : this(new PointLatLng(lat, lon))
        {
    
    
            
        }

        public static PointLatLng GetWGS84Point(PointLatLng p)
        {
    
    
            double lon, lat;
            if (p != PointLatLng.Empty)
            {
    
    
                if (p.Type == CoordType.WGS84)
                {
    
    
                    return p;
                }
                else if (p.Type == CoordType.GCJ02)
                {
    
    
                    CoordinateTransform.ConvertGcj02ToWgs84(p.Lng, p.Lat, out lon, out lat);
                    return new PointLatLng(lat, lon, CoordType.WGS84);
                }
                else if (p.Type == CoordType.BD09)
                {
    
    
                    CoordinateTransform.ConvertBd09ToWgs84(p.Lng, p.Lat, out lon, out lat);
                    return new PointLatLng(lat, lon, CoordType.WGS84);
                }
                else
                {
    
    
                    return PointLatLng.Empty;
                }
            }
            else
            {
    
    
                return PointLatLng.Empty;
            }
        }

        public static PointLatLng GetGCJ02Point(PointLatLng p)
        {
    
    
            double lon, lat;
            if (p != PointLatLng.Empty)
            {
    
    
                if (p.Type == CoordType.WGS84)
                {
    
    
                    CoordinateTransform.ConvertWgs84ToGcj02(p.Lng, p.Lat, out lon, out lat);
                    return new PointLatLng(lat, lon, CoordType.GCJ02);
                }
                else if (p.Type == CoordType.GCJ02)
                {
    
    
                    return p;
                }
                else if (p.Type == CoordType.BD09)
                {
    
    
                    CoordinateTransform.ConvertBd09ToGcj02(p.Lng, p.Lat, out lon, out lat);
                    return new PointLatLng(lat, lon, CoordType.GCJ02);
                }
                else
                {
    
    
                    return PointLatLng.Empty;
                }
            }
            else
            {
    
    
                return PointLatLng.Empty;
            }
        }

        public static PointLatLng GetBD09Point(PointLatLng p)
        {
    
    
            double lon, lat;
            if (p != PointLatLng.Empty)
            {
    
    
                if (p.Type == CoordType.WGS84)
                {
    
    
                    CoordinateTransform.ConvertWgs84ToBd09(p.Lng, p.Lat, out lon, out lat);
                    return new PointLatLng(lat, lon, CoordType.BD09);
                }
                else if (p.Type == CoordType.GCJ02)
                {
    
    
                    CoordinateTransform.ConvertGcj02ToBd09(p.Lng, p.Lat, out lon, out lat);
                    return new PointLatLng(lat, lon, CoordType.BD09);
                }
                else if (p.Type == CoordType.BD09)
                {
    
    
                    return p;
                }
                else
                {
    
    
                    return PointLatLng.Empty;
                }
            }
            else
            {
    
    
                return PointLatLng.Empty;
            }
        }

        public static PointLatLng GetPointInCoordType(PointLatLng p, CoordType destType)
        {
    
    
            if (destType == CoordType.WGS84)
            {
    
    
                return GetWGS84Point(p);
            }
            else if (destType == CoordType.GCJ02)
            {
    
    
                return GetGCJ02Point(p);
            }
            else if (destType == CoordType.BD09)
            {
    
    
                return GetBD09Point(p);
            }
            else
            {
    
    
                return p;
            }
        }

        public static PointLatLng GetPointInCoordType(PointLatLng p, CoordType srcType, CoordType destType)
        {
    
    
            p.Type = srcType;
            if (destType == CoordType.WGS84)
            {
    
    
                return GetWGS84Point(p);
            }
            else if (destType == CoordType.GCJ02)
            {
    
    
                return GetGCJ02Point(p);
            }
            else if (destType == CoordType.BD09)
            {
    
    
                return GetBD09Point(p);
            }
            else
            {
    
    
                return p;
            }
        }

        public static PointLatLng GetPointInCoordType(double lat, double lon, CoordType srcType, CoordType destType)
        {
    
    
            PointLatLng p = new PointLatLng(lat, lon, srcType);
            if (destType == CoordType.WGS84)
            {
    
    
                return GetWGS84Point(p);
            }
            else if (destType == CoordType.GCJ02)
            {
    
    
                return GetGCJ02Point(p);
            }
            else if (destType == CoordType.BD09)
            {
    
    
                return GetBD09Point(p);
            }
            else
            {
    
    
                return p;
            }
        }

        public static List<PointLatLng> GetPointListInCoordType(List<PointLatLng> pList, CoordType srcType, CoordType destType)
        {
    
    
            if (srcType == destType)
            {
    
    
                return pList;
            }
            List<PointLatLng> retList = new List<PointLatLng>();
            foreach (var item in pList)
            {
    
    
                retList.Add(GetPointInCoordType(item, srcType, destType));
            }
            return retList;
        }
    }
}
  • Coordinate conversion sample code:
// 创建一个GCJ02坐标
PointLatLng p = new PointLatLng(25.254845, 118.658454, CoordType.GCJ02);
// 获取指定类型坐标点
PointLatLng p_type = PointInDiffCoord.GetPointInCoordType(p, type);
// 通过GCJ02坐标点创建PointInDiffCoord对象
PointInDiffCoord pidc = new PointInDiffCoord(p);
// 获取WGS84坐标
PointLatLng p_wgs = pidc.WGS84;
// 获取GCJ02坐标
PointLatLng p_gcj = pidc.GCJ02;
// 获取BD09坐标
PointLatLng p_bd = pidc.BD09;

2.4 Simulation sports car

When using historical tracks to simulate sports cars, the program will create a NamedPipeServer service to send out GPS information, and other processes or programs can receive GPS information by connecting to this service. The NamedPipeServer service code is as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Pipes;
using System.Threading;

namespace MapToolsWinForm
{
    
    
    /// <summary>
    /// Windows命名管道服务类
    /// </summary>
    class NamedPipeServer
    {
    
    
        private NamedPipeServerStream serverStream;
        private string pipeName;
        private Thread connThread;
        private Thread sendThread;
        private int sleepTime = 10;

        public NamedPipeServer(string pipeName)
        {
    
    
            this.pipeName = pipeName;
            serverStream = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 254, PipeTransmissionMode.Message);
            connThread = new Thread(ConnThreadTask);
            connThread.Start();
            sendThread = new Thread(SendThreadTask);
            sendThread.Start();
        }

        private void ConnThreadTask(object obj)
        {
    
    
            while (true)
            {
    
    
                if (!serverStream.IsConnected)
                {
    
    
                    try
                    {
    
    
                        serverStream.WaitForConnection();
                        sendQueue.Clear();
                    }
                    catch (Exception)
                    {
    
    
                        serverStream.Disconnect();
                        serverStream.Dispose();
                        serverStream = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Message);
                    }
                }
                Thread.Sleep(sleepTime);
            }
        }

        Queue<string> sendQueue = new Queue<string>();
        private void SendThreadTask(object obj)
        {
    
    
            while (true)
            {
    
    
                try
                {
    
    
                    if (!serverStream.IsConnected)
                    {
    
    
                        Thread.Sleep(sleepTime);
                        continue;
                    }
                    if (sendQueue.Count <= 0)
                    {
    
    
                        Thread.Sleep(sleepTime);
                        continue;
                    }
                    string send_str = sendQueue.Dequeue();
                    byte[] byteArr = Encoding.UTF8.GetBytes(send_str);
                    serverStream.Write(byteArr, 0, byteArr.Length);
                    serverStream.Flush();
                    Thread.Sleep(sleepTime);
                }
                catch (Exception ex)
                {
    
    
                    
                }
            }
        }

        public bool sendCanData(string send_str)
        {
    
    
            if (!serverStream.IsConnected)
            {
    
    
                return false;
            }
            lock (sendQueue)
            {
    
    
                if (sendQueue.Count > 20)
                {
    
    
                    sendQueue.Clear();
                }
                sendQueue.Enqueue(send_str);
            }
            return true;
        }

        public void Close()
        {
    
    
            if (connThread != null && connThread.IsAlive)
            {
    
    
                connThread.Abort();
            }
            if (sendThread != null && sendThread.IsAlive)
            {
    
    
                sendThread.Abort();
            }
            if (sendQueue != null && sendQueue.Count > 0)
            {
    
    
                sendQueue.Clear();
            }
            try
            {
    
    
                serverStream.Disconnect();
                serverStream.Dispose();
            }
            catch (Exception)
            {
    
    
            }
        }
    }
}

Service creation and data sending:

// 服务创建
NamedPipeServer namePipeServer = new NamedPipeServer("com.lois.pipe.gps.string");

// 数据发送,格式:lon,lat,dir,speed,alt
if (namePipeServer != null)
{
    
    
  namePipeServer.sendCanData(string.Format("{0},{1},{2},{3},{4}", wgsP.Lng, wgsP.Lat, historyGeoData.Direction, historyGeoData.Speed, historyGeoData.Altitude));
}

Guess you like

Origin blog.csdn.net/loutengyuan/article/details/126539427