Working with maps. GMAP C #

I was prompted to write this article not so much textual information on working with GMap on the Internet as I would like.

The task was to visualize the position of objects on the map by known coordinates for further analysis and to identify any patterns in the location of these objects.

The first thing I can recommend from my experience is to start working right away with WinForm, and not with WPF. easier and more information can be obtained from it.

A short glossary of terms that will be found in my article:

  • Tiled, tiled or familiar graphics (from the English tile – tile) – a method of creating large images (as a rule, levels in computer games) from small fragments of the same size

  • Tile – split element

  • Layer can be compared to a transparency overlay on an image to which custom elements are applied

  • Heat map – graphical presentation of data, where individual values ​​in the table are displayed using color. The term “heatmap” was originally coined and officially registered as a trademark by software developer Cormac Kinney in 1991.

  • Polygon – polygon, the minimum surface for visualization in 3D graphics.

  • Marker – mark on the map

Let’s move on to working with the library.

We need GMap.NET.Core.dll and GMap.NET.WindowsForms.dll You can use Nuget for installation.

or download dll from the Internet and insert links

Right-click the toolbar and click Select Items …. In the window that appears, use the Browse button to find the GMap.NET.WindowsForms.dll file:

When the window is closed, the new control appears in the toolbox. Drag it to the shape and adjust the position and size.

We create an event (event) for loading the contral.

Paste in the code:

GMap.NET.GMaps.Instance.Mode = GMap.NET.AccessMode.ServerAndCache; //выбор подгрузки карты – онлайн или из ресурсов
            gMapControl1.MapProvider = GMap.NET.MapProviders.GoogleMapProvider.Instance; //какой провайдер карт используется (в нашем случае гугл) 
            gMapControl1.MinZoom = 2; //минимальный зум
            gMapControl1.MaxZoom = 16; //максимальный зум
           gMapControl1.Zoom = 4; // какой используется зум при открытии
            gMapControl1.Position = new GMap.NET.PointLatLng(66.4169575018027, 94.25025752215694);// точка в центре карты при открытии (центр России)
            gMapControl1.MouseWheelZoomType = GMap.NET.MouseWheelZoomType.MousePositionAndCenter; // как приближает (просто в центр карты или по положению мыши)
            gMapControl1.CanDragMap = true; // перетаскивание карты мышью
            gMapControl1.DragButton = MouseButtons.Left; // какой кнопкой осуществляется перетаскивание
            gMapControl1.ShowCenter = false; //показывать или скрывать красный крестик в центре
            gMapControl1.ShowTileGridLines = false; //показывать или скрывать тайлы

The result of executing the code. The map is divided into squares called tiles. Tiles and center cross are included.

Working with the library. Markers

To display an object on the map, we create a marker with the coordinates of the object and display it on the map. Now let’s create a function that returns the same marker. In the code below, the function takes parameters: Us classes where I get the name and coordinates and an optional parameter gMarkerGoogleType – marker type.

private GMarkerGoogle GetMarker(Us us, GMarkerGoogleType gMarkerGoogleType= GMarkerGoogleType.red)
        {
            GMarkerGoogle mapMarker = new GMarkerGoogle(new GMap.NET.PointLatLng(us.сoordinates[0].lat, us.сoordinates[0].lon), gMarkerGoogleType);//широта, долгота, тип маркера
            mapMarker.ToolTip = new GMap.NET.WindowsForms.ToolTips.GMapRoundedToolTip(mapMarker);//всплывающее окно с инфой к маркеру
            mapMarker.ToolTipText = us.id; // текст внутри всплывающего окна
            mapMarker.ToolTipMode = MarkerTooltipMode.OnMouseOver; //отображение всплывающего окна (при наведении)
            return mapMarker;
        }

It is necessary to say about GMapOverlay Is a layer similar to Photoshop’s, which can be described as a map-sized transparent canvas on which we place all the markers.

Now the function returns the layer with markers. Input parameters: list of classes with names and coordinates, layer name and all the same optional parameter gMarkerGoogleType

private GMapOverlay GetOverlayMarkers(List<Us> uss, string name, GMarkerGoogleType gMarkerGoogleType= GMarkerGoogleType.red)
        {
            GMapOverlay gMapMarkers = new GMapOverlay(name);// создание именованного слоя 
            foreach (Us us in uss)
            {
                gMapMarkers.Markers.Add(GetMarker(us, gMarkerGoogleType));// добавление маркеров на слой
            }
            return gMapMarkers;
        }

Adding a layer. Call the function that creates the layer and add it to the map control layers:

gMapControl1.Overlays.Add(GetOverlayMarkers(groups, "GroupsMarkers"));

the same, but specifying the types of markers:

gMapControl1.Overlays.Add(GetOverlayMarkers(LUs, " GroupsMarkers", GMarkerGoogleType.blue));

You can show / hide layers

gMapControl1.Overlays[0].IsVisibile = false;

The layer has been added, now just update the control

gMapControl1.Update();// обновить контрол

At the exit, we get a map with markers applied to it

