1

I'm trying to display GPS coordinates in a canvas. I have 400 towns in France + USA. I just want to display them in a canvas.

For each town I have its latitude and longitude (taken with google api : https://developers.google.com/maps/documentation/geocoding/ ). I've managed to have a first result using this thread : Converting from longitude\latitude to Cartesian coordinates

Here is my result : enter image description here

My code is the following (assuming "_liste" contains a list of Towns) :

private void Button_visualise_Click(object sender, RoutedEventArgs e)
        {

                    System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
                    watch.Start();
                    List<Town> _list = LibDAO.Towns_DAO.GetAllTown().Where(u=>u.IdPays == 2 || u.IdPays == 1).ToList<Town>();

                    this.my_canvas.Children.Clear();
                    double min_x = 0;
                    double max_x = 0;
                    double min_y = 0;
                    double max_y = 0;
                    for (int i = 0; i < _list .Count; i++)
                    {
                        Ellipse ell = new Ellipse() { Width = 30, Height = 30, Fill = Brushes.Blue };
                        Point p = ToCanvas(_list [i].Latitude, _list [i].Longitude);
                        Canvas.SetLeft(ell, p.X);
                        Canvas.SetTop(ell, p.Y);

                        if (p.X < min_x) min_x = p.X;
                        if (p.X > max_x) max_x = p.X;
                        if (p.Y < min_y) min_y = p.Y;
                        if (p.Y > max_y) max_y = p.Y;
                        this.my_canvas.Children.Add(ell);
                    }
                    SetCoordinateSystem(this.my_canvas, min_x, max_x, min_y, max_y);
                    watch.Stop();


        }
        public static Canvas SetCoordinateSystem(Canvas canvas, Double xMin, Double xMax, Double yMin, Double yMax)
        {
            var width = xMax - xMin;
            var height = yMax - yMin;

            var translateX = -xMin;
            var translateY = height + yMin;

            var group = new TransformGroup();

            group.Children.Add(new TranslateTransform(translateX, -translateY));
            group.Children.Add(new ScaleTransform(canvas.ActualWidth / width, canvas.ActualHeight / -height));

            canvas.RenderTransform = group;

            return canvas;
        }
        private const int earthRadius = 6367;
        private Point ToCanvas(double lat, double lon)
        {
            lon = ConvertToRadians(lon);
            lat = ConvertToRadians(lat);

            double x = earthRadius * Math.Cos(lat) * Math.Cos(lon); //((lon * my_canvas.ActualWidth) / 360.0) - 180.0; ;// // 
            double y = earthRadius * Math.Cos(lat) * Math.Sin(lon);// ((lat * my_canvas.ActualHeight) / 180.0) - 90.0;
            return new Point(x, y);
        }
        public double ConvertToRadians(double angle)
        {
            return (Math.PI / 180) * angle;
        }

As you can see in my result it's almost perfect, we can recognize the 2 countries but why are they in the wrong place ? (I would like to have them like this : http://geology.com/world/world-map.gif

Am I missing something ?

Based on this link, my result may be displayed with "Azimuthal (projections onto a plane)" while I would prefer this : http://en.wikipedia.org/wiki/Equirectangular_projection So I'm thinking of changing my function "ToCanvas" but I don't know the component "the standard parallels (north and south of the equator) where the scale of the projection is true;"

Bonus question : What's the best way to get the border from a country in GPS coordinates ? I would like to draw the border of USA for example, so I guessed I could just get coordinates of borders to draw the country. I've tried several websites, managed to get a .shp file from there : http://www.naturalearthdata.com/downloads/110m-cultural-vectors/, but I didn't manage to retrieve borders coordinates from there.

Thank you

EDIT Seems better with this code :

private Point ToCanvas(double lat, double lon)
        {
            // Equirectangular projection
            double x1 = lon * Math.Cos(ConvertToRadians(lat));
            double y1 = lat;

            //lon = ConvertToRadians(lon);
            //lat = ConvertToRadians(lat);

            //double x = earthRadius * Math.Cos(lat) * Math.Cos(lon); //((lon * my_canvas.ActualWidth) / 360.0) - 180.0; ;// // 
            //double y = earthRadius * Math.Cos(lat) * Math.Sin(lon);// ((lat * my_canvas.ActualHeight) / 180.0) - 90.0;
            return new Point(x1 * 10, y1 * 10);
        }
Community
  • 1
  • 1
user2088807
  • 1,378
  • 2
  • 25
  • 47
  • Why not use a map control for WPF? It will do the projection from lat/lon to cartesian coordinates, and *also display a map* (e.g. provided by OpenStreetMap) below your points. That said, the most commonly used map projection is the so-called Web Mercator Projection. It is used by OpenStreetMap, Google Maps and Bing Maps. – Clemens Mar 02 '15 at 21:10
  • I didn't find any map control free for WPF (my control needs to be offline and be able to draw countries/cities offline). – user2088807 Mar 02 '15 at 21:17
  • 1
    I can recommend [XAML Map Control](https://xamlmapcontrol.codeplex.com/), because I am the author of that library. It is able to display offline (cached) content. You may also add your own custom map content provider. Even if you do not display a base map, the control can still do the coordinate projection for you, and display a collection of items in its MapItemsControl. – Clemens Mar 02 '15 at 21:22
  • What about the styling of your control ? How can we add countries in cache ? – user2088807 Mar 02 '15 at 21:33
  • The base map layer displays (optionally cached) map tile bitmaps (256 * 256 pixels), just like the Bing Maps control. Then you can add arbitrary overlays with map geometries. If you've got a country's border as collection of lat/lon values, you could create a filled and stroked MapPolyline from that data. – Clemens Mar 02 '15 at 21:38
  • What I see on your graphic is a spherical projection with top dead centre North Pole(90º ) and the left/right centre is 90º West. – Nodak Mar 03 '15 at 10:38
  • What's the projection I've to use to have a "classic" representation of the world ? I tried Equirectangular_projection with wikipedia's formulas and it works on European countries but not with americans. – user2088807 Mar 06 '15 at 12:20
  • XAML Map Control has migrated to: https://github.com/ClemensFischer/XAML-Map-Control – user2677034 Jun 24 '21 at 21:04

0 Answers0