public static List <GeocodingResult> ParseLatLongFromOKResponse(string address, string response, out string status, out string errorMessage) { var results = new List <GeocodingResult>(); // Need to box the struct to use a ref instead of copy value; see: https://docs.unity3d.com/ScriptReference/EditorJsonUtility.FromJsonOverwrite.html var root = new SunStudyGeocodingJson.RootObject(); object boxedRoot = root; JsonUtility.FromJsonOverwrite(response, boxedRoot); root = (SunStudyGeocodingJson.RootObject)boxedRoot; if (root != null) { status = root.status; if (root.results != null && root.results.Length > 0 && root.results[0] != null) { errorMessage = null; foreach (var jsonResult in root.results) { if (jsonResult != null) { var result = new GeocodingResult(); result.FormattedAddress = jsonResult.formatted_address; result.Latitude = jsonResult.geometry.location.lat; result.Longitude = jsonResult.geometry.location.lng; result.IsPartial = jsonResult.partial_match; result.IsApproximate = jsonResult.geometry.location_type == "APPROXIMATE" || jsonResult.geometry.location_type == "RANGE_INTERPOLATED"; results.Add(result); } } s_ResultCache.Add(address, results); } else { if (root.status == "ZERO_RESULTS") { // The error message is empty for this type of error. errorMessage = $"No results found for this address."; } else { errorMessage = root.error_message; } } } else { status = "unknown"; errorMessage = "Google geocoding response object is null."; } return(results); }
// Must be called on every update loop, otherwise the networking code will stop functioning properly. void ComputeAzimuthAltitude() { if (PlacementMode == SunPlacementMode.Geographical) { if (CoordinateMode == SunCoordinateMode.Address) { if (m_WaitingOnWebOperation != null && m_WaitingOnWebOperation.isDone) { var webRequest = m_WaitingOnWebOperation.webRequest; m_CurrentGeocodingAddressRequest = null; if (!webRequest.isHttpError && !webRequest.isNetworkError) { string status = ""; string errorMessage = null; List <GeocodingResult> results = SunStudyGeocoding.ParseLatLongFromOKResponse(CoordAddress, webRequest.downloadHandler.text, out status, out errorMessage); if (string.IsNullOrEmpty(errorMessage)) { if (results.Count > 0) { GeocodingResult result = results[0]; CoordLatitude = result.Latitude; CoordLongitude = result.Longitude; if (result.IsApproximate) { GeocodingMessage = "This address gives an approximate location."; } else if (result.IsPartial) { GeocodingMessage = "This address gives a partial match."; } else { GeocodingMessage = "This address gives many locations; using the first one."; } } else { GeocodingMessage = string.Empty; } } else { if (status == "ZERO_RESULTS") { GeocodingMessage = $"Need more details for the address, like street, city and country."; } else { GeocodingMessage = "The request has failed, see the console for details."; Debug.LogError($"Sun Study geocoding request error for '{CoordAddress}': {status} {errorMessage}"); } } } else { GeocodingMessage = "The request has failed; see the console for details."; Debug.LogError($"Sun Study geocoding request error for '{CoordAddress}': network error."); } webRequest.Dispose(); webRequest = null; m_WaitingOnWebOperation = null; } else if (m_WaitingOnWebOperation != null && !m_WaitingOnWebOperation.isDone) { if (m_CurrentGeocodingAddressRequest != null && m_CurrentGeocodingAddressRequest != CoordAddress) { // Since the address changed, abort the current request (set it to done, then clean up). m_WaitingOnWebOperation.webRequest.Abort(); } } else if (string.IsNullOrEmpty(m_CurrentGeocodingAddressRequest) && !string.IsNullOrWhiteSpace(CoordAddress)) { float cachedLatitude = 0f; float cachedLongitude = 0f; bool isCached = SunStudyGeocoding.TryGetAddressLatLong(CoordAddress, out cachedLatitude, out cachedLongitude); if (!isCached) { m_CurrentGeocodingAddressRequest = CoordAddress; bool errorFlag = false; m_WaitingOnWebOperation = SunStudyGeocoding.ConvertAddressToLatLong(CoordAddress, out errorFlag); if (errorFlag) { if (m_WaitingOnWebOperation != null) { if (m_WaitingOnWebOperation.webRequest != null) { m_WaitingOnWebOperation.webRequest.Dispose(); } m_WaitingOnWebOperation = null; } m_CurrentGeocodingAddressRequest = null; GeocodingMessage = "Make sure the Geocoding API Key is valid."; } } else { CoordLatitude = cachedLatitude; CoordLongitude = cachedLongitude; } } else if (string.IsNullOrWhiteSpace(CoordAddress)) { m_CurrentGeocodingAddressRequest = null; GeocodingMessage = string.Empty; } } else if (CoordinateMode == SunCoordinateMode.DegreesMinutesSeconds) { CoordLatitude = (CoordNSDeg + CoordNSMin / 60f + CoordNSSec / 3600f); CoordLatitude *= (CoordNS == SunCoordinateNS.South) ? -1f : +1f; CoordLongitude = (CoordEWDeg + CoordEWMin / 60f + CoordEWSec / 3600f); CoordLongitude *= (CoordEW == SunCoordinateEW.West) ? -1f : +1f; } int utcOffsetHour = (int)UtcOffset; int utcOffsetMinute = (int)((UtcOffset - utcOffsetHour) * 60f); var dateTime = new DateTimeOffset(Year, Month, Day, Hour, Minute, 0, new TimeSpan(utcOffsetHour, utcOffsetMinute, 0)); (Azimuth, Altitude) = CalculateSunPosition(dateTime, CoordLatitude, CoordLongitude); if (ApplyDimming) { Dimming = CalculateSolarDimming(dateTime, CoordLatitude, CoordLongitude, Altitude); } } }