How to get Coordinate (Longitude, Latitude) by double-click (using OpenStreetMap)

Topics: Algorithms, SharpMap v0.9 / v1.x
Oct 27, 2014 at 9:46 AM
I want to get Coordinate (Longitude, Latitude) by double-click in the map.

There are some points which are set by Vector Layer in the map.
Each of them have GPS data (Longitude, Latitude).

When not using OpenStreetMap as the Bese Layer, Coordinate (Longitude, Latitude) which is gotten by the double-click is the same as the original GPS coordinates.

But when I added OpenStreetMap as the Bese Layer with (change into WGS84 geographic coordinate system), Coordinate (Longitude, Latitude) which is gotten by the double-click is too different.

For example)
original Coordinate (Longitude, Latitude) : (-95.00, 48.00)
obtained one by double-click : (-10578404.9004584, 6110457.26907456)

Is there a way to get original GPS Coordinate (Longitude, Latitude) by double-click?

Below is my source code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SharpMap;
using SharpMap.Layers;
using SharpMap.Data.Providers;
using System.Collections.ObjectModel;
using GeoAPI;
using GeoAPI.CoordinateSystems;
using NetTopologySuite;
using ProjNet.CoordinateSystems.Transformations;
using ProjNet.CoordinateSystems.Projections;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        string[,] GpsPoint = new string[3, 3];
        GeoAPI.Geometries.Coordinate[] FPoints = new GeoAPI.Geometries.Coordinate[3];
        NetTopologySuite.Geometries.Point[] fmp = new NetTopologySuite.Geometries.Point[3];

        double Test_X;
        double Test_Y;

        public Form1()
        {
            InitializeComponent();

            //change into WGS84 geographic coordinate system
            ProjNet.CoordinateSystems.Transformations.CoordinateTransformationFactory ctFact = new ProjNet.CoordinateSystems.Transformations.CoordinateTransformationFactory();
            ProjNet.CoordinateSystems.CoordinateSystemFactory csFact = new ProjNet.CoordinateSystems.CoordinateSystemFactory();


            //VectorLayer(vlay) setting
            SharpMap.Layers.VectorLayer vlay = new SharpMap.Layers.VectorLayer("States");
            vlay.DataSource = new SharpMap.Data.Providers.ShapeFile(@"..\..\path_to_data\\states_ugl.shp", true);

            //(vlay) change into WGS84 geographic coordinate system
            vlay.CoordinateTransformation = ctFact.CreateFromCoordinateSystems(ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84, GetEPSG900913(csFact));
            vlay.ReverseCoordinateTransformation = ctFact.CreateFromCoordinateSystems(GetEPSG900913(csFact), ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);
            
            mapBox1.Map.Layers.Add(vlay);
            mapBox1.Map.ZoomToExtents();
            mapBox1.Refresh();


            //VectorLayer(flay) setting
            SharpMap.Layers.VectorLayer flay = new SharpMap.Layers.VectorLayer("GpsPoint");

            List<NetTopologySuite.Geometries.Geometry> geometries = new List<NetTopologySuite.Geometries.Geometry>();

            GpsPoint[0, 0] = "48.00";   //PointA(latitude)
            GpsPoint[0, 1] = "-95.00";  //PointA(longitude)
            GpsPoint[1, 0] = "46.00";   //PointB(latitude)
            GpsPoint[1, 1] = "-90.00";  //PointB(longitude)
            GpsPoint[2, 0] = "44.00";   //PointC(latitude)
            GpsPoint[2, 1] = "-85.00";  //PointC(longitude)

            for (int n = 0; n <= 2; n++)
            {
                FPoints[n] = new GeoAPI.Geometries.Coordinate((Convert.ToDouble(GpsPoint[n, 1])), (Convert.ToDouble(GpsPoint[n, 0])));
                fmp[n] = new NetTopologySuite.Geometries.Point(FPoints[n]);
                geometries.Add(fmp[n]); //packing three coordination points into one layer.
            }

            flay.DataSource = new SharpMap.Data.Providers.GeometryProvider(geometries);

            //(flay) change into WGS84 geographic coordinate system
            flay.CoordinateTransformation = ctFact.CreateFromCoordinateSystems(ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84, GetEPSG900913(csFact));
            flay.ReverseCoordinateTransformation = ctFact.CreateFromCoordinateSystems(GetEPSG900913(csFact), ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);
            
            mapBox1.Map.Layers.Add(flay);

            //Base Layer(ONLINE OpenStreetMap)
            mapBox1.Map.BackgroundLayer.Add(new SharpMap.Layers.TileAsyncLayer(new BruTile.Web.OsmTileSource(), "OSM"));

            mapBox1.Refresh();
        }

        private static IProjectedCoordinateSystem GetEPSG900913(ProjNet.CoordinateSystems.CoordinateSystemFactory csFact)
        {
            List<GeoAPI.CoordinateSystems.ProjectionParameter> parameters = new List<GeoAPI.CoordinateSystems.ProjectionParameter>();
            parameters.Add(new GeoAPI.CoordinateSystems.ProjectionParameter("semi_major", 6378137.0));
            parameters.Add(new GeoAPI.CoordinateSystems.ProjectionParameter("semi_minor", 6378137.0));
            parameters.Add(new GeoAPI.CoordinateSystems.ProjectionParameter("latitude_of_origin", 0.0));
            parameters.Add(new GeoAPI.CoordinateSystems.ProjectionParameter("central_meridian", 0.0));
            parameters.Add(new GeoAPI.CoordinateSystems.ProjectionParameter("scale_factor", 1.0));
            parameters.Add(new GeoAPI.CoordinateSystems.ProjectionParameter("false_easting", 0.0));
            parameters.Add(new GeoAPI.CoordinateSystems.ProjectionParameter("false_northing", 0.0));
            GeoAPI.CoordinateSystems.IProjection projection = csFact.CreateProjection("Google Mercator", "mercator_1sp", parameters);

            GeoAPI.CoordinateSystems.IGeographicCoordinateSystem wgs84 = csFact.CreateGeographicCoordinateSystem(
                "WGS 84", ProjNet.CoordinateSystems.AngularUnit.Degrees, ProjNet.CoordinateSystems.HorizontalDatum.WGS84, ProjNet.CoordinateSystems.PrimeMeridian.Greenwich,
                new GeoAPI.CoordinateSystems.AxisInfo("north", GeoAPI.CoordinateSystems.AxisOrientationEnum.North), new GeoAPI.CoordinateSystems.AxisInfo("east", GeoAPI.CoordinateSystems.AxisOrientationEnum.East)
            );

            GeoAPI.CoordinateSystems.IProjectedCoordinateSystem epsg900913 = csFact.CreateProjectedCoordinateSystem("Google Mercator", wgs84, projection, ProjNet.CoordinateSystems.LinearUnit.Metre,
                new GeoAPI.CoordinateSystems.AxisInfo("East", GeoAPI.CoordinateSystems.AxisOrientationEnum.East), new GeoAPI.CoordinateSystems.AxisInfo("North", GeoAPI.CoordinateSystems.AxisOrientationEnum.North));

            return epsg900913;
        }

        private void mapBox1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            GeoAPI.Geometries.Coordinate p = mapBox1.Map.ImageToWorld(new PointF(e.X, e.Y));

            Test_X = p.X;
            Test_Y = p.Y;
        }
    }
}
Coordinator
Oct 27, 2014 at 6:19 PM
You need to transform back to WGS84.
Oct 28, 2014 at 1:39 AM
The conversion equation to transform WGS84 to OpenStreetMap coordination is too complex for me.

