コード例 #1
0
        public void ZoomToBox(Geometries.Point beginPoint, Geometries.Point endPoint)
        {
            var width  = Math.Abs(endPoint.X - beginPoint.X);
            var height = Math.Abs(endPoint.Y - beginPoint.Y);

            if (width <= 0)
            {
                return;
            }
            if (height <= 0)
            {
                return;
            }

            ZoomHelper.ZoomToBoudingbox(
                beginPoint.X, beginPoint.Y, endPoint.X, endPoint.Y,
                Map.Viewport.Width, Map.Viewport.Height,
                out var x, out var y, out var resolution);

            resolution = ViewportLimiter.LimitResolution(resolution, _map.Viewport.Width, _map.Viewport.Height, _map.ZoomMode, _map.ZoomLimits,
                                                         _map.Resolutions, _map.Envelope);

            _map.Viewport.Resolution = resolution;

            _map.Viewport.Center = new Geometries.Point(x, y);


            _map.RefreshData(true);
            RefreshGraphics();
            ClearBBoxDrawing();
        }
コード例 #2
0
        private void LimitViewport()
        {
            GraphControl.UpdateContentRect();
            ViewportLimiter limiter = GraphControl.ViewportLimiter;

            limiter.HonorBothDimensions = false;
            limiter.Bounds = GraphControl.ContentRect.GetEnlarged(100);
        }
コード例 #3
0
ファイル: MapControl.cs プロジェクト: vkctata/Mapsui
        private void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            var(center, radius, angle)             = (e.Position.ToMapsui(), e.Delta.Scale, e.Delta.Rotation);
            var(prevCenter, prevRadius, prevAngle) = (e.Position.ToMapsui().Offset(-e.Delta.Translation.X, -e.Delta.Translation.Y), 1f, 0f);

            double rotationDelta = 0;

            if (!RotationLock)
            {
                _innerRotation += angle - prevAngle;
                _innerRotation %= 360;

                if (_innerRotation > 180)
                {
                    _innerRotation -= 360;
                }
                else if (_innerRotation < -180)
                {
                    _innerRotation += 360;
                }

                if (_map.Viewport.Rotation == 0 && Math.Abs(_innerRotation) >= Math.Abs(UnSnapRotationDegrees))
                {
                    rotationDelta = _innerRotation;
                }
                else if (_map.Viewport.Rotation != 0)
                {
                    if (Math.Abs(_innerRotation) <= Math.Abs(ReSnapRotationDegrees))
                    {
                        rotationDelta = -_map.Viewport.Rotation;
                    }
                    else
                    {
                        rotationDelta = _innerRotation - _map.Viewport.Rotation;
                    }
                }
            }

            _map.Viewport.Transform(center.X, center.Y, prevCenter.X, prevCenter.Y, radius / prevRadius, rotationDelta);

            ViewportLimiter.Limit(_map.Viewport, _map.ZoomMode, _map.ZoomLimits, _map.Resolutions,
                                  _map.PanMode, _map.PanLimits, _map.Envelope);
            RefreshGraphics();
            _map.RefreshData(false);
            OnViewChanged(true);

            e.Handled = true;
        }
コード例 #4
0
        public void TestRestrictZoom()
        {
            // arrange
            var viewport = new Viewport {
                Center = new Point(0, 0), Width = 100, Height = 100, Resolution = 1
            };
            // viewport.Center is (0, 0) at this point
            var restrictTo = new BoundingBox(20, 40, 120, 140); // Minimal X value is 20, Minimal Y value is 40

            // act
            ViewportLimiter.LimitExtent(viewport, PanMode.KeepCenterWithinExtents, restrictTo, viewport.Extent);

            // assert
            Assert.AreEqual(viewport.Center.X, 20);
            Assert.AreEqual(viewport.Center.Y, 40);
        }
