예제 #1
0
        /// <summary>
        /// Converts a LineString (list of Mapsui points) in world coordinates to a Skia path
        /// </summary>
        /// <param name="lineString">List of points in Mapsui world coordinates</param>
        /// <param name="viewport">Viewport implementation</param>
        /// <param name="clipRect">Rectangle to clip to. All lines outside aren't drawn.</param>
        /// <returns></returns>
        public static SKPath ToSkiaPath(this IEnumerable <Point> lineString, IReadOnlyViewport viewport, SKRect clipRect)
        {
            // First convert List<Points> to screen coordinates
            var vertices = WorldToScreen(viewport, lineString);

            var     path      = new SKPath();
            SKPoint lastPoint = SKPoint.Empty;

            for (var i = 1; i < vertices.Count; i++)
            {
                // Check each part of LineString, if it is inside or intersects the clipping rectangle
                var intersect = LiangBarskyClip(vertices[i - 1], vertices[i], clipRect, out var intersectionPoint1, out var intersectionPoint2);

                if (intersect != Intersection.CompleteOutside)
                {
                    // If the last point isn't the same as actuall starting point ...
                    if (lastPoint.IsEmpty || !lastPoint.Equals(intersectionPoint1))
                    {
                        // ... than move to this point
                        path.MoveTo(intersectionPoint1);
                    }
                    // Draw line
                    path.LineTo(intersectionPoint2);

                    // Save last end point for later use
                    lastPoint = intersectionPoint2;
                }
            }
            return(path);
        }
        public bool Draw(SKCanvas canvas, IReadOnlyViewport viewport, ILayer layer, IFeature feature, IStyle istyle,
                         ISymbolCache symbolCache)
        {
            var style = ((PolylineMarkerStyle)istyle);

            var zoom = 1 / (float)viewport.Resolution;
            //
            var dest = viewport.WorldToScreen(style.start.X, style.start.Y);

            canvas.Translate((float)dest.X, (float)dest.Y);
            canvas.Scale(zoom, zoom);

            canvas.RotateDegrees((float)viewport.Rotation, 0.0f, 0.0f);

            //#TODO store paint with shader in the style
            using (SKPaint paint = new SKPaint())
            {
                paint.Color       = style.color;
                paint.StrokeWidth = 3f * (float)viewport.Resolution;
                paint.Style       = SKPaintStyle.Stroke;
                paint.IsAntialias = true;

                canvas.DrawPath(style.path, paint);
            }

            return(true);
        }
예제 #3
0
        private static void Render(Canvas canvas, IReadOnlyViewport viewport, IEnumerable <ILayer> layers,
                                   SymbolCache symbolCache, bool rasterizing)
        {
            canvas.BeginInit();
            canvas.Visibility = Visibility.Hidden;

            layers = layers.ToList();

            foreach (var layer in layers)
            {
                if (!layer.Enabled)
                {
                    continue;
                }
                if (layer.MinVisible > viewport.Resolution)
                {
                    continue;
                }
                if (layer.MaxVisible < viewport.Resolution)
                {
                    continue;
                }

                RenderLayer(canvas, viewport, layer, symbolCache, rasterizing);
            }

            canvas.Visibility = Visibility.Visible;
            canvas.EndInit();
        }
예제 #4
0
        public bool Draw(SKCanvas canvas, IReadOnlyViewport viewport, ILayer layer, IFeature feature, IStyle style, ISymbolCache symbolCache, long iteration)
        {
            var symbolStyle = (SymbolStyle)style;

            switch (feature)
            {
            case PointFeature pointFeature:
                DrawXY(canvas, viewport, layer, pointFeature.Point.X, pointFeature.Point.Y, symbolStyle, symbolCache);
                break;

            case GeometryFeature geometryFeature:
                switch (geometryFeature.Geometry)
                {
                case GeometryCollection collection:
                    foreach (var point in GetPoints(collection))
                    {
                        DrawXY(canvas, viewport, layer, point.X, point.Y, symbolStyle, symbolCache);
                    }
                    break;

                case Point point:
                    DrawXY(canvas, viewport, layer, point.X, point.Y, symbolStyle, symbolCache);
                    break;
                }
                break;
            }

            return(true);
        }