Heat map

Initially, we wanted to make a heat map by the number of markers in the districts of different cities, but for this we will have to search and extract the coordinates of the boundaries of these districts. And this is more work and time, and the deadline, as always, is already the day before yesterday, so it was thought up to draw up a map by concentration in tiles. To make it look good, it is better to take tiles smaller than for the current zoom. And from such considerations, I make a set of layers for each zoom, and when the zoom changes, I change the layer.

The code for creating layers with colored polygons:

public void GetHeatMap(List<Us> LUs, string name, bool AllCoord = true)
        {
            MercatorProjection mercatorProjection = new MercatorProjection(); // класс с функциями https://github.com/radioman/greatmaps/blob/master/GMap.NET.Core/GMap.NET.Projections/MercatorProjection.cs#L73
            for (int myZoom = gMapControl1.MinZoom + 3; myZoom <= gMapControl1.MaxZoom + 3; myZoom++)
            {
                GMapOverlay gMapOverlay = new GMapOverlay(name + myZoom); // создание слоя с именем включающий зум
                int tileSizePx = (int)mercatorProjection.TileSize.Height; //размер тайла
                List<GPoint> gPoints = new List<GPoint>();//список точек 
                foreach (Us us in LUs)
                {
                    if (AllCoord)
                    {
                        foreach (Coordinat coordinat in us.сoordinates)
                        {
                            GPoint pixelCoord = mercatorProjection.FromLatLngToPixel(coordinat.lat, coordinat.lon, myZoom);
                            gPoints.Add(new GPoint(pixelCoord.X / tileSizePx * tileSizePx, pixelCoord.Y / tileSizePx * tileSizePx));
                        }
                    }
                    else
                    {
                        GPoint pixelCoord = mercatorProjection.FromLatLngToPixel(us.сoordinates[0].lat, us.сoordinates[0].lon, myZoom);//из широты долготы в пиксели
                        gPoints.Add(new GPoint(pixelCoord.X / tileSizePx * tileSizePx, pixelCoord.Y / tileSizePx * tileSizePx));
                    }
                }
                var group = gPoints.GroupBy(r => r).ToList();
                int TileMaxCount = group.Max(r => r.Count());// максимальное содержание маркеров на тайле
                foreach (var item in group)
                {
                    int minus = Convert.ToInt32(155 * item.Count() / TileMaxCount);//сколько вычитать из РГБ
                    if (minus == 0) { minus++; }
                    Color color = Color.FromArgb(200, 255, 155 - minus, 155 - minus);// задаем цвет для использования
                    List<PointLatLng> pointLatLngs = new List<PointLatLng>()
                {
                    mercatorProjection.FromPixelToLatLng(item.Key, myZoom),
                    mercatorProjection.FromPixelToLatLng(item.Key.X+tileSizePx, item.Key.Y, myZoom),
                    mercatorProjection.FromPixelToLatLng(item.Key.X+tileSizePx, item.Key.Y+tileSizePx, myZoom),
                    mercatorProjection.FromPixelToLatLng(item.Key.X, item.Key.Y+tileSizePx, myZoom)
                }; //создаем список точек для полигона
                    GMapPolygon gMapPolygon = new GMapPolygon(pointLatLngs, item.Key.ToString()); //создаем полигон из списка точек
                    gMapPolygon.Fill = new SolidBrush(color);// заливка
                    gMapPolygon.Stroke = new Pen(color, -1); // рамка
                    gMapPolygon.IsVisible = true; // видимость 
                    gMapOverlay.Polygons.Add(gMapPolygon); // добавляем полигон
                }
                gMapControl1.Overlays.Add(gMapOverlay);// добавляем слой
                GC.Collect();// сбор мусора
            }
        }

Code when changing zoom:

private void gMapControl1_OnMapZoomChanged()
        {
            if (AllPolygonsToolStripMenuItem.CheckState == CheckState.Checked)
            {
                CheckHeatMap("AllPolygons");
                gMapControl1.Update();
            }
        }

Function code:

private void CheckHeatMap(string name)
        {
            foreach (GMapOverlay gMapOverlay in gMapControl1.Overlays.Where(r => r.Id.Contains("Polygons")))
            {
                gMapOverlay.IsVisibile = false;
            }// все слои содержащие слово полигон невидимы
            if (name != null)
            {
                name += gMapControl1.Zoom + 3;
                GMapOverlay gMapOverlaySearch = gMapControl1.Overlays.Where(r => r.Id == name).FirstOrDefault();
                gMapControl1.Overlays.Where(r => r.Id == name).FirstOrDefault().IsVisibile = true;//видимость слоя с заданным именем
            }
        }

As you zoom in, the size of the tiles changes:

Conclusion

This article shows you how to get started with GMap: work with layers, tiles, polygons and add markers. I hope the ideas and code presented in the article will be useful in solving your problems.

I also suggest taking a look:

Gmap.Net Beginners Tutorial

OpenStreetMap in Visual Studio 2017. GMap.Net

Similar Posts

Leave a Reply