コード例 #5
0
ファイル: MapControl.cs プロジェクト: pranker/Mapsui
        private double DetermineNewResolution(int mouseWheelDelta, double currentResolution)
        {
            if (mouseWheelDelta > 0)
            {
                var resolution = ZoomHelper.ZoomIn(_map.Resolutions, currentResolution);

                return(ViewportLimiter.LimitResolution(resolution, Viewport.Width, Viewport.Height,
                                                       _map.Limits.ZoomMode, _map.Limits.ZoomLimits, _map.Resolutions, _map.Envelope));
            }
            if (mouseWheelDelta < 0)
            {
                var resolution = ZoomHelper.ZoomOut(_map.Resolutions, currentResolution);

                return(ViewportLimiter.LimitResolution(resolution, Viewport.Width, Viewport.Height,
                                                       _map.Limits.ZoomMode, _map.Limits.ZoomLimits, _map.Resolutions, _map.Envelope));
            }
            return(currentResolution);
        }
コード例 #6
0
        public void TestRestrictZoom()
        {
            // arrange
            var viewport = new Viewport {
                CenterX = 0, CenterY = 0, Width = 100, Height = 100, Resolution = 1
            };
            // viewport.Center is (0, 0) at this point
            var limiter = new ViewportLimiter
            {
                PanLimits = new MRect(20, 40, 120, 140)  // Minimal X value is 20, Minimal Y value is 40
            };

            // act
            limiter.LimitExtent(viewport, viewport.Extent);

            // assert
            Assert.AreEqual(viewport.Center.X, 20);
            Assert.AreEqual(viewport.Center.Y, 40);
        }
コード例 #7
0
        public void MapView_Touch(object sender, TouchEventArgs args)
        {
            if (_gestureDetector.OnTouchEvent(args.Event))
            {
                return;
            }

            var touchPoints = GetMapPositions(args.Event, this);

            switch (args.Event.Action)
            {
            case MotionEventActions.Up:
                InvalidateCanvas();
                _mode = TouchMode.None;
                _map.ViewChanged(true);
                break;

            case MotionEventActions.Down:
            case MotionEventActions.Pointer1Down:
            case MotionEventActions.Pointer2Down:
            case MotionEventActions.Pointer3Down:
                if (touchPoints.Count >= 2)
                {
                    (_previousCenter, _previousRadius, _previousAngle) = GetPinchValues(touchPoints);
                    _mode          = TouchMode.Zooming;
                    _innerRotation = _map.Viewport.Rotation;
                }
                else
                {
                    _mode           = TouchMode.Dragging;
                    _previousCenter = touchPoints.First();
                }
                break;

            case MotionEventActions.Pointer1Up:
            case MotionEventActions.Pointer2Up:
            case MotionEventActions.Pointer3Up:
                // Remove the touchPoint that was released from the locations to reset the
                // starting points of the move and rotation
                touchPoints.RemoveAt(args.Event.ActionIndex);

                if (touchPoints.Count >= 2)
                {
                    (_previousCenter, _previousRadius, _previousAngle) = GetPinchValues(touchPoints);
                    _mode          = TouchMode.Zooming;
                    _innerRotation = _map.Viewport.Rotation;
                }
                else
                {
                    _mode           = TouchMode.Dragging;
                    _previousCenter = touchPoints.First();
                }
                break;

            case MotionEventActions.Move:
                switch (_mode)
                {
                case TouchMode.Dragging:
                {
                    if (touchPoints.Count != 1)
                    {
                        return;
                    }

                    var touchPosition = touchPoints.First();
                    if (_previousCenter != null && !_previousCenter.IsEmpty())
                    {
                        _map.Viewport.Transform(touchPosition.X, touchPosition.Y, _previousCenter.X, _previousCenter.Y);

                        ViewportLimiter.LimitExtent(_map.Viewport, _map.PanMode, _map.PanLimits, _map.Envelope);

                        InvalidateCanvas();
                    }
                    _previousCenter = touchPosition;
                }
                break;

                case TouchMode.Zooming:
                {
                    if (touchPoints.Count < 2)
                    {
                        return;
                    }

                    var(prevCenter, prevRadius, prevAngle) = (_previousCenter, _previousRadius, _previousAngle);
                    var(center, radius, angle)             = GetPinchValues(touchPoints);

                    double rotationDelta = 0;

                    if (RotationLock)
                    {
                        _innerRotation += angle - prevAngle;
                        _innerRotation %= 360;

                        if (_innerRotation > 180)
                        {
                            _innerRotation -= 360;
                        }
                        else if (_innerRotation < -180)
                        {
                            _innerRotation += 360;
                        }

                        if (_map.Viewport.Rotation == 0 && Math.Abs(_innerRotation) >= Math.Abs(UnSnapRotationDegrees))
                        {
                            rotationDelta = _innerRotation;
                        }
                        else if (_map.Viewport.Rotation != 0)
                        {
                            if (Math.Abs(_innerRotation) <= Math.Abs(ReSnapRotationDegrees))
                            {
                                rotationDelta = -_map.Viewport.Rotation;
                            }
                            else
                            {
                                rotationDelta = _innerRotation - _map.Viewport.Rotation;
                            }
                        }
                    }

                    _map.Viewport.Transform(center.X, center.Y, prevCenter.X, prevCenter.Y, radius / prevRadius, rotationDelta);

                    (_previousCenter, _previousRadius, _previousAngle) = (center, radius, angle);

                    ViewportLimiter.Limit(_map.Viewport,
                                          _map.ZoomMode, _map.ZoomLimits, _map.Resolutions,
                                          _map.PanMode, _map.PanLimits, _map.Envelope);

                    InvalidateCanvas();
                }
                break;
                }
                break;
            }
        }