I can not think of the conversion equation for carrying out inverse transform of the coordinates (p. X, p.Y) acquired when I double-clicked.

Could you please present the detailed method on reverse conversion equation?

I am so sorry to trouble you.
Coordinator
Oct 28, 2014 at 6:25 AM
You have it all coded in your map generation code, you only need to use it.
You set up a coordinate transformation for your GPS points, you need the reverse transformation.
Oct 30, 2014 at 12:30 AM
Thank you for your advice.
I am checking the source code of GPS coordinate conversion now.
Coordinator
Oct 30, 2014 at 10:15 AM
All you need to do is apply the "ReverseCoordinateTransformation" to the point you clicked.
private void mapBox1_MouseDoubleClick(object sender, MouseEventArgs e)
{
    var map = mapBox1.Map;
    var lyr = map.FindLayer("GpsPoints").FirstOrDefault() as VectorLayer;
    if (lyr == null) return;
    var ct = lyr.ReverseCoordinateTransformation;
    if (ct == null)
    {
        ct = lyr.CoordinateTransformation;
        if (ct == null) return;
        ct.MathTransform.Invert();
    }

    var point = SharpMap.Utilities.Transform.MapToWorld(new PointF(e.X, e.Y), map);
    point = ct.MathTransform.Transform(point);

    if (ct == lyr.CoordinateTransformation) ct.MathTransform.Invert();
}
Oct 31, 2014 at 6:55 AM
Thank you for your advice.

I tried the source code.

At the line
if (lyr == null) return;
lyr is always null, and always returned.

So ReverseCoordinateTransformation can not be applied.

Is there any processing which I should set in advance?
Coordinator
Oct 31, 2014 at 8:06 AM
Edited Oct 31, 2014 at 8:08 AM
Come on, when your layer is named "GpsPoint", you cannot get a result for "GpsPoints".
Code snipplets I post are ususally not validated, they only help you understand the concept. You have to put some effort in it yourself.
Nov 4, 2014 at 12:26 PM
Thank you for your advice.
I will try to make efforts to understand the source code of GPS coordinate conversion.