AR + GPS Location  3.0.0
All Classes Namespaces Functions Variables Properties Events Pages
Location.cs
1 using UnityEngine;
2 using System;
3 using UnityEngine.Serialization;
4 
5 namespace ARLocation
6 {
7  public enum AltitudeMode {
8  GroundRelative,
9  DeviceRelative,
10  Absolute,
11  Ignore
12  };
13 
17  [Serializable]
18  public class Location
19  {
20  [FormerlySerializedAs("latitude")] [Tooltip("The latitude, in degrees.")]
21  public double Latitude;
22 
23  [FormerlySerializedAs("longitude")] [Tooltip("The longitude, in degrees.")]
24  public double Longitude;
25 
26  [FormerlySerializedAs("altitude")] [Tooltip("The altitude, in meters.")]
27  public double Altitude;
28 
29  [FormerlySerializedAs("altitudeMode")]
30  [Space(4)]
31 
32  [Tooltip("The altitude mode. 'Absolute' means absolute altitude, relative to the sea level. 'DeviceRelative' meas it is " +
33  "relative to the device's initial position. 'GroundRelative' means relative to the nearest detected plane, and 'Ignore' means the " +
34  "altitude is ignored (equivalent to setting it to zero).")]
35  public AltitudeMode AltitudeMode = AltitudeMode.GroundRelative;
36 
37  [FormerlySerializedAs("label")] [Tooltip("An optional label for the location.")]
38  public string Label = "";
39 
40  public bool IgnoreAltitude => AltitudeMode == AltitudeMode.Ignore;
41 
46  public DVector2 HorizontalVector => new DVector2(Latitude, Longitude);
47 
48  public Location(double latitude = 0.0, double longitude = 0.0, double altitude = 0.0)
49  {
50  Latitude = latitude;
51  Longitude = longitude;
52  Altitude = altitude;
53  }
54 
59  public Location Clone()
60  {
61  return new Location()
62  {
63  Label = Label,
64  Latitude = Latitude,
65  Longitude = Longitude,
66  Altitude = Altitude,
67  AltitudeMode = AltitudeMode
68  };
69  }
70 
71  public override string ToString()
72  {
73  return "(" + Latitude + ", " + Longitude + ", " + Altitude + ")";
74  }
75 
76  public DVector3 ToDVector3()
77  {
78  return new DVector3(Longitude, Altitude, Latitude);
79  }
80 
81  public Vector3 ToVector3()
82  {
83  return ToDVector3().toVector3();
84  }
85 
91  public static DVector3 LocationToEcef(Location l) {
92  var rad = Math.PI / 180;
93 
94  var lat = l.Latitude * rad;
95  var lon = l.Longitude * rad;
96  var a = ARLocation.Config.EarthEquatorialRadiusInKM * 1000;
97  var e2 = ARLocation.Config.EarthFirstEccentricitySquared;
98  var N = a / Math.Sqrt(1 - e2 * Math.Pow(Math.Sin(lat), 2));
99 
100  var x = N * Math.Cos(lat) * Math.Cos(lon);
101  var y = N * Math.Cos(lat) * Math.Sin(lon);
102  var z = (1 - e2) * N * Math.Sin(lat);
103 
104  return new DVector3(x, y, z);
105  }
106 
114  var rad = Math.PI / 180;
115  var lat = l1.Latitude * rad;
116  var lon = l1.Longitude * rad;
117  var p1 = LocationToEcef(l1);
118  var p2 = LocationToEcef(l2);
119  var delta = p2 - p1;
120 
121  var slat = Math.Sin(lat);
122  var clat = Math.Cos(lat);
123  var slon = Math.Sin(lon);
124  var clon = Math.Cos(lon);
125 
126  var e = -slon * delta.x + clon * delta.y;
127  var n = -clon * slat * delta.x -slat * slon * delta.y+ clat*delta.z;
128 
129  return new DVector2(n, e);
130  }
131 
140  public static Location LocationFromEnu(Location center, double e, double n, double u)
141  {
142  var lat = DegToRad(center.Latitude);
143  var lon = DegToRad(center.Longitude);
144 
145  var slat = Math.Sin(lat);
146  var clat = Math.Cos(lat);
147  var slon = Math.Sin(lon);
148  var clon = Math.Cos(lon);
149 
150  var dx = -e * slon - n * clon * slat + u * clon * clat;
151  var dy = e * clon - n * slon * slat + u * slon * clat;
152  var dz = n * clat + u * slat;
153 
154  var centerEcef = LocationToEcef(center);
155 
156  var pointEcef = centerEcef + new DVector3(dx, dy, dz);
157 
158  var pointLocation = EcefToLocation(pointEcef);
159 
160  return pointLocation;
161  }
162 
168  public static Location EcefToLocation(DVector3 ecef)
169  {
170  var a = ARLocation.Config.EarthEquatorialRadiusInKM * 1000.0;
171  var e2 = ARLocation.Config.EarthFirstEccentricitySquared;
172  var b = a * Math.Sqrt(1 - e2);
173 
174  var x = ecef.x;
175  var y = ecef.y;
176  var z = ecef.z;
177 
178  var r = Math.Sqrt(x * x + y * y);
179  var E2 = (a * a - b * b) / (b * b);
180  var F = 54 * b * b * z * z;
181  var G = r * r + (1 - e2) * z * z - e2 * (a * a - b * b);
182  var c = (e2 * e2 * F * r * r) / (G * G * G);
183  var s = Math.Pow(1 + c + Math.Sqrt(c*c + 2*c), 1.0 / 3.0);
184  var P = F / (3 * Math.Pow(s + (1.0/s) +1, 2.0) * G * G);
185  var Q = Math.Sqrt(1 + 2 * e2 * e2 * P);
186  var r0 = -(P * e2 * r) / (1 + Q) + Math.Sqrt(((a * a * 0.5) * (1.0 + (1.0 / Q))) - ((P * (1 - e2) * z * z) / (Q * (1.0 + Q))) - (P*r*r*0.5));
187  var U = Math.Sqrt(Math.Pow(r - e2 * r0, 2) + z*z);
188  var V = Math.Sqrt(Math.Pow(r - e2 * r0, 2) + (1 - e2) * z * z);
189  var z0 = (b * b * z) / (a * V);
190 
191  var h = U * (1 - ((b * b) / (a * V)));
192  var phi = Math.Atan((z + E2 * z0) / r);
193  var lambda = Math.Atan2(y, x);
194 
195  var rad2deg = 180.0 / Math.PI;
196 
197  return new Location()
198  {
199  Latitude = rad2deg * phi,
200  Longitude = rad2deg * lambda,
201  Altitude = h,
202  AltitudeMode = AltitudeMode.GroundRelative
203  };
204  }
205 
206 
214  public static double HorizontalDistance(Location l1, Location l2)
215  {
216 #if ARGPS_CUSTOM_GEO_CALC
217  return ArGpsCustomGeoCalc.HorizontalVectorFromTo(l1, l2).magnitude;
218 #else
219  return VectorFromToEcefEnu(l1, l2).magnitude;
220 #endif
221  }
222 
229  public static double DistanceWithAltitude(Location l1, Location l2)
230  {
231  var d = HorizontalDistance(l1, l2);
232  var h = Math.Abs(l1.Altitude - l2.Altitude);
233 
234  return Math.Sqrt(d * d + h * h);
235  }
236 
244  {
245 #if ARGPS_USE_CUSTOM_GEO_CALC
246  return ArGpsCustomGeoCalc.HorizontalVectorFromTo(l1, l2);
247 #else
248  return VectorFromToEcefEnu(l1, l2);
249 #endif
250  }
251 
259  public static DVector3 VectorFromTo(Location l1, Location l2, bool ignoreHeight = false)
260  {
261  var horizontal = HorizontalVectorFromTo(l1, l2);
262  var height = l2.Altitude - l1.Altitude;
263 
264  return new DVector3(horizontal.y, ignoreHeight ? 0 : height, horizontal.x);
265  }
266 
276  public static Vector3 GetGameObjectPositionForLocation(Transform arLocationRoot, Vector3 userPosition, Location userLocation, Location objectLocation, bool heightIsRelative)
277  {
278  var displacementVector = VectorFromTo(userLocation, objectLocation, objectLocation.IgnoreAltitude || heightIsRelative)
279  .toVector3();
280 
281  var displacementPosition = arLocationRoot ? arLocationRoot.TransformVector(displacementVector) : displacementVector;
282 
283  return userPosition + displacementPosition + new Vector3(0, (heightIsRelative && !objectLocation.IgnoreAltitude) ? ((float)objectLocation.Altitude - userPosition.y) : 0, 0);
284  }
285 
296  public static Vector3 GetGameObjectPositionForLocation(Transform arLocationRoot, Transform user, Location userLocation, Location objectLocation, bool heightIsRelative)
297  {
298  return GetGameObjectPositionForLocation(arLocationRoot, user.position, userLocation, objectLocation,
299  heightIsRelative);
300  }
301 
311  public static void PlaceGameObjectAtLocation(Transform arLocationRoot, Transform transform, Transform user, Location userLocation, Location objectLocation, bool heightIsRelative)
312  {
313  transform.position = GetGameObjectPositionForLocation(arLocationRoot, user, userLocation, objectLocation, heightIsRelative);
314  }
315 
324  public static Location GetLocationForWorldPosition(Transform arLocationRoot, Vector3 center, Location userLocation, Vector3 worldPosition)
325  {
326  var cameraLocalPosition = arLocationRoot.InverseTransformVector(center);
327  var position = arLocationRoot.InverseTransformVector(worldPosition);
328  var n = position.z - center.z;
329  var e = position.x - center.x;
330  var u = 0;
331  var loc = LocationFromEnu(userLocation, e, n, u);
332 
333  Debug.Log(loc);
334 
335  return loc;
336  }
337 
338  public static bool Equal(Location a, Location b, double eps = 0.0000001)
339  {
340  return (Math.Abs(a.Latitude - b.Latitude) <= eps) &&
341  (Math.Abs(a.Longitude - b.Longitude) <= eps) &&
342  (Math.Abs(a.Altitude - b.Altitude) <= eps);
343  }
344 
345  public static double RadToDeg(double rad)
346  {
347  return (180.0 * Math.PI) * rad;
348  }
349 
350  public static double DegToRad(double deg)
351  {
352  return (Math.PI/ 180.0) * deg;
353  }
354  }
355 }
ARLocation.Location.EcefToLocation
static Location EcefToLocation(DVector3 ecef)
Converts from (x, y, z) ECEF coordinates to a wgs84 Location.
Definition: Location.cs:168
ARLocation.Location.HorizontalVector
DVector2 HorizontalVector
Gets the horizontal vector.
Definition: Location.cs:46
ARLocation.Location.Clone
Location Clone()
Clones this instance.
Definition: Location.cs:59
ARLocation.Location.HorizontalVectorFromTo
static DVector2 HorizontalVectorFromTo(Location l1, Location l2)
Calculates the horizontal vector pointing from l1 to l2, in meters.
Definition: Location.cs:243
ARLocation.DVector2.magnitude
double magnitude
Gets the magnitude of the vector.
Definition: DVector2.cs:18
ARLocation.Location
Represents a geographical location.
Definition: Location.cs:19
ARLocation.Location.DistanceWithAltitude
static double DistanceWithAltitude(Location l1, Location l2)
Calculates the full distance between locations, taking altitude into account.
Definition: Location.cs:229
ARLocation.DVector3
Definition: DVector3.cs:9
ARLocation.Location.LocationToEcef
static DVector3 LocationToEcef(Location l)
Given a Location returns the corresponding (x, y, z) ECEF coordinates.
Definition: Location.cs:91
ARLocation.DVector3.toVector3
Vector3 toVector3()
Converts to a Vector3.
Definition: DVector3.cs:66
ARLocation.Location.VectorFromToEcefEnu
static DVector2 VectorFromToEcefEnu(Location l1, Location l2)
Given a pair of locations, returns the local-plane ENU coordinates, considering the first location,...
Definition: Location.cs:113
ARLocation.Location.GetLocationForWorldPosition
static Location GetLocationForWorldPosition(Transform arLocationRoot, Vector3 center, Location userLocation, Vector3 worldPosition)
Calculates the wgs84 Location for a given world position vector.
Definition: Location.cs:324
ARLocation.Location.HorizontalDistance
static double HorizontalDistance(Location l1, Location l2)
Calculates the horizontal distance according to the current function set in the configuration.
Definition: Location.cs:214
ARLocation.Location.GetGameObjectPositionForLocation
static Vector3 GetGameObjectPositionForLocation(Transform arLocationRoot, Transform user, Location userLocation, Location objectLocation, bool heightIsRelative)
Gets the game object world-position for location.
Definition: Location.cs:296
ARLocation.Location.GetGameObjectPositionForLocation
static Vector3 GetGameObjectPositionForLocation(Transform arLocationRoot, Vector3 userPosition, Location userLocation, Location objectLocation, bool heightIsRelative)
Gets the game object world-position for location.
Definition: Location.cs:276
ARLocation
Definition: ARLocationConfigInspector.cs:7
ARLocation.DVector2
Definition: DVector2.cs:9
ARLocation.Location.PlaceGameObjectAtLocation
static void PlaceGameObjectAtLocation(Transform arLocationRoot, Transform transform, Transform user, Location userLocation, Location objectLocation, bool heightIsRelative)
Places the game object at location.
Definition: Location.cs:311
ARLocation.Location.LocationFromEnu
static Location LocationFromEnu(Location center, double e, double n, double u)
Given a center location, and the local-plane ENU coordinates of a second point, calculates the Locati...
Definition: Location.cs:140
ARLocation.Location.VectorFromTo
static DVector3 VectorFromTo(Location l1, Location l2, bool ignoreHeight=false)
Calculates the vector from l1 to l2, in meters, taking altitude into account.
Definition: Location.cs:259