Exemple #1
0
        /// <summary>
        /// Adds the image.
        /// </summary>
        /// <returns>The image.</returns>
        /// <param name="layer">Layer.</param>
        /// <param name="minZoom">Minimum zoom.</param>
        /// <param name="maxZoom">Max zoom.</param>
        /// <param name="rectangle">Rectangle.</param>
        /// <param name="imageData">Image data.</param>
        /// <param name="tag">Tag.</param>
        public override uint AddImage(int layer, float minZoom, float maxZoom, RectangleF2D rectangle, byte[] imageData, object tag)
        {
            if (imageData == null)
            {
                throw new ArgumentNullException("imageData");
            }


            lock (_primitives)
            {
                uint id = _nextId;
                _nextId++;

                var imageTilted2D = new ImageTilted2D(rectangle, imageData, minZoom, maxZoom);
                imageTilted2D.Tag = tag;
                this.AddPrimitive(layer, id, imageTilted2D);
                return(id);
            }
        }
        /// <summary>
        /// Diposes of all resources associated with this object.
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            if (disposing == true)
            {
                //someone wants the deterministic release of all resources
                //Let us release all the managed resources
            }
            else
            {
                // Do nothing, no one asked a dispose, the object went out of
                // scope and finalized is called so lets next round of GC
                // release these resources
            }

            // Release the unmanaged resource in any case as they will not be
            // released by GC
            this._cacheRenderer = null;
            if (this._offScreenBuffer != null)
            { // dispose of the map view surface.
                this._offScreenBuffer.Dispose();
                this._offScreenBuffer = null;
            }
            if (this._onScreenBuffer != null)
            { // dispose of the map view surface.
                this._onScreenBuffer.Dispose();
                this._onScreenBuffer = null;
            }
            if (this._mapViewAnimator != null)
            {
                _mapViewAnimator.Stop();
                _mapViewAnimator = null;
            }
            if (this._map != null)
            {
                this._map = null;
            }

            this._scaleGestureDetector  = null;
            this._tagGestureDetector    = null;
            this._moveGestureDetector   = null;
            this._rotateGestureDetector = null;
        }