예제 #5
0
        public void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IWidget widget, float layerOpacity)
        {
            var performanceWidget = (PerformanceWidget)widget;

            _text[0] = performanceWidget.Performance.LastDrawingTime.ToString("0.000 ms");
            _text[1] = performanceWidget.Performance.Mean.ToString("0.000 ms");
            _text[2] = performanceWidget.Performance.FPS.ToString("0 fps");
            _text[3] = performanceWidget.Performance.Min.ToString("0.000 ms");
            _text[4] = performanceWidget.Performance.Max.ToString("0.000 ms");
            _text[5] = performanceWidget.Performance.Count.ToString("0");
            _text[6] = performanceWidget.Performance.Dropped.ToString("0");

            var paint = _backgroundPaint;

            paint.Color = _backgroundPaint.Color.WithAlpha((byte)(255.0f * performanceWidget.Opacity));

            canvas.DrawRect(_rect, paint);

            for (var i = 0; i < _textHeader.Length; i++)
            {
                canvas.DrawText(_textHeader[i], _rect.Left + 2, _rect.Top + 2 * i + _textSize * (i + 1), _textPaint);
                canvas.DrawText(_text[i], _rect.Right - 2 - _textPaint.MeasureText(_text[i]), _rect.Top + (2 + _textSize) * (i + 1), _textPaint);
            }

            widget.Envelope = _envelope;
        }
예제 #6
0
        public bool Draw(SKCanvas canvas, IReadOnlyViewport viewport, ILayer layer, IFeature feature, IStyle style, ISymbolCache symbolCache)
        {
            if (!(feature.Geometry is global::Mapsui.Geometries.Point worldPoint))
            {
                return(false);
            }

            var screenPoint = viewport.WorldToScreen(worldPoint);
            var color       = new SKColor((byte)rnd.Next(0, 256), (byte)rnd.Next(0, 256), (byte)rnd.Next(0, 256), (byte)(256.0 * layer.Opacity * style.Opacity));
            var colored     = new SKPaint()
            {
                Color = color, IsAntialias = true
            };
            var black = new SKPaint()
            {
                Color = SKColors.Black, IsAntialias = true
            };

            canvas.Translate((float)screenPoint.X, (float)screenPoint.Y);
            canvas.DrawCircle(0, 0, 15, colored);
            canvas.DrawCircle(-8, -12, 8, colored);
            canvas.DrawCircle(8, -12, 8, colored);
            canvas.DrawCircle(8, -8, 2, black);
            canvas.DrawCircle(-8, -8, 2, black);
            using (var path = new SKPath())
            {
                path.ArcTo(new SKRect(-8, 2, 8, 10), 25, 135, true);
                canvas.DrawPath(path, new SKPaint()
                {
                    Style = SKPaintStyle.Stroke, Color = SKColors.Black, IsAntialias = true
                });
            }

            return(true);
        }
예제 #7
0
        public static XamlShapes.Shape RenderPoint(Point point, IStyle style, IReadOnlyViewport viewport,
                                                   SymbolCache symbolCache)
        {
            XamlShapes.Shape symbol;
            var matrix = XamlMedia.Matrix.Identity;

            var symbolStyle = style as SymbolStyle;

            if (symbolStyle != null)
            {
                if (symbolStyle.BitmapId < 0)
                {
                    symbol = CreateSymbolFromVectorStyle(symbolStyle, symbolStyle.Opacity, symbolStyle.SymbolType, symbolCache, (float)viewport.Rotation);
                }
                else
                {
                    symbol = CreateSymbolFromBitmap(symbolStyle.BitmapId, symbolStyle.Opacity, symbolCache);
                }
                matrix = CreatePointSymbolMatrix(viewport.Resolution, viewport.Rotation, symbolStyle, symbol.Width, symbol.Height);
            }
            else
            {
                symbol = CreateSymbolFromVectorStyle((style as VectorStyle) ?? new VectorStyle(), symbolCache: symbolCache, rotate: (float)viewport.Rotation);
                MatrixHelper.ScaleAt(ref matrix, viewport.Resolution, viewport.Resolution);
            }

            MatrixHelper.Append(ref matrix, GeometryRenderer.CreateTransformMatrix(viewport, point));

            symbol.RenderTransform = new XamlMedia.MatrixTransform {
                Matrix = matrix
            };
            symbol.IsHitTestVisible = false;

            return(symbol);
        }
