/// <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); }
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(); }
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); }
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; }
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); }
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); }
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); } }
/// <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); }
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); }
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); } }
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); }
public MemoryStream RenderToBitmapStream(IReadOnlyViewport viewport, IEnumerable <ILayer> layers, Color background = null) { MemoryStream bitmapStream = null; RunMethodOnStaThread(() => bitmapStream = RenderToBitmapStreamStatic(viewport, layers, _symbolCache)); return(bitmapStream); }
/// <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)); }
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); }
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); } }
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"); } }
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); }
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); } } }
/// <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); }
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); }
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); }
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); } }
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); } }
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)); }
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); } }
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); } }
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); } }
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(); }
/// <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); }