Exemple #3
0
        /// <summary>
        /// Renders the primities for the given scene.
        /// </summary>
        /// <param name="target"></param>
        /// <param name="view"></param>
        /// <param name="zoomFactor"></param>
        /// <param name="primitives"></param>
        private bool RenderPrimitives(Target2DWrapper <TTarget> target, View2D view, float zoomFactor,
                                      IEnumerable <Primitive2D> primitives)
        {
            try {
                // calculate current simplification epsilon.
                double epsilon = Scene2D.CalculateSimplificationEpsilon(new WebMercator(), zoomFactor);

                // loop over all primitives in the scene.
                int simplifiedLines = 0;
                int droppedLines    = 0;
                foreach (Primitive2D primitive in primitives)
                {     // the primitive is visible.
                    if (_cancelFlag)
                    {
                        return(false);                        // stop rendering on cancel and return false for an incomplete rendering.
                    }

                    if (primitive == null)
                    {
                        continue;
                    }
                    double[] x, y;
                    switch (primitive.Primitive2DType)
                    {
                    case Primitive2DType.Line2D:
                        Line2D line = (Line2D)primitive;

                        x = line.X;
                        y = line.Y;
                        if (x.Length > 4 && line.MaxZoom > zoomFactor * 2 && line.MaxZoom < 512)
                        {     // try and simplify.
                            double[][] simplified = OsmSharp.Math.Algorithms.SimplifyCurve.Simplify(new double[][] { x, y },
                                                                                                    epsilon);
                            if (simplified[0].Length < line.X.Length)
                            {
                                simplifiedLines++;
                                x = simplified[0];
                                y = simplified[1];
                            }
                            double distance = epsilon * 2;
                            if (simplified[0].Length == 2)
                            {     // check if the simplified version is smaller than epsilon.
                                distance = System.Math.Sqrt(
                                    System.Math.Pow((simplified[0][0] - simplified[0][1]), 2) +
                                    System.Math.Pow((simplified[1][0] - simplified[1][1]), 2));
                            }
                            if (distance < epsilon)
                            {
                                droppedLines++;
                                continue;
                            }
                        }
                        this.DrawLine(target, x, y, line.Color,
                                      this.FromPixels(target, view, line.Width), line.LineJoin, line.Dashes);
                        break;

                    case Primitive2DType.Polygon2D:
                        Polygon2D polygon = (Polygon2D)primitive;

                        x = polygon.X;
                        y = polygon.Y;
                        //if (x.Length > 4 && polygon.MaxZoom > zoomFactor * 2 && polygon.MaxZoom < 512)
                        //{ // try and simplify.
                        //    double[][] simplified = OsmSharp.Math.Algorithms.SimplifyCurve.Simplify(new double[][] { x, y },
                        //        epsilon);
                        //    if (simplified[0].Length < polygon.X.Length)
                        //    {
                        //        simplifiedLines++;
                        //        x = simplified[0];
                        //        y = simplified[1];
                        //    }
                        //    double distance = epsilon * 2;
                        //    if (simplified[0].Length == 2)
                        //    { // check if the simplified version is smaller than epsilon.
                        //        distance = System.Math.Sqrt(
                        //            System.Math.Pow((simplified[0][0] - simplified[0][1]), 2) +
                        //            System.Math.Pow((simplified[1][0] - simplified[1][1]), 2));
                        //    }
                        //    //if (distance < epsilon)
                        //    //{
                        //    //    droppedLines++;
                        //    //    continue;
                        //    //}
                        //}
                        this.DrawPolygon(target, x, y, polygon.Color,
                                         this.FromPixels(target, view, polygon.Width), polygon.Fill);
                        break;

                    case Primitive2DType.LineText2D:
                        LineText2D lineText = (LineText2D)primitive;
                        this.DrawLineText(target, lineText.X, lineText.Y, lineText.Text, lineText.Color,
                                          this.FromPixels(target, view, lineText.Size), lineText.HaloColor, lineText.HaloRadius, lineText.Font);
                        break;

                    case Primitive2DType.Point2D:
                        Point2D point = (Point2D)primitive;
                        this.DrawPoint(target, point.X, point.Y, point.Color,
                                       this.FromPixels(target, view, point.Size));
                        break;

                    case Primitive2DType.Icon2D:
                        Icon2D icon = (Icon2D)primitive;
                        this.DrawIcon(target, icon.X, icon.Y, icon.Image);
                        break;

                    case Primitive2DType.ImageTilted2D:
                        ImageTilted2D imageTilted = (ImageTilted2D)primitive;
                        this.DrawImage(target, imageTilted.Bounds, imageTilted.NativeImage);
                        break;

                    case Primitive2DType.Image2D:
                        Image2D image = (Image2D)primitive;
                        this.DrawImage(target, image.Left, image.Top, image.Right, image.Bottom, image.NativeImage);
                        break;

                    case Primitive2DType.Text2D:
                        Text2D text = (Text2D)primitive;
                        this.DrawText(target, text.X, text.Y, text.Text, text.Color,
                                      this.FromPixels(target, view, text.Size), text.HaloColor, text.HaloRadius, text.Font);
                        break;
                    }
                }
                return(true);
            }
            catch (Exception ex) {
                OsmSharp.Logging.Log.TraceEvent("Renderer2D", OsmSharp.Logging.TraceEventType.Error,
                                                ex.Message);
                throw ex;
            }
        }