예제 #8
0
 public MemoryStream RenderToBitmapStream(IReadOnlyViewport viewport, IEnumerable <ILayer> layers, Color background = null)
 {
     try
     {
         using (var surface = SKSurface.Create(
                    (int)viewport.Width, (int)viewport.Height, SKImageInfo.PlatformColorType, SKAlphaType.Unpremul))
         {
             if (surface == null)
             {
                 return(null);
             }
             // Not sure if this is needed here:
             if (background != null)
             {
                 surface.Canvas.Clear(background.ToSkia(1));
             }
             Render(surface.Canvas, viewport, layers);
             using (var image = surface.Snapshot())
             {
                 using (var data = image.Encode())
                 {
                     var memoryStream = new MemoryStream();
                     data.SaveTo(memoryStream);
                     return(memoryStream);
                 }
             }
         }
     }
     catch (Exception ex)
     {
         Logger.Log(LogLevel.Error, ex.Message);
         return(null);
     }
 }
예제 #9
0
        /// <summary>
        /// Convert a list of Mapsui points in world coordinates to SKPoint in screen coordinates
        /// </summary>
        /// <param name="viewport">Viewport implementation</param>
        /// <param name="points">List of points in Mapsui world coordinates</param>
        /// <returns>List of screen coordinates in SKPoint</returns>
        private static List <SKPoint> WorldToScreen(IReadOnlyViewport viewport, IEnumerable <Point> points)
        {
            var result        = new List <SKPoint>();
            var screenCenterX = viewport.Width * 0.5;
            var screenCenterY = viewport.Height * 0.5;
            var centerX       = viewport.Center.X;
            var centerY       = viewport.Center.Y;
            var resolution    = 1.0 / viewport.Resolution;
            var rotation      = viewport.Rotation / 180f * Math.PI;
            var sin           = Math.Sin(rotation);
            var cos           = Math.Cos(rotation);

            foreach (var point in points)
            {
                var screenX = (point.X - centerX) * resolution;
                var screenY = (centerY - point.Y) * resolution;

                if (viewport.IsRotated)
                {
                    var newX = screenX * cos - screenY * sin;
                    var newY = screenX * sin + screenY * cos;
                    screenX = newX;
                    screenY = newY;
                }

                screenX += screenCenterX;
                screenY += screenCenterY;

                result.Add(new SKPoint((float)screenX, (float)screenY));
            }

            return(result);
        }
예제 #10
0
        private static SKMatrix CreateRotationMatrix(IReadOnlyViewport viewport, MRect rect, SKMatrix priorMatrix)
        {
            // The front-end sets up the canvas with a matrix based on screen scaling (e.g. retina).
            // We need to retain that effect by combining our matrix with the incoming matrix.

            // We'll create four matrices in addition to the incoming matrix. They perform the
            // zoom scale, focal point offset, user rotation and finally, centering in the screen.

            var userRotation     = SKMatrix.CreateRotationDegrees((float)viewport.Rotation);
            var focalPointOffset = SKMatrix.CreateTranslation(
                (float)(rect.Left - viewport.Center.X),
                (float)(viewport.Center.Y - rect.Top));
            var zoomScale      = SKMatrix.CreateScale((float)(1.0 / viewport.Resolution), (float)(1.0 / viewport.Resolution));
            var centerInScreen = SKMatrix.CreateTranslation((float)(viewport.Width / 2.0), (float)(viewport.Height / 2.0));

            // We'll concatenate them like so: incomingMatrix * centerInScreen * userRotation * zoomScale * focalPointOffset

            var matrix = SKMatrix.Concat(zoomScale, focalPointOffset);

            matrix = SKMatrix.Concat(userRotation, matrix);
            matrix = SKMatrix.Concat(centerInScreen, matrix);
            matrix = SKMatrix.Concat(priorMatrix, matrix);

            return(matrix);
        }
