// - Implementation of: https://github.com/mapbox/utfgrid-spec by [email protected] /// <summary> /// Gets utf grid data from the layer .mbtiles file representing the tile > pixel location directly below the mouse pointer. /// </summary> /// <value>JSON formatted string from the mbtiles file's utf grid data.</value> public string UtfGridJsonString() { if (Map.CurrentZoom > maxZoom || Map.CurrentZoom < minZoom) { return(null); } RaycastHit[] _raycastHits; Ray _ray = Map.CurrentCamera.ScreenPointToRay(UnityEngine.Input.mousePosition); _raycastHits = Physics.RaycastAll(_ray); RaycastHit _tileHit = new RaycastHit(); bool _tileFound = false; // RaycastHit is not nullable so we need a flag to check against foreach (RaycastHit _rch in _raycastHits) { // make sure it's a tile if (_rch.transform.GetComponent <TileBehaviour>() != null) { // don't bother if the renderer is off if (_rch.transform.GetComponent <MeshRenderer>().enabled == true) { _tileHit = _rch; _tileFound = true; #if DEBUG_LOG Debug.Log("Using tile: " + _tileHit.transform.name); #endif break; } } } if (!_tileFound) { #if DEBUG_LOG Debug.LogWarning("No suitable tile found."); #endif return(null); } double[] _locWgs84 = GeoHelpers.RaycastHitToWGS84(Map, _tileHit); // there's no sensible way to resolve _raycastHits[_hitIndex] to a tile location (z,x,y) so we'll get it here using WGS84ToTile int[] _tileLoc = UnitySlippyMap.Helpers.GeoHelpers.WGS84ToTile(_locWgs84[0], -_locWgs84[1], Map.RoundedZoom); _tileLoc = new int[3] { _tileLoc[0], _tileLoc[1], Map.RoundedZoom }; // Use the tile location to get the grid blob containing the utf keys DataTable dt; string _query = string.Format("SELECT grid FROM grids WHERE zoom_level={0} AND tile_column={1} AND tile_row={2}", _tileLoc[2], _tileLoc[0], _tileLoc[1]); #if DEBUG_LOG Debug.Log("Executing query: " + _query); #endif try { dt = db.ExecuteQuery(_query); } catch (Exception e) { #if DEBUG_LOG Debug.LogWarning("No utf data? " + e); #endif // make sure the sql shiznit can continue to be used for getting tile images Close(); Open(); return(null); } if (dt.Rows.Count == 0) { #if DEBUG_LOG Debug.LogWarning(String.Format("No utf grid blob data returned for tile: x={0}, y={1}, zoom={2}.", _tileLoc[2], _tileLoc[0], _tileLoc[1])); #endif } byte[] _gridBlobBytes = (byte[])dt.Rows[0]["grid"]; // decompress the bytes to a json string string _jsonString = Zip.DecompressGzipJsonBytes(_gridBlobBytes); #if DEBUG_LOG Debug.Log("JSON char key string exctracted:\n" + _jsonString); #endif // - NOTE: I'd prefer to use Newtonsoft.Json.dll for this and deserialise it to a class // object, but the lib is ~500KB of additional data. So, I'm using SimpleJson as it is tiny // at only 33KB and can be found here: http://wiki.unity3d.com/index.php/SimpleJSON SimpleJSON.JSONNode _jsonData = SimpleJSON.JSON.Parse(_jsonString); string _tileKey = TileBehaviour.GetTileKey(_tileLoc[2], _tileLoc[0], _tileLoc[1]); if (!tiles.ContainsKey(_tileKey)) { #if DEBUG_LOG Debug.LogWarning("No tile found for key: " + _tileKey); #endif return(null); } else { TileBehaviour _tile = tiles[_tileKey]; int _res = _jsonData["grid"].Count; int _tileSize = 256; // pixel resolution of the tile image Vector3 _invPt = _tileHit.transform.InverseTransformPoint(_tileHit.point); int _px = Mathf.FloorToInt(256 * (_invPt.x + 0.5f)); int _py = Mathf.FloorToInt(256 * (_invPt.z + 0.5f)); int _x = Mathf.FloorToInt(_px / (_tileSize / _res)); int _y = Mathf.FloorToInt(_py / (_tileSize / _res)); // the y order is top down, reverse it _y = (_res - _y) - 1; _x--; #if DEBUG_LOG Debug.Log(string.Format("Finding utf data for pixel {0}, {1}...", _x, _y)); #endif // try to get the key from the json data char _charKey; try { _charKey = ((string)_jsonData["grid"][_y])[_x]; } catch (Exception e) { #if DEBUG_LOG Debug.LogWarning(string.Format("Could not retrive char key {0}, {1} - {2}", _x, _y, e)); #endif return(null); } string _hexValue = Convert.ToInt32(_charKey).ToString("X"); //if (_charKey == ' ') //return null; int _resolvedkey = ResolveCode(int.Parse(_hexValue, System.Globalization.NumberStyles.HexNumber)); _resolvedkey--; // ?!? string _gridDataKey = _jsonData["keys"][_resolvedkey].ToString().Replace("\"", ""); if (_gridDataKey != null) { _query = string.Format("SELECT key_json FROM grid_data WHERE key_name=\"{0}\" AND zoom_level={1} AND tile_column={2} AND tile_row={3}", _gridDataKey, _tileLoc[2], _tileLoc[0], _tileLoc[1]); #if DEBUG_LOG Debug.Log("Executing sql query: " + _query); #endif try { dt = db.ExecuteQuery(_query); } catch (Exception e) { #if DEBUG_LOG Debug.LogWarning("Could not resolve key: " + _gridDataKey + ". - " + e); #endif // make sure the sql shiznit can continue to be used for getting tile images Close(); Open(); return(null); } if (dt.Rows.Count != 0) { string _returnString = (string)dt.Rows[0]["key_json"]; #if DEBUG_LOG Debug.Log("Successfully retrieved json data from utf grid: " + _returnString); #endif return(_returnString); } else { #if DEBUG_LOG Debug.LogWarning("UTF data table contained no rows."); #endif return(null); } } else { #if DEBUG_LOG Debug.LogWarning("The returned char key was null or invalid"); #endif return(null); } } }