コード例 #8
0
        public override void TouchesMoved(NSSet touches, UIEvent evt)
        {
            base.TouchesMoved(touches, evt);

            if (evt.AllTouches.Count == 1)
            {
                if (touches.AnyObject is UITouch touch)
                {
                    var currentPos  = touch.LocationInView(this);
                    var previousPos = touch.PreviousLocationInView(this);

                    _map.Viewport.Transform(currentPos.X, currentPos.Y, previousPos.X, previousPos.Y);

                    ViewportLimiter.LimitExtent(_map.Viewport, _map.PanMode, _map.PanLimits, _map.Envelope);

                    RefreshGraphics();
                }
            }
            else if (evt.AllTouches.Count >= 2)
            {
                var prevLocations = evt.AllTouches.Select(t => ((UITouch)t).PreviousLocationInView(this))
                                    .Select(p => new Point(p.X, p.Y)).ToList();

                var locations = evt.AllTouches.Select(t => ((UITouch)t).LocationInView(this))
                                .Select(p => new Point(p.X, p.Y)).ToList();

                var(prevCenter, prevRadius, prevAngle) = GetPinchValues(prevLocations);
                var(center, radius, angle)             = GetPinchValues(locations);

                double rotationDelta = 0;

                if (AllowPinchRotation)
                {
                    _innerRotation += angle - prevAngle;
                    _innerRotation %= 360;

                    if (_innerRotation > 180)
                    {
                        _innerRotation -= 360;
                    }
                    else if (_innerRotation < -180)
                    {
                        _innerRotation += 360;
                    }

                    if (_map.Viewport.Rotation == 0 && Math.Abs(_innerRotation) >= Math.Abs(UnSnapRotationDegrees))
                    {
                        rotationDelta = _innerRotation;
                    }
                    else if (_map.Viewport.Rotation != 0)
                    {
                        if (Math.Abs(_innerRotation) <= Math.Abs(ReSnapRotationDegrees))
                        {
                            rotationDelta = -_map.Viewport.Rotation;
                        }
                        else
                        {
                            rotationDelta = _innerRotation - _map.Viewport.Rotation;
                        }
                    }
                }

                _map.Viewport.Transform(center.X, center.Y, prevCenter.X, prevCenter.Y, radius / prevRadius, rotationDelta);

                ViewportLimiter.Limit(_map.Viewport,
                                      _map.ZoomMode, _map.ZoomLimits, _map.Resolutions,
                                      _map.PanMode, _map.PanLimits, _map.Envelope);

                RefreshGraphics();
            }
        }