Exemple #4
0
        /// <summary>
        /// Renders the current complete scene.
        /// </summary>
        private void Render()
        {
            try
            {
                if (_renderingSuspended)
                { // no rendering when rendering is suspended.
                    return;
                }

                if (_cacheRenderer.IsRunning)
                { // cancel previous render.
                    _cacheRenderer.CancelAndWait();
                }

                // make sure only on thread at the same time is using the renderer.
                lock (_cacheRenderer)
                {
                    this.Map.ViewChangedCancel();

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

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

                    if (this.SurfaceHeight == 0)
                    { // the surface has no height yet. Impossible to render like this.
                        return;
                    }

                    // get old image if available.
                    NativeImage image = null;
                    if (_offScreenBuffer != null)
                    { // get the native image from the off-screen buffer.
                        image = _offScreenBuffer.NativeImage as NativeImage;
                    }

                    // resize image if needed.
                    float sizeX = this.SurfaceWidth;
                    float sizeY = this.SurfaceHeight;
                    //if(this.MapAllowTilt)
                    //{ // when rotation is allowed make sure a square is rendered.
                    //    sizeX = System.Math.Max(this.SurfaceWidth, this.SurfaceHeight);
                    //    sizeY = System.Math.Max(this.SurfaceWidth, this.SurfaceHeight);
                    //}
                    // float size = System.Math.Max(this.SurfaceHeight, this.SurfaceWidth);
                    if (image == null ||
                        image.Image.Width != (int)(sizeX * _extra) ||
                        image.Image.Height != (int)(sizeY * _extra))
                    {     // create a bitmap and render there.
                        if (image != null)
                        { // make sure to dispose the old image.
                            image.Dispose();
                        }
                        image = new NativeImage(global::Android.Graphics.Bitmap.CreateBitmap((int)(sizeX * _extra),
                                                                                             (int)(sizeY * _extra),
                                                                                             global::Android.Graphics.Bitmap.Config.Argb8888));
                    }

                    // create and reset the canvas.
                    using (var canvas = new global::Android.Graphics.Canvas(image.Image))
                    {
                        canvas.DrawColor(new global::Android.Graphics.Color(
                                             SimpleColor.FromKnownColor(KnownColor.White).Value));

                        // create the view.
                        double[] sceneCenter     = this.Map.Projection.ToPixel(this.MapCenter.Latitude, this.MapCenter.Longitude);
                        float    mapZoom         = this.MapZoom;
                        float    sceneZoomFactor = (float)this.Map.Projection.ToZoomFactor(this.MapZoom);

                        // create the view for this control.
                        float scaledNormalWidth  = image.Image.Width / _bufferFactor;
                        float scaledNormalHeight = image.Image.Height / _bufferFactor;
                        var   view = View2D.CreateFrom((float)sceneCenter[0], (float)sceneCenter[1],
                                                       scaledNormalWidth * _extra, scaledNormalHeight * _extra, sceneZoomFactor,
                                                       _invertX, _invertY, this.MapTilt);

                        long before = DateTime.Now.Ticks;

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

                        // notify the map that the view has changed.
                        if (_previouslyChangedView == null ||
                            !_previouslyChangedView.Equals(view))
                        { // report change once!
                            var normalView = View2D.CreateFrom((float)sceneCenter[0], (float)sceneCenter[1],
                                                               scaledNormalWidth, scaledNormalHeight, sceneZoomFactor,
                                                               _invertX, _invertY, this.MapTilt);
                            this.Map.ViewChanged((float)this.Map.Projection.ToZoomFactor(this.MapZoom), this.MapCenter,
                                                 normalView, view);
                            _previouslyChangedView = view;
                            long afterViewChanged = DateTime.Now.Ticks;
                            OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", TraceEventType.Information,
                                                            "View change took: {0}ms @ zoom level {1}",
                                                            (new TimeSpan(afterViewChanged - before).TotalMilliseconds), this.MapZoom);
                        }

                        // does the rendering.
                        bool complete = _cacheRenderer.Render(canvas, layers, view, (float)this.Map.Projection.ToZoomFactor(this.MapZoom));

                        long afterRendering = DateTime.Now.Ticks;
                        OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", TraceEventType.Information,
                                                        "Rendering took: {0}ms @ zoom level {1} and {2}",
                                                        (new TimeSpan(afterRendering - before).TotalMilliseconds), this.MapZoom, this.MapCenter);
                        if (complete)
                        { // there was no cancellation, the rendering completely finished.
                            // add the result to the scene cache.
                            // add the newly rendered image again.
                            if (_offScreenBuffer == null)
                            { // create the offscreen buffer first.
                                _offScreenBuffer = new ImageTilted2D(view.Rectangle, image, float.MinValue, float.MaxValue);
                            }
                            else
                            { // augment the previous buffer.
                                _offScreenBuffer.Bounds      = view.Rectangle;
                                _offScreenBuffer.NativeImage = image;
                            }

                            var temp = _onScreenBuffer;
                            _onScreenBuffer  = _offScreenBuffer;
                            _offScreenBuffer = temp;
                        }

                        long after = DateTime.Now.Ticks;

                        if (complete)
                        { // report a successful render to listener.
                            _listener.NotifyRenderSuccess(view, mapZoom, (int)new TimeSpan(after - before).TotalMilliseconds);
                        }
                    }
                }

                // notify the the current surface of the new rendering.
                this.PostInvalidate();
            }
            catch (Exception ex)
            { // exceptions can be thrown when the mapview is disposed while rendering.
                // don't worry too much about these, the mapview is garbage anyway.
                OsmSharp.Logging.Log.TraceEvent("MapViewSurface", TraceEventType.Critical,
                                                string.Format("An unhandled exception occured:{0}", ex.ToString()));
            }
        }