예제 #11
0
 private void RenderFeature(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature, float layerOpacity)
 {
     if (feature.Geometry is Point)
     {
         PointRenderer.Draw(canvas, viewport, style, feature, feature.Geometry, _symbolCache, layerOpacity * style.Opacity);
     }
     else if (feature.Geometry is MultiPoint)
     {
         MultiPointRenderer.Draw(canvas, viewport, style, feature, feature.Geometry, _symbolCache, layerOpacity * style.Opacity);
     }
     else if (feature.Geometry is LineString)
     {
         LineStringRenderer.Draw(canvas, viewport, style, feature, feature.Geometry, layerOpacity * style.Opacity);
     }
     else if (feature.Geometry is MultiLineString)
     {
         MultiLineStringRenderer.Draw(canvas, viewport, style, feature, feature.Geometry, layerOpacity * style.Opacity);
     }
     else if (feature.Geometry is Polygon)
     {
         PolygonRenderer.Draw(canvas, viewport, style, feature, feature.Geometry, layerOpacity * style.Opacity, _symbolCache);
     }
     else if (feature.Geometry is MultiPolygon)
     {
         MultiPolygonRenderer.Draw(canvas, viewport, style, feature, feature.Geometry, layerOpacity * style.Opacity, _symbolCache);
     }
     else if (feature.Geometry is IRaster)
     {
         RasterRenderer.Draw(canvas, viewport, style, feature, layerOpacity * style.Opacity, _tileCache, _currentIteration);
     }
 }
예제 #12
0
 private static Shape RenderGeometry(IReadOnlyViewport viewport, IStyle style, IFeature feature,
                                     SymbolCache symbolCache)
 {
     if (feature.Geometry is Geometries.Point)
     {
         return(PointRenderer.RenderPoint(feature.Geometry as Geometries.Point, style, viewport, symbolCache));
     }
     if (feature.Geometry is MultiPoint)
     {
         return(GeometryRenderer.RenderMultiPoint(feature.Geometry as MultiPoint, style, viewport, symbolCache));
     }
     if (feature.Geometry is LineString)
     {
         return(LineStringRenderer.RenderLineString(feature.Geometry as LineString, style, viewport));
     }
     if (feature.Geometry is MultiLineString)
     {
         return(MultiLineStringRenderer.Render(feature.Geometry as MultiLineString, style, viewport));
     }
     if (feature.Geometry is Polygon)
     {
         return(PolygonRenderer.RenderPolygon(feature.Geometry as Polygon, style, viewport, symbolCache));
     }
     if (feature.Geometry is MultiPolygon)
     {
         return(MultiPolygonRenderer.RenderMultiPolygon(feature.Geometry as MultiPolygon, style, viewport, symbolCache));
     }
     if (feature.Geometry is IRaster)
     {
         return(GeometryRenderer.RenderRaster(feature.Geometry as IRaster, style, viewport));
     }
     return(null);
 }
예제 #13
0
        public MemoryStream RenderToBitmapStream(IReadOnlyViewport viewport, IEnumerable <ILayer> layers, Color background = null)
        {
            MemoryStream bitmapStream = null;

            RunMethodOnStaThread(() => bitmapStream = RenderToBitmapStreamStatic(viewport, layers, _symbolCache));
            return(bitmapStream);
        }
예제 #14
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="layers">The layers to query for MapInfo</param>
        /// <param name="viewport">The current Viewport</param>
        /// <param name="screenPosition">The screenposition to query</param>
        /// <param name="symbolCache">The </param>
        /// <param name="margin">Margin of error in pixels. If the distance between screen position and geometry
        /// is smaller than the margin it is seen as a hit.</param>
        /// <returns></returns>
        public static MapInfo GetMapInfo(IEnumerable <ILayer> layers, IReadOnlyViewport viewport, Point screenPosition,
                                         ISymbolCache symbolCache, int margin = 0)
        {
            var worldPosition = viewport.ScreenToWorld(screenPosition);

            return(GetMapInfo(layers, worldPosition, screenPosition, viewport.Resolution, symbolCache, margin));
        }