コード例 #9
0
ファイル: MapControl.cs プロジェクト: andifrei/Mapsui
        public void MapView_Touch(object sender, TouchEventArgs args)
        {
            var x = (int)args.Event.RawX;
            var y = (int)args.Event.RawY;

            switch (args.Event.Action)
            {
            case MotionEventActions.Down:
                _previousMap = null;
                _mode        = Dragging;
                break;

            case MotionEventActions.Up:
                _previousMap = null;
                _canvas.Invalidate();
                _mode = None;
                _map.ViewChanged(true);
                Map.InvokeInfo(GetScreenPosition(args.Event), _scale, _renderer.SymbolCache);
                break;

            case MotionEventActions.Pointer2Down:
                _previousMap = null;
                _oldDist     = Spacing(args.Event);
                MidPoint(_currentMid, args.Event);
                _previousMid = _currentMid;
                if (AllowPinchRotation)
                {
                    _previousAngle = Angle(args.Event);
                }
                _mode = Zoom;
                break;

            case MotionEventActions.Pointer2Up:
                _previousMap = null;
                _previousMid = null;
                _mode        = Dragging;
                break;

            case MotionEventActions.Move:
                switch (_mode)
                {
                case Dragging:
                    _currentMap = new PointF(x, y);
                    if (_previousMap != null)
                    {
                        _map.Viewport.Transform(
                            _currentMap.X / _scale,
                            _currentMap.Y / _scale,
                            _previousMap.X / _scale,
                            _previousMap.Y / _scale);

                        ViewportLimiter.LimitExtent(_map.Viewport,
                                                    _map.PanMode, _map.PanLimits, _map.Envelope);

                        _canvas.Invalidate();
                    }
                    _previousMap = _currentMap;
                    break;

                case Zoom:
                {
                    if (args.Event.PointerCount < 2)
                    {
                        return;
                    }

                    var newDist = Spacing(args.Event);
                    var scale   = newDist / _oldDist;

                    _oldDist     = Spacing(args.Event);
                    _previousMid = new PointF(_currentMid.X, _currentMid.Y);
                    MidPoint(_currentMid, args.Event);


                    _map.Viewport.Transform(
                        _currentMid.X / _scale,
                        _currentMid.Y / _scale,
                        _previousMid.X / _scale,
                        _previousMid.Y / _scale,
                        scale);

                    if (AllowPinchRotation)
                    {
                        var angle = Angle(args.Event);
                        _map.Viewport.Rotation += angle - _previousAngle;
                        _previousAngle          = angle;
                    }

                    ViewportLimiter.Limit(_map.Viewport,
                                          _map.ZoomMode, _map.ZoomLimits, _map.Resolutions,
                                          _map.PanMode, _map.PanLimits, _map.Envelope);

                    _canvas.Invalidate();
                }
                break;
                }
                break;
            }
        }
コード例 #10
0
        public void MapView_Touch(object sender, TouchEventArgs args)
        {
            var x = (int)args.Event.GetX(0);
            var y = (int)args.Event.GetY(0);

            switch (args.Event.Action)
            {
            case MotionEventActions.Down:
                _previousTouchPosition = null;
                _touchDownPosition     = new PointF(x, y);
                _mode = Dragging;
                break;

            case MotionEventActions.Up:
                _canvas.Invalidate();
                _mode = None;
                _map.ViewChanged(true);
                var position = GetScreenPosition(args.Event);
                Map.InvokeInfo(position, _touchDownPosition.ToMapsui(), _scale, _renderer.SymbolCache, WidgetTouch);
                break;

            case MotionEventActions.Pointer2Down:
                _previousTouchPosition = null;
                _oldDist             = Spacing(args.Event);
                _touchCenter         = GetTouchCenter(args.Event);
                _previousTouchCenter = _touchCenter;
                if (AllowPinchRotation)
                {
                    _previousAngle = Angle(args.Event);
                }
                _touchDownPosition = _touchCenter;
                _mode = Zoom;
                break;

            case MotionEventActions.Pointer2Up:
                _previousTouchPosition = null;
                _previousTouchCenter   = null;
                _mode = Dragging;
                break;

            case MotionEventActions.Move:
                switch (_mode)
                {
                case Dragging:
                    _touchPosition = new PointF(x, y);
                    if (_previousTouchPosition != null)
                    {
                        _map.Viewport.Transform(
                            _touchPosition.X / _scale,
                            _touchPosition.Y / _scale,
                            _previousTouchPosition.X / _scale,
                            _previousTouchPosition.Y / _scale);

                        ViewportLimiter.LimitExtent(_map.Viewport,
                                                    _map.PanMode, _map.PanLimits, _map.Envelope);

                        _canvas.Invalidate();
                    }
                    _previousTouchPosition = _touchPosition;
                    break;

                case Zoom:
                {
                    if (args.Event.PointerCount < 2)
                    {
                        return;
                    }

                    var newDist = Spacing(args.Event);
                    var scale   = newDist / _oldDist;

                    _oldDist             = Spacing(args.Event);
                    _previousTouchCenter = new PointF(_touchCenter.X, _touchCenter.Y);
                    _touchCenter         = GetTouchCenter(args.Event);


                    _map.Viewport.Transform(
                        _touchCenter.X / _scale,
                        _touchCenter.Y / _scale,
                        _previousTouchCenter.X / _scale,
                        _previousTouchCenter.Y / _scale,
                        scale);

                    if (AllowPinchRotation)
                    {
                        var angle = Angle(args.Event);
                        _map.Viewport.Rotation += angle - _previousAngle;
                        _previousAngle          = angle;
                    }

                    ViewportLimiter.Limit(_map.Viewport,
                                          _map.ZoomMode, _map.ZoomLimits, _map.Resolutions,
                                          _map.PanMode, _map.PanLimits, _map.Envelope);

                    _canvas.Invalidate();
                }
                break;
                }
                break;
            }
        }
