1 (edited by elfasito 2020-12-03 20:30:06)

Topic: script for calculate distance to a multiple marks in map.

Hello im triying to create a script for add multiple markers to the map and calculate the distance from gps to all markers at the same time.

seeing the atlas examples I do some progress but im stuck now.

I want to update the distance to the markers what already exist in the list, getting the cordinares from gps sensor.

my main problem is I cant update the distance to the markers in each itineration, the function just duplicate the markers each itineration.

EDIT: SOLVED, new code solution:

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;

namespace InfinityCode.OnlineMapsDemos
{
    public class CustomMarkersEngineV5 : MonoBehaviour
    {
        private List<MarkerInstance> markers;
        public RectTransform containerCanvas;
        public GameObject MarkerIcons;
        public Options Using;
        public Vector2 UserGPS;
        private Vector2 SensorGPS;
        public MarkerData[] datas;

        private Canvas canvas;
        private OnlineMaps map;
        private OnlineMapsTileSetControl control;

        private float longitude;
        private float latitude;
        public float longitudeGPS;
        public float latitudeGPS;

        private float distance;

        private Camera worldCamera
        {
            get
            {
                if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) return null;
                return canvas.worldCamera;
            }
        }

        private void OnEnable()
        {
            canvas = containerCanvas.GetComponentInParent<Canvas>();
        }

        private void SetText(RectTransform rt, string childName, string value)
        {
            Transform child = rt.Find(childName);
            if (child == null) return;

            Text t = child.gameObject.GetComponent<Text>();
            if (t != null) t.text = value;
        }

        private void Start()
        {
            map = OnlineMaps.instance;
            control = OnlineMapsTileSetControl.instance;

            map.OnMapUpdated += UpdateMarkers;
            OnlineMapsCameraOrbit.instance.OnCameraControl += UpdateMarkers;

            markers = new List<MarkerInstance>();

            foreach (MarkerData data in datas)
            {
                GameObject markerGameObject = Instantiate(MarkerIcons) as GameObject;
                markerGameObject.name = data.title;
                RectTransform rectTransform = markerGameObject.transform as RectTransform;
                rectTransform.SetParent(containerCanvas);
                markerGameObject.transform.localScale = Vector3.one;
                MarkerInstance marker = new MarkerInstance();
                marker.data = data;
                marker.gameObject = markerGameObject;
                marker.transform = rectTransform;
                if (markers.Any(m => m.data == data))
                {
                    distance = OnlineMapsUtils.DistanceBetweenPoints(UserGPS, marker.data.MarkerGPS).magnitude; //this not work in unity editor (show value 0), because PC dont have a GPS Sensor
                    marker.data.DistanceKM.text = distance.ToString("F1") + " KM";
                    continue;
                }
                markers.Add(marker);
                SetText(rectTransform, "Title", data.title);
                SetText(rectTransform, "cellphoneNumber", data.cellphoneNumber);
                SetText(rectTransform, "emailAdress", data.emailAdress);
            }

            MarkersInMap();
            UpdateMarkers();
            InvokeRepeating("UpdateLocation", 2.0f, 1.0f); //initiate function in 2 seconds after start, and repeat it every 1 seconds.                        
        }

        private void MarkersInMap()
        {
            foreach (MarkerData data in datas)
            {
                MarkerInstance marker = new MarkerInstance();
                marker.data = data;
                if (markers.Any(m => m.data == data))
                {
                    distance = OnlineMapsUtils.DistanceBetweenPoints(UserGPS, marker.data.MarkerGPS).magnitude;
                    marker.data.DistanceKM.text = distance.ToString("F1") + " KM";
                    continue;
                }
                markers.Add(marker);                             
            }
            UpdateMarkers();
        }

        private void UpdateMarkers()
        {
            foreach (MarkerInstance marker in markers) UpdateMarker(marker);
        }

        private void UpdateMarker(MarkerInstance marker)
        {            
            Vector2 screenPosition = control.GetScreenPosition(marker.data.MarkerGPS.y, marker.data.MarkerGPS.x); // y is inverted with x because shows the cordinares incorrectly if X axis is at firt.
            if (screenPosition.x < 0 || screenPosition.x > Screen.width ||
                screenPosition.y < 0 || screenPosition.y > Screen.height)
            {
                marker.gameObject.SetActive(false);
                return;
            }

            RectTransform markerRectTransform = marker.transform;

            if (!marker.gameObject.activeSelf) marker.gameObject.SetActive(true);

            Vector2 point;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(markerRectTransform.parent as RectTransform, screenPosition, worldCamera, out point);
            markerRectTransform.localPosition = point;
        }


        private void UpdateLocation()
        {
            switch (Using)
            {
                case Options.Simulator:
                    MarkersInMap(); //I used this function here just for test in unity editor.

                    break;

                case Options.gpsSensor:
                    GetLocationGPS();
                    MarkersInMap();
                    //Debug.Log("use gps sensor");

                    break;
            }
        }