예제 #15
0
        public void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IWidget widget, float layerOpacity)
        {
            var hyperlink = (Hyperlink)widget;

            if (string.IsNullOrEmpty(hyperlink.Text))
            {
                return;
            }
            using var textPaint = new SKPaint { Color = hyperlink.TextColor.ToSkia(layerOpacity), IsAntialias = true };
            using var backPaint = new SKPaint { Color = hyperlink.BackColor.ToSkia(layerOpacity) };
            // The textRect has an offset which can be confusing.
            // This is because DrawText's origin is the baseline of the text, not the bottom.
            // Read more here: https://developer.xamarin.com/guides/xamarin-forms/advanced/skiasharp/basics/text/
            var textRect = new SKRect();

            textPaint.MeasureText(hyperlink.Text, ref textRect);
            // The backRect is straight forward. It is leading for our purpose.
            var backRect = new SKRect(0, 0,
                                      textRect.Width + hyperlink.PaddingX * 2,
                                      textPaint.TextSize + hyperlink.PaddingY * 2); // Use the font's TextSize for consistency
            var offsetX = GetOffsetX(backRect.Width, hyperlink.MarginX, hyperlink.HorizontalAlignment, viewport.Width);
            var offsetY = GetOffsetY(backRect.Height, hyperlink.MarginY, hyperlink.VerticalAlignment, viewport.Height);

            backRect.Offset(offsetX, offsetY);
            canvas.DrawRoundRect(backRect, hyperlink.CornerRadius, hyperlink.CornerRadius, backPaint);
            hyperlink.Envelope = backRect.ToMRect();
            // To position the text within the backRect correct using the textRect's offset.
            canvas.DrawText(hyperlink.Text,
                            offsetX - textRect.Left + hyperlink.PaddingX,
                            offsetY - textRect.Top + hyperlink.PaddingY, textPaint);
        }
예제 #16
0
 private static void PositionGeometry(Shape renderedGeometry, IReadOnlyViewport viewport, IStyle style, IFeature feature)
 {
     if (feature.Geometry is Geometries.Point)
     {
         PointRenderer.PositionPoint(renderedGeometry, feature.Geometry as Geometries.Point, style, viewport);
     }
     else if (feature.Geometry is MultiPoint)
     {
         GeometryRenderer.PositionGeometry(renderedGeometry, viewport);
     }
     else if (feature.Geometry is LineString)
     {
         GeometryRenderer.PositionGeometry(renderedGeometry, viewport);
     }
     else if (feature.Geometry is MultiLineString)
     {
         GeometryRenderer.PositionGeometry(renderedGeometry, viewport);
     }
     else if (feature.Geometry is Polygon)
     {
         GeometryRenderer.PositionGeometry(renderedGeometry, viewport);
     }
     else if (feature.Geometry is MultiPolygon)
     {
         GeometryRenderer.PositionGeometry(renderedGeometry, viewport);
     }
     else if (feature.Geometry is IRaster)
     {
         GeometryRenderer.PositionRaster(renderedGeometry, feature.Geometry.BoundingBox, viewport);
     }
 }
예제 #17
0
        public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature,
                                IGeometry geometry, SymbolCache symbolCache, float opacity)
        {
            var point       = geometry as Point;
            var destination = viewport.WorldToScreen(point);

            if (style is LabelStyle labelStyle)    // case 1) LabelStyle
            {
                LabelRenderer.Draw(canvas, labelStyle, feature, (float)destination.X, (float)destination.Y,
                                   opacity);
            }
            else if (style is SymbolStyle)
            {
                var symbolStyle = (SymbolStyle)style;

                if (symbolStyle.BitmapId >= 0)    // case 2) Bitmap Style
                {
                    DrawPointWithBitmapStyle(canvas, symbolStyle, destination, symbolCache, opacity, (float)viewport.Rotation);
                }
                else                              // case 3) SymbolStyle without bitmap
                {
                    DrawPointWithSymbolStyle(canvas, symbolStyle, destination, opacity, symbolStyle.SymbolType, (float)viewport.Rotation);
                }
            }
            else if (style is VectorStyle)        // case 4) VectorStyle
            {
                DrawPointWithVectorStyle(canvas, (VectorStyle)style, destination, opacity);
            }
            else
            {
                throw new Exception($"Style of type '{style.GetType()}' is not supported for points");
            }
        }
예제 #18
0
        public void Render(object target, IReadOnlyViewport viewport, IEnumerable <ILayer> layers,
                           IEnumerable <IWidget> widgets, Color background = null)
        {
            var allWidgets = layers.Select(l => l.Attribution).ToList().Where(w => w != null).Concat(widgets).ToList();

            RenderTypeSave((Canvas)target, viewport, layers, allWidgets, background);
        }
