public BitmapImage TileRender(long x, long y, int zoomLevel) { if (!string.IsNullOrWhiteSpace(_tilePath)) { var q = new QuadKey((int)x, (int)y, zoomLevel); var filePath = _tilePath.Replace("{quadkey}", q.Key).Replace("{x}", x.ToString()).Replace("{y}", y.ToString()).Replace("{zoomlevel}", zoomLevel.ToString()); var fi = new FileInfo(filePath); if (fi.Exists) { using (var fStream = fi.OpenRead()) { var bmp = new BitmapImage(); bmp.BeginInit(); bmp.StreamSource = fStream; bmp.CacheOption = BitmapCacheOption.OnLoad; bmp.EndInit(); return(bmp); } } } return(CreateTransparentTile()); }
private void OnPosition(GeoCoordinate geoPosition, Vector3 position, int levelOfDetails) { // call update logic only if threshold is reached if (Vector3.Distance(position, _lastUpdatePosition) > _moveSensitivity || _currentQuadKey.LevelOfDetail != levelOfDetails) { lock (_lockObj) { _lastUpdatePosition = position; _currentQuadKey = GeoUtils.CreateQuadKey(geoPosition, levelOfDetails); UnloadFarTiles(_currentQuadKey); if (_loadedTiles.ContainsKey(_currentQuadKey)) { var tile = _loadedTiles[_currentQuadKey]; if (ShouldPreload(tile, position)) { PreloadNextTile(tile, position); } return; } Load(_currentQuadKey); } } }
private bool CheckQuadKey(QuadKey actual, QuadKey expected) { Assert.AreEqual(expected.LevelOfDetail, actual.LevelOfDetail); Assert.AreEqual(expected.TileX, actual.TileX); Assert.AreEqual(expected.TileY, actual.TileY); return(true); }
private void OnPosition(GeoCoordinate geoPosition, Vector3 position, int levelOfDetails) { if (!IsValidLevelOfDetails(levelOfDetails)) { throw new ArgumentException(String.Format("Invalid level of details: {0}", levelOfDetails), "levelOfDetails"); } // call update logic only if threshold is reached if (Vector3.Distance(position, _lastUpdatePosition) > _moveSensitivity) { lock (_lockObj) { _lastUpdatePosition = position; _currentQuadKey = GeoUtils.CreateQuadKey(geoPosition, levelOfDetails); UnloadFarTiles(_currentQuadKey); if (_loadedTiles.ContainsKey(_currentQuadKey)) { var tile = _loadedTiles[_currentQuadKey]; if (ShouldPreload(tile, position)) { PreloadNextTile(tile, position); } return; } Load(_currentQuadKey); } } }
public ViewInfo(QuadKey quadKey) { _width = 256; _height = 256; _topLeftGlobalPixel = new PointF(quadKey.X * 256, quadKey.Y * 256); _zoom = quadKey.ZoomLevel; }
public ViewInfo(int width, int height, QuadKey quadKey) { _width = width; _height = height; _topLeftGlobalPixel = new PointF(quadKey.X * 256, quadKey.Y * 256); _zoom = quadKey.ZoomLevel; }
/// <inheritdoc /> protected override string GetUri(QuadKey quadKey) { var quadKeyToDownload = GetDownloadQuadKey(quadKey); return(String.Format(_mapDataServerUri, _mapDataLayers, quadKeyToDownload.LevelOfDetail, quadKeyToDownload.TileX, quadKeyToDownload.TileY, _mapDataApiKey)); }
public void CanAddNode() { // ARRANGE var quadKey = new QuadKey(0, 0, 6); var levelOfDetails = new Range <int>(quadKey.LevelOfDetail, quadKey.LevelOfDetail); var node = new Element(7, new [] { GeoUtils.QuadKeyToBoundingBox(quadKey).Center() }, new [] { 0.0 }, // NOTE must be corresponding rule in mapcss. new Dictionary <string, string>() { { "kind", "locality" }, { "name", "secret place" } }, new Dictionary <string, string>()); // ACT _mapDataEditor.Add(MapDataStorageType.InMemory, node, levelOfDetails); // ASSERT var result = _dataStore.GetResultSync(new Tile(quadKey, _stylesheet, _projection, ElevationDataType.Flat)); result.Variant.Match( e => CompareElements(node, e), mesh => { throw new ArgumentException(); }); }
public static Rectangle QuadKeyToRect(IProjection projection, QuadKey quadKey) { var boundingBox = QuadKeyToBoundingBox(quadKey); var minPoint = projection.Project(boundingBox.MinPoint, 0); var maxPoint = projection.Project(boundingBox.MaxPoint, 0); return new Rectangle(minPoint.x, minPoint.z, maxPoint.x - minPoint.x, maxPoint.z - minPoint.z); }
public static Rectangle QuadKeyToRect(IProjection projection, QuadKey quadKey) { var boundingBox = QuadKeyToBoundingBox(quadKey); var minPoint = projection.Project(boundingBox.MinPoint, 0); var maxPoint = projection.Project(boundingBox.MaxPoint, 0); return(new Rectangle(minPoint.x, minPoint.z, maxPoint.x - minPoint.x, maxPoint.z - minPoint.z)); }
/// <summary> Loads tile for given quadKey. </summary> private void Load(QuadKey quadKey) { var tile = new Tile(quadKey, Stylesheet, Projection); _loadedTiles.Add(quadKey, tile); NotifyOnNextObservers(tile); }
public void CanOnPositionLoadFirstTile() { QuadKey quadKey = GeoUtils.CreateQuadKey(_worldZeroPoint, LevelOfDetails); _tileController.OnPosition(_worldZeroPoint, LevelOfDetails); _tileObserver.Verify(o => o.OnNext(It.Is <Tile>(tile => CheckQuadKey(tile.QuadKey, quadKey)))); }
/// <summary> Creates <see cref="Tile"/>. </summary> /// <param name="quadKey"></param> /// <param name="stylesheet"></param> /// <param name="projection"> Projection. </param> public Tile(QuadKey quadKey, Stylesheet stylesheet, IProjection projection) { QuadKey = quadKey; Stylesheet = stylesheet; Projection = projection; BoundingBox = GeoUtils.QuadKeyToBoundingBox(quadKey); Rectangle = GeoUtils.QuadKeyToRect(projection, quadKey); }
/// <summary> Get side size in meters of grid consists of 9 quadkeys. </summary> private float GetGridHeight(QuadKey quadKey) { var bbox = GeoUtils.QuadKeyToBoundingBox(quadKey); var bboxHeight = bbox.MaxPoint.Latitude - bbox.MinPoint.Latitude; var minPoint = new GeoCoordinate(bbox.MinPoint.Latitude - bboxHeight, bbox.MinPoint.Longitude); var maxPoint = new GeoCoordinate(bbox.MinPoint.Latitude + bboxHeight, bbox.MaxPoint.Longitude); return((float)GeoUtils.Distance(minPoint, maxPoint) * _scale); }
/// <summary> Creates <see cref="Tile"/>. </summary> /// <param name="quadKey"></param> /// <param name="stylesheet"></param> /// <param name="projection"> Projection. </param> internal Tile(QuadKey quadKey, Stylesheet stylesheet, IProjection projection) { QuadKey = quadKey; Stylesheet = stylesheet; Projection = projection; BoundingBox = GeoUtils.QuadKeyToBoundingBox(quadKey); Rectangle = GeoUtils.QuadKeyToRect(projection, quadKey); }
/// <inheritdoc /> protected override string GetUri(QuadKey quadKey) { var padding = 0.001; var query = GeoUtils.QuadKeyToBoundingBox(quadKey); var queryString = String.Format(_mapDataServerQuery, query.MinPoint.Latitude - padding, query.MinPoint.Longitude - padding, query.MaxPoint.Latitude + padding, query.MaxPoint.Longitude + padding); return(String.Format("{0}{1}", _mapDataServerUri, Uri.EscapeDataString(queryString))); }
public override Uri GetUri(int x, int y, int zoomLevel) { var quadKey = new QuadKey(x, y, zoomLevel); return(new Uri( String.Format( this.UriFormat, quadKey.Key[quadKey.Key.Length - 1] quadKey.Key, DateTime.Now.ToString("g", System.Globalization.DateTimeFormatInfo.InvariantInfo)))); }
public void CanOnPositionLoadNextNorthTile() { var newQuadKey = new QuadKey(17602, 10743, LevelOfDetails); _tileController.OnPosition(_worldZeroPoint, LevelOfDetails); _tileObserver.ResetCalls(); _tileController.OnPosition(MovePosition(_worldZeroPoint, new Vector2(0, 1), 400), LevelOfDetails); _tileObserver.Verify(o => o.OnNext(It.Is <Tile>(tile => CheckQuadKey(tile.QuadKey, newQuadKey)))); }
/// <summary> Build specific quadkey. </summary> private Tile BuildQuadKey(Transform parent, QuadKey quadKey) { var tileGameObject = new GameObject(quadKey.ToString()); tileGameObject.transform.parent = parent.transform; var tile = CreateTile(quadKey, tileGameObject); _loadedQuadKeys.Add(quadKey, tile); LoadTile(tile); return(tile); }
public void CanLoadTilesAtDetailedLevelOfDetails() { // ARRANGE int lod = 16; SetupMapData(TestHelper.BerlinPbfData, lod); var count = 1; var centerQuadKey = new QuadKey(35205, 21489, lod); // ACT & ASSERT TestQuadKeys(centerQuadKey, count, lod); }
public void CanOnPositionUnloadFarTile() { _configSection.Setup(c => c.GetInt(@"tile/max_tile_distance", It.IsAny <int>())).Returns(1); QuadKey quadKey = GeoUtils.CreateQuadKey(_worldZeroPoint, LevelOfDetails); for (int i = 0; i < 2; ++i) { _tileController.OnPosition(MovePosition(_worldZeroPoint, new Vector2(1, 0), i * 400), LevelOfDetails); } _tileObserver.Verify(o => o.OnNext(It.Is <Tile>(tile => tile.IsDisposed && CheckQuadKey(tile.QuadKey, quadKey)))); }
public void CanLoadNextNorthTile() { var newQuadKey = new QuadKey(17602, 10743, LevelOfDetails); _tileController.OnPosition(_worldZeroPoint, LevelOfDetails); _tileLoader.ResetCalls(); _messageBus.ResetCalls(); _tileController.OnPosition(MovePosition(_worldZeroPoint, new Vector2(0, 1), 400), LevelOfDetails); _tileLoader.Verify(t => t.Load(It.Is<Tile>(tile => CheckQuadKey(tile.QuadKey, newQuadKey)))); _messageBus.Verify(mb => mb.Send(It.Is<TileLoadStartMessage>(m => CheckQuadKey(m.Tile.QuadKey, newQuadKey)))); }
private void TestQuadKeys(QuadKey centerQuadKey, int count, int lod) { for (var y = 0; y < count; ++y) { for (var x = 0; x < count; ++x) { var quadKey = new QuadKey(centerQuadKey.TileX + x, centerQuadKey.TileY + y, lod); var tile = new Tile(quadKey, _stylesheet, _projection, ElevationDataType.Flat); AssertResult(_mapDataStore.GetResultSync(tile)); } } Assert.IsTrue(_isCalled); }
/// <summary> Loads quadkey waiting for completion callback. </summary> private void LoadQuadKeySync(QuadKey quadKey) { var manualResetEvent = new ManualResetEvent(false); var tile = new Tile(quadKey, _tileController.Stylesheet, _tileController.Projection); _mapDataLoader .Load(tile) .SubscribeOn(Scheduler.CurrentThread) .ObserveOn(Scheduler.CurrentThread) .Subscribe(AssertData, () => manualResetEvent.Set()); manualResetEvent.WaitOne(); }
/// <summary> Gets childrent for quadkey. </summary> private IEnumerable <QuadKey> GetChildren(QuadKey quadKey) { // TODO can be optimized to avoid string allocations. var quadKeyName = quadKey.ToString(); yield return(QuadKey.FromString(quadKeyName + "0")); yield return(QuadKey.FromString(quadKeyName + "1")); yield return(QuadKey.FromString(quadKeyName + "2")); yield return(QuadKey.FromString(quadKeyName + "3")); }
public static BoundingBox QuadKeyToBoundingBox(QuadKey quadKey) { int levelOfDetail = quadKey.LevelOfDetail; var minPoint = new GeoCoordinate( TileYToLat(quadKey.TileY + 1, levelOfDetail), TileXToLon(quadKey.TileX, levelOfDetail)); var maxPoint = new GeoCoordinate( TileYToLat(quadKey.TileY, levelOfDetail), TileXToLon(quadKey.TileX + 1, levelOfDetail)); return new BoundingBox(minPoint, maxPoint); }
public static BoundingBox QuadKeyToBoundingBox(QuadKey quadKey) { int levelOfDetail = quadKey.LevelOfDetail; var minPoint = new GeoCoordinate( TileYToLat(quadKey.TileY + 1, levelOfDetail), TileXToLon(quadKey.TileX, levelOfDetail)); var maxPoint = new GeoCoordinate( TileYToLat(quadKey.TileY, levelOfDetail), TileXToLon(quadKey.TileX + 1, levelOfDetail)); return(new BoundingBox(minPoint, maxPoint)); }
/// <summary> Builds quadkeys if necessary. Decision is based on visible quadkey and lod level. </summary> private void BuildIfNecessary(Transform planet) { var lod = (int)_zoom; var actualGameObject = GetActual(planet, Coordinate, lod); if (actualGameObject == planet) { return; } var actualQuadKey = QuadKey.FromString(actualGameObject.name); var actualName = actualGameObject.name; var parent = planet; var quadKeys = new List <QuadKey>(); // zoom in int disposedTiles = 0; if (actualQuadKey.LevelOfDetail < lod) { quadKeys.AddRange(GetChildren(actualQuadKey)); var oldParent = actualGameObject.transform.parent; disposedTiles = SafeDestroy(actualQuadKey, actualName) ? 1 : 0; parent = new GameObject(actualName).transform; parent.transform.parent = oldParent; } // zoom out else if (actualQuadKey.LevelOfDetail > lod) { string name = actualName.Substring(0, actualName.Length - 1); var quadKey = QuadKey.FromString(name); // destroy all siblings foreach (var child in GetChildren(quadKey)) { disposedTiles += SafeDestroy(child, child.ToString()) ? 1 : 0; } // destroy current as it might be just placeholder. SafeDestroy(actualQuadKey, name); parent = GetParent(planet, quadKey); quadKeys.Add(quadKey); } UnloadAssets(disposedTiles); BuildQuadKeys(parent, quadKeys); }
/// <summary> Destroys gameobject by its name if it exists. </summary> private void SafeDestroy(QuadKey quadKey, string name = null) { if (_loadedQuadKeys.ContainsKey(quadKey)) { _loadedQuadKeys[quadKey].Dispose(); _loadedQuadKeys.Remove(quadKey); return; } var go = GameObject.Find(name); if (go != null) { Object.Destroy(go); } }
/// <summary> Gets parent game object for given quadkey. Creates hierarchy if necessary. </summary> private Transform GetParent(Transform planet, QuadKey quadKey) { // recursion end if (quadKey.LevelOfDetail <= LodRange.Minimum) { return(planet); } string quadKeyName = quadKey.ToString(); string parentName = quadKeyName.Substring(0, quadKeyName.Length - 1); var parent = GameObject.Find(parentName); return(parent != null ? parent.transform : GetParent(planet, QuadKey.FromString(parentName))); }
void Start() { // init utymap library _compositionRoot = InitTask.Run((container, config) => { container .Register(Component.For <Stylesheet>().Use <Stylesheet>(@"mapcss/default/index.mapcss")) .Register(Component.For <MaterialProvider>().Use <MaterialProvider>()) .Register(Component.For <GameObjectBuilder>().Use <GameObjectBuilder>()) .RegisterInstance <IEnumerable <IElementBuilder> >(new List <IElementBuilder>()); }); // store map data store reference to member variable _mapDataStore = _compositionRoot.GetService <IMapDataStore>(); // get reference for active stylesheet var stylesheet = _compositionRoot.GetService <Stylesheet>(); // define level of detail const int levelOfDetail = 14; // create center coordinate; var coordinate = (new GeoCoordinate(Latitude, Longitude)); // create "center" tile var center = GeoUtils.CreateQuadKey(coordinate, levelOfDetail); // load multiply tiles at once for (var tileX = center.TileX - 1; tileX <= center.TileX + 1; ++tileX) { for (var tileY = center.TileY - 1; tileY <= center.TileY + 1; ++tileY) { var quadKey = new QuadKey(tileX, tileY, levelOfDetail); var parent = new GameObject(quadKey.ToString()); parent.transform.SetParent(gameObject.transform); _mapDataStore.OnNext(new Tile( // quadkey to load. quadKey, // provide stylesheet stylesheet, // use cartesian projection as we want to build flat world new CartesianProjection(coordinate), // use grid elevation: uses mapzen servers by default, // stores elevation in simple NxN grid format. ElevationDataType.Grid, // parent for built game objects parent)); } } }
private IEnumerable <GeoCoordinate> CreatePolyline(QuadKey quadkey) { var bbox = GeoUtils.QuadKeyToBoundingBox(quadkey); var latStep = (bbox.MaxPoint.Latitude - bbox.MinPoint.Latitude) / _eleGrid; var lonStep = (bbox.MaxPoint.Longitude - bbox.MinPoint.Longitude) / _eleGrid; for (int i = 0; i < _eleGrid; ++i) { var lat = bbox.MinPoint.Latitude + i * latStep; for (int j = 0; j < _eleGrid; ++j) { var lon = bbox.MinPoint.Longitude + j * lonStep; yield return(new GeoCoordinate(lat, lon)); } } }
/// <summary> Removes far tiles from list of loaded and sends corresponding message. </summary> private void UnloadFarTiles(QuadKey currentQuadKey) { var tiles = _loadedTiles.ToArray(); foreach (var loadedTile in tiles) { var quadKey = loadedTile.Key; if ((Math.Abs(quadKey.TileX - currentQuadKey.TileX) + Math.Abs(quadKey.TileY - currentQuadKey.TileY)) <= _maxTileDistance) { continue; } loadedTile.Value.Dispose(); _loadedTiles.Remove(quadKey); NotifyOnNextObservers(loadedTile.Value); } }
public void CanLoadMultipleTilesAtDetailedLevelOfDetails() { // ARRANGE int lod = 16; SetupMapData(TestHelper.BerlinPbfData, lod); var count = 10; var centerQuadKey = new QuadKey(35205, 21489, lod); // ACT & ASSERT for (var y = 0; y < count; ++y) { for (var x = 0; x < count; ++x) { LoadQuadKeySync(new QuadKey(centerQuadKey.TileX + x, centerQuadKey.TileY + y, lod)); } } Assert.IsTrue(_isCalled); }
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); } }
protected void collectGeometryKeys(QuadMap qmap, QuadKeyList geom_keys) { // the starting LOD is the best fit the the cell size: uint top_lod = getTopLod(qmap, map_layer); foreach (MapLayerLevelOfDetail i in map_layer.getLevels()) { MapLayerLevelOfDetail level_def = i; uint lod = top_lod + level_def.getDepth(); // get the extent of tiles that we will build based on the AOI: uint cell_xmin, cell_ymin, cell_xmax, cell_ymax; qmap.getCells( map_layer.getAreaOfInterest(), lod, cell_xmin, cell_ymin, cell_xmax, cell_ymax); for (uint y = cell_ymin; y <= cell_ymax; y++) { for (uint x = cell_xmin; x <= cell_xmax; x++) { QuadKey key = new QuadKey(x, y, lod, qmap); for (uint k = 0; k < 4; k++) { geom_keys.push_back(key.createSubKey(k)); } } } } }
protected osg.Node createIntermediateIndexNode(QuadKey key, float min_range, float max_range, SmartReadCallback cb) { osg.Group group = null; for (uint quadrant = 0; quadrant < 4; quadrant++) { QuadKey subkey = key.createSubKey(quadrant); if (osgDB.fileExists(createAbsPathFromTemplate("g" + subkey.toString()))) { if (!group) { group = new osg.Group(); group.setName(key.toString()); } //osgGIS.notice() << "QK=" << subkey.toString() << ", Extent=" << subkey.getExtent().toString() << std.endl; // enter the subtile set as a paged index node reference: osg.PagedLOD plod = new osg.PagedLOD(); setCenterAndRadius(plod, subkey.getExtent(), reader); #if USE_PAGEDLODS_IN_INDEX osg.PagedLOD* pointer = new osg.PagedLOD(); pointer.setFileName( 0, createRelPathFromTemplate( "g" + subkey.toString() ) ); pointer.setRange( 0, 0, 1e10 ); pointer.setPriorityScale( 0, 1000.0f ); // top priority, hopefully pointer.setPriorityOffset( 0, 1000.0f ); pointer.setCenter( plod.getCenter() ); pointer.setRadius( plod.getRadius() ); #else osg.ProxyNode pointer = new osg.ProxyNode(); pointer.setLoadingExternalReferenceMode(osg.ProxyNode.LOAD_IMMEDIATELY); pointer.setFileName(0, createRelPathFromTemplate("g" + subkey.toString())); //setCenterAndRadius( pointer, subkey.getExtent(), reader ); #endif plod.addChild(pointer, max_range, 1e10); plod.setFileName(1, createRelPathFromTemplate("i" + subkey.toString())); plod.setRange(1, 0, max_range); // last one should always be min=0 plod.setPriorityScale(1, MY_PRIORITY_SCALE); group.addChild(plod); //osg.Geode* geode = new osg.Geode(); //osg.Sphere* g1 = new osg.Sphere( osg.Vec3(0,0,0), plod.getRadius() ); //osg.ShapeDrawable* sd1 = new osg.ShapeDrawable( g1 ); //sd1.setColor( osg.Vec4f(1,0,0,.2) ); //geode.addDrawable( sd1 ); ////osg.Vec3d p = terrain_srs.transform( subkey.getExtent().getCentroid() ); ////osg.Vec3d n = p; n.normalize(); ////osg.Geometry* g3 = new osg.Geometry(); ////osg.Vec3Array* v3 = new osg.Vec3Array(2); ////(*v3)[0] = osg.Vec3d(0,0,0); ////(*v3)[1] = n * 3000.0; ////g3.setVertexArray( v3 ); ////osg.Vec4Array* c3 = new osg.Vec4Array(1); ////(*c3)[0].set(1,1,0,1); ////g3.setColorArray( c3 ); ////g3.setColorBinding(osg.Geometry.BIND_OVERALL); ////g3.addPrimitiveSet( new osg.DrawArrays(GL_LINES, 0, 2) ); ////g3.getOrCreateStateSet().setMode( GL_LIGHTING, osg.StateAttribute.OFF ); ////geode.addDrawable( g3 ); ////osg.Sphere* g2 = new osg.Sphere( osg.Vec3(0,0,0), 25 ); ////osg.ShapeDrawable* sd2 = new osg.ShapeDrawable( g2 ); ////sd2.setColor( osg.Vec4f(1,1,0,1) ); ////geode.addDrawable( sd2 ); ////osg.Matrixd mx = osg.Matrixd.translate( p ); //osg.Matrixd mx = osg.Matrixd.translate( plod.getCenter() ); //osg.MatrixTransform* mt = new osg.MatrixTransform( mx ); //mt.addChild( geode ); //mt.getOrCreateStateSet().setMode( GL_BLEND, osg.StateAttribute.ON ); //mt.getOrCreateStateSet().setRenderingHint( osg.StateSet.TRANSPARENT_BIN ); //group.addChild( mt ); } } return group; }
protected osg.Node createLeafIndexNode(QuadKey key, SmartReadCallback cb) { osg.Group group = null; for (uint i = 0; i < 4; i++) { QuadKey quadrant_key = key.createSubKey(i); if (osgDB.fileExists(createAbsPathFromTemplate("g" + quadrant_key.toString()))) { if (!group) { group = new osg.Group(); group.setName(key.toString()); } #if USE_PAGEDLODS_IN_INDEX osg.PagedLOD* pointer = new osg.PagedLOD(); pointer.setFileName( 0, createRelPathFromTemplate( "g" + quadrant_key.toString() ) ); pointer.setRange( 0, 0, 1e10 ); pointer.setPriorityScale( 0, 1000.0f ); // top priority! pointer.setPriorityOffset( 0, 1000.0f ); setCenterAndRadius( pointer, quadrant_key.getExtent(), reader ); #else osg.ProxyNode pointer = new osg.ProxyNode(); pointer.setLoadingExternalReferenceMode(osg.ProxyNode.LOAD_IMMEDIATELY); pointer.setFileName(0, createRelPathFromTemplate("g" + quadrant_key.toString())); //setCenterAndRadius( pointer, quadrant_key.getExtent(), reader ); #endif group.addChild(pointer); } } return group; }
protected Task createQuadKeyTask(QuadKey key) { // construct a filter environment template to use for all tasks: FilterEnv cell_env = getSession().createFilterEnv(); cell_env.setTerrainNode(getTerrainNode()); cell_env.setTerrainSRS(getTerrainSRS()); string abs_path = createAbsPathFromTemplate("g" + key.toString()); Task task = null; MapLayerLevelOfDetail def = getDefinition(key.createParentKey(), map_layer); if (def != null) { cell_env.setInputSRS(def.getFeatureLayer().getSRS()); cell_env.setExtent(map_layer.getAreaOfInterest().getSRS().transform(key.getExtent())); cell_env.setProperty(new Property("compiler.cell_id", key.toString())); foreach (Property i in def.getEnvProperties()) cell_env.setProperty(i); task = new CellCompiler( key.toString(), abs_path, def.getFeatureLayer(), def.getFilterGraph(), def.getMinRange(), def.getMaxRange(), cell_env, def.getResourcePackager() ? def.getResourcePackager() : resource_packager.get(), getArchive(), def.getUserData()); // osgGIS.info() // << "Task: Key = " << key.toString() << ", LOD = " << key.getLOD() << ", Extent = " << key.getExtent().toString() // << " (w=" << key.getExtent().getWidth() << ", h=" << key.getExtent().getHeight() << ")" // << std.endl; } return task; }
static MapLayerLevelOfDetail getDefinition(QuadKey key, MapLayer map_layer) { uint top_lod = getTopLod(key.getMap(), map_layer); uint depth_to_find = key.getLOD() - top_lod; foreach (MapLayerLevelOfDetail i in map_layer.getLevels()) { if (i.getDepth() == depth_to_find) return i; } return null; }
/// <summary> /// Adds map data to in-memory storage to specific quadkey. /// Supported formats: shapefile, osm xml, osm pbf. /// </summary> /// <param name="storageType"> Map data storage. </param> /// <param name="stylePath"> Stylesheet path. </param> /// <param name="path"> Path to file. </param> /// <param name="quadKey"> QuadKey. </param> /// <param name="onError"> OnError callback. </param> public static void AddToStore(MapStorageType storageType, string stylePath, string path, QuadKey quadKey, OnError onError) { addToStoreInQuadKey(GetStoreKey(storageType), stylePath, path, quadKey.TileX, quadKey.TileY, quadKey.LevelOfDetail, onError); }
private void OnPosition(GeoCoordinate geoPosition, Vector2 position, int levelOfDetails) { CurrentMapPoint = position; CurrentPosition = geoPosition; // call update logic only if threshold is reached if (Math.Abs(position.x - _lastUpdatePosition.x) > _moveSensitivity || Math.Abs(position.y - _lastUpdatePosition.y) > _moveSensitivity) { lock (_lockObj) { _lastUpdatePosition = position; _currentQuadKey = GeoUtils.CreateQuadKey(geoPosition, levelOfDetails); if (_loadedTiles.ContainsKey(_currentQuadKey)) { var tile = _loadedTiles[_currentQuadKey]; if (ShouldPreload(tile, position)) PreloadNextTile(tile, position); return; } Load(_currentQuadKey); // TODO add unload old tiles logic } } }
/// <summary> Loads quadkey. </summary> /// <param name="stylePath"> Stylesheet path. </param> /// <param name="quadKey"> QuadKey</param> /// <param name="onMeshBuilt"></param> /// <param name="onElementLoaded"></param> /// <param name="onError"></param> public static void LoadQuadKey(string stylePath, QuadKey quadKey, OnMeshBuilt onMeshBuilt, OnElementLoaded onElementLoaded, OnError onError) { loadQuadKey(stylePath, quadKey.TileX, quadKey.TileY, quadKey.LevelOfDetail, onMeshBuilt, onElementLoaded, onError); }
/// <summary> Checks whether there is data for given quadkey. </summary> /// <returns> True if there is data for given quadkey. </returns> public static bool HasData(QuadKey quadKey) { return hasData(quadKey.TileX, quadKey.TileY, quadKey.LevelOfDetail); }
/// <summary> Gets url for given quadkey. </summary> protected abstract string GetUrl(QuadKey quadkey);
/// <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))); }
protected virtual void buildIndex(Profile _profile, osg.Group scene_graph) { QuadTreeProfile profile = (QuadTreeProfile)_profile; if (profile == null) return; //osgGIS.notice() << "Rebuilding index..." << std.endl; // first, determine the SRS of the output scene graph so that we can // make pagedlod/lod centroids. SpatialReference output_srs = map_layer.getOutputSRS(getSession(), getTerrainSRS()); // first build the very top level. //scene_graph = new osg.Group(); // the starting LOD is the best fit the the cell size: uint top_lod = getTopLod(profile.getQuadMap(), map_layer); SmartReadCallback reader = new SmartReadCallback(); foreach (MapLayerLevelOfDetail i in map_layer.getLevels()) { MapLayerLevelOfDetail level_def = i; uint lod = top_lod + level_def.getDepth(); MapLayerLevelOfDetail sub_level_def = i + 1 != map_layer.getLevels().end() ? (i + 1).get() : null; float min_range, max_range; if (sub_level_def != null) { min_range = sub_level_def.getMinRange(); max_range = sub_level_def.getMaxRange(); } // get the extent of tiles that we will build based on the AOI: uint cell_xmin, cell_ymin, cell_xmax, cell_ymax; profile.getQuadMap().getCells( map_layer.getAreaOfInterest(), lod, cell_xmin, cell_ymin, cell_xmax, cell_ymax); for (uint y = cell_ymin; y <= cell_ymax; y++) { for (uint x = cell_xmin; x <= cell_xmax; x++) { osg.Node node; QuadKey key = new QuadKey(x, y, lod, profile.getQuadMap()); //osgGIS.notify( osg.NOTICE ) // << "Cell: " << std.endl // << " Quadkey = " << key.toString() << std.endl // << " LOD = " << key.getLOD() << std.endl // << " Extent = " << key.getExtent().toString() << " (w=" << key.getExtent().getWidth() << ", h=" << key.getExtent().getHeight() << ")" << std.endl // << std.endl; node = sub_level_def ? createIntermediateIndexNode(key, min_range, max_range, reader.get()) : createLeafIndexNode(key, reader); if (node.valid()) { string out_file = createAbsPathFromTemplate("i" + key.toString()); if (!osgDB.writeNodeFile(*(node.get()), out_file)) { // osgGIS.warn() << "FAILED to write index file " << out_file << std.endl; } // at the top level, assemble the root node if (i == map_layer.getLevels().begin()) { double top_min_range = sub_level_def != null ? 0 : level_def.getMinRange(); osg.PagedLOD plod = new osg.PagedLOD(); plod.setName(key.toString()); plod.setFileName(0, createRelPathFromTemplate("i" + key.toString())); plod.setRange(0, top_min_range, level_def.getMaxRange()); plod.setPriorityScale(0, MY_PRIORITY_SCALE); setCenterAndRadius(plod, key.getExtent(), reader.get()); //osgGIS.notice() << "QK=" << key.toString() << ", Ex=" << key.getExtent().toString() << ", Cen=" << key.getExtent().getCentroid().toString() << std.endl; scene_graph.addChild(plod); } } } } } }
/// <summary> Preloads elevation data for given quadkey. </summary> /// <param name="quadKey">Quadkey.</param> public static void PreloadElevation(QuadKey quadKey) { preloadElevation(quadKey.TileX, quadKey.TileY, quadKey.LevelOfDetail); }
private bool CheckQuadKey(QuadKey actual, QuadKey expected) { Assert.AreEqual(expected.LevelOfDetail, actual.LevelOfDetail); Assert.AreEqual(expected.TileX, actual.TileX); Assert.AreEqual(expected.TileY, actual.TileY); return true; }
/// <inheritdoc /> protected override string GetUrl(QuadKey quadkey) { return String.Format(UrlSchema, quadkey); }