microsoft / MapsSDK-Unity

This repository contains samples, documentation, and supporting scripts for Maps SDK, a Microsoft Garage project.
MIT License
652 stars 127 forks source link

Draw on Map #127

Closed minimalisticMe closed 2 years ago

minimalisticMe commented 3 years ago

Hi, I have trouble drawing on the 2D map example. I have coordinates that I want to convert lonlat-points to Vector3 in the local space in order to interpolate and animate a route.

I tried MapRendererTransformExtensions.TransformLatLonAltToLocalPoint with no success as it gives me coordinates like (0, 0.1, 0) which positions a point in the lower left corner.

How can I get Vector3 coordinates from Geo-points (longitude and latitude)?

kircher1 commented 3 years ago

TransformLatLonAltToLocalPoint should work, but since it's local space of the MapRenderer's GameObject, any transform position that use this local space value will need to be a child of the MapRenderer's GameObject.

A Vector3 value like (0, 0.1, 0) implies the LatLon is at the center of the map. X-axis here maps to east-west, Y-axis is altitude, Z-axis is north-south.

minimalisticMe commented 3 years ago

I chose my latlon to be not in the center and checked on another map that they are still in the visible map. I now also added the Images inside the MapRenderer's GameObject, but the results are still the same.

What else could I try? MapRendererTransformExtensions.TransformLatLonAltToLocalPoint(mapRenderer, latlonAlt) now returns (0.0, 0.1, 0.1) and MapRendererTransformExtensions.TransformLatLonAltToWorldPoint(mapRenderer, latlonAlt) returns (0.0, 0.1, 1.0) and are both not visible on the map.

kircher1 commented 3 years ago

I created a gist to test how LatLon => local. Check that out here. It is working as expected.

If you are trying to overlay waypoints of a route on the map, a more robust solution would involve using the MapPin system. The MapPin will automatically position the GameObject to a specified LatLon on the map, so if the map is zoomed, panned, or scaled, the MapPin will keep the position of the GameObject in sync automatically. (You can achieve similar functionality by calling TransformLatLonAltToLocalPoint/WorldPoint every frame.)

minimalisticMe commented 3 years ago

I don't know, what I am doing wrong, but even with your example, points are all on the lower left corner of the Game-View. The issue is the following: The map in Scene-View is very small on the lower left corner (see image below): grafik

If I zoom in very close, the map will be shown (and the instances of your example, even if not visible, are in that area): grafik

However in Game-View while running, it looks like this: grafik GameObjects still have the coordinates close to (0, 0) on the lower left, like where the mini map from the Scene-View is, but the map itself is fit to the screen.

minimalisticMe commented 3 years ago

I tried using MapPin with a minimal example: Create a GameObject, rotate x-axis by -90 and add a Script to it, that only contains

using Microsoft.Maps.Unity;

public class TestMapPinObject : MapPin
{  }

and reference that GameObject in a Script inside the MapRender Update:

mapPin.Location = latlon;

var mapPinList = new List<MapPin>();
mapPinList.Add(mapPin);

MapPin.SynchronizeLayers(mapPinList, mapRenderer);
MapPin.UpdateScales(mapPinList, mapRenderer);
var localSpace = mapPin.PositionInMapLocalSpace;

But localSpace then shows the initial coordinates of the MapPins-GameObject transform. Am I missing something?

kircher1 commented 3 years ago

The best path for generating MapPins via a script is: create a new GameObject, add a MapPin component to it, and assign the LatLon to that MapPin component. Then parent the MapPin GameObject to the MapRenderer GameObject.

var newGo = new GameObject();
var mapPin = newGo.AddComponent<MapPin>();
mapPin.Location = new LatLon(...);
newGo.transform.parent = _mapRenderer.transform;

The MapRenderer will update the positions of direct children objects with MapPin components every frame.

kircher1 commented 3 years ago

Note, the above code will have no visual associated with it, so you would need to attach some other object (like a sphere) to the new GameObject. A better way to do this is create a prefab asset that has a MapPin component at the root object, then Instantiate the prefab in a script, get the MapPin component, assign a LatLon value to it, and set the transform's parent to the MapRenderer's transform.

minimalisticMe commented 3 years ago

I tried MapPin and referencing the MapRenderer like you suggested but still have no luck with it. The coordinates still seem to refer to the small map mentioned above.

I create a minimal working example featuring my problem where I cannot draw on map/get the position of the desired coordinates). Please see https://github.com/minimalisticMe/MapTest2021 for my project (I removed the MapKey).

The script of interest is file Microsoft_Map.cs.

costarita commented 2 years ago

hey minimalisticMe, i am having problems displaying the location of my smartphone live on the map. can you please help me with that? its for my bachelorproject and i need help asap.

minimalisticMe commented 2 years ago

Well I didn't follow up on this and just had a look at it again. I went horribly wrong with camera perspective and multiple canvas.

For me the fix was to start from scratch and combine both Example Projects 2DMapExample and MapPinExample. Be aware to not create a canvas inside your Map-component.

@costarita What do you mean by "having trouble displaying the location of your smart phone"? Do you have access to the Location API of your phone? What is handling the GPS? As for me I do that operation outside of Unity and just "feed" the unity project with LatLon information. Also it might be better to create a new Issue for new problems, else they get overloaded and lack their initial purpose.