コード例 #1
0
ファイル: TileLayer.cs プロジェクト: tilemapjp/MapsforgeSharp
        public override void Draw(BoundingBox boundingBox, sbyte zoomLevel, ICanvas canvas, Point topLeftPoint)
        {
            IList <TilePosition> tilePositions = LayerUtil.GetTilePositions(boundingBox, zoomLevel, topLeftPoint, this.displayModel.TileSize);

            // In a rotation situation it is possible that drawParentTileBitmap sets the
            // clipping bounds to portrait, while the device is just being rotated into
            // landscape: the result is a partially painted screen that only goes away
            // after zooming (which has the effect of resetting the clip bounds if drawParentTileBitmap
            // is called again).
            // Always resetting the clip bounds here seems to avoid the problem,
            // I assume that this is a pretty cheap operation, otherwise it would be better
            // to hook this into the onConfigurationChanged call chain.
            canvas.ResetClip();

            if (!isTransparent)
            {
                canvas.FillColor(this.displayModel.BackgroundColor);
            }

            ISet <Job> jobs = new HashSet <Job>();

            foreach (TilePosition tilePosition in tilePositions)
            {
                jobs.Add(CreateJob(tilePosition.Tile));
            }
            this.tileCache.WorkingSet = jobs;

            for (int i = tilePositions.Count - 1; i >= 0; --i)
            {
                TilePosition tilePosition = tilePositions[i];
                Point        point        = tilePosition.Point;
                Tile         tile         = tilePosition.Tile;
                T            job          = CreateJob(tile);
                ITileBitmap  bitmap       = this.tileCache.GetImmediately(job);

                if (bitmap == null)
                {
                    if (this.hasJobQueue && !this.tileCache.ContainsKey(job))
                    {
                        this.jobQueue.Add(job);
                    }
                    DrawParentTileBitmap(canvas, point, tile);
                }
                else
                {
                    if (IsTileStale(tile, bitmap) && this.hasJobQueue && !this.tileCache.ContainsKey(job))
                    {
                        this.jobQueue.Add(job);
                    }
                    RetrieveLabelsOnly(job);
                    canvas.DrawBitmap(bitmap, (int)Math.Round(point.X), (int)Math.Round(point.Y));
                    bitmap.DecrementRefCount();
                }
            }
            if (this.hasJobQueue)
            {
                this.jobQueue.NotifyWorkers();
            }
        }
コード例 #2
0
 /// <summary>
 /// Stores a list of MapElements against a tile.
 /// </summary>
 /// <param name="tile"> tile on which the mapItems reside. </param>
 /// <param name="mapItems"> the map elements. </param>
 public virtual void StoreMapItems(Tile tile, ICollection <MapElementContainer> mapItems)
 {
     lock (this)
     {
         this.Add(tile, LayerUtil.CollisionFreeOrdered(mapItems));
         this.version += 1;
     }
 }
コード例 #3
0
        public override void Draw(BoundingBox boundingBox, sbyte zoomLevel, ICanvas canvas, Point topLeftPoint)
        {
            IList <TilePosition> tilePositions = LayerUtil.GetTilePositions(boundingBox, zoomLevel, topLeftPoint, this.displayModel.TileSize);

            for (int i = tilePositions.Count - 1; i >= 0; --i)
            {
                DrawTileCoordinates(tilePositions[i], canvas);
            }
        }
コード例 #4
0
        public override void Draw(BoundingBox boundingBox, sbyte zoomLevel, ICanvas canvas, Point topLeftPoint)
        {
            ISet <Tile> currentTileSet = LayerUtil.GetTiles(boundingBox, zoomLevel, displayModel.TileSize);

            if (!currentTileSet.Equals(lastTileSet) || lastLabelStoreVersion != labelStore.Version)
            {
                // only need to get new data set if either set of tiles changed or the label store
                lastTileSet           = currentTileSet;
                lastLabelStoreVersion = labelStore.Version;
                IList <MapElementContainer> visibleItems = this.labelStore.GetVisibleItems(currentTileSet);

                // TODO this is code duplicated from CanvasRasterer::drawMapElements, should be factored out
                // what LayerUtil.collisionFreeOrdered gave us is a list where highest priority comes first,
                // so we need to reverse that in order to
                // draw elements in order of priority: lower priority first, so more important
                // elements will be drawn on top (in case of display=true) items.
                elementsToDraw = from element in LayerUtil.CollisionFreeOrdered(visibleItems) orderby element.Priority ascending select element;
            }

            foreach (MapElementContainer item in elementsToDraw)
            {
                item.Draw(canvas, topLeftPoint, this.matrix);
            }
        }
