Пример #1
0
        /// <summary>
        /// Called when the mapview has changed.
        /// </summary>
        /// <param name="map"></param>
        /// <param name="zoomFactor"></param>
        /// <param name="center"></param>
        /// <param name="view"></param>
        public void ViewChanged(Map map, float zoomFactor, GeoCoordinate center,
                                View2D view)
        {
            // calculate the current zoom level.
            var zoomLevel = (int)System.Math.Round(map.Projection.ToZoomLevel(zoomFactor), 0);

            // build the boundingbox.
            var box = new GeoCoordinateBox(
                map.Projection.ToGeoCoordinates(view.Left, view.Top),
                map.Projection.ToGeoCoordinates(view.Right, view.Bottom));

            // build the tile range.
            TileRange range = TileRange.CreateAroundBoundingBox(box, zoomLevel);
            DateTime  now   = DateTime.Now;

            // build the new scene.
            Scene2D newScene = new Scene2D();

            if (_connection.State == System.Data.ConnectionState.Closed)
            {
                _connection.Open();
            }
            lock (_connection)
            { // make sure the connection is accessed synchronously.
                // TODO: Investigate the SQLite multithreaded behaviour..
                // TODO: this a very naive way of loading these tiles. Find a way to query SQLite more efficiently
                // TODO: find a way to have some cached tiles.
                foreach (var tile in range)
                {
                    Tile invertTile = tile.InvertY();

                    SQLiteCommand command = new SQLiteCommand("SELECT * FROM tiles WHERE zoom_level = :zoom_level AND tile_column = :tile_column AND tile_row = :tile_row;",
                                                              _connection);
                    command.Parameters.AddWithValue("zoom_level", invertTile.Zoom);
                    command.Parameters.AddWithValue("tile_column", invertTile.X);
                    command.Parameters.AddWithValue("tile_row", invertTile.Y);
                    using (var tileReader = command.ExecuteReader())
                    {
                        while (tileReader.Read())
                        {
                            //Tile readTile = new Tile((int)tileReader["tile_column"],
                            //    (int)tileReader["tile_row"], (int)tileReader["zoom_level"]);

                            float minZoom = (float)map.Projection.ToZoomFactor(tile.Zoom - 0.5f);
                            float maxZoom = (float)map.Projection.ToZoomFactor(tile.Zoom + 0.5f);
                            float left    = (float)map.Projection.LongitudeToX(tile.TopLeft.Longitude);
                            float right   = (float)map.Projection.LongitudeToX(tile.BottomRight.Longitude);
                            float bottom  = (float)map.Projection.LatitudeToY(tile.BottomRight.Latitude);
                            float top     = (float)map.Projection.LatitudeToY(tile.TopLeft.Latitude);

                            newScene.AddImage(0, minZoom, maxZoom, left, top, right, bottom,
                                              (byte[])tileReader["tile_data"]);
                        }
                    }
                }
                this.Scene = newScene;
            }
        }
Пример #2
0
        /// <summary>
        /// Render the current complete scene.
        /// </summary>
        void Render()
        {
            if (_cacheRenderer.IsRunning)
            {
                _cacheRenderer.CancelAndWait();
            }

            if (_rect == null)               // only render if a proper size is known.
            {
                return;
            }

            lock (_cacheRenderer) {             // make sure only on thread at the same time is using the renderer.
                double extra = 1.25;

                // build the layers list.
                var layers = new List <ILayer> ();
                for (int layerIdx = 0; layerIdx < this.Map.LayerCount; layerIdx++)
                {
                    layers.Add(this.Map [layerIdx]);
                }

                // add the internal layer.
                // TODO: create marker layer.

                // create a new bitmap context.
                CGColorSpace space            = CGColorSpace.CreateDeviceRGB();
                int          bytesPerPixel    = 4;
                int          bytesPerRow      = bytesPerPixel * (int)_rect.Width;
                int          bitsPerComponent = 8;
                if (_bytescache == null)
                {
                    _bytescache = new byte[bytesPerRow * (int)_rect.Height];
                }
                CGBitmapContext gctx = new CGBitmapContext(null, (int)_rect.Width, (int)_rect.Height,
                                                           bitsPerComponent, bytesPerRow,
                                                           space,                  // kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast
                                                           CGBitmapFlags.PremultipliedFirst | CGBitmapFlags.ByteOrder32Big);

                // create the view.
                View2D view = _cacheRenderer.Create(_rect.Width, _rect.Height,
                                                    this.Map, (float)this.Map.Projection.ToZoomFactor(this.MapZoomLevel),
                                                    this.MapCenter, false, true);
                long before = DateTime.Now.Ticks;
                OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information,
                                                "Rendering Start");

                // notify the map that the view has changed.
                this.Map.ViewChanged((float)this.Map.Projection.ToZoomFactor(this.MapZoomLevel), this.MapCenter,
                                     view);
                long afterViewChanged = DateTime.Now.Ticks;
                OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information,
                                                "View change took: {0}ms @ zoom level {1}",
                                                (new TimeSpan(afterViewChanged - before).TotalMilliseconds), this.MapZoomLevel);