예제 #19
0
        public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature, IGeometry geometry,
                                float opacity)
        {
            if (style is LabelStyle labelStyle)
            {
                var worldCenter = geometry.BoundingBox.Centroid;
                var center      = viewport.WorldToScreen(worldCenter);
                LabelRenderer.Draw(canvas, labelStyle, feature, center, opacity);
            }
            else
            {
                var lineString = ((LineString)geometry).Vertices;

                float lineWidth = 1;
                var   lineColor = new Color();

                var     vectorStyle      = style as VectorStyle;
                var     strokeCap        = PenStrokeCap.Butt;
                var     strokeJoin       = StrokeJoin.Miter;
                var     strokeMiterLimit = 4f;
                var     strokeStyle      = PenStyle.Solid;
                float[] dashArray        = null;
                float   dashOffset       = 0;

                if (vectorStyle != null)
                {
                    lineWidth        = (float)vectorStyle.Line.Width;
                    lineColor        = vectorStyle.Line.Color;
                    strokeCap        = vectorStyle.Line.PenStrokeCap;
                    strokeJoin       = vectorStyle.Line.StrokeJoin;
                    strokeMiterLimit = vectorStyle.Line.StrokeMiterLimit;
                    strokeStyle      = vectorStyle.Line.PenStyle;
                    dashArray        = vectorStyle.Line.DashArray;
                    dashOffset       = vectorStyle.Line.DashOffset;
                }

                using (var path = lineString.ToSkiaPath(viewport, canvas.LocalClipBounds))
                    using (var paint = new SKPaint {
                        IsAntialias = true
                    })
                    {
                        paint.IsStroke    = true;
                        paint.StrokeWidth = lineWidth;
                        paint.Color       = lineColor.ToSkia(opacity);
                        paint.StrokeCap   = strokeCap.ToSkia();
                        paint.StrokeJoin  = strokeJoin.ToSkia();
                        paint.StrokeMiter = strokeMiterLimit;
                        if (strokeStyle != PenStyle.Solid)
                        {
                            paint.PathEffect = strokeStyle.ToSkia(lineWidth, dashArray, dashOffset);
                        }
                        else
                        {
                            paint.PathEffect = null;
                        }
                        canvas.DrawPath(path, paint);
                    }
            }
        }
예제 #20
0
        /// <summary>
        /// Converts a LineString (list of Mapsui points) in world coordinates to a Skia path
        /// </summary>
        /// <param name="lineString">List of points in Mapsui world coordinates</param>
        /// <param name="viewport">Viewport implementation</param>
        /// <param name="clipRect">Rectangle to clip to. All lines outside aren't drawn.</param>
        /// <returns></returns>
        public static SKPath ToSkiaPath(this IEnumerable <Point> lineString, IReadOnlyViewport viewport, SKRect clipRect)
        {
            // First convert List<Points> to screen coordinates
            var vertices = WorldToScreen(viewport, lineString);

            var     path      = new SKPath();
            SKPoint lastPoint = SKPoint.Empty;

            // Calculate step size in which we iterate the list of vertices
            var simplificationStep = 1;

            if (EnableAutoSimplification && (vertices.Count > 50))
            {
                simplificationStep = (int)Math.Max(viewport.Resolution / 5.0, 1.0);
                if ((double)vertices.Count / (double)simplificationStep < 4.0)
                {
                    // Iterate at least in 4 steps through vertices list
                    simplificationStep = (int)Math.Round(vertices.Count / 4.0);
                }
            }

            var lastRunPassed = false;
            var lastIndex     = 0;

            for (var i = simplificationStep; !lastRunPassed; i += simplificationStep)
            {
                // Ensure that we render the last point of the line
                if (i >= vertices.Count)
                {
                    if (lastIndex == (vertices.Count - 1))
                    {
                        break;
                    }
                    lastRunPassed = true;

                    i = vertices.Count - 1;
                }
                lastIndex = i;

                // Check each part of LineString, if it is inside or intersects the clipping rectangle
                var intersect = LiangBarskyClip(vertices[i - simplificationStep], vertices[i], clipRect, out var intersectionPoint1, out var intersectionPoint2);

                if (intersect != Intersection.CompleteOutside)
                {
                    // If the last point isn't the same as actuall starting point ...
                    if (lastPoint.IsEmpty || !lastPoint.Equals(intersectionPoint1))
                    {
                        // ... than move to this point
                        path.MoveTo(intersectionPoint1);
                    }
                    // Draw line
                    path.LineTo(intersectionPoint2);

                    // Save last end point for later use
                    lastPoint = intersectionPoint2;
                }
            }
            return(path);
        }
예제 #21
0
        public static XamlShapes.Path RenderRaster(IRaster raster, IStyle style, IReadOnlyViewport viewport)
        {
            var path = CreateRasterPath(style, raster.Data);

            path.Data = new XamlMedia.RectangleGeometry();
            PositionRaster(path, raster.BoundingBox, viewport);
            return(path);
        }