コード例 #11
0
        public void MapView_Touch(object sender, TouchEventArgs args)
        {
            switch (args.Event.Action)
            {
            case MotionEventActions.Down:
                _previousTouchPosition = null;
                _touchDownPosition     = GetScreenPosition(args.Event, this);
                _mode = Dragging;
                break;

            case MotionEventActions.Up:
                _canvas.Invalidate();
                _mode = None;
                _map.ViewChanged(true);
                var position = GetScreenPosition(args.Event, this);
                Map.InvokeInfo(position, _touchDownPosition, _scale, _renderer.SymbolCache, WidgetTouch);
                break;

            case MotionEventActions.Pointer2Down:
                _previousTouchPosition = null;
                _previousDistance      = DistanceBetweenTouches(args.Event);
                _touchCenter           = GetTouchCenter(args.Event, this);
                _previousTouchCenter   = _touchCenter;
                if (AllowPinchRotation)
                {
                    _previousAngle = Angle(args.Event);
                    _innerRotation = _map.Viewport.Rotation;
                }
                _touchDownPosition = _touchCenter;
                _mode = Zoom;
                break;

            case MotionEventActions.Pointer2Up:
                _previousTouchPosition = null;
                _previousTouchCenter   = null;
                _mode = Dragging;
                break;

            case MotionEventActions.Move:
                switch (_mode)
                {
                case Dragging:
                    _touchPosition = GetScreenPosition(args.Event, this);
                    if (_previousTouchPosition != null)
                    {
                        _map.Viewport.Transform(
                            _touchPosition.X / _scale,
                            _touchPosition.Y / _scale,
                            _previousTouchPosition.X / _scale,
                            _previousTouchPosition.Y / _scale);

                        ViewportLimiter.LimitExtent(_map.Viewport,
                                                    _map.PanMode, _map.PanLimits, _map.Envelope);

                        _canvas.Invalidate();
                    }
                    _previousTouchPosition = _touchPosition;
                    break;

                case Zoom:
                {
                    if (args.Event.PointerCount < 2)
                    {
                        return;
                    }

                    var distance = DistanceBetweenTouches(args.Event);
                    var scale    = distance / _previousDistance;
                    _previousDistance = distance;

                    _previousTouchCenter = _touchCenter;
                    _touchCenter         = GetTouchCenter(args.Event, this);

                    _map.Viewport.Transform(
                        _touchCenter.X / _scale,
                        _touchCenter.Y / _scale,
                        _previousTouchCenter.X / _scale,
                        _previousTouchCenter.Y / _scale,
                        scale);

                    if (AllowPinchRotation)
                    {
                        var angle = Angle(args.Event);
                        _innerRotation += angle - _previousAngle;
                        _innerRotation %= 360;

                        if (_innerRotation > 180)
                        {
                            _innerRotation -= 360;
                        }
                        else if (_innerRotation < -180)
                        {
                            _innerRotation += 360;
                        }

                        if (_map.Viewport.Rotation == 0 && Math.Abs(_innerRotation) >= Math.Abs(UnSnapRotationDegrees))
                        {
                            _map.Viewport.Rotation = _innerRotation;
                        }
                        else if (_map.Viewport.Rotation != 0)
                        {
                            if (Math.Abs(_innerRotation) <= Math.Abs(ReSnapRotationDegrees))
                            {
                                _map.Viewport.Rotation = 0;
                            }
                            else
                            {
                                _map.Viewport.Rotation = _innerRotation;
                            }
                        }

                        _previousAngle = angle;
                    }

                    ViewportLimiter.Limit(_map.Viewport,
                                          _map.ZoomMode, _map.ZoomLimits, _map.Resolutions,
                                          _map.PanMode, _map.PanLimits, _map.Envelope);

                    _canvas.Invalidate();
                }
                break;
                }
                break;
            }
        }