        private void GetLocationGPS()
        {
            longitude = Input.location.lastData.longitude;    //get last longitude from GPS Sensor
            latitude = Input.location.lastData.latitude;      //get last latitude from GPS Sensor
            SensorGPS = new Vector2(latitude, longitude);  //store the longitude & latitude from GPS sensor in a Vector2
            UserGPS = SensorGPS;  //copy the gps sensor cordinares for use in distance updates.

            longitudeGPS = SensorGPS.x;
            latitudeGPS = SensorGPS.y;
        }

        public enum Options
        {
            Simulator,
            gpsSensor
        }

        [Serializable]
        public class MarkerData
        {
            public string title;
            public string cellphoneNumber;
            public string emailAdress;
            public Vector2 MarkerGPS;
            
            public Text DistanceKM;
        }

        public class MarkerInstance
        {
            public MarkerData data;
            public GameObject gameObject;
            public RectTransform transform;
        }
    }
}

Im using this function:

switch (Using)
            {
                case Options.Simulator:
                    MarkersInMap(); //I used this function here just for test in unity editor.
                    break;

to simulate the iterations from gps sensor. If I disable it go works fine in editor, because only itinerates one time (Start function).

maybe my explanation is a bit unclear, I will try to rewrite, if it is not understandable.

Re: script for calculate distance to a multiple marks in map.

Hello.

You have two ways:
1. (Recommended) Check that the marker with the current data is already in the list.

if (markers.Any(m => m.data == data)) 
{
  // update distance and continue
  continue;
}

2. At the beginning of MarkersInMap remove all markers.

P.S. You cannot work with GPS in the editor because you are using the Unity Location Service.
Use Online Maps Location Service instead. It has a GPS emulator and you will be able to debug your application in the editor.

P.P.S. In MarkersInMap, move the UpdateMarkers call outside of the foreach.

Kind Regards,
Infinity Code Team.

uContext is Editor PowerPack (more than 50 tools) that take your workflow in Unity Editor to a next level, simplifies working with content, adds new features, corrects and improves the editor’s built-in behaviors. Click here to download uContext Basic for free.

3 (edited by elfasito 2020-12-03 21:34:12)

Re: script for calculate distance to a multiple marks in map.

@Alex Vertax
Thanks, its working now, I dont see any problems.
I updated the code in my post, If you want to point something for make improvements.

A doubt, is possible what the markers created by this script cant be scaled when I zooming the map?.

Re: script for calculate distance to a multiple marks in map.

In MarkersInMap, why would you create a marker?
Also, you don't even need a check.

private void MarkersInMap()
{
  foreach (MarkerData data in datas)
  {
    distance = OnlineMapsUtils.DistanceBetweenPoints(UserGPS, data.MarkerGPS).magnitude;
    data.DistanceKM.text = distance.ToString("F1") + " KM";
  }
  UpdateMarkers();
}
Kind Regards,
Infinity Code Team.

uContext is Editor PowerPack (more than 50 tools) that take your workflow in Unity Editor to a next level, simplifies working with content, adds new features, corrects and improves the editor’s built-in behaviors. Click here to download uContext Basic for free.

Re: script for calculate distance to a multiple marks in map.

getting an error NullReferenceException: Object reference not set to an instance of an object
InfinityCode.OnlineMapsDemos.dist.Start () (at Assets/dist.cs:69)

line no 69 is this    rectTransform.SetParent(containerCanvas);

Re: script for calculate distance to a multiple marks in map.

This is a bug in your script.
rectTransform is null.

Kind Regards,
Infinity Code Team.

uContext is Editor PowerPack (more than 50 tools) that take your workflow in Unity Editor to a next level, simplifies working with content, adds new features, corrects and improves the editor’s built-in behaviors. Click here to download uContext Basic for free.

Re: script for calculate distance to a multiple marks in map.

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;

namespace InfinityCode.OnlineMapsDemos
{
    public class CustomMarkersEngineV5 : MonoBehaviour
    {
        private List<MarkerInstance> markers;
        public RectTransform containerCanvas;
        public GameObject MarkerIcons;
        public Options Using;
        public Vector2 UserGPS;
        private Vector2 SensorGPS;
        public MarkerData[] datas;

        private Canvas canvas;
        private OnlineMaps map;
        private OnlineMapsTileSetControl control;

        private float longitude;
        private float latitude;
        public float longitudeGPS;
        public float latitudeGPS;

        private float distance;

        private Camera worldCamera
        {
            get
            {
                if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) return null;
                return canvas.worldCamera;
            }
        }

        private void OnEnable()
        {
            canvas = containerCanvas.GetComponentInParent<Canvas>();
        }

        private void SetText(RectTransform rt, string childName, string value)
        {
            Transform child = rt.Find(childName);
            if (child == null) return;

            Text t = child.gameObject.GetComponent<Text>();
            if (t != null) t.text = value;
        }

        private void Start()
        {
            map = OnlineMaps.instance;
            control = OnlineMapsTileSetControl.instance;

            map.OnMapUpdated += UpdateMarkers;
            OnlineMapsCameraOrbit.instance.OnCameraControl += UpdateMarkers;

            markers = new List<MarkerInstance>();

            foreach (MarkerData data in datas)
            {
                GameObject markerGameObject = Instantiate(MarkerIcons) as GameObject;
                markerGameObject.name = data.title;
                RectTransform rectTransform = markerGameObject.transform as RectTransform;
                rectTransform.SetParent(containerCanvas);
                markerGameObject.transform.localScale = Vector3.one;
                MarkerInstance marker = new MarkerInstance();
                marker.data = data;
                marker.gameObject = markerGameObject;
                marker.transform = rectTransform;
                if (markers.Any(m => m.data == data))
                {
                    distance = OnlineMapsUtils.DistanceBetweenPoints(UserGPS, marker.data.MarkerGPS).magnitude; //this not work in unity editor (show value 0), because PC dont have a GPS Sensor
                    marker.data.DistanceKM.text = distance.ToString("F1") + " KM";
                    continue;
                }
                markers.Add(marker);
                SetText(rectTransform, "Title", data.title);
                SetText(rectTransform, "cellphoneNumber", data.cellphoneNumber);
                SetText(rectTransform, "emailAdress", data.emailAdress);
            }

            MarkersInMap();
            UpdateMarkers();
            InvokeRepeating("UpdateLocation", 2.0f, 1.0f); //initiate function in 2 seconds after start, and repeat it every 1 seconds.                       
        }

        private void MarkersInMap()
        {
            foreach (MarkerData data in datas)
            {
                MarkerInstance marker = new MarkerInstance();
                marker.data = data;
                if (markers.Any(m => m.data == data))
                {
                    distance = OnlineMapsUtils.DistanceBetweenPoints(UserGPS, marker.data.MarkerGPS).magnitude;
                    marker.data.DistanceKM.text = distance.ToString("F1") + " KM";
                    continue;
                }
                markers.Add(marker);                             
            }
            UpdateMarkers();
        }

        private void UpdateMarkers()
        {
            foreach (MarkerInstance marker in markers) UpdateMarker(marker);
        }

        private void UpdateMarker(MarkerInstance marker)
        {           
            Vector2 screenPosition = control.GetScreenPosition(marker.data.MarkerGPS.y, marker.data.MarkerGPS.x); // y is inverted with x because shows the cordinares incorrectly if X axis is at firt.
            if (screenPosition.x < 0 || screenPosition.x > Screen.width ||
                screenPosition.y < 0 || screenPosition.y > Screen.height)
            {
                marker.gameObject.SetActive(false);
                return;
            }

            RectTransform markerRectTransform = marker.transform;

            if (!marker.gameObject.activeSelf) marker.gameObject.SetActive(true);

            Vector2 point;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(markerRectTransform.parent as RectTransform, screenPosition, worldCamera, out point);
            markerRectTransform.localPosition = point;
        }


        private void UpdateLocation()
        {
            switch (Using)
            {
                case Options.Simulator:
                    MarkersInMap(); //I used this function here just for test in unity editor.

                    break;

                case Options.gpsSensor:
                    GetLocationGPS();
                    MarkersInMap();
                    //Debug.Log("use gps sensor");

                    break;
            }
        }

        private void GetLocationGPS()
        {
            longitude = Input.location.lastData.longitude;    //get last longitude from GPS Sensor
            latitude = Input.location.lastData.latitude;      //get last latitude from GPS Sensor
            SensorGPS = new Vector2(latitude, longitude);  //store the longitude & latitude from GPS sensor in a Vector2
            UserGPS = SensorGPS;  //copy the gps sensor cordinares for use in distance updates.

            longitudeGPS = SensorGPS.x;
            latitudeGPS = SensorGPS.y;
        }

        public enum Options
        {
            Simulator,
            gpsSensor
        }

        [Serializable]
        public class MarkerData
        {
            public string title;
            public string cellphoneNumber;
            public string emailAdress;
            public Vector2 MarkerGPS;
           
            public Text DistanceKM;
        }

        public class MarkerInstance
        {
            public MarkerData data;
            public GameObject gameObject;
            public RectTransform transform;
        }
    }
}

i was using this script only which was mentioned above getting error at line 69

Re: script for calculate distance to a multiple marks in map.

In this case, the problem is that your MarkerIcons is not UI element and does not contain RectTransform.

Kind Regards,
Infinity Code Team.

uContext is Editor PowerPack (more than 50 tools) that take your workflow in Unity Editor to a next level, simplifies working with content, adds new features, corrects and improves the editor’s built-in behaviors. Click here to download uContext Basic for free.