예제 #22
0
        public static bool DrawSymbol(SKCanvas canvas, IReadOnlyViewport viewport, ILayer layer, double x, double y, SymbolStyle symbolStyle)
        {
            var opacity = (float)(layer.Opacity * symbolStyle.Opacity);

            var(destX, destY) = viewport.WorldToScreenXY(x, y);

            canvas.Save();

            canvas.Translate((float)destX, (float)destY);
            canvas.Scale((float)symbolStyle.SymbolScale, (float)symbolStyle.SymbolScale);
            if (symbolStyle.SymbolOffset.IsRelative)
            {
                canvas.Translate((float)(SymbolStyle.DefaultWidth * symbolStyle.SymbolOffset.X), (float)(-SymbolStyle.DefaultWidth * symbolStyle.SymbolOffset.Y));
            }
            else
            {
                canvas.Translate((float)symbolStyle.SymbolOffset.X, (float)-symbolStyle.SymbolOffset.Y);
            }
            if (symbolStyle.SymbolRotation != 0)
            {
                var rotation = symbolStyle.SymbolRotation;
                if (symbolStyle.RotateWithMap)
                {
                    rotation += viewport.Rotation;
                }
                canvas.RotateDegrees((float)rotation);
            }

            var width      = (float)SymbolStyle.DefaultWidth;
            var halfWidth  = width / 2;
            var halfHeight = (float)SymbolStyle.DefaultHeight / 2;

            using var fillPaint = CreateFillPaint(symbolStyle.Fill, opacity);
            using var linePaint = CreateLinePaint(symbolStyle.Outline, opacity);

            switch (symbolStyle.SymbolType)
            {
            case SymbolType.Ellipse:
                DrawCircle(canvas, 0, 0, halfWidth, fillPaint, linePaint);
                break;

            case SymbolType.Rectangle:
                var rect = new SKRect(-halfWidth, -halfHeight, halfWidth, halfHeight);
                DrawRect(canvas, rect, fillPaint, linePaint);
                break;

            case SymbolType.Triangle:
                DrawTriangle(canvas, 0, 0, width, fillPaint, linePaint);
                break;

            default:     // Invalid value
                throw new ArgumentOutOfRangeException();
            }

            canvas.Restore();

            return(true);
        }
예제 #23
0
 public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature,
                         MultiLineString multiLineString, float opacity)
 {
     foreach (var geometry in multiLineString.Geometries)
     {
         var lineString = (LineString)geometry;
         LineStringRenderer.Draw(canvas, viewport, style, feature, lineString, opacity);
     }
 }
예제 #24
0
 public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature,
                         MultiPolygon multiPolygon, float opacity, SymbolCache?symbolCache = null)
 {
     foreach (var geometry in multiPolygon.Geometries)
     {
         var polygon = (Polygon)geometry;
         PolygonRenderer.Draw(canvas, viewport, style, feature, polygon, opacity, symbolCache);
     }
 }
예제 #25
0
        public static void RenderLayer(Canvas target, IReadOnlyViewport viewport, ILayer layer, SymbolCache symbolCache, bool rasterizing = false)
        {
            if (layer.Enabled == false)
            {
                return;
            }

            target.Children.Add(RenderLayerStatic(viewport, layer, symbolCache, rasterizing));
        }
예제 #26
0
 public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature,
                         MultiPoint multiPoint, SymbolCache symbolCache, float opacity)
 {
     foreach (var geometry in multiPoint)
     {
         var point = (Point)geometry;
         PointRenderer.Draw(canvas, viewport, style, feature, point.X, point.Y, symbolCache, opacity);
     }
 }
예제 #27
0
        public static void Render(object target, IReadOnlyViewport viewport, IEnumerable <IWidget> widgets,
                                  IDictionary <Type, IWidgetRenderer> renders, float layerOpacity)
        {
            var canvas = (SKCanvas)target;

            foreach (var widget in widgets)
            {
                ((ISkiaWidgetRenderer)renders[widget.GetType()]).Draw(canvas, viewport, widget, layerOpacity);
            }
        }
예제 #28
0
        public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature, IGeometry geometry,
                                float opacity, SymbolCache symbolCache = null)
        {
            var multiPolygon = (MultiPolygon)geometry;

            foreach (var polygon in multiPolygon)
            {
                PolygonRenderer.Draw(canvas, viewport, style, feature, polygon, opacity, symbolCache);
            }
        }