コード例 #5
0
        private ISet <MapElementContainer> ProcessLabels(RenderContext renderContext)
        {
            // if we are drawing the labels per tile, we need to establish which tile-overlapping
            // elements need to be drawn.

            ISet <MapElementContainer> labelsToDraw = new HashSet <MapElementContainer>();

            lock (tileDependencies)
            {
                // first we need to get the labels from the adjacent tiles if they have already been drawn
                // as those overlapping items must also be drawn on the current tile. They must be drawn regardless
                // of priority clashes as a part of them has alread been drawn.
                ISet <Tile> neighbours = renderContext.rendererJob.tile.Neighbours;
                ISet <MapElementContainer> undrawableElements = new HashSet <MapElementContainer>();

                tileDependencies.AddTileInProgress(renderContext.rendererJob.tile);
                for (var i = neighbours.Count - 1; i >= 0; i--)
                {
                    Tile neighbour = neighbours.ElementAt(i);

                    if (tileDependencies.IsTileInProgress(neighbour) || tileCache.ContainsKey(renderContext.rendererJob.OtherTile(neighbour)))
                    {
                        // if a tile has already been drawn, the elements drawn that overlap onto the
                        // current tile should be in the tile dependencies, we add them to the labels that
                        // need to be drawn onto this tile. For the multi-threaded renderer we also need to take
                        // those tiles into account that are not yet in the TileCache: this is taken care of by the
                        // set of tilesInProgress inside the TileDependencies.
                        labelsToDraw.UnionWith(tileDependencies.GetOverlappingElements(neighbour, renderContext.rendererJob.tile));

                        // but we need to remove the labels for this tile that overlap onto a tile that has been drawn
                        foreach (MapElementContainer current in renderContext.labels)
                        {
                            if (current.Intersects(neighbour.BoundaryAbsolute))
                            {
                                undrawableElements.Add(current);
                            }
                        }
                        // since we already have the data from that tile, we do not need to get the data for
                        // it, so remove it from the neighbours list.
                        neighbours.Remove(neighbour);
                    }
                    else
                    {
                        tileDependencies.RemoveTileData(neighbour);
                    }
                }

                // now we remove the elements that overlap onto a drawn tile from the list of labels
                // for this tile
                foreach (var element in undrawableElements)
                {
                    renderContext.labels.Remove(element);
                }

                // at this point we have two lists: one is the list of labels that must be drawn because
                // they already overlap from other tiles. The second one is currentLabels that contains
                // the elements on this tile that do not overlap onto a drawn tile. Now we sort this list and
                // remove those elements that clash in this list already.
                ICollection <MapElementContainer> currentElementsOrdered = LayerUtil.CollisionFreeOrdered(renderContext.labels);

                // now we go through this list, ordered by priority, to see which can be drawn without clashing.
                IEnumerator <MapElementContainer> currentMapElementsIterator = currentElementsOrdered.GetEnumerator();
                while (currentMapElementsIterator.MoveNext())
                {
                    MapElementContainer current = currentMapElementsIterator.Current;
                    foreach (MapElementContainer label in labelsToDraw)
                    {
                        if (label.ClashesWith(current))
                        {
                            break;
                        }
                    }
                }

                labelsToDraw.UnionWith(currentElementsOrdered);

                // update dependencies, add to the dependencies list all the elements that overlap to the
                // neighbouring tiles, first clearing out the cache for this relation.
                foreach (Tile tile in neighbours)
                {
                    tileDependencies.RemoveTileData(renderContext.rendererJob.tile, tile);
                    foreach (MapElementContainer element in labelsToDraw)
                    {
                        if (element.Intersects(tile.BoundaryAbsolute))
                        {
                            tileDependencies.AddOverlappingElement(renderContext.rendererJob.tile, tile, element);
                        }
                    }
                }
            }
            return(labelsToDraw);
        }