//				// add the current canvas to the scene.
//				uint canvasId = _scene.AddImage (-1, float.MinValue, float.MaxValue,
//				                                 view.Left, view.Top, view.Right, view.Bottom, new byte[0], _canvasBitmap);

                // does the rendering.
                bool complete = _cacheRenderer.Render(new CGContextWrapper(gctx, new RectangleF(0, 0, _rect.Width, _rect.Height)),
                                                      layers, view);

                long afterRendering = DateTime.Now.Ticks;
                OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information,
                                                "Rendering took: {0}ms @ zoom level {1}",
                                                (new TimeSpan(afterRendering - afterViewChanged).TotalMilliseconds), this.MapZoomLevel);
                if (complete)                   // there was no cancellation, the rendering completely finished.
                // add the result to the scene cache.
                {
                    lock (_cachedScene) {
                        // add the newly rendered image again.
                        //this.Layer.Contents = gctx.ToImage ();

                        BoxF2D rectangle = view.OuterBox;

                        _cachedScene.Clear();
                        _cachedScene.AddImage(0, float.MinValue, float.MaxValue,
                                              rectangle.Min[0], rectangle.Min[1], rectangle.Max[0], rectangle.Max[1], new byte[0], gctx.ToImage());
//						_cachedScene.AddImage (0, float.MinValue, float.MaxValue,
//						                       view.Left, view.Top, view.Right, view.Bottom, new byte[0], _layer);
                    }

                    this.InvokeOnMainThread(Test);
                }

                long after = DateTime.Now.Ticks;
                if (!complete)
                {
                    OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information, "Rendering in {0}ms after cancellation!",
                                                    new TimeSpan(after - before).TotalMilliseconds);
                }
                else
                {
                    OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information, "Rendering in {0}ms",
                                                    new TimeSpan(after - before).TotalMilliseconds);
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Renders the current complete scene.
        /// </summary>
        void Render()
        {
            if (_cacheRenderer.IsRunning)
            {
                _cacheRenderer.CancelAndWait();
            }

            // make sure only on thread at the same time is using the renderer.
            lock (_cacheRenderer) {
                double extra = 1.25;

                // build the layers list.
                var layers = new List <ILayer> ();
                for (int layerIdx = 0; layerIdx < this.Map.LayerCount; layerIdx++)
                {
                    // get the layer.
                    layers.Add(this.Map[layerIdx]);
                }

                // add the internal layers.
                layers.Add(_makerLayer);

                // create a new cache if size has changed.
                if (_canvasBitmap == null ||
                    _canvasBitmap.Width != (int)(this.Width * extra) ||
                    _canvasBitmap.Height != (int)(this.Height * extra))
                {
                    // create a bitmap and render there.
                    _canvasBitmap = global::Android.Graphics.Bitmap.CreateBitmap((int)(this.Width * extra),
                                                                                 (int)(this.Height * extra),
                                                                                 global::Android.Graphics.Bitmap.Config.Argb8888);
                }
                else
                {
                    // clear the cache???
                }

                // create and reset the canvas.
                global::Android.Graphics.Canvas canvas = new global::Android.Graphics.Canvas(_canvasBitmap);
                canvas.DrawColor(new global::Android.Graphics.Color(
                                     SimpleColor.FromKnownColor(KnownColor.Transparent).Value));

                // create the view.
                View2D view = _cacheRenderer.Create(canvas.Width, canvas.Height,
                                                    this.Map, (float)this.Map.Projection.ToZoomFactor(this.MapZoomLevel),
                                                    this.MapCenter, _invertX, _invertY);
                long before = DateTime.Now.Ticks;

                OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information,
                                                "Rendering Start");

                // notify the map that the view has changed.
                this.Map.ViewChanged((float)this.Map.Projection.ToZoomFactor(this.MapZoomLevel), this.MapCenter,
                                     view);
                long afterViewChanged = DateTime.Now.Ticks;
                OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information,
                                                "View change took: {0}ms @ zoom level {1}",
                                                (new TimeSpan(afterViewChanged - before).TotalMilliseconds), this.MapZoomLevel);

                // add the current canvas to the scene.
                double left     = view.LeftTop [0];
                double right    = view.RightTop [0];
                double top      = view.LeftTop [1];
                double bottom   = view.LeftBottom [1];
                uint   canvasId = _scene.AddImage(-1, float.MinValue, float.MaxValue,
                                                  left, top, right, bottom, new byte[0], _canvasBitmap);

                // does the rendering.
                bool complete = _cacheRenderer.Render(canvas, layers, view);

                long afterRendering = DateTime.Now.Ticks;
                OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information,
                                                "Rendering took: {0}ms @ zoom level {1}",
                                                (new TimeSpan(afterRendering - afterViewChanged).TotalMilliseconds), this.MapZoomLevel);
                if (complete)
                {                 // there was no cancellation, the rendering completely finished.
                    // add the result to the scene cache.
                    lock (_scene) {
//						if (_previousCache.HasValue) {
//							_scene.Remove (_previousCache.Value);
//						}
//						_scene.Remove (canvasId);
//
                        // add the newly rendered image again.
                        _scene.Clear();
                        //_previousCache =
                        BoxF2D viewBox = view.OuterBox;
                        _scene.AddImage(0, float.MinValue, float.MaxValue,
                                        viewBox.Min[0], viewBox.Min[1], viewBox.Max[0], viewBox.Max[1], new byte[0], _canvasBitmap);

                        // switch cache and canvas to prevent re-allocation of bitmaps.
                        global::Android.Graphics.Bitmap newCanvas = _cache;
                        _cache        = _canvasBitmap;
                        _canvasBitmap = newCanvas;
                    }
                }

                this.PostInvalidate();

                long after = DateTime.Now.Ticks;
                if (!complete)
                {
                    OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information, "Rendering in {0}ms after cancellation!",
                                                    new TimeSpan(after - before).TotalMilliseconds);
                }
                else
                {
                    OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information, "Rendering in {0}ms",
                                                    new TimeSpan(after - before).TotalMilliseconds);
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Translates a node.
        /// </summary>
        /// <param name="scene">The scene to add primitives to.</param>
        /// <param name="projection">The projection used to convert the objects.</param>
        /// <param name="node"></param>
        private void TranslateNode(Scene2D scene, IProjection projection, CompleteNode node)
        {
            // build the rules.
            IEnumerable <MapCSSRuleProperties> rules =
                this.BuildRules(new MapCSSObject(node));

            // interpret the results.
            foreach (var rule in rules)
            {
                int zIndex;
                if (!rule.TryGetProperty <int>("zIndex", out zIndex))
                {
                    zIndex = 0;
                }

                float minZoom = (float)projection.ToZoomFactor(rule.MinZoom);
                float maxZoom = (float)projection.ToZoomFactor(rule.MaxZoom);

                uint?pointId = null;
                int  color;
                if (rule.TryGetProperty <int>("color", out color))
                {
                    float width;
                    if (rule.TryGetProperty <float>("width", out width))
                    {
                        pointId = scene.AddPoint(projection.LongitudeToX(node.Coordinate.Longitude),
                                                 projection.LatitudeToY(node.Coordinate.Latitude));
                        scene.AddStylePoint(pointId.Value, this.CalculateSceneLayer(OffsetPoint, zIndex), minZoom, maxZoom, color, width);
                    }
                    else
                    {
                        pointId = scene.AddPoint(projection.LongitudeToX(node.Coordinate.Longitude),
                                                 projection.LatitudeToY(node.Coordinate.Latitude));
                        scene.AddStylePoint(pointId.Value, this.CalculateSceneLayer(OffsetPoint, zIndex), minZoom, maxZoom, color, 1);
                    }
                }
                byte[] iconImage;
                if (rule.TryGetProperty("iconImage", out iconImage))
                {
                    if (!pointId.HasValue)
                    {
                        pointId = scene.AddPoint(projection.LongitudeToX(node.Coordinate.Longitude),
                                                 projection.LatitudeToY(node.Coordinate.Latitude));
                    }
                    // an icon is to be drawn!
                    ushort imageId = scene.AddImage(iconImage);
                    scene.AddIcon(pointId.Value, this.CalculateSceneLayer(OffsetPoint, zIndex), minZoom, maxZoom, imageId);
                }

                string text;
                if (rule.TryGetProperty("text", out text))
                {
                    int textColor;
                    if (!rule.TryGetProperty("textColor", out textColor))
                    {
                        textColor = SimpleColor.FromKnownColor(KnownColor.Black).Value;
                    }
                    int haloColor;
                    int?haloColorNullable = null;
                    if (rule.TryGetProperty("textHaloColor", out haloColor))
                    {
                        haloColorNullable = haloColor;
                    }
                    int haloRadius;
                    int?haloRadiusNullable = null;
                    if (rule.TryGetProperty("textHaloRadius", out haloRadius))
                    {
                        haloRadiusNullable = haloRadius;
                    }
                    int fontSize;
                    if (!rule.TryGetProperty("fontSize", out fontSize))
                    {
                        fontSize = 10;
                    }
                    string fontFamily;
                    if (!rule.TryGetProperty("fontFamily", out fontFamily))
                    {
                        fontFamily = "Arial";                         // just some default font.
                    }

                    // a text is to be drawn.
                    string value;
                    if (node.Tags.TryGetValue(text, out value))
                    {
                        if (!pointId.HasValue)
                        {
                            pointId = scene.AddPoint(projection.LongitudeToX(node.Coordinate.Longitude),
                                                     projection.LatitudeToY(node.Coordinate.Latitude));
                        }
                        scene.AddText(pointId.Value, this.CalculateSceneLayer(OffsetPointText, zIndex), minZoom, maxZoom, fontSize, value, textColor,
                                      haloColorNullable, haloRadiusNullable, fontFamily);
                    }
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Render the current complete scene.
        /// </summary>
        void Render()
        {
            try {
                RectangleF rect = _rect;

                lock (this.Map) {
                    //lock (_cacheRenderer) { // make sure only on thread at the same time is using the renderer.
                    // create the view.
                    View2D view = _cacheRenderer.Create((int)(rect.Width * _extra), (int)(rect.Height * _extra),
                                                        this.Map, (float)this.Map.Projection.ToZoomFactor(this.MapZoom),
                                                        this.MapCenter, _invertX, _invertY, this.MapTilt);

                    if (view.Equals(_previousRenderedZoom))
                    {
                        return;
                    }

                    if (rect.Width == 0)               // only render if a proper size is known.
                    {
                        return;
                    }

                    OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information,
                                                    "Before lock.");

                    long before = DateTime.Now.Ticks;
                    //				OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information,
                    //				                                "Rendering Start");

                    // build the layers list.
                    var layers = new List <ILayer> ();
                    for (int layerIdx = 0; layerIdx < this.Map.LayerCount; layerIdx++)
                    {
                        layers.Add(this.Map [layerIdx]);
                    }

                    // add the internal layer.
                    // TODO: create marker layer.
                    int imageWidth  = (int)(rect.Width * _extra * _scaleFactor);
                    int imageHeight = (int)(rect.Height * _extra * _scaleFactor);

                    // create a new bitmap context.
                    CGColorSpace space            = CGColorSpace.CreateDeviceRGB();
                    int          bytesPerPixel    = 4;
                    int          bytesPerRow      = bytesPerPixel * imageWidth;
                    int          bitsPerComponent = 8;
                    if (_bytescache == null)
                    {
                        _bytescache = new byte[bytesPerRow * imageHeight];
                    }
                    CGBitmapContext gctx = new CGBitmapContext(null, imageWidth, imageHeight,
                                                               bitsPerComponent, bytesPerRow,
                                                               space,               // kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast
                                                               CGBitmapFlags.PremultipliedFirst | CGBitmapFlags.ByteOrder32Big);

                    // notify the map that the view has changed.
                    this.Map.ViewChanged((float)this.Map.Projection.ToZoomFactor(this.MapZoom), this.MapCenter,
                                         view);
                    long afterViewChanged = DateTime.Now.Ticks;
                    OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information,
                                                    "View change took: {0}ms @ zoom level {1}",
                                                    (new TimeSpan(afterViewChanged - before).TotalMilliseconds), this.MapZoom);

                    // does the rendering.
                    bool complete = _cacheRenderer.Render(new CGContextWrapper(gctx,
                                                                               new RectangleF(0, 0, (int)(rect.Width * _extra), (int)(rect.Height * _extra))),
                                                          layers, view);

                    long afterRendering = DateTime.Now.Ticks;
                    OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information,
                                                    "Rendering took: {0}ms @ zoom level {1}",
                                                    (new TimeSpan(afterRendering - afterViewChanged).TotalMilliseconds), this.MapZoom);

                    if (complete)               // there was no cancellation, the rendering completely finished.
                    // add the result to the scene cache.
                    {
                        lock (_cachedScene) {
                            // add the newly rendered image again.
                            _cachedScene.Clear();
                            _cachedScene.AddImage(0, float.MinValue, float.MaxValue, view.Rectangle, new byte[0], gctx.ToImage());
                        }
                        this.InvokeOnMainThread(InvalidateMap);

                        // store the previous view.
                        _previousRenderedZoom = view;
                    }

                    long after = DateTime.Now.Ticks;
                    //				if (!complete) {
                    //					OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information,"Rendering CANCELLED!",
                    //					                                new TimeSpan (after - before).TotalMilliseconds);
                    //				} else {
                    OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information,
                                                    "Rendering in {0}ms", new TimeSpan(after - before).TotalMilliseconds);
                    //				}
                    //}
                }
            }
            catch (Exception ex) {
                _cacheRenderer.Reset();
            }
        }