예제 #29
0
        public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport,
                                float opacity, Point destination, CalloutStyle calloutStyle)
        {
            if (calloutStyle.BitmapId < 0 || calloutStyle.Invalidated)
            {
                if (calloutStyle.Content < 0 && calloutStyle.Type == CalloutType.Custom)
                {
                    return;
                }

                if (calloutStyle.Invalidated)
                {
                    UpdateContent(calloutStyle);
                }

                RenderCallout(calloutStyle);
            }

            // Now we have the complete callout rendered, so we could draw it
            if (calloutStyle.BitmapId < 0)
            {
                return;
            }

            var picture = (SKPicture)BitmapRegistry.Instance.Get(calloutStyle.BitmapId);

            // Calc offset (relative or absolute)
            var symbolOffsetX = calloutStyle.SymbolOffset.IsRelative ? picture.CullRect.Width * (float)calloutStyle.SymbolOffset.X : (float)calloutStyle.SymbolOffset.X;
            var symbolOffsetY = calloutStyle.SymbolOffset.IsRelative ? picture.CullRect.Height * (float)calloutStyle.SymbolOffset.Y : (float)calloutStyle.SymbolOffset.Y;

            var rotation = (float)calloutStyle.SymbolRotation;

            if (calloutStyle.RotateWithMap)
            {
                rotation += (float)viewport.Rotation;
            }

            // Save state of the canvas, so we could move and rotate the canvas
            canvas.Save();

            // Move 0/0 to the Anchor point of Callout
            canvas.Translate((float)destination.X - symbolOffsetX, (float)destination.Y - symbolOffsetY);
            canvas.Scale((float)calloutStyle.SymbolScale, (float)calloutStyle.SymbolScale);

            // 0/0 are assumed at center of image, but Picture has 0/0 at left top position
            canvas.RotateDegrees(rotation);
            canvas.Translate((float)calloutStyle.Offset.X, (float)calloutStyle.Offset.Y);

            canvas.DrawPicture(picture, new SKPaint()
            {
                IsAntialias = true
            });

            canvas.Restore();
        }
예제 #30
0
        /// <summary>
        /// Converts a Polygon into a SKPath, that is clipped to cliptRect, where exterior is bigger than interior
        /// </summary>
        /// <param name="polygon">Polygon to convert</param>
        /// <param name="viewport">Viewport implementation</param>
        /// <param name="clipRect">Rectangle to clip to. All lines outside aren't drawn.</param>
        /// <param name="strokeWidth">StrokeWidth for inflating cliptRect</param>
        /// <returns></returns>
        public static SKPath ToSkiaPath(this Polygon polygon, IReadOnlyViewport viewport, SKRect clipRect, float strokeWidth)
        {
            // Reduce exterior ring to parts, that are visible in clipping rectangle
            // Inflate clipRect, so that we could be sure, nothing of stroke is visible on screen
            var exterior = ReducePointsToClipRect(polygon.ExteriorRing.Vertices, viewport, SKRect.Inflate(clipRect, strokeWidth * 2, strokeWidth * 2));

            // Create path for exterior and interior parts
            var path = new SKPath();

            if (exterior.Count == 0)
            {
                return(path);
            }

            // Draw exterior path
            path.MoveTo(exterior[0]);

            for (var i = 1; i < exterior.Count; i++)
            {
                path.LineTo(exterior[i]);
            }

            // Close exterior path
            path.Close();

            foreach (var interiorRing in polygon.InteriorRings)
            {
                // note: For Skia inner rings need to be clockwise and outer rings
                // need to be counter clockwise (if this is the other way around it also
                // seems to work)
                // this is not a requirement of the OGC polygon.

                // Reduce interior ring to parts, that are visible in clipping rectangle
                var interior = ReducePointsToClipRect(interiorRing.Vertices, viewport, SKRect.Inflate(clipRect, strokeWidth, strokeWidth));

                if (interior.Count == 0)
                {
                    continue;
                }

                // Draw interior pathes
                path.MoveTo(interior[0]);

                for (var i = 1; i < interior.Count; i++)
                {
                    path.LineTo(interior[i]);
                }
            }

            // Close interior pathes
            path.Close();

            return(path);
        }