internal static void RunTest(MapFile mapFile) { // Calculate tile X and Y for lat=0 and lon=0 int tileX = MercatorProjection.LongitudeToTileX(0, ZOOM_LEVEL); int tileY = MercatorProjection.LatitudeToTileY(0, ZOOM_LEVEL); Tile tile = new Tile(tileX, tileY, ZOOM_LEVEL); MapReadResult mapReadResult = mapFile.ReadMapData(tile); mapFile.Close(); Assert.AreEqual(mapReadResult.PointOfInterests.Count, 0); Assert.AreEqual(1, mapReadResult.Ways.Count); Point point1 = new Point(0.0, 0.0); Point point2 = new Point(0.1, 0.0); Point point3 = new Point(0.1, -0.1); Point point4 = new Point(0.0, -0.1); Point[][] latLongsExpected = new Point[][] { new Point[] { point1, point2, point3, point4, point1 } }; Way way = mapReadResult.Ways[0]; // TODO: Was ArrayEquals() Assert.AreEqual(latLongsExpected, way.Points); }
public virtual void FileEmptyTest() { MapFile mapFile = new MapFile(EmbeddedResourceLoader.Load("Resources.Empty.output.map", this.GetType())); for (sbyte zoomLevel = 0; zoomLevel <= ZOOM_LEVEL_MAX; ++zoomLevel) { int tileX = MercatorProjection.LongitudeToTileX(1, zoomLevel); int tileY = MercatorProjection.LatitudeToTileY(1, zoomLevel); Tile tile = new Tile(tileX, tileY, zoomLevel); MapReadResult mapReadResult = mapFile.ReadMapData(tile); Assert.AreEqual(0, mapReadResult.PointOfInterests.Count); Assert.AreEqual(0, mapReadResult.Ways.Count); } mapFile.Close(); }
private void ProcessReadMapData(RenderContext renderContext, MapReadResult mapReadResult) { if (mapReadResult == null) { return; } foreach (PointOfInterest pointOfInterest in mapReadResult.PointOfInterests) { RenderPointOfInterest(renderContext, pointOfInterest); } foreach (Way way in mapReadResult.Ways) { RenderWay(renderContext, new PolylineContainer(way, renderContext.rendererJob.tile)); } if (mapReadResult.IsWater) { RenderWaterBackground(renderContext); } }
private void processReadMapData(MapReadResult mapReadResult) { if (mapReadResult == null) { return; } foreach (Node pointOfInterest in mapReadResult.Nodes) { renderpointOfInterest(pointOfInterest); } foreach (Way way in mapReadResult.Ways) { renderWay(way); } if (mapReadResult.IsWater) { renderWaterBackground(); } }
public virtual void WithDataTest() { MapFile mapFile = new MapFile(EmbeddedResourceLoader.Load("Resources.WithData.output.map", this.GetType())); MapFileInfo mapFileInfo = mapFile.MapFileInfo; Assert.True(mapFileInfo.DebugFile); for (sbyte zoomLevel = ZOOM_LEVEL_MIN; zoomLevel <= ZOOM_LEVEL_MAX; ++zoomLevel) { Point poi = new Point(0.04, 0.04); int tileX = MercatorProjection.LongitudeToTileX(0.04, zoomLevel); int tileY = MercatorProjection.LatitudeToTileY(0.04, zoomLevel); Tile tile = new Tile(tileX, tileY, zoomLevel); double lonMin = MercatorProjection.TileXToLongitude(tileX, zoomLevel); double lonMax = MercatorProjection.TileXToLongitude(tileX + 1, zoomLevel); double latMin = MercatorProjection.TileYToLatitude(tileY + 1, zoomLevel); double latMax = MercatorProjection.TileYToLatitude(tileY, zoomLevel); //tile.Index = new TileIndex(tileX, tileY, zoomLevel.ToString()); //tile.Extent = new Extent(lonMin, latMin, lonMax, latMax); MapReadResult mapReadResult = mapFile.ReadMapData(tile); Assert.AreEqual(1, mapReadResult.PointOfInterests.Count); Assert.AreEqual(1, mapReadResult.Ways.Count); CheckPointOfInterest(mapReadResult.PointOfInterests[0]); CheckWay(mapReadResult.Ways[0]); } mapFile.Close(); }
/// <summary> /// Called when a job needs to be executed. /// </summary> /// <param name="rendererJob"> /// the job that should be executed. </param> public virtual SKImage ExecuteJob(RendererJob rendererJob) { RenderTheme renderTheme; try { // Wait until RenderTheme is ready renderTheme = rendererJob.renderThemeFuture.Result; } catch (Exception e) { LOGGER.Fatal("Error to retrieve render theme from future", e); return(null); } RenderContext renderContext = null; try { renderContext = new RenderContext(renderTheme, rendererJob, new CanvasRasterer(graphicFactory)); renderContext.canvasRasterer.Canvas = graphicFactory.CreateCanvas(renderContext.rendererJob.tile.TileSize, renderContext.rendererJob.tile.TileSize); if (RenderBitmap(renderContext)) { if (this.mapDatabase != null) { MapReadResult mapReadResult = this.mapDatabase.ReadMapData(rendererJob.tile); ProcessReadMapData(renderContext, mapReadResult); } if (!rendererJob.labelsOnly) { //bitmap = this.graphicFactory.CreateTileBitmap(renderContext.rendererJob.tile.TileSize, renderContext.rendererJob.hasAlpha); //bitmap.Timestamp = rendererJob.mapDataStore.GetDataTimestamp(renderContext.rendererJob.tile); //renderContext.canvasRasterer.CanvasBitmap = bitmap; if (!rendererJob.hasAlpha && rendererJob.displayModel.BackgroundColor != renderContext.renderTheme.MapBackground) { renderContext.canvasRasterer.Fill(renderContext.renderTheme.MapBackground); } renderContext.canvasRasterer.DrawWays(renderContext); } if (renderLabels) { ISet <MapElementContainer> labelsToDraw = ProcessLabels(renderContext); // now draw the ways and the labels renderContext.canvasRasterer.DrawMapElements(labelsToDraw, renderContext.rendererJob.tile); } else { // store elements for this tile in the label cache this.labelStore.StoreMapItems(renderContext.rendererJob.tile, renderContext.labels); } //if (!rendererJob.labelsOnly && renderContext.renderTheme.HasMapBackgroundOutside()) //{ // // blank out all areas outside of map // Rectangle insideArea = this.mapDatabase.BoundingBox.GetPositionRelativeToTile(renderContext.rendererJob.tile); // if (!rendererJob.hasAlpha) // { // //renderContext.canvasRasterer.FillOutsideAreas(renderContext.renderTheme.MapBackgroundOutside, insideArea); // } // else // { // //renderContext.canvasRasterer.FillOutsideAreas(Color.Transparent, insideArea); // } //} return(((SkiaCanvas)renderContext.canvasRasterer.Canvas).Image); } // Draws a bitmap just with outside colour, used for bitmaps outside of map area. if (!renderContext.rendererJob.hasAlpha) { //renderContext.canvasRasterer.Fill(renderContext.renderTheme.MapBackgroundOutside); } return(((SkiaCanvas)renderContext.canvasRasterer.Canvas).Image); } finally { if (renderContext != null) { renderContext.Destroy(); } } }
private MapReadResult ProcessBlocks(QueryParameters queryParameters, SubFileParameter subFileParameter, BoundingBox boundingBox) { bool queryIsWater = true; bool queryReadWaterInfo = false; MapReadResult mapFileReadResult = new MapReadResult(); // read and process all blocks from top to bottom and from left to right for (long row = queryParameters.fromBlockY; row <= queryParameters.toBlockY; ++row) { for (long column = queryParameters.fromBlockX; column <= queryParameters.toBlockX; ++column) { // calculate the actual block number of the needed block in the file long blockNumber = row * subFileParameter.BlocksWidth + column; // get the current index entry long currentBlockIndexEntry = this.databaseIndexCache.GetIndexEntry(subFileParameter, blockNumber); // check if the current query would still return a water tile if (queryIsWater) { // check the water flag of the current block in its index entry queryIsWater &= (currentBlockIndexEntry & BITMASK_INDEX_WATER) != 0; queryReadWaterInfo = true; } // get and check the current block pointer long currentBlockPointer = currentBlockIndexEntry & BITMASK_INDEX_OFFSET; if (currentBlockPointer < 1 || currentBlockPointer > subFileParameter.SubFileSize) { Logger.Log(LogLevel.Warning, "invalid current block pointer: " + currentBlockPointer); Logger.Log(LogLevel.Warning, "subFileSize: " + subFileParameter.SubFileSize); return(null); } long nextBlockPointer; // check if the current block is the last block in the file if (blockNumber + 1 == subFileParameter.NumberOfBlocks) { // set the next block pointer to the end of the file nextBlockPointer = subFileParameter.SubFileSize; } else { // get and check the next block pointer nextBlockPointer = this.databaseIndexCache.GetIndexEntry(subFileParameter, blockNumber + 1) & BITMASK_INDEX_OFFSET; if (nextBlockPointer > subFileParameter.SubFileSize) { Logger.Log(LogLevel.Warning, "invalid next block pointer: " + nextBlockPointer); Logger.Log(LogLevel.Warning, "sub-file size: " + subFileParameter.SubFileSize); return(null); } } // calculate the size of the current block int currentBlockSize = (int)(nextBlockPointer - currentBlockPointer); if (currentBlockSize < 0) { Logger.Log(LogLevel.Warning, "current block size must not be negative: " + currentBlockSize); return(null); } else if (currentBlockSize == 0) { // the current block is empty, continue with the next block continue; } else if (currentBlockSize > ReadBuffer.MaximumBufferSize) { // the current block is too large, continue with the next block Logger.Log(LogLevel.Warning, "current block size too large: " + currentBlockSize); continue; } else if (currentBlockPointer + currentBlockSize > this.fileSize) { Logger.Log(LogLevel.Warning, "current block largher than file size: " + currentBlockSize); return(null); } // read the current block into the buffer ReadBuffer readBuffer = new ReadBuffer(inputStream); if (!readBuffer.ReadFromStream(subFileParameter.StartAddress + currentBlockPointer, currentBlockSize)) { // skip the current block Logger.Log(LogLevel.Warning, "reading current block has failed: " + currentBlockSize); return(null); } // calculate the top-left coordinates of the underlying tile double tileLatitude = MercatorProjection.TileYToLatitude(subFileParameter.BoundaryTileTop + row, subFileParameter.BaseZoomLevel); double tileLongitude = MercatorProjection.TileXToLongitude(subFileParameter.BoundaryTileLeft + column, subFileParameter.BaseZoomLevel); try { PoiWayBundle poiWayBundle = ProcessBlock(queryParameters, subFileParameter, boundingBox, tileLatitude, tileLongitude, readBuffer); if (poiWayBundle != null) { mapFileReadResult.Add(poiWayBundle); } } catch (System.IndexOutOfRangeException e) { Logger.Log(LogLevel.Error, e.Message, e); } } } // the query is finished, was the water flag set for all blocks? if (queryIsWater && queryReadWaterInfo) { // Deprecate water tiles rendering // mapFileReadResult.IsWater = true; } return(mapFileReadResult); }
/** * Called when a job needs to be executed. * * @param mapGeneratorJob * the job that should be executed. * @param BitmapImage * the BitmapImage for the generated map tile. * @return true if the job was executed successfully, false otherwise. */ public bool executeJob(MapGeneratorJob mapGeneratorJob, BitmapImage BitmapImage) { this.currentTile = mapGeneratorJob.tile; System.Windows.Media.Imaging.WriteableBitmap bmp; XmlRenderTheme jobTheme = mapGeneratorJob.jobParameters.jobTheme; if (!jobTheme.Equals(this.previousJobTheme)) { if (this.renderTheme != null) { this.renderTheme.Dispose(); } this.renderTheme = getRenderTheme(jobTheme); if (this.renderTheme == null) { this.previousJobTheme = null; return(false); } createWayLists(); this.previousJobTheme = jobTheme; this.previousZoomLevel = byte.MinValue; // invalidate the previousTextScale so that textScale from jobParameters will // be applied next time this.previousTextScale = -1; } byte zoomLevel = this.currentTile.ZoomFactor; if (zoomLevel != this.previousZoomLevel) { setScaleStrokeWidth(zoomLevel); this.previousZoomLevel = zoomLevel; } float textScale = mapGeneratorJob.jobParameters.textScale; if (textScale != this.previousTextScale) { this.renderTheme.scaleTextSize(textScale); this.previousTextScale = textScale; } if (this.mapDatabase != null) { MapReadResult mapReadResult = this.mapDatabase.ReadMapData(this.currentTile); processReadMapData(mapReadResult); } this.nodes = this.labelPlacement.placeLabels(this.nodes, this.Pointsymbols, this.areaLabels, this.currentTile); this.canvasRasterer.setCanvasBitmap(BitmapImage); this.canvasRasterer.fill(this.renderTheme.getMapBackground()); this.canvasRasterer.drawWays(this.ways); this.canvasRasterer.drawSymbols(this.waySymbols); this.canvasRasterer.drawSymbols(this.Pointsymbols); this.canvasRasterer.drawWayNames(this.wayNames); this.canvasRasterer.drawNodes(this.nodes); this.canvasRasterer.drawNodes(this.areaLabels); if (mapGeneratorJob.debugSettings.drawTileFrames) { this.canvasRasterer.drawTileFrame(); } if (mapGeneratorJob.debugSettings.drawTileCoordinates) { this.canvasRasterer.drawTileCoordinates(this.currentTile); } clearLists(); return(true); }
public IEnumerable <VectorTileLayer> GetTile(TileInfo tileInfo) { // Check MapFile if (mapFile == null) { throw new NullReferenceException("mapFile shouldn't be null"); } // Read tile data MapReadResult mapReadResult = mapFile.ReadMapData(tileInfo); List <VectorTileLayer> result = new List <VectorTileLayer>(); Dictionary <int, VectorTileLayer> layers = new Dictionary <int, VectorTileLayer>(); if (mapReadResult == null) { return(result); } if (mapReadResult.PointOfInterests.Count == 0 && mapReadResult.Ways.Count == 0) { return(result); } // Convert PointOfInterests to Features for (int i = 0; i < mapReadResult.PointOfInterests.Count; i++) { PointOfInterest poi = mapReadResult.PointOfInterests[i]; Feature feature = new Feature(); feature.GeometryType = GeometryType.Point; feature.Geometry.Add(new VectorTileGeometry(poi.Position)); feature.Tags.Add(poi.Tags); VectorTileLayer layer; if (!layers.ContainsKey(poi.Layer)) { layers.Add(poi.Layer, new VectorTileLayer { Name = poi.Layer.ToString() }); } layers.TryGetValue(poi.Layer, out layer); layer.VectorTileFeatures.Add(feature); } // Convert Ways to Features for (int i = 0; i < mapReadResult.Ways.Count; i++) { Way way = mapReadResult.Ways[i]; List <Feature> features = new List <Feature>(); foreach (List <Point> points in way.Points) { Feature feature = new Feature(); if (Math.Abs(points[0].X - points[points.Count - 1].X) < epsilon && Math.Abs(points[0].Y - points[points.Count - 1].Y) < epsilon) { feature.GeometryType = GeometryType.Polygon; } else { feature.GeometryType = GeometryType.LineString; } feature.Geometry.Add(new VectorTileGeometry(points)); feature.Tags.Add(way.Tags); features.Add(feature); } VectorTileLayer layer; if (!layers.ContainsKey(way.Layer)) { layers.Add(way.Layer, new VectorTileLayer { Name = way.Layer.ToString() }); } layers.TryGetValue(way.Layer, out layer); layer.VectorTileFeatures.AddRange(features); } foreach (var layer in layers) { result.Add(layer.Value); } return(result); // Get zoom level for resolution // Get tiles for bounding box // For each tile // Get POIs and Ways for tile // Convert POIs and Ways to Feature // Add to Feature list // Return Feature list }