Пример #6
0
        /// <summary>
        /// Called when the mapview has changed.
        /// </summary>
        /// <param name="map"></param>
        /// <param name="zoomFactor"></param>
        /// <param name="center"></param>
        /// <param name="view"></param>
        public void ViewChanged(Map map, float zoomFactor, GeoCoordinate center, 
            View2D view)
        {
            // calculate the current zoom level.
            var zoomLevel = (int)System.Math.Round(map.Projection.ToZoomLevel(zoomFactor), 0);

            // build the boundingbox.
            var box = new GeoCoordinateBox(
                    map.Projection.ToGeoCoordinates(view.Left, view.Top),
                    map.Projection.ToGeoCoordinates(view.Right, view.Bottom));

            // build the tile range.
            TileRange range = TileRange.CreateAroundBoundingBox(box, zoomLevel);
            DateTime now = DateTime.Now;

            // build the new scene.
            Scene2D newScene = new Scene2D();
            if (_connection.State == System.Data.ConnectionState.Closed)
            {
                _connection.Open();
            }
            lock (_connection)
            { // make sure the connection is accessed synchronously.
                // TODO: Investigate the SQLite multithreaded behaviour..
                // TODO: this a very naive way of loading these tiles. Find a way to query SQLite more efficiently
                // TODO: find a way to have some cached tiles.
                foreach (var tile in range)
                {
                    Tile invertTile = tile.InvertY();

                    SQLiteCommand command = new SQLiteCommand("SELECT * FROM tiles WHERE zoom_level = :zoom_level AND tile_column = :tile_column AND tile_row = :tile_row;",
                        _connection);
                    command.Parameters.AddWithValue("zoom_level", invertTile.Zoom);
                    command.Parameters.AddWithValue("tile_column", invertTile.X);
                    command.Parameters.AddWithValue("tile_row", invertTile.Y);
                    using (var tileReader = command.ExecuteReader())
                    {
                        while (tileReader.Read())
                        {
                            //Tile readTile = new Tile((int)tileReader["tile_column"],
                            //    (int)tileReader["tile_row"], (int)tileReader["zoom_level"]);

                            float minZoom = (float)map.Projection.ToZoomFactor(tile.Zoom - 0.5f);
                            float maxZoom = (float)map.Projection.ToZoomFactor(tile.Zoom + 0.5f);
                            float left = (float)map.Projection.LongitudeToX(tile.TopLeft.Longitude);
                            float right = (float)map.Projection.LongitudeToX(tile.BottomRight.Longitude);
                            float bottom = (float)map.Projection.LatitudeToY(tile.BottomRight.Latitude);
                            float top = (float)map.Projection.LatitudeToY(tile.TopLeft.Latitude);

                            newScene.AddImage(0, minZoom, maxZoom, left, top, right, bottom,
                                                (byte[])tileReader["tile_data"]);
                        }
                    }
                }
                this.Scene = newScene;
            }
        }