コード例 #12
0
        /// <summary>
        /// Called, when mouse/finger/pen moves over map
        /// </summary>
        /// <param name="touchPoints">List of all touched points</param>
        private bool OnTouchMove(List <Geometries.Point> touchPoints)
        {
            var args = new TouchedEventArgs(touchPoints);

            TouchMove?.Invoke(this, args);

            if (args.Handled)
            {
                return(true);
            }

            switch (_mode)
            {
            case TouchMode.Dragging:
            {
                if (touchPoints.Count != 1)
                {
                    return(false);
                }

                var touchPosition = touchPoints.First();

                if (_previousCenter != null && !_previousCenter.IsEmpty())
                {
                    _map.Viewport.Transform(touchPosition.X, touchPosition.Y, _previousCenter.X, _previousCenter.Y);

                    ViewportLimiter.LimitExtent(_map.Viewport, _map.PanMode, _map.PanLimits, _map.Envelope);

                    InvalidateCanvas();
                }

                _previousCenter = touchPosition;
            }
            break;

            case TouchMode.Zooming:
            {
                if (touchPoints.Count < 2)
                {
                    return(false);
                }

                var(prevCenter, prevRadius, prevAngle) = (_previousCenter, _previousRadius, _previousAngle);
                var(center, radius, angle)             = GetPinchValues(touchPoints);

                double rotationDelta = 0;

                if (RotationLock)
                {
                    _innerRotation += angle - prevAngle;
                    _innerRotation %= 360;

                    if (_innerRotation > 180)
                    {
                        _innerRotation -= 360;
                    }
                    else if (_innerRotation < -180)
                    {
                        _innerRotation += 360;
                    }

                    if (_map.Viewport.Rotation == 0 && Math.Abs(_innerRotation) >= Math.Abs(UnSnapRotationDegrees))
                    {
                        rotationDelta = _innerRotation;
                    }
                    else if (_map.Viewport.Rotation != 0)
                    {
                        if (Math.Abs(_innerRotation) <= Math.Abs(ReSnapRotationDegrees))
                        {
                            rotationDelta = -_map.Viewport.Rotation;
                        }
                        else
                        {
                            rotationDelta = _innerRotation - _map.Viewport.Rotation;
                        }
                    }
                }

                _map.Viewport.Transform(center.X, center.Y, prevCenter.X, prevCenter.Y, radius / prevRadius, rotationDelta);

                (_previousCenter, _previousRadius, _previousAngle) = (center, radius, angle);

                ViewportLimiter.Limit(_map.Viewport,
                                      _map.ZoomMode, _map.ZoomLimits, _map.Resolutions,
                                      _map.PanMode, _map.PanLimits, _map.Envelope);

                InvalidateCanvas();
            }
            break;
            }

            return(true);
        }