Exemple #5
0
        /// <summary>
        /// Renders the current complete scene.
        /// </summary>
        private void Render()
        {
            if (_cacheRenderer.IsRunning)
            {
                _cacheRenderer.CancelAndWait();
            }

            // make sure only on thread at the same time is using the renderer.
            lock (_cacheRenderer)
            {
                this.Map.ViewChangedCancel();

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

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

                // get old image if available.
                global::Android.Graphics.Bitmap image = null;
                if (_offScreenBuffer != null)
                {
                    image = _offScreenBuffer.Tag as global::Android.Graphics.Bitmap;
                }

                if (this.SurfaceHeight == 0)
                {
                    return;
                }

                // resize image if needed.
                float size = System.Math.Max(this.SurfaceHeight, this.SurfaceWidth);
                if (image == null ||
                    image.Width != (int)(size * _extra) ||
                    image.Height != (int)(size * _extra))
                { // create a bitmap and render there.
                    image = global::Android.Graphics.Bitmap.CreateBitmap((int)(size * _extra),
                                                                         (int)(size * _extra),
                                                                         global::Android.Graphics.Bitmap.Config.Argb8888);
                }

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

                // create the view.
                double[] sceneCenter     = this.Map.Projection.ToPixel(this.MapCenter.Latitude, this.MapCenter.Longitude);
                float    mapZoom         = this.MapZoom;
                float    sceneZoomFactor = (float)this.Map.Projection.ToZoomFactor(this.MapZoom);

                // create the view for this control.
                View2D view = View2D.CreateFrom((float)sceneCenter[0], (float)sceneCenter[1],
                                                size * _extra, size * _extra, sceneZoomFactor,
                                                _invertX, _invertY, this.MapTilt);

                long before = DateTime.Now.Ticks;

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

                // 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", TraceEventType.Information,
                                                "View change took: {0}ms @ zoom level {1}",
                                                (new TimeSpan(afterViewChanged - before).TotalMilliseconds), this.MapZoom);

                // does the rendering.
                bool complete = _cacheRenderer.Render(canvas, layers, view, (float)this.Map.Projection.ToZoomFactor(this.MapZoom));

                long afterRendering = DateTime.Now.Ticks;
                OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", 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.

                    // add the newly rendered image again.
                    _offScreenBuffer     = new ImageTilted2D(view.Rectangle, new byte[0], float.MinValue, float.MaxValue);
                    _offScreenBuffer.Tag = image;

                    var temp = _onScreenBuffer;
                    _onScreenBuffer  = _offScreenBuffer;
                    _offScreenBuffer = temp;
                }

                // notify the the current surface of the new rendering.
                this.PostInvalidate();

                long after = DateTime.Now.Ticks;

                if (complete)
                { // report a successfull render to listener.
                    _listener.NotifyRenderSuccess(view, mapZoom, (int)new TimeSpan(after - before).TotalMilliseconds);
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Render the current complete scene.
        /// </summary>
        void Render()
        {
            try
            {
                if (Monitor.TryEnter(_cacheRenderer, 1000))
                {
                    try
                    {
                        // use object
                        RectangleF rect = _rect;

                        // create the view.
                        float  size = System.Math.Max(_rect.Width, _rect.Height);
                        View2D view = _cacheRenderer.Create((int)(size * _extra), (int)(size * _extra),
                                                            this.Map, (float)this.Map.Projection.ToZoomFactor(this.MapZoom),
                                                            this.MapCenter, _invertX, _invertY, this.MapTilt);
                        if (rect.Width == 0)
                        {                         // only render if a proper size is known.
                            return;
                        }

                        // calculate width/height.
                        int imageWidth  = (int)(size * _extra * _scaleFactor);
                        int imageHeight = (int)(size * _extra * _scaleFactor);

                        // create a new bitmap context.
                        CGColorSpace space            = CGColorSpace.CreateDeviceRGB();
                        int          bytesPerPixel    = 4;
                        int          bytesPerRow      = bytesPerPixel * imageWidth;
                        int          bitsPerComponent = 8;

                        // get old image if available.
                        CGBitmapContext image = new CGBitmapContext(null, imageWidth, imageHeight,
                                                                    bitsPerComponent, bytesPerRow,
                                                                    space,             // kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast
                                                                    CGBitmapFlags.PremultipliedFirst | CGBitmapFlags.ByteOrder32Big);

                        long before = DateTime.Now.Ticks;

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

                        // add the internal layer.
                        try
                        {
                            image.SetRGBFillColor(1, 1, 1, 1);
                            image.FillRect(new RectangleF(
                                               0, 0, imageWidth, imageHeight));

                            // 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", TraceEventType.Information,
                                                            "View change took: {0}ms @ zoom level {1}",
                                                            (new TimeSpan(afterViewChanged - before).TotalMilliseconds), this.MapZoom);

                            float zoomFactor      = this.MapZoom;
                            float sceneZoomFactor = (float)this.Map.Projection.ToZoomFactor(this.MapZoom);

                            // does the rendering.
                            bool complete = _cacheRenderer.Render(new CGContextWrapper(image,
                                                                                       new RectangleF(0, 0, (int)(size * _extra), (int)(size * _extra))),
                                                                  layers, view, sceneZoomFactor);

                            long afterRendering = DateTime.Now.Ticks;

                            if (complete)
                            {                             // there was no cancellation, the rendering completely finished.
                                lock (_bufferSynchronisation)
                                {
                                    if (_onScreenBuffer != null &&
                                        _onScreenBuffer.Tag != null)
                                    {                                     // on screen buffer.
                                        (_onScreenBuffer.Tag as CGImage).Dispose();
                                    }

                                    // add the newly rendered image again.
                                    _onScreenBuffer     = new ImageTilted2D(view.Rectangle, new byte[0], float.MinValue, float.MaxValue);
                                    _onScreenBuffer.Tag = image.ToImage();

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

                                // make sure this view knows that there is a new rendering.
                                this.InvokeOnMainThread(SetNeedsDisplay);
                            }

                            long after = DateTime.Now.Ticks;

                            if (complete)
                            {                             // notify invalidation listener about a succesfull rendering.
                                OsmSharp.Logging.Log.TraceEvent("OsmSharp.iOS.UI.MapView", TraceEventType.Information,
                                                                "Rendering succesfull after {0}ms.", new TimeSpan(after - before).TotalMilliseconds);

                                _listener.NotifyRenderSuccess(view, zoomFactor, (int)new TimeSpan(after - before).TotalMilliseconds);
                            }
                            else
                            {                             // rendering incomplete.
                                OsmSharp.Logging.Log.TraceEvent("OsmSharp.iOS.UI.MapView", TraceEventType.Information,
                                                                "Rendering cancelled.", new TimeSpan(after - before).TotalMilliseconds);
                            }
                        }
                        finally
                        {
                        }
                    }
                    finally
                    {                     // make sure the object lock is release.
                        Monitor.Exit(_cacheRenderer);
                    }
                }
            }
            catch (Exception)
            {
                _cacheRenderer.Reset();
            }
        }