private void CenterFrameBufferToMapView(Dimension mapViewDimension) { float dx = (this.dimension.Width - mapViewDimension.Width) / -2f; float dy = (this.dimension.Height - mapViewDimension.Height) / -2f; this.matrix.Translate(dx, dy); }
private void AdjustFrameBufferMatrix(MapPosition mapPositionFrameBuffer, Dimension mapViewDimension, double scaleFactor, LatLong pivot) { MapPosition mapViewPosition = this.model.mapViewPosition.MapPosition; long mapSize = MercatorProjection.GetMapSize(mapPositionFrameBuffer.ZoomLevel, model.displayModel.TileSize); Point pointFrameBuffer = MercatorProjection.GetPixel(mapPositionFrameBuffer.LatLong, mapSize); Point pointMapPosition = MercatorProjection.GetPixel(mapViewPosition.LatLong, mapSize); double diffX = pointFrameBuffer.X - pointMapPosition.X; double diffY = pointFrameBuffer.Y - pointMapPosition.Y; // we need to compute the pivot distance from the map center // as we will need to find the pivot point for the // frame buffer (which generally has not the same size as the // map view). double pivotDistanceX = 0d; double pivotDistanceY = 0d; if (pivot != null) { Point pivotXY = MercatorProjection.GetPixel(pivot, mapSize); pivotDistanceX = pivotXY.X - pointFrameBuffer.X; pivotDistanceY = pivotXY.Y - pointFrameBuffer.Y; } float currentScaleFactor = (float)(scaleFactor / Math.Pow(2, mapPositionFrameBuffer.ZoomLevel)); this.frameBuffer.AdjustMatrix((float)diffX, (float)diffY, currentScaleFactor, mapViewDimension, (float)pivotDistanceX, (float)pivotDistanceY); }
private bool DimensionChangeNeeded(Dimension mapViewDimension, double overdrawFactor) { if (overdrawFactor.CompareTo(this.lastOverdrawFactor) != 0) { return(true); } else if (!mapViewDimension.Equals(this.lastMapViewDimension)) { return(true); } return(false); }
public static Point GetTopLeftPoint(MapPosition mapPosition, Dimension canvasDimension, int tileSize) { LatLong centerPoint = mapPosition.LatLong; int halfCanvasWidth = canvasDimension.Width / 2; int halfCanvasHeight = canvasDimension.Height / 2; long mapSize = MercatorProjection.GetMapSize(mapPosition.ZoomLevel, tileSize); double pixelX = Math.Round(MercatorProjection.LongitudeToPixelX(centerPoint.Longitude, mapSize)); double pixelY = Math.Round(MercatorProjection.LatitudeToPixelY(centerPoint.Latitude, mapSize)); return(new Point((int)pixelX - halfCanvasWidth, (int)pixelY - halfCanvasHeight)); }
protected internal override void DoWork() { long startTime = System.DateTime.Now.Ticks; this.redrawNeeded = false; FrameBuffer frameBuffer = this.mapView.FrameBuffer; IBitmap bitmap = frameBuffer.DrawingBitmap; if (bitmap != null) { this.drawingCanvas.Bitmap = bitmap; MapPosition mapPosition = this.mapViewPosition.MapPosition; Dimension canvasDimension = this.drawingCanvas.Dimension; int tileSize = this.mapView.Model.displayModel.TileSize; BoundingBox boundingBox = MapPositionUtil.GetBoundingBox(mapPosition, canvasDimension, tileSize); Point topLeftPoint = MapPositionUtil.GetTopLeftPoint(mapPosition, canvasDimension, tileSize); foreach (Layer layer in this.layers) { if (layer.Visible) { layer.Draw(boundingBox, mapPosition.ZoomLevel, this.drawingCanvas, topLeftPoint); } } if (!mapViewPosition.AnimationInProgress()) { // this causes a lot of flickering when an animation // is in progress frameBuffer.FrameFinished(mapPosition); this.mapView.Repaint(); } else { // make sure that we redraw at the end this.redrawNeeded = true; } } long elapsedMilliseconds = (System.DateTime.Now.Ticks - startTime) / 10000; long timeSleep = MILLISECONDS_PER_FRAME - elapsedMilliseconds; if (timeSleep > 1 && !Interrupted) { System.Threading.Tasks.Task.Delay((int)timeSleep); } }
public static Dimension CalculateFrameBufferDimension(Dimension mapViewDimension, double overdrawFactor) { int width = (int)(mapViewDimension.Width * overdrawFactor); int height = (int)(mapViewDimension.Height * overdrawFactor); if (useSquareFrameBuffer) { float aspectRatio = ((float)mapViewDimension.Width) / mapViewDimension.Height; if (aspectRatio < maxAspectRatio && aspectRatio > 1 / maxAspectRatio) { width = Math.Max(width, height); height = width; } } return(new Dimension(width, height)); }
public static BoundingBox GetBoundingBox(MapPosition mapPosition, Dimension canvasDimension, int tileSize) { long mapSize = MercatorProjection.GetMapSize(mapPosition.ZoomLevel, tileSize); double pixelX = MercatorProjection.LongitudeToPixelX(mapPosition.LatLong.Longitude, mapSize); double pixelY = MercatorProjection.LatitudeToPixelY(mapPosition.LatLong.Latitude, mapSize); int halfCanvasWidth = canvasDimension.Width / 2; int halfCanvasHeight = canvasDimension.Height / 2; double pixelXMin = Math.Max(0, pixelX - halfCanvasWidth); double pixelYMin = Math.Max(0, pixelY - halfCanvasHeight); double pixelXMax = Math.Min(mapSize, pixelX + halfCanvasWidth); double pixelYMax = Math.Min(mapSize, pixelY + halfCanvasHeight); double minLatitude = MercatorProjection.PixelYToLatitude(pixelYMax, mapSize); double minLongitude = MercatorProjection.PixelXToLongitude(pixelXMin, mapSize); double maxLatitude = MercatorProjection.PixelYToLatitude(pixelYMin, mapSize); double maxLongitude = MercatorProjection.PixelXToLongitude(pixelXMax, mapSize); return(new BoundingBox(minLatitude, minLongitude, maxLatitude, maxLongitude)); }
public void OnChange() { Dimension mapViewDimension = this.model.mapViewDimension.Dimension; if (mapViewDimension == null) { // at this point map view not visible return; } double overdrawFactor = this.model.frameBufferModel.OverdrawFactor; if (DimensionChangeNeeded(mapViewDimension, overdrawFactor)) { Dimension newDimension = CalculateFrameBufferDimension(mapViewDimension, overdrawFactor); if (!useSquareFrameBuffer || frameBuffer.Dimension == null || newDimension.Width > frameBuffer.Dimension.Width || newDimension.Height > frameBuffer.Dimension.Height) { // new dimensions if we either always reallocate on config change or if new dimension // is larger than the old this.frameBuffer.Dimension = newDimension; } this.lastMapViewDimension = mapViewDimension; this.lastOverdrawFactor = overdrawFactor; } lock (this.model.mapViewPosition) { lock (this.frameBuffer) { // we need resource ordering here to avoid deadlock MapPosition mapPositionFrameBuffer = this.model.frameBufferModel.MapPosition; if (mapPositionFrameBuffer != null) { double scaleFactor = this.model.mapViewPosition.ScaleFactor; LatLong pivot = this.model.mapViewPosition.Pivot; AdjustFrameBufferMatrix(mapPositionFrameBuffer, mapViewDimension, scaleFactor, pivot); } } } }
public virtual void ZoomForBoundsTest() { // TODO rewrite this unit tests to make it easier to understand Dimension[] dimensions = new Dimension[] { new Dimension(200, 300), new Dimension(500, 400), new Dimension(1000, 600), new Dimension(3280, 1780), new Dimension(100, 200), new Dimension(500, 200) }; BoundingBox[] boundingBoxes = new BoundingBox[] { new BoundingBox(12.2, 0, 34.3, 120), new BoundingBox(-30, 20, 30, 30), new BoundingBox(20.3, 100, 30.4, 120), new BoundingBox(4.4, 2, 4.5, 2.2), new BoundingBox(50.43, 12.23, 50.44, 12.24), new BoundingBox(50.43, 12, 50.44, 40) }; int[] tileSizes = new int[] { 256, 512, 500, 620, 451 }; sbyte[] results = new sbyte[] { 1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 3, 2, 2, 2, 2, 10, 9, 9, 9, 9, 14, 13, 13, 13, 13, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 3, 2, 2, 1, 2, 5, 4, 4, 3, 4, 11, 10, 10, 10, 10, 15, 14, 14, 13, 14, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 6, 5, 5, 4, 5, 12, 11, 11, 11, 11, 15, 14, 14, 14, 14, 5, 4, 4, 4, 4, 5, 4, 4, 3, 4, 5, 4, 4, 4, 4, 7, 6, 6, 6, 6, 14, 13, 13, 13, 13, 17, 16, 16, 16, 16, 7, 6, 6, 6, 6, 0, 0, 0, 0, 0, 2, 1, 1, 0, 1, 2, 1, 1, 1, 1, 9, 8, 8, 8, 8, 13, 12, 12, 12, 12, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 0, 1, 4, 3, 3, 3, 3, 11, 10, 10, 10, 10, 14, 13, 13, 12, 13, 4, 3, 3, 3, 3 }; int i = 0; foreach (Dimension dimension in dimensions) { foreach (BoundingBox boundingBox in boundingBoxes) { foreach (int tileSize in tileSizes) { Assert.AreEqual(results[i], LatLongUtils.ZoomForBounds(dimension, boundingBox, tileSize)); ++i; } } } }
public virtual void AdjustMatrix(float diffX, float diffY, float scaleFactor, Dimension mapViewDimension, float pivotDistanceX, float pivotDistanceY) { lock (this) { if (this.dimension == null) { return; } this.matrix.Reset(); CenterFrameBufferToMapView(mapViewDimension); if (pivotDistanceX == 0 && pivotDistanceY == 0) { // only translate the matrix if we are not zooming around a pivot, // the translation happens only once the zoom is finished. this.matrix.Translate(diffX, diffY); } Scale(scaleFactor, pivotDistanceX, pivotDistanceY); } }