Getting cursor position from 3D Globe

Sep 22, 2010 at 3:08 PM
Edited Sep 22, 2010 at 3:19 PM

Hi all. I am using VEMap for wpf but i am having trouble trying to get the latitude and longtitude where the mouse is pointed to in the 3D bing map (Globe).

 

Methods I had tried:

 

Point? ptTest=MyMap.LatLongToPoint(MyMap.VELatLong);
VELatLong latTest=MyMap.PointToLatLong(ptTest); 



 

This will only return the point at the center.

 

Another method:

 

private void map_MapLoaded(object sender, EventArgs e)
        {
            map.Show3DCursor = true;

            map.MouseMove += new MouseEventHandler(map_MouseMove);
        }

        void map_MouseMove(object sender, MouseEventArgs e)
        {
            LatLonAlt location = map.GlobeControl.Host.Navigation.PointerPosition.Location;
            double lat = location.LatitudeDegrees;
        }
lat doesn't seems to return the correct value too. And at the same time i am having compilation error when using map.GlobeControl.
Error 1 The type 'System.Windows.Forms.Control' is defined in an assembly that is not referenced. You must add a reference to assembly 
'System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. C:\Users\sss\Documents\Visual Studio 2010\Projects\Bing Map\Bing Map\MainWindow.xaml.cs 42 13 Bing Map
Any helps? Thank you.
Coordinator
Sep 22, 2010 at 3:24 PM

In your first example, you were half correct. What you are doing there is taking the current latitude and longitude of the map (i.e. the lat/long at the center), converting it to a point with screen coordinates, then converting it back to a latitude and longitude.

Don't bother with map.GlobeControl.Host.Navigation.PointerPosition. That is not updated properly in the WPF version.

The compilation error tells you you need to add a reference to System.Windows.Forms, so if you need to resolve that error just add the reference it is telling you.

To get the lat/long of any screen coordinate point, you just need to use PointToLatLong(). So for example, if you use this, you will get the information you want:

void map_MouseMove(object sender, MouseEventArgs e){

            Point p = e.GetPosition(MyMap);
            VELatLong latlong = MyMap.PointToLatLong(p);
//Do something useful with latlong
}
Sep 22, 2010 at 3:33 PM

Thanks for the asap reply. =)

Is there any reason why

latlong.Longitude

latlong.Latitude



still have value when my pointer is already out of the globe? Is there a way to check it?

Coordinator
Sep 22, 2010 at 3:53 PM

Not sure, it depends upon the specific values you are giving it and the current position and altitude (zoom level) of the map.

In general, if you use LatLongToPoint() and the point is outside the globe, such as on the black/starry background, it will return null. This is why it returns Point?.

For PointToLatLong if you pass it a value that is outside the boundary of the map control, it might still return a proper lat/long if you are zoomed in. You could check this by making sure the control-relative point is inside the boundary of the map control.

Sep 23, 2010 at 6:16 AM
Edited Sep 23, 2010 at 12:11 PM

Hi joshb,

After using your method, it seems that the latitude and longitude is not accurate. And whenever I used the mouse wheel to do the zoom out of the globe, the null area seem to increase even my pointer is in the globe it return me with a null value and beside this, adding vepushpin to the latlong position where the cursor is doesn't seem to be in the right position too.

void map_MouseMove(object sender, MouseEventArgs e)
{
    Point pointerLoc = e.GetPosition(map);
    VELatLong pointerLatLong = map.PointToLatLong(pointerLoc);

    if (pointerLatLong != null)
    {
        txtLat.Text = pointerLatLong.Latitude.ToString();
        txtLong.Text = pointerLatLong.Longitude.ToString();
        txtAltitude.Text = pointerLatLong.Altitude.ToString();
    }
}
Coordinator
Sep 23, 2010 at 4:45 PM

I just tried this and it is working fine for me. Are you using the latest source code drop from the Source Code tab?

Sep 23, 2010 at 5:39 PM

Hi joshb,

Sorry for the trouble. Guess I had downloaded the release V2 thinking it is the latest version. Anyway I got it working! Thanks you very much.

Sep 23, 2010 at 5:44 PM

Oh.. Just to inform you that the altitude always return a 0 value. Not sure why is it.

Coordinator
Sep 23, 2010 at 5:46 PM

No problem, I should probably update the official release tab.

Yes I noticed the altitude is always 0.

Coordinator
Sep 23, 2010 at 5:47 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Aug 2, 2011 at 11:40 AM
Edited Aug 2, 2011 at 12:02 PM

Is this still working for you? I tried the following code and the coordinates are off pretty significantly:

 

private readonly List<LatLonAlt> _polygon = new List<LatLonAlt>();

private void MapMouseClicked(object sender, MouseButtonEventArgs e)
{
    VEMap map = (VEMap)sender;
    VELatLong coordinates = map.PointToLatLong(e.GetPosition(map));
    LatLonAlt latLonAlt = LatLonAlt.CreateUsingDegrees(coordinates.Latitude, coordinates.Longitude, coordinates.Altitude);

    System.Diagnostics.Debug.WriteLine("Latitude: {0} - Longitude: {1}", coordinates.Latitude, coordinates.Longitude);

    _polygon.Add(latLonAlt);

    if (_polygon.Count > 1)
    {
        PolyInfo lineStyle = PolyInfo.DefaultPolyline;
        PolylineGeometry line = new PolylineGeometry("Location", Guid.NewGuid().ToString(), null, _polygon.ToArray(), PolylineGeometry.PolylineFormat.Polyline2D, lineStyle);

        lineStyle.AltitudeMode = AltitudeMode.FromGround;
        lineStyle.Filled = false;
        lineStyle.LineColor = System.Drawing.Color.Green;

        map.GlobeControl.Host.Geometry.AddGeometry(line);
    }
}

 

The XAML is incredibly short as this was a test:

 

<Window x:Class="TestMap.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ve="clr-namespace:InfoStrat.VE;assembly=InfoStrat.VE"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ve:VEMap MouseLeftButtonUp="MapMouseClicked" />
    </Grid>
</Window>

Aug 2, 2011 at 12:29 PM

Upon further investigation, I don't see how the coordinates could ever be accurate. I found the following code in VEMap.PointToLatLong():


LatLonAlt? lla = this.globeControl.Host.Navigation.LatLonAltFromScreenPosition(new System.Drawing.Point((int)point.Value.X, (int)point.Value.Y));

The System.Drawing.Point structure was built to work with Int32 points (hence, your casting). This poses a very significant problem for users that require accurate coordinates to be obtained from the mouse cursor location. As you have wrapped the MapPoint API, I don't see how you could improve upon this.

Is there an alternative technique I could look into? I don't mind updating your library, if that's what it's going to take.

Coordinator
Aug 20, 2011 at 6:30 AM

The mouse cursor location is reported as integers, even if the data structure is a double, so I don't see why this is a significant problem.