private Matrix <double> GetPictureDrawMatrix(SKPicture picture, Position gpsPosition, Size pixelSize) { Size platformPixelsSize = pixelSize * PlatformPixelScale; Matrix <double> matrix = Matrix <double> .Build.DenseIdentity(3, 3); Point mercatorPosition = gpsPosition.ToMercator(); SKRect sourceRect = picture.CullRect; SKMapSpan drawSpan = PixelsToMapSpanAtScale(platformPixelsSize, gpsPosition, _ScaleFactor); double xScale = platformPixelsSize.Width / sourceRect.Width; double yScale = platformPixelsSize.Height / sourceRect.Height; SKPoint canvasPoint; if (drawSpan.Crosses180thMeridianRight() && _MercatorRenderArea.Left < SKMapExtensions.MercatorCenterOffset) { // We cross the 180th meridian to the right and are drawing to a tile on the left side of the map, so wrap around mercatorPosition.X -= SKMapExtensions.MercatorMapSize; } if (drawSpan.Crosses180thMeridianLeft() && _MercatorRenderArea.Right > SKMapExtensions.MercatorCenterOffset) { // We cross the 180th meridian to the right and are drawing to a tile on the left side of the map, so wrap around mercatorPosition.X += SKMapExtensions.MercatorMapSize; } canvasPoint = ApplyMatrix(mercatorPosition); matrix *= Matrix <double> .Build.Translation(canvasPoint.X, canvasPoint.Y); matrix *= Matrix <double> .Build.Scale(xScale, yScale); matrix *= Matrix <double> .Build.Translation(sourceRect.Width * -0.5, sourceRect.Height * -0.5); return(matrix); }
private async Task HandleGroundOverlayForTile(TileInfo tileInfo) { if (SharedOverlay.IsVisible) { int virtualTileSize = Extensions.SKMapExtensions.MercatorMapSize >> tileInfo.Zoom; int xPixelsStart = tileInfo.X * virtualTileSize; int yPixelsStart = tileInfo.Y * virtualTileSize; double zoomScale = SKMapCanvas.MapTileSize / (double)virtualTileSize; Rectangle mercatorSpan = new Rectangle(xPixelsStart, yPixelsStart, virtualTileSize, virtualTileSize); SKMapSpan tileSpan = mercatorSpan.ToGps(); if (tileSpan.FastIntersects(SharedOverlay.GpsBounds)) { SKBitmap bitmap = DrawTileToBitmap(tileSpan, zoomScale); BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.FromBitmap(bitmap.ToBitmap()); TaskCompletionSource <object> drawingTcs = new TaskCompletionSource <object>(); Console.WriteLine($"Refreshing ground tile at ({tileInfo.X}, {tileInfo.Y}) for zoom level {tileInfo.Zoom} ({zoomScale}) with GPS bounds {tileSpan}"); Device.BeginInvokeOnMainThread(() => { GroundOverlay overlay; lock (_GroundOverlays) { overlay = _GroundOverlays.FirstOrDefault(o => (o.Tag as TileInfo)?.Equals(tileInfo) ?? false); } if (overlay == null) { GroundOverlayOptions overlayOptions = new GroundOverlayOptions().PositionFromBounds(tileSpan.ToLatLng()) .InvokeImage(bitmapDescriptor); overlay = _NativeMap.AddGroundOverlay(overlayOptions); overlay.Tag = tileInfo; lock (_GroundOverlays) { _GroundOverlays.Add(overlay); } } else if ((overlay.Tag as TileInfo)?.NeedsRedraw ?? false) { overlay.SetImage(bitmapDescriptor); } drawingTcs.TrySetResult(null); }); await drawingTcs.Task.ConfigureAwait(false); ReleaseOverlayBitmap(bitmap); } else { Console.WriteLine($"Ground tile at ({tileInfo.X}, {tileInfo.Y}) for zoom level {tileInfo.Zoom} already exists"); } } }
private SKBitmap DrawTileToBitmap(SKMapSpan tileSpan, double zoomScale) { Rectangle mercatorSpan = tileSpan.ToMercator(); SKBitmap bitmap = GetOverlayBitmap(); SKMapCanvas mapCanvas = new SKMapCanvas(bitmap, mercatorSpan, zoomScale); SharedOverlay.DrawOnMap(mapCanvas, tileSpan, zoomScale); return(bitmap); }
public static SKMapSpan WrapIfRequired(this SKMapSpan self) { SKMapSpan result = self; if (self.Crosses180thMeridian()) { // If we cross the 180th meridian, our map span is the full world width result = new SKMapSpan(new Position(result.Center.Latitude, 0), result.LatitudeDegrees, MaxLongitude); } return(result); }
public static Rectangle ToMercator(this SKMapSpan gpsSpan) { SKMapPosition topLeftGps = gpsSpan.TopLeft; SKMapPosition bottomRightGps = gpsSpan.BottomRight; Point canvasTopLeft = topLeftGps.ToMercator(); Point canvasBottomRight = bottomRightGps.ToMercator(); return(new Rectangle(canvasTopLeft.X, canvasTopLeft.Y, canvasBottomRight.X - canvasTopLeft.X, canvasBottomRight.Y - canvasTopLeft.Y)); }
public override void DrawMapRect(MKMapRect mapRect, nfloat zoomScale, CGContext context) { SKMapSpan rectSpan = mapRect.ToMapSpan(); if (_SharedOverlay.IsVisible && rectSpan.FastIntersects(_SharedOverlay.GpsBounds)) { CGRect coreDrawRect = RectForMapRect(mapRect); SKBitmap drawBitmap = GetOverlayBitmap(); SKMapCanvas mapCanvas = new SKMapCanvas(drawBitmap, mapRect.ToRectangle(), zoomScale, true); _SharedOverlay.DrawOnMap(mapCanvas, rectSpan, zoomScale); Console.WriteLine($"Drawing tile for zoom scale {zoomScale} with GPS bounds {mapRect} and Mercator {mapRect.ToRectangle()}"); context.DrawImage(coreDrawRect, drawBitmap.ToCGImage()); // Let's exit this method so MapKit renders to screen while we free our resources in the background. Task.Run(() => ReleaseOverlayBitmap(drawBitmap)); } }
public override void DrawOnMap(SKMapCanvas canvas, SKMapSpan canvasMapRect, double zoomScale) { SKPaint paint = new SKPaint(); paint.IsAntialias = true; paint.StrokeWidth = 1; paint.Color = Color.Fuchsia.ToSKColor(); MvxLog.Instance.Log(MvxLogLevel.Trace, () => $"Drawing line with coords \n" + $"[{GpsBounds.Center.Longitude - GpsBounds.LongitudeDegrees - canvasMapRect.LongitudeDegrees}, " + $"{GpsBounds.Center.Latitude - GpsBounds.LatitudeDegrees - canvasMapRect.LatitudeDegrees}; \n" + $" {GpsBounds.Center.Longitude + GpsBounds.LongitudeDegrees}, " + $"{GpsBounds.Center.Latitude + GpsBounds.LatitudeDegrees}]"); canvas.DrawLine(GpsBounds.Center.Latitude + GpsBounds.LatitudeDegrees - canvasMapRect.LatitudeDegrees, GpsBounds.Center.Longitude + GpsBounds.LongitudeDegrees - canvasMapRect.LongitudeDegrees, GpsBounds.Center.Latitude + GpsBounds.LatitudeDegrees, GpsBounds.Center.Longitude + GpsBounds.LongitudeDegrees, paint); }
public override void DrawOnMap(SKMapCanvas canvas, SKMapSpan canvasMapRect, double zoomScale) { SKPaint paint = new SKPaint(); paint.IsAntialias = true; paint.StrokeWidth = 1; paint.Color = Color.Fuchsia.ToSKColor(); if (canvasMapRect.Center.Latitude > 0) { canvas.DrawLine(new Position(canvasMapRect.Center.Latitude + canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude), new Position(canvasMapRect.Center.Latitude - canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude + canvasMapRect.LongitudeDegrees), paint); canvas.DrawLine(new Position(canvasMapRect.Center.Latitude - canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude + canvasMapRect.LongitudeDegrees), new Position(canvasMapRect.Center.Latitude - canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude - canvasMapRect.LongitudeDegrees), paint); canvas.DrawLine(new Position(canvasMapRect.Center.Latitude - canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude - canvasMapRect.LongitudeDegrees), new Position(canvasMapRect.Center.Latitude + canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude), paint); } else { canvas.DrawLine(new Position(canvasMapRect.Center.Latitude - canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude), new Position(canvasMapRect.Center.Latitude + canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude + canvasMapRect.LongitudeDegrees), paint); canvas.DrawLine(new Position(canvasMapRect.Center.Latitude + canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude + canvasMapRect.LongitudeDegrees), new Position(canvasMapRect.Center.Latitude + canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude - canvasMapRect.LongitudeDegrees), paint); canvas.DrawLine(new Position(canvasMapRect.Center.Latitude + canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude - canvasMapRect.LongitudeDegrees), new Position(canvasMapRect.Center.Latitude - canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude), paint); } paint.Style = SKPaintStyle.Stroke; paint.StrokeWidth = 10; paint.StrokeCap = SKStrokeCap.Round; paint.StrokeJoin = SKStrokeJoin.Round; paint.Color = Color.Red.ToSKColor(); SKMapPath zonePath = canvas.CreateEmptyMapPath(); zonePath.MoveTo((float)(baseBounds.Center.Latitude - baseBounds.LatitudeDegrees), (float)baseBounds.Center.Longitude); zonePath.LineTo((float)(baseBounds.Center.Latitude + baseBounds.LatitudeDegrees), (float)(baseBounds.Center.Longitude + baseBounds.LongitudeDegrees)); zonePath.LineTo((float)(baseBounds.Center.Latitude + baseBounds.LatitudeDegrees), (float)(baseBounds.Center.Longitude - baseBounds.LongitudeDegrees)); zonePath.Close(); canvas.DrawPath(zonePath, paint); paint.Color = Color.Green.MultiplyAlpha(0.5).ToSKColor(); Size currentScaleStrokeArea = SKMapCanvas.PixelsToMapSizeAtScale(new Size(5, 5), baseBounds.Center, zoomScale); MapSpan insetBounds = new MapSpan(baseBounds.Center, baseBounds.LatitudeDegrees - currentScaleStrokeArea.Height, baseBounds.LongitudeDegrees - currentScaleStrokeArea.Width); canvas.DrawRect(insetBounds, paint); paint.StrokeWidth = 1; paint.Color = Color.Black.ToSKColor(); canvas.DrawRect(baseBounds, paint); paint.Color = Color.Black.ToSKColor(); canvas.DrawRect(GpsBounds, paint); IResourceLocator resLocator = Mvx.IoCProvider.Resolve <IResourceLocator>(); string resPath = resLocator.GetResourcePath(ResourceKeys.ImagesKey, "symbol_logo.svg"); SKSvg logoSvg = new SKSvg(); logoSvg.Load(resLocator.ResourcesAssembly.GetManifestResourceStream(resPath)); canvas.DrawPicture(logoSvg.Picture, baseBounds.Center, new Size(100, 100)); }
public static bool Crosses180thMeridianLeft(this SKMapSpan self) { return(self.Center.Longitude - self.LongitudeDegrees < MinLongitude); }
public static bool Crosses180thMeridianRight(this SKMapSpan self) { return(self.Center.Longitude + self.LongitudeDegrees > MaxLongitude); }
public static bool Crosses180thMeridian(this SKMapSpan self) { return(self.Crosses180thMeridianRight() || self.Crosses180thMeridianLeft()); }
public override void DrawOnMap(SKMapCanvas canvas, SKMapSpan canvasMapRect, double zoomScale) { SKPaint paint = new SKPaint(); paint.IsAntialias = true; paint.StrokeWidth = 1; paint.Color = Color.Fuchsia.ToSKColor(); if (canvasMapRect.Center.Latitude > 0) { canvas.DrawLine(canvasMapRect.Center.Latitude - canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude - canvasMapRect.LongitudeDegrees, canvasMapRect.Center.Latitude + canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude + canvasMapRect.LongitudeDegrees, paint); } else { canvas.DrawLine(canvasMapRect.Center.Latitude + canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude - canvasMapRect.LongitudeDegrees, canvasMapRect.Center.Latitude - canvasMapRect.LatitudeDegrees, canvasMapRect.Center.Longitude + canvasMapRect.LongitudeDegrees, paint); } paint.StrokeWidth = 5; paint.Color = Color.Blue.ToSKColor(); canvas.DrawLine(baseBounds.Center.Latitude + baseBounds.LatitudeDegrees, baseBounds.Center.Longitude + baseBounds.LongitudeDegrees, baseBounds.Center.Latitude - baseBounds.LatitudeDegrees, baseBounds.Center.Longitude - baseBounds.LongitudeDegrees, paint); canvas.DrawLine(baseBounds.Center.Latitude - baseBounds.LatitudeDegrees, baseBounds.Center.Longitude + baseBounds.LongitudeDegrees, baseBounds.Center.Latitude + baseBounds.LatitudeDegrees, baseBounds.Center.Longitude - baseBounds.LongitudeDegrees, paint); paint.Color = Color.Red.ToSKColor(); canvas.DrawLine(baseBounds.Center.Latitude + baseBounds.LatitudeDegrees, baseBounds.Center.Longitude + baseBounds.LongitudeDegrees, baseBounds.Center.Latitude - baseBounds.LatitudeDegrees, baseBounds.Center.Longitude - baseBounds.LongitudeDegrees, paint, false); canvas.DrawLine(baseBounds.Center.Latitude - baseBounds.LatitudeDegrees, baseBounds.Center.Longitude + baseBounds.LongitudeDegrees, baseBounds.Center.Latitude + baseBounds.LatitudeDegrees, baseBounds.Center.Longitude - baseBounds.LongitudeDegrees, paint, false); paint.StrokeWidth = 5; paint.Color = Color.Orange.ToSKColor(); canvas.DrawLine(GpsBounds.Center.Latitude + GpsBounds.LatitudeDegrees, GpsBounds.Center.Longitude - GpsBounds.LongitudeDegrees, GpsBounds.Center.Latitude - GpsBounds.LatitudeDegrees, GpsBounds.Center.Longitude + GpsBounds.LongitudeDegrees, paint, false); canvas.DrawLine(GpsBounds.Center.Latitude + GpsBounds.LatitudeDegrees, GpsBounds.Center.Longitude + GpsBounds.LongitudeDegrees, GpsBounds.Center.Latitude - GpsBounds.LatitudeDegrees, GpsBounds.Center.Longitude - GpsBounds.LongitudeDegrees, paint, false); }
public TestLineMapOverlay() { baseBounds = new SKMapSpan(new Position(0, -180), 1, 1); GpsBounds = MapSpanExtensions.WorldSpan; }
public static Size PixelsToMapSizeAtScale(Size pixelsSize, Position mapPosition, double zoomScale) { SKMapSpan gpsArea = PixelsToMapSpanAtScale(pixelsSize, mapPosition, zoomScale); return(new Size(gpsArea.LongitudeDegrees * 2, gpsArea.LatitudeDegrees * 2)); }
public static LatLngBounds ToLatLng(this Rectangle self) { SKMapSpan mapSpan = self.ToGps(); return(mapSpan.ToLatLng()); }
public static LatLngBounds ToLatLng(this SKMapSpan self) { LatLngBounds.Builder builder = new LatLngBounds.Builder().Include(self.BottomLeft.ToLatLng()) .Include(self.TopRight.ToLatLng()); return(builder.Build()); }