コード例 #13
0
        public void MapView_Touch(object sender, TouchEventArgs args)
        {
            try
            {
                if (_gestureDetector.OnTouchEvent(args.Event))
                {
                    return;
                }
            }
            catch (ObjectDisposedException e)
            {
                System.Diagnostics.Debug.WriteLine(e.Message);

                _gestureDetector = new GestureDetector(Context, new GestureDetector.SimpleOnGestureListener());
                _gestureDetector.SingleTapConfirmed += OnSingleTapped;
                _gestureDetector.DoubleTap          += OnDoubleTapped;

                Invalidate();
            }

            var touchPoints = GetScreenPositions(args.Event, this);

            switch (args.Event.Action)
            {
            case MotionEventActions.Up:
                if (_mode == TouchMode.FeatureDrag)
                {
                    StopFeatureDrag(args.Event);
                }

                RefreshGraphics();
                _mode = TouchMode.None;
                RefreshData();
                break;

            case MotionEventActions.Down:
            case MotionEventActions.Pointer1Down:
            case MotionEventActions.Pointer2Down:
            case MotionEventActions.Pointer3Down:
                if (_mode != TouchMode.FeatureDrag)
                {
                    if (touchPoints.Count >= 2)
                    {
                        (_previousCenter, _previousRadius, _previousAngle) = GetPinchValues(touchPoints);
                        _mode          = TouchMode.Zooming;
                        _innerRotation = Viewport.Rotation;
                    }
                    else
                    {
                        var mapInfoArgs = CheckStartDragHandled(args.Event);

                        if (mapInfoArgs.Handled)
                        {
                            System.Diagnostics.Debug.WriteLine("Drag consumed!!");
                            _draggedFeature = mapInfoArgs.MapInfo.Feature;

                            _mode = TouchMode.FeatureDrag;
                        }
                        else
                        {
                            _mode           = TouchMode.Dragging;
                            _previousCenter = touchPoints.First();
                        }
                    }
                }
                break;

            case MotionEventActions.Pointer1Up:
            case MotionEventActions.Pointer2Up:
            case MotionEventActions.Pointer3Up:
                if (_mode != TouchMode.FeatureDrag)
                {
                    // Remove the touchPoint that was released from the locations to reset the
                    // starting points of the move and rotation
                    touchPoints.RemoveAt(args.Event.ActionIndex);

                    if (touchPoints.Count >= 2)
                    {
                        (_previousCenter, _previousRadius, _previousAngle) = GetPinchValues(touchPoints);
                        _mode          = TouchMode.Zooming;
                        _innerRotation = Viewport.Rotation;
                    }
                    else
                    {
                        _mode           = TouchMode.Dragging;
                        _previousCenter = touchPoints.First();
                    }
                }
                break;

            case MotionEventActions.Move:
                switch (_mode)
                {
                case TouchMode.FeatureDrag:
                    DragFeatureTo(args.Event);
                    break;

                case TouchMode.Dragging:
                {
                    if (touchPoints.Count != 1)
                    {
                        return;
                    }

                    var touchPosition = touchPoints.First();
                    if (_previousCenter != null && !_previousCenter.IsEmpty())
                    {
                        _viewport.Transform(touchPosition.X, touchPosition.Y, _previousCenter.X, _previousCenter.Y);

                        ViewportLimiter.LimitExtent(_viewport, _map.Limits.PanMode, _map.Limits.PanLimits, _map.Envelope);

                        RefreshGraphics();
                    }
                    _previousCenter = touchPosition;
                }
                break;

                case TouchMode.Zooming:
                {
                    if (touchPoints.Count < 2)
                    {
                        return;
                    }

                    var(prevCenter, prevRadius, prevAngle) = (_previousCenter, _previousRadius, _previousAngle);
                    var(center, radius, angle)             = GetPinchValues(touchPoints);

                    double rotationDelta = 0;

                    if (!RotationLock)
                    {
                        _innerRotation += angle - prevAngle;
                        _innerRotation %= 360;

                        if (_innerRotation > 180)
                        {
                            _innerRotation -= 360;
                        }
                        else if (_innerRotation < -180)
                        {
                            _innerRotation += 360;
                        }

                        if (Viewport.Rotation == 0 && Math.Abs(_innerRotation) >= Math.Abs(UnSnapRotationDegrees))
                        {
                            rotationDelta = _innerRotation;
                        }
                        else if (Viewport.Rotation != 0)
                        {
                            if (Math.Abs(_innerRotation) <= Math.Abs(ReSnapRotationDegrees))
                            {
                                rotationDelta = -Viewport.Rotation;
                            }
                            else
                            {
                                rotationDelta = _innerRotation - Viewport.Rotation;
                            }
                        }
                    }

                    _viewport.Transform(center.X, center.Y, prevCenter.X, prevCenter.Y, radius / prevRadius, rotationDelta);

                    (_previousCenter, _previousRadius, _previousAngle) = (center, radius, angle);

                    ViewportLimiter.Limit(_viewport,
                                          _map.Limits.ZoomMode, _map.Limits.ZoomLimits, _map.Resolutions,
                                          _map.Limits.PanMode, _map.Limits.PanLimits, _map.Envelope);

                    RefreshGraphics();
                }
                break;
                }
                break;
            }
        }