using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using Coordinate; using System.Globalization; public delegate void MyEventHandler(); public class CtrlCoordinate : MonoBehaviour { // delegate per richiamare un evento, una volta terminato di caricare la lista di punti public event MyEventHandler OnEventTriggered; string coordinateString = "(8.93266215617905 44.40604327943526, 8.932524131901832 44.40601228591227, 8.932359430658943 44.405996835286025, 8.93207661034279 44.40596474551083)"; public List coordinateList = new List(); public List PuntiList = new List(); public List cubeTextures = new List(); private static float scale = 10750000f; public GameObject referenceObject; public GameObject markerPrefab; public Transform markerParent; OnlineMapsMarkerManager onlineMaps; // Start is called before the first frame update void Start() { onlineMaps = GameObject.Find("Map").GetComponent(); // All of this stuff is used to convert the string to float and serialize the class Coordinate for eac value from the array! string modifiedCoordinaateString = coordinateString.Replace("(", "").Replace(")", ""); string[] coordinateArray = modifiedCoordinaateString.Split(new string[] { ", " }, StringSplitOptions.None); foreach (string coordinatePair in coordinateArray) { string[] coordinateValues = coordinatePair.Split(' '); decimal decimLongitude = decimal.Parse(coordinateValues[0], CultureInfo.InvariantCulture); decimal decimLatitude = decimal.Parse(coordinateValues[1], CultureInfo.InvariantCulture); float longitude = (float)decimal.Round(decimLongitude, 6); float latitude = (float)decimal.Round(decimLatitude, 6); CoordinateStruct coordinate = new CoordinateStruct(latitude, longitude); coordinateList.Add(coordinate); //Debug.Log(coordinate.latitude); } InstantiatePoints(); } // use this method to instanciate the gameobjects! void InstantiatePoints() { float distanzaTotale=0; float distanzaTotaleGeografica = 0; for (int i = 0; i < coordinateList.Count; i++) { CoordinateStruct coordinate = coordinateList[i]; GameObject pointObject = Instantiate(referenceObject); Vector2 coordinateAttuali = new Vector2(coordinate.longitude, coordinate.latitude); //Vector3 position = FromLongLat(coordinateAttuali); Vector3 position = AlbersProjection(coordinate.longitude, coordinate.latitude); pointObject.transform.position = position; PuntiList.Add(pointObject); if (i > 0) { float geographicDistance = CalculateGeographicDistance(coordinateList[i], coordinateList[i-1]); float distance = Vector3.Distance(PuntiList[i].transform.position, PuntiList[i-1].transform.position); Debug.Log($"distanza geografica = {geographicDistance}"); Debug.Log($"distnza vettori = {distance}"); distanzaTotale += distance; distanzaTotaleGeografica += geographicDistance; } } OnEventTriggered.Invoke(); Debug.Log(distanzaTotale); Debug.Log(distanzaTotaleGeografica); List line = new List(); for(int i = 0; i<= coordinateList.Count-1; i++) { Vector2 vector2 = new Vector2(coordinateList[i].longitude, coordinateList[i].latitude); line.Add(vector2); } OnlineMapsDrawingElementManager.AddItem(new OnlineMapsDrawingLine(line, Color.magenta, 5)); InstantiateMarkers(coordinateList); } // creiamo i marker in base alla mia lista di punti public void InstantiateMarkers(List coordinates) { foreach (CoordinateStruct coordinate in coordinates) { //GameObject markerObject = Instantiate(OnlineMapsMarkerManager. markerPrefab, markerParent);; OnlineMapsMarkerManager.CreateItem(coordinate.longitude, coordinate.latitude, onlineMaps.defaultTexture); } } public static Vector3 AlbersProjection(float latitude, float longitude) { // Coordinate di riferimento per Genova float centralMeridian = 8.9463f; // Longitudine di riferimento float standardParallel1 = 44f; // Primo parallelo standard float standardParallel2 = 45f; // Secondo parallelo standard // Conversione da gradi a radianti float latRad = Mathf.Deg2Rad * latitude; float longRad = Mathf.Deg2Rad * longitude; float centralMeridianRad = Mathf.Deg2Rad * centralMeridian; float stdParallel1Rad = Mathf.Deg2Rad * standardParallel1; float stdParallel2Rad = Mathf.Deg2Rad * standardParallel2; // Parametri per la proiezione di Albers float n = (Mathf.Sin(stdParallel1Rad) + Mathf.Sin(stdParallel2Rad)) / 2f; float c = Mathf.Pow(Mathf.Cos(stdParallel1Rad), 2f) + 2f * n * Mathf.Sin(stdParallel1Rad); float rho0 = Mathf.Sqrt(c - 2f * n * Mathf.Sin(stdParallel1Rad)) / n; // Calcolo della proiezione di Albers float rho = Mathf.Sqrt(c - 2f * n * Mathf.Sin(latRad)) / n; float theta = n * (longRad - centralMeridianRad); float x = scale * (rho * Mathf.Sin(theta)); float z = scale * (rho0 - rho * Mathf.Cos(theta)); return new Vector3(ScaleCoordinates(x)/2, 0, ScaleCoordinates(z)/2); } public static Vector3 GPSToMapCoords(float latitude, float longitude) { float radius = 6371000f; // raggio della Terra in metri float longitude0 = 0f; // longitudine di riferimento float latRad = Mathf.Deg2Rad * latitude; float longRad = Mathf.Deg2Rad * longitude; float x = scale*(radius * (longRad - Mathf.Deg2Rad * longitude0)); float y = 0; float z = scale*(radius * Mathf.Log(Mathf.Tan(Mathf.PI / 4f + latRad / 2f))); return new Vector3(ScaleCoordinates(x), y, ScaleCoordinates(z)); } //use this method to reduce the size of the number cause u really dont need all the firs part of the number, and smaller one can readed easily from unity transform! public static float ScaleCoordinates(float num) { // Converti il numero in una stringa string numString = num.ToString(); // Rimuovi le prime quattro cifre decimali string scaledString = numString.Substring(2); // Converti la stringa risultante in float float scaledNum = float.Parse(scaledString); // Restituisce il numero con le cifre decimali ridotte return scaledNum; } public static float CalculateGeographicDistance(CoordinateStruct coordinate1, CoordinateStruct coordinate2) { float earthRadius = 6371000f; float lat1Rad = Mathf.Deg2Rad * coordinate1.latitude; float lat2Rad = Mathf.Deg2Rad * coordinate2.latitude; float lon1Rad = Mathf.Deg2Rad * coordinate1.longitude; float lon2Rad = Mathf.Deg2Rad * coordinate2.longitude; float deltaLat = lat2Rad - lat1Rad; float deltaLon = lon2Rad - lon1Rad; float a = Mathf.Sin(deltaLat / 2) * Mathf.Sin(deltaLat / 2) + Mathf.Cos(lat1Rad) * Mathf.Cos(lat2Rad) * Mathf.Sin(deltaLon / 2) * Mathf.Sin(deltaLon / 2); float c = 2 * Mathf.Atan2(Mathf.Sqrt(a), Mathf.Sqrt(1 - a)); float distance = earthRadius * c; return distance; } }