/// <summary> Tries to download and store in cache remote tile. </summary> public IObservable<string> Get(Tile tile) { string filePath = Path.Combine(_cachePath, tile.QuadKey + FormatExtension); return FileSystemService.Exists(filePath) ? Observable.Return(filePath) : ObservableWWW .GetAndGetBytes(GetUrl(tile.QuadKey)) .Select(bytes => { using(var stream = FileSystemService.WriteStream(filePath)) stream.Write(bytes, 0, bytes.Length); return filePath; }); }
public GameObject Build(Tile tile, Element element) { GameObject gameObject = GameObject.CreatePrimitive(PrimitiveType.Cube); gameObject.name = GetName(element); var transform = gameObject.transform; transform.position = tile.Projection.Project(element.Geometry[0], GetMinHeight(element)); transform.localScale = new Vector3(2, 2, 2); gameObject.GetComponent<MeshFilter>().mesh.uv = GetUV(element); gameObject.GetComponent<MeshRenderer>().sharedMaterial = GetMaterial(element); return gameObject; }
/// <inheritdoc /> public void BuildMesh(Tile tile, Mesh mesh) { var gameObject = new GameObject(mesh.Name); var uMesh = new UnityEngine.Mesh(); uMesh.vertices = mesh.Vertices; uMesh.triangles = mesh.Triangles; uMesh.colors = mesh.Colors; uMesh.uv = new Vector2[mesh.Vertices.Length]; uMesh.RecalculateNormals(); gameObject.isStatic = true; gameObject.AddComponent<MeshFilter>().mesh = uMesh; gameObject.AddComponent<MeshRenderer>().sharedMaterial = _customizationService.GetSharedMaterial(@"Materials/Default"); gameObject.AddComponent<MeshCollider>(); gameObject.transform.parent = tile.GameObject.transform; }
public void CanLoadMultipleTiles() { // ARRANGE SetupMapData(TestHelper.BerlinPbfData); var count = 10; var centerQuadKey = new QuadKey(35205, 21489, LevelOfDetails); // ACT & ASSERT for (var y = 0; y < count; ++y) for (var x = 0; x < count; ++x) { var quadKey = new QuadKey(centerQuadKey.TileX + x, centerQuadKey.TileY + y, LevelOfDetails); var tile = new Tile(quadKey, _tileController.Stylesheet, _tileController.Projection); _mapDataLoader .Load(tile) .SubscribeOn(Scheduler.CurrentThread) .ObserveOn(Scheduler.CurrentThread) .Subscribe(AssertData); } }
/// <summary> Downloads map data for given tile. </summary> private IObservable<Tile> CreateDownloadSequence(Tile tile) { // data exists in store if (CoreLibrary.HasData(tile.QuadKey)) return Observable.Return(tile); // data exists in cache var filePath = GetCacheFilePath(tile); if (_fileSystemService.Exists(filePath)) { var errorMsg = SaveTileDataInMemory(tile, filePath); return errorMsg == null ? Observable.Return(tile) : Observable.Throw<Tile>(new MapDataException(Strings.CannotAddDataToInMemoryStore, errorMsg)); } // need to download from remote server return Observable.Create<Tile>(observer => { double padding = 0.001; BoundingBox query = tile.BoundingBox; var queryString = String.Format(_mapDataServerQuery, query.MinPoint.Latitude - padding, query.MinPoint.Longitude - padding, query.MaxPoint.Latitude + padding, query.MaxPoint.Longitude + padding); var uri = String.Format("{0}{1}", _mapDataServerUri, Uri.EscapeDataString(queryString)); Trace.Warn(TraceCategory, Strings.NoPresistentElementSourceFound, query.ToString(), uri); ObservableWWW.GetAndGetBytes(uri) .ObserveOn(Scheduler.ThreadPool) .Subscribe(bytes => { Trace.Debug(TraceCategory, "saving bytes: {0}", bytes.Length.ToString()); lock (_lockObj) { if (!_fileSystemService.Exists(filePath)) using (var stream = _fileSystemService.WriteStream(filePath)) stream.Write(bytes, 0, bytes.Length); } // try to add in memory store var errorMsg = SaveTileDataInMemory(tile, filePath); if (errorMsg != null) observer.OnError(new MapDataException(String.Format(Strings.CannotAddDataToInMemoryStore, errorMsg))); else { observer.OnNext(tile); observer.OnCompleted(); } }); return Disposable.Empty; }); }
/// <inheritdoc /> public IObservable<Union<Element, Mesh>> Load(Tile tile) { return CreateDownloadSequence(tile) //CreateElevationSequence(tile) //.SelectMany(t => _imaginaryProvider.Get(t).Select(_ => t)) //.SelectMany(t => CreateDownloadSequence(t)) .SelectMany(t => CreateLoadSequence(t)); }
public MapTileAdapter(Tile tile, IObserver<Union<Element, Mesh>> observer, ITrace trace) { _tile = tile; _observer = observer; _trace = trace; }
public void SetUp() { var tile = new Tile(new QuadKey(), new Mock<Stylesheet>("").Object, new Mock<IProjection>().Object); _observer = new Mock<IObserver<Union<Element, Mesh>>>(); _adapter = new MapTileAdapter(tile, _observer.Object, new DefaultTrace()); }
private bool ShouldPreload(Tile tile, Vector2 position) { return !tile.Contains(position, tile.Rectangle.Width * _offsetRatio); }
/// <summary> Returns cache file name for given tile. </summary> private string GetCacheFilePath(Tile tile) { var cacheFileName = tile.QuadKey + _mapDataFormatExtension; return Path.Combine(_cachePath, cacheFileName); }
/// <summary> Gets next quadkey. </summary> private QuadKey GetNextQuadKey(Tile tile, Vector2 position) { var quadKey = tile.QuadKey; // NOTE left-right and top-bottom orientation Vector2 topLeft = new Vector2(tile.Rectangle.Left, tile.Rectangle.Top); Vector2 topRight = new Vector2(tile.Rectangle.Right, tile.Rectangle.Top); // top if (IsPointInTriangle(position, tile.Rectangle.Center, topLeft, topRight)) return new QuadKey(quadKey.TileX, quadKey.TileY - 1, quadKey.LevelOfDetail); Vector2 bottomLeft = new Vector2(tile.Rectangle.Left, tile.Rectangle.Bottom); // left if (IsPointInTriangle(position, tile.Rectangle.Center, topLeft, bottomLeft)) return new QuadKey(quadKey.TileX - 1, quadKey.TileY, quadKey.LevelOfDetail); Vector2 bottomRight = new Vector2(tile.Rectangle.Right, tile.Rectangle.Bottom); // right if (IsPointInTriangle(position, tile.Rectangle.Center, topRight, bottomRight)) return new QuadKey(quadKey.TileX + 1, quadKey.TileY, quadKey.LevelOfDetail); // bottom return new QuadKey(quadKey.TileX, quadKey.TileY + 1, quadKey.LevelOfDetail); }
/// <inheritdoc /> public void BuildMesh(Tile tile, Mesh mesh) { }
/// <inheritdoc /> public void BuildElement(Tile tile, Element element) { }
/// <summary> Downloads elevation data for given tile. </summary> private IObservable<Tile> CreateElevationSequence(Tile tile) { return _elevationProvider.HasElevation(tile.BoundingBox) ? Observable.Return(tile) : _elevationProvider.Download(tile.BoundingBox).Select(_ => tile); }
/// <summary> Loads tile for given quadKey. </summary> private void Load(QuadKey quadKey) { Tile tile = new Tile(quadKey, Stylesheet, Projection); _loadedTiles.Add(quadKey, tile); // TODO remove tile from hashmap if exception is raised _messageBus.Send(new TileLoadStartMessage(tile)); _tileLoader .Load(tile) .SubscribeOn(Scheduler.ThreadPool) .ObserveOn(Scheduler.MainThread) .Subscribe( u => u.Match(e => _modelBuilder.BuildElement(tile, e), m => _modelBuilder.BuildMesh(tile, m)), () => _messageBus.Send(new TileLoadFinishMessage(tile))); }
/// <summary> Creates <see cref="IObservable{T}"/> for loading element of given tile. </summary> private IObservable<Union<Element, Mesh>> CreateLoadSequence(Tile tile) { return Observable.Create<Union<Element, Mesh>>(observer => { Trace.Info(TraceCategory, "loading tile: {0}", tile.ToString()); var adapter = new MapTileAdapter(tile, observer, Trace); CoreLibrary.LoadQuadKey( _pathResolver.Resolve(tile.Stylesheet.Path), tile.QuadKey, adapter.AdaptMesh, adapter.AdaptElement, adapter.AdaptError); Trace.Info(TraceCategory, "tile loaded: {0}", tile.ToString()); observer.OnCompleted(); return Disposable.Empty; }); }
private void PreloadNextTile(Tile tile, Vector2 position) { var quadKey = GetNextQuadKey(tile, position); if (!_loadedTiles.ContainsKey(quadKey)) Load(quadKey); }
/// <summary> Adds tile data into in memory storage. </summary> private string SaveTileDataInMemory(Tile tile, string filePath) { Trace.Info(TraceCategory, "try to save: {0} from {1}", tile.ToString(), filePath); string errorMsg = null; CoreLibrary.AddToStore(MapStorageType.InMemory, _pathResolver.Resolve(tile.Stylesheet.Path), _pathResolver.Resolve(filePath), tile.QuadKey, error => errorMsg = error); return errorMsg; }
/// <inheritdoc /> public void BuildElement(Tile tile, Element element) { if (element.Styles["builders"].Contains("info")) _placeElementBuilder.Build(tile, element).transform.parent = tile.GameObject.transform; }