/// <summary> /// Initializes a new instance of the <see cref="OsmSharp.Math.Primitives.RectangleF2D"/> class. /// </summary> /// <param name="x">The x coordinate of the bottom-left corner.</param> /// <param name="y">The y coordinate of the bottom-left corner.</param> /// <param name="width">Width.</param> /// <param name="height">Height.</param> /// <param name="angleY">The angle relative to the y-axis.</param> public RectangleF2D(double x, double y, double width, double height, Degree angleY) { _bottomLeft = new PointF2D (x, y); VectorF2D directionY = VectorF2D.FromAngleY (angleY); _vectorY = directionY * height; _vectorX = directionY.Rotate90 (true) * width; }
/// <summary> /// Converts the latitude to a projected y-coordinate. /// </summary> /// <param name="lat"></param> /// <returns></returns> public double LatitudeToY(double lat) { double n = System.Math.Floor(System.Math.Pow(2, DefaultZoom)); Radian rad = new Degree(lat); return ( (1.0f - (System.Math.Log(System.Math.Tan(rad.Value) + (1.0f / System.Math.Cos(rad.Value)))) / System.Math.PI) / 2f * (double)n); }
/// <summary> /// Creates a new angle in degrees. /// </summary> /// <param name="value"></param> public Degree(double value) : base(Degree.Normalize(value)) { }
/// <summary> /// Sets the map view. /// </summary> /// <param name="center">Center.</param> /// <param name="mapTilt">Map tilt.</param> /// <param name="mapZoom">Map zoom.</param> public void SetMapView(GeoCoordinate center, Degree mapTilt, float mapZoom) { this.SetMapView (center, mapTilt, mapZoom, true); }
/// <summary> /// Sets the map view. /// </summary> /// <param name="center">Center.</param> /// <param name="mapTilt">Map tilt.</param> /// <param name="mapZoom">Map zoom.</param> public void SetMapView(GeoCoordinate center, Degree mapTilt, float mapZoom) { _mapCenter = center; _mapTilt = mapTilt; this.MapZoom = mapZoom; (this.Context as Activity).RunOnUiThread(NotifyMovement); }
/// <summary> /// Initialize the specified defaultMapCenter, defaultMap, defaultMapTilt and defaultMapZoom. /// </summary> /// <param name="defaultMapCenter">Default map center.</param> /// <param name="defaultMap">Default map.</param> /// <param name="defaultMapTilt">Default map tilt.</param> /// <param name="defaultMapZoom">Default map zoom.</param> public void Initialize(GeoCoordinate defaultMapCenter, Map defaultMap, Degree defaultMapTilt, float defaultMapZoom) { // register the default listener. (this as IInvalidatableMapSurface).RegisterListener(new DefaultTrigger(this)); // enable all interactions by default. this.MapAllowPan = true; this.MapAllowTilt = true; this.MapAllowZoom = true; // set clip to bounds to prevent objects from being rendered/show outside of the mapview. this.ClipsToBounds = true; MapCenter = defaultMapCenter; _map = defaultMap; MapTilt = defaultMapTilt; MapZoom = defaultMapZoom; _map.MapChanged += MapChanged; _doubleTapAnimator = new MapViewAnimator(this); this.BackgroundColor = UIColor.White; this.UserInteractionEnabled = true; if (UIDevice.CurrentDevice.CheckSystemVersion(7, 0)) { var panGesture = new UIPanGestureRecognizer(Pan); panGesture.ShouldRecognizeSimultaneously += (UIGestureRecognizer r, UIGestureRecognizer other) => { return true; }; // TODO: workaround for xamarin bug, remove later! panGesture.ShouldRequireFailureOf = (a, b) => { return false; }; panGesture.ShouldBeRequiredToFailBy = (a, b) => { return false; }; this.AddGestureRecognizer(panGesture); var pinchGesture = new UIPinchGestureRecognizer(Pinch); pinchGesture.ShouldRecognizeSimultaneously += (UIGestureRecognizer r, UIGestureRecognizer other) => { return true; }; // TODO: workaround for xamarin bug, remove later! pinchGesture.ShouldRequireFailureOf = (a, b) => { return false; }; pinchGesture.ShouldBeRequiredToFailBy = (a, b) => { return false; }; this.AddGestureRecognizer(pinchGesture); var rotationGesture = new UIRotationGestureRecognizer(Rotate); rotationGesture.ShouldRecognizeSimultaneously += (UIGestureRecognizer r, UIGestureRecognizer other) => { return true; }; // TODO: workaround for xamarin bug, remove later! rotationGesture.ShouldRequireFailureOf = (a, b) => { return false; }; rotationGesture.ShouldBeRequiredToFailBy = (a, b) => { return false; }; this.AddGestureRecognizer(rotationGesture); var singleTapGesture = new UITapGestureRecognizer(SingleTap); singleTapGesture.NumberOfTapsRequired = 1; // TODO: workaround for xamarin bug, remove later! // singleTapGesture.ShouldRequireFailureOf = (a, b) => { return false; }; // singleTapGesture.ShouldBeRequiredToFailBy = (a, b) => { return false; }; var doubleTapGesture = new UITapGestureRecognizer(DoubleTap); doubleTapGesture.NumberOfTapsRequired = 2; // TODO: workaround for xamarin bug, remove later! // doubleTapGesture.ShouldRequireFailureOf = (a, b) => { return false; }; // doubleTapGesture.ShouldBeRequiredToFailBy = (a, b) => { return false; }; //singleTapGesture.RequireGestureRecognizerToFail (doubleTapGesture); this.AddGestureRecognizer(singleTapGesture); this.AddGestureRecognizer(doubleTapGesture); } else { var panGesture = new UIPanGestureRecognizer(Pan); panGesture.ShouldRecognizeSimultaneously += (UIGestureRecognizer r, UIGestureRecognizer other) => { return true; }; this.AddGestureRecognizer(panGesture); var pinchGesture = new UIPinchGestureRecognizer(Pinch); pinchGesture.ShouldRecognizeSimultaneously += (UIGestureRecognizer r, UIGestureRecognizer other) => { return true; }; this.AddGestureRecognizer(pinchGesture); var rotationGesture = new UIRotationGestureRecognizer(Rotate); rotationGesture.ShouldRecognizeSimultaneously += (UIGestureRecognizer r, UIGestureRecognizer other) => { return true; }; this.AddGestureRecognizer(rotationGesture); var singleTapGesture = new UITapGestureRecognizer(SingleTap); singleTapGesture.NumberOfTapsRequired = 1; //singleTapGesture.ShouldRecognizeSimultaneously += ShouldRecognizeSimultaneouslySingle; //singleTapGesture.ShouldBeRequiredToFailBy += ShouldRecognizeSimultaneouslySingle; var doubleTapGesture = new UITapGestureRecognizer(DoubleTap); doubleTapGesture.NumberOfTapsRequired = 2; //doubleTapGesture.ShouldRecognizeSimultaneously += ShouldRecognizeSimultaneouslySingle; //doubleTapGesture.ShouldBeRequiredToFailBy += ShouldRecognizeSimultaneouslyDouble; singleTapGesture.RequireGestureRecognizerToFail(doubleTapGesture); this.AddGestureRecognizer(singleTapGesture); this.AddGestureRecognizer(doubleTapGesture); } // set scalefactor. _scaleFactor = (float)this.ContentScaleFactor; // create the cache renderer. _cacheRenderer = new MapRenderer<CGContextWrapper>( new CGContextRenderer(_scaleFactor)); _backgroundColor = SimpleColor.FromKnownColor(KnownColor.White).Value; }
/// <summary> /// Creates a new instance of the <see cref="OsmSharp.UI.Renderer.View2D"/> class. /// </summary> /// <param name="width">The width.</param> /// <param name="height">The height.</param> /// <param name="centerX">The center x.</param> /// <param name="centerY">The center y.</param> /// <param name="xInverted">When true x increases from left to right, when false otherwise.</param> /// <param name="yInverted">When true y increases from bottom to top, when false otherwise.</param> /// <param name="angleY"></param> public static View2D CreateFromCenterAndSize(double width, double height, double centerX, double centerY, bool xInverted, bool yInverted, Degree angleY) { if(width <= 0) { throw new ArgumentOutOfRangeException("width", "width has to be larger and not equal to zero."); } if(height <= 0) { throw new ArgumentOutOfRangeException("height", "height has to be larger and not equal to zero."); } return new View2D(RectangleF2D.FromBoundsAndCenter(width, height, centerX, centerY, angleY), xInverted, yInverted); }
/// <summary> /// Sets the map view. /// </summary> /// <param name="center">Center.</param> /// <param name="mapTilt">Map tilt.</param> /// <param name="mapZoom">Map zoom.</param> public void SetMapView(GeoCoordinate center, Degree mapTilt, float mapZoom) { //this.MapCenter = center; if (this.Width == 0 || this.MapBoundingBox == null) { _mapCenter = center; } else { _mapCenter = this.Map.EnsureViewWithinBoundingBox(center, this.MapBoundingBox, this.CurrentView); } //this.MapTilt = mapTilt; _mapTilt = mapTilt; //this.MapZoom = mapZoom; if (mapZoom > this.MapMaxZoomLevel) { _mapZoomLevel = this.MapMaxZoomLevel; } else if (mapZoom < this.MapMinZoomLevel) { _mapZoomLevel = this.MapMinZoomLevel; } else { _mapZoomLevel = mapZoom; } _previouslyRenderedView = null; _previouslyChangedView = null; (this.Context as Activity).RunOnUiThread(NotifyMovement); }
/// <summary> /// Creates a new RectangleF2D from given bounds, center and angle. /// </summary> /// <param name="centerX"></param> /// <param name="centerY"></param> /// <param name="width">Width.</param> /// <param name="height">Height.</param> /// <param name="angleY">The angle.</param> /// <returns></returns> public static RectangleF2D FromBoundsAndCenter(double width, double height, double centerX, double centerY, Degree angleY) { return RectangleF2D.FromBoundsAndCenter(width, height, centerX, centerY, VectorF2D.FromAngleY(angleY)); }
/// <summary> /// Substracts the two angles returning an angle in the range -180, +180 /// </summary> /// <param name="angle"></param> /// <returns></returns> public double Subtract180(Degree angle) { return -angle.Range180() + this.Range180(); }
/// <summary> /// Starts an animation to the given parameters. /// </summary> /// <param name="center"></param> /// <param name="zoomLevel"></param> /// <param name="mapTilt"></param> /// <param name="time"></param> public void Start(GeoCoordinate center, float zoomLevel, Degree mapTilt, TimeSpan time) { lock (this) { // stop the previous timer. if (_timer != null) { // timer exists. _timer.Dispose(); _timer = null; } // set the targets. _targetCenter = center; _targetTilt = mapTilt; _targetZoom = zoomLevel; // calculate the animation steps. _maxSteps = (int)System.Math.Round((double)time.TotalMilliseconds / (double)_minimumTimeSpan.TotalMilliseconds, 0); _currentStep = 0; _stepCenter = new GeoCoordinate( (_targetCenter.Latitude - _mapView.MapCenter.Latitude) / _maxSteps, (_targetCenter.Longitude - _mapView.MapCenter.Longitude) / _maxSteps); _stepZoom = (float)((_targetZoom - _mapView.MapZoom) / _maxSteps); // calculate the map tilt, make sure it turns along the smallest corner. double diff = _targetTilt.Subtract180(_mapView.MapTilt); OsmSharp.Logging.Log.TraceEvent ("MapViewAnimator", OsmSharp.Logging.TraceEventType.Information, diff.ToString()); _stepTilt = (diff / _maxSteps); OsmSharp.Logging.Log.TraceEvent("MapViewAnimator", OsmSharp.Logging.TraceEventType.Verbose, string.Format("Started new animation with steps z:{0} t:{1} c:{2} to z:{3} t:{4} c:{5} from z:{6} t:{7} c:{8}.", _stepZoom, _stepTilt, _stepCenter.ToString(), _targetZoom, _targetTilt, _targetCenter.ToString(), _mapView.MapZoom, _mapView.MapTilt, _mapView.MapCenter.ToString())); // disable auto invalidate. //_mapView.AutoInvalidate = false; _mapView.RegisterAnimator (this); // start the timer. _timer = new Timer(new TimerCallback(_timer_Elapsed), null, 0, (int)_minimumTimeSpan.TotalMilliseconds); } }
/// <summary> /// Maps the view map touched. /// </summary> /// <param name="mapView">Map view.</param> /// <param name="newZoom">New zoom.</param> /// <param name="newTilt">New tilt.</param> /// <param name="newCenter">New center.</param> private void MapViewMapTouched(IMapView mapView, float newZoom, Degree newTilt, GeoCoordinate newCenter) { if (newZoom > this.MinZoom) { this.DefaultZoom = System.Math.Min (newZoom, this.MaxZoom); } else { _lastTouch = DateTime.Now.Ticks; } }
/// <summary> /// Starts an animation to a given map tilt that will take the given timespan. /// </summary> /// <param name="mapTilt"></param> /// <param name="time"></param> public void Start(Degree mapTilt, TimeSpan time) { this.Start(_mapView.MapCenter, _mapView.MapZoom, mapTilt, time); }
/// <summary> /// Starts an animation to a given map tilt. /// </summary> /// <param name="mapTilt"></param> public void Start(Degree mapTilt) { this.Start(_mapView.MapCenter, _mapView.MapZoom, mapTilt, _defaultTimeSpan); }
/// <summary> /// Updates the tracker with the given location and angle. /// </summary> /// <param name="location">The measured location.</param> /// <param name="angle">The angle relative to the north measure clockwise.</param> public void Track(GeoCoordinate location, Degree angle) { if (location == null) { throw new ArgumentNullException("location"); } if (_lastTouch.HasValue) { // is tracking disabled now? TimeSpan timeFromLastTouch = new TimeSpan (DateTime.Now.Ticks - _lastTouch.Value); if (timeFromLastTouch.TotalSeconds >= this.RestartAfterTouch.Value) { // ok, the animator has waited long enough. _lastTouch = null; } else { // ok, the animator still has to wait for user-input. return; } } // check if the minimum gap between tracking events is respected. long now = DateTime.Now.Ticks; if (_lastTrack.HasValue) { if (_minimumTrackGap > now - _lastTrack.Value) { return; // too fast! } } _lastTrack = now; // animate the next step(s). TimeSpan lastTrackInterval = new TimeSpan(0, 0, 0, 0, 750); long ticks = DateTime.Now.Ticks; if (_lastTicks.HasValue) { // update the last track interval. lastTrackInterval = TimeSpan.FromTicks(ticks - _lastTicks.Value); } _lastTicks = ticks; OsmSharp.Logging.Log.TraceEvent("RouteTrackerAnimator", OsmSharp.Logging.TraceEventType.Information, "Interval: {0}ms", lastTrackInterval.TotalMilliseconds); // give location to the route tracker. _routeTracker.Track(location); // calculate all map view parameters (zoom, location, tilt) to display the route/direction correctly. float zoom = this.DefaultZoom; GeoCoordinate center = _routeTracker.PositionRoute; double nextDistance = 50; Degree tilt = _mapView.MapTilt; GeoCoordinate next = _routeTracker.PositionAfter(nextDistance); if (next != null) { IProjection projection = _mapView.Map.Projection; VectorF2D direction = new PointF2D(projection.ToPixel(next)) - new PointF2D(projection.ToPixel(center)); tilt = direction.Angle(new VectorF2D(0, -1)); } // overwrite calculated tilt with the given degrees. if (angle != null) { tilt = angle; } OsmSharp.Logging.Log.TraceEvent("RouteTrackerAnimator", OsmSharp.Logging.TraceEventType.Information, "Tracking Event: {0}, {1}, {2}", center, zoom, tilt); // animate to the given parameter (zoom, location, tilt). _animator.Stop(); _animator.Start(center, zoom, tilt, lastTrackInterval.Subtract(new TimeSpan(0, 0, 0, 0, 50))); }
/// <summary> /// Rotate the specified rotation. /// </summary> /// <param name="rotation">Rotation.</param> private void Rotate(UIRotationGestureRecognizer rotation) { //RectangleF2D rect = _rect; RectangleF rect = this.Frame; if (this.MapAllowTilt && rect.Width > 0) { this.StopCurrentAnimation(); if (rotation.State == UIGestureRecognizerState.Ended) { // View2D rotatedView = _mapViewBefore.RotateAroundCenter ((Radian)rotation.Rotation); // _mapTilt = (float)((Degree)rotatedView.Rectangle.Angle).Value; // PointF2D sceneCenter = rotatedView.Rectangle.Center; // _mapCenter = this.Map.Projection.ToGeoCoordinates ( // sceneCenter [0], sceneCenter [1]); this.Change(true); _mapViewBefore = null; } else if (rotation.State == UIGestureRecognizerState.Began) { _mapViewBefore = this.CreateView(rect); } else { //_mapViewBefore = this.CreateView (_rect); View2D rotatedView = _mapViewBefore.RotateAroundCenter((Radian)rotation.Rotation); _mapTilt = (float)((Degree)rotatedView.Rectangle.Angle).Value; PointF2D sceneCenter = rotatedView.Rectangle.Center; _mapCenter = this.Map.Projection.ToGeoCoordinates( sceneCenter[0], sceneCenter[1]); this.InvokeOnMainThread(InvalidateMap); } } }
/// <summary> /// Rotates this rectangle around the given center point with a given angle in clockwise direction. /// </summary> /// <returns>The around.</returns> /// <param name="angle">Angle.</param> /// <param name="center">Center.</param> public RectangleF2D RotateAround(Degree angle, PointF2D center) { PointF2D[] corners = new PointF2D[] { this.TopLeft, this.TopRight, this.BottomLeft, this.BottomRight }; PointF2D[] cornersRotated = Rotation.RotateAroundPoint (angle, center, corners); return new RectangleF2D (cornersRotated [2], this.Width, this.Height, cornersRotated [0] - cornersRotated [2]); }
/// <summary> /// Sets the map view. /// </summary> /// <param name="center">Center.</param> /// <param name="mapTilt">Map tilt.</param> /// <param name="mapZoom">Map zoom.</param> void IMapView.SetMapView(GeoCoordinate center, Degree mapTilt, float mapZoom) { _mapCenter = center; _mapTilt = mapTilt; this.MapZoom = mapZoom; this.InvalidateMapCenter(); this.InvokeOnMainThread(InvalidateMap); }
/// <summary> /// Rotates this rectangle around it's center point with a given angle in clockwise direction. /// </summary> /// <returns>The around center.</returns> /// <param name="angle">Angle.</param> public RectangleF2D RotateAroundCenter(Degree angle) { return this.RotateAround (angle, this.Center); }
/// <summary> /// Creates a view based on a center location a zoomfactor and the size of the current viewport. /// </summary> /// <param name="centerX"></param> /// <param name="centerY"></param> /// <param name="pixelsWidth"></param> /// <param name="pixelsHeight"></param> /// <param name="zoomFactor"></param> /// <param name="xInverted"></param> /// <param name="yInverted"></param> /// <param name="angleY"></param> /// <returns></returns> public static View2D CreateFrom(double centerX, double centerY, double pixelsWidth, double pixelsHeight, double zoomFactor, bool xInverted, bool yInverted, Degree angleY) { double realZoom = zoomFactor; double width = pixelsWidth / realZoom; double height = pixelsHeight / realZoom; return View2D.CreateFromCenterAndSize(width, height, centerX, centerY, xInverted, yInverted, angleY); }
/// <summary> /// Calculates the real distance in meters between this point and the given point. /// </summary> /// <param name="point"></param> /// <returns></returns> /// <remarks>http://en.wikipedia.org/wiki/Haversine_formula</remarks> public Meter DistanceReal(GeoCoordinate point) { Meter radius_earth = Constants.RadiusOfEarth; Radian lat1_rad = new Degree(this.Latitude); Radian lon1_rad = new Degree(this.Longitude); Radian lat2_rad = new Degree(point.Latitude); Radian lon2_rad = new Degree(point.Longitude); double dLat = (lat2_rad - lat1_rad).Value; double dLon = (lon2_rad - lon1_rad).Value; double a = System.Math.Pow(System.Math.Sin(dLat / 2), 2) + System.Math.Cos(lat1_rad.Value) * System.Math.Cos(lat2_rad.Value) * System.Math.Pow(System.Math.Sin(dLon / 2), 2); double c = 2 * System.Math.Atan2(System.Math.Sqrt(a), System.Math.Sqrt(1 - a)); double distance = radius_earth.Value * c; return distance; }
/// <summary> /// Raises the touch event. /// </summary> /// <param name="v">V.</param> /// <param name="e">E.</param> public bool OnTouch(global::Android.Views.View v, MotionEvent e) { try { if (!_renderingSuspended && this.Map != null && this.Map.Projection != null && this.MapCenter != null) { var actionCode = e.Action & MotionEventActions.Mask; switch (actionCode) { case MotionEventActions.Down: _mapView.RaiseMapTouchedDown(); break; case MotionEventActions.Up: _mapView.RaiseMapTouchedUp(); break; } _tagGestureDetector.OnTouchEvent(e); _scaleGestureDetector.OnTouchEvent(e); _rotateGestureDetector.OnTouchEvent(e); _moveGestureDetector.OnTouchEvent(e); if (_deltaX != 0 || _deltaY != 0 || // was there movement? _deltaScale != 1.0 || // was there scale? _deltaDegrees != 0) { // was there rotation? bool movement = false; if (this.MapAllowZoom && _deltaScale != 1.0) { // calculate the scale. double zoomFactor = this.Map.Projection.ToZoomFactor(this.MapZoom); zoomFactor = zoomFactor * _deltaScale; this.MapZoom = (float)this.Map.Projection.ToZoomLevel(zoomFactor); movement = true; } if (this.MapAllowPan) { // stop the animation. this.StopCurrentAnimation(); // recreate the view. View2D view = this.CreateView(); // calculate the new center in pixels. double centerXPixels = this.SurfaceWidth / 2.0f - _deltaX; double centerYPixles = this.SurfaceHeight / 2.0f - _deltaY; // calculate the new center from the view. double[] sceneCenter = view.FromViewPort(this.SurfaceWidth, this.SurfaceHeight, centerXPixels, centerYPixles); // convert to the projected center. this.MapCenter = this.Map.Projection.ToGeoCoordinates(sceneCenter[0], sceneCenter[1]); movement = true; } // do the rotation stuff around the new center. if (this.MapAllowTilt && _deltaDegrees != 0) { // recreate the view. View2D view = this.CreateView(); View2D rotatedView = view.RotateAroundCenter((Degree)(-_deltaDegrees)); _mapTilt = (float)((Degree)rotatedView.Rectangle.Angle).Value; movement = true; } _deltaScale = 1; _deltaDegrees = 0; _deltaX = 0; _deltaY = 0; // notify touch. if (movement) { _mapView.RaiseMapTouched(); _mapView.RaiseMapMove(); this.NotifyMovement(); } } } } catch (Exception ex) { OsmSharp.Logging.Log.TraceEvent("MapViewSurface.OnTouch", TraceEventType.Critical, string.Format("An unhandled exception occured:{0}", ex.ToString())); } return true; }
/// <summary> /// Initializes a new instance of the <see cref="OsmSharp.iOS.UI.MapView"/> class. /// </summary> /// <param name="mapCenter">Map center.</param> /// <param name="map">Map.</param> /// <param name="mapTilt">Map tilt.</param> /// <param name="defaultZoom">Default zoom.</param> public MapView(GeoCoordinate mapCenter, Map map, Degree mapTilt, float defaultZoom) { this.Initialize(mapCenter, map, mapTilt, defaultZoom); }
/// <summary> /// Returns the tile at the given location at the given zoom. /// </summary> /// <param name="latitude">The latitude to create the tile around</param> /// <param name="longitude">The longitude to create the tile around</param> /// <param name="zoom">The zoom level to create the tile at</param> public static Tile CreateAroundLocation(double latitude, double longitude, int zoom) { int n = (int)System.Math.Floor(System.Math.Pow(2, zoom)); Radian rad = new Degree(latitude); int x = (int)(((longitude + 180.0f) / 360.0f) * (double)n); int y = (int)( (1.0f - (System.Math.Log(System.Math.Tan(rad.Value) + (1.0f / System.Math.Cos(rad.Value)))) / System.Math.PI) / 2f * (double)n); return new Tile(x, y, zoom); }
/// <summary> /// Raises the touch event. /// </summary> /// <param name="v">V.</param> /// <param name="e">E.</param> public bool OnTouch(global::Android.Views.View v, MotionEvent e) { _tagGestureDetector.OnTouchEvent (e); _scaleGestureDetector.OnTouchEvent (e); _rotateGestureDetector.OnTouchEvent (e); _moveGestureDetector.OnTouchEvent (e); if (_deltaX != 0 || _deltaY != 0 || // was there movement? _deltaScale != 1.0 || // was there scale? _deltaDegrees != 0) { // was there rotation? bool movement = false; if (this.MapAllowZoom && _deltaScale != 1.0) { // calculate the scale. double zoomFactor = this.Map.Projection.ToZoomFactor(this.MapZoom); zoomFactor = zoomFactor * _deltaScale; this.MapZoom = (float)this.Map.Projection.ToZoomLevel(zoomFactor); movement = true; } if (this.MapAllowPan) { // stop the animation. this.StopCurrentAnimation(); // recreate the view. View2D view = this.CreateView(); // calculate the new center in pixels. double centerXPixels = this.SurfaceWidth / 2.0f - _deltaX; double centerYPixles = this.SurfaceHeight / 2.0f - _deltaY; // calculate the new center from the view. double[] sceneCenter = view.FromViewPort(this.SurfaceWidth, this.SurfaceHeight, centerXPixels, centerYPixles); // convert to the projected center. _mapCenter = this.Map.Projection.ToGeoCoordinates(sceneCenter[0], sceneCenter[1]); movement = true; } // do the rotation stuff around the new center. if (this.MapAllowTilt && _deltaDegrees != 0) { // recreate the view. View2D view = this.CreateView(); View2D rotatedView = view.RotateAroundCenter((Degree)(-_deltaDegrees)); _mapTilt = (float)((Degree)rotatedView.Rectangle.Angle).Value; movement = true; } _deltaScale = 1; _deltaDegrees = 0; _deltaX = 0; _deltaY = 0; // notify touch. if (movement) { _mapView.RaiseMapTouched(); this.NotifyMovement(); } } return true; }
/// <summary> /// Rotate the specified rotation. /// </summary> /// <param name="rotation">Rotation.</param> private void Rotate(UIRotationGestureRecognizer rotation) { CGRect rect = this.Frame; if (this.MapAllowTilt && rect.Width > 0 && this.Map != null) { this.StopCurrentAnimation(); if (rotation.State == UIGestureRecognizerState.Ended) { this.NotifyMovementByInvoke();; _mapViewBefore = null; // raise map touched event. this.RaiseMapTouched(); this.RaiseMapTouchedUp(); } else if (rotation.State == UIGestureRecognizerState.Began) { this.RaiseMapTouchedDown(); _mapViewBefore = this.CreateView(rect); } else { //_mapViewBefore = this.CreateView (_rect); View2D rotatedView = _mapViewBefore.RotateAroundCenter((Radian)(float)rotation.Rotation); _mapTilt = (float)((Degree)rotatedView.Rectangle.Angle).Value; PointF2D sceneCenter = rotatedView.Rectangle.Center; this.MapCenter = this.Map.Projection.ToGeoCoordinates( sceneCenter[0], sceneCenter[1]); this.NotifyMovementByInvoke(); // raise map move event. this.RaiseMapMove(); } } }
/// <summary> /// Creates a new lambert projection. /// </summary> /// <param name="name"></param> /// <param name="ellipsoid"></param> /// <param name="standard_parallel_1"></param> /// <param name="standard_parallel_2"></param> /// <param name="latitude_origin_1"></param> /// <param name="longitude_origin_2"></param> /// <param name="x_origin"></param> /// <param name="y_origin"></param> protected LambertProjectionBase(string name, LambertEllipsoid ellipsoid, double standard_parallel_1, double standard_parallel_2, double latitude_origin_1, double longitude_origin_2, double x_origin, double y_origin) { _name = name; _ellipsoid = ellipsoid; _standard_parallel_1 = standard_parallel_1; Radian temp = new Degree(_standard_parallel_1); _standard_parallel_1_radians = temp.Value; _standard_parallel_2 = standard_parallel_2; temp = new Degree(_standard_parallel_2); _standard_parallel_2_radians = temp.Value; _latitude_origin = latitude_origin_1; temp = new Degree(_latitude_origin); _latitude_origin_radians = temp.Value; _longitude_origin = longitude_origin_2; temp = new Degree(_longitude_origin); _longitude_origin_radians = temp.Value; _x_origin = x_origin; _y_origin = y_origin; // calculate common calculation intermidiates. _m_1 = (System.Math.Cos(_standard_parallel_1_radians) / System.Math.Sqrt((1.0 - _ellipsoid.Eccentricity * _ellipsoid.Eccentricity * System.Math.Pow(System.Math.Sin(_standard_parallel_1_radians), 2.0)))); _m_2 = (System.Math.Cos(_standard_parallel_2_radians) / System.Math.Sqrt((1 - _ellipsoid.Eccentricity * _ellipsoid.Eccentricity * System.Math.Pow(System.Math.Sin(_standard_parallel_2_radians), 2.0)))); _t_0 = (System.Math.Tan(System.Math.PI / 4.0 - _latitude_origin_radians / 2.0) / System.Math.Pow(((1 - _ellipsoid.Eccentricity * System.Math.Sin(_latitude_origin_radians)) / (1 + _ellipsoid.Eccentricity * System.Math.Sin(_latitude_origin_radians))), _ellipsoid.Eccentricity / 2.0)); _t_1 = (System.Math.Tan(System.Math.PI / 4.0 - _standard_parallel_1_radians / 2.0) / System.Math.Pow(((1 - _ellipsoid.Eccentricity * System.Math.Sin(_standard_parallel_1_radians)) / (1 + _ellipsoid.Eccentricity * System.Math.Sin(_standard_parallel_1_radians))), _ellipsoid.Eccentricity / 2.0)); _t_2 = (System.Math.Tan(System.Math.PI / 4.0 - _standard_parallel_2_radians / 2.0) / System.Math.Pow(((1 - _ellipsoid.Eccentricity * System.Math.Sin(_standard_parallel_2_radians)) / (1 + _ellipsoid.Eccentricity * System.Math.Sin(_standard_parallel_2_radians))), _ellipsoid.Eccentricity / 2.0)); _n = ((System.Math.Log(_m_1) - System.Math.Log(_m_2)) / (System.Math.Log(_t_1) - System.Math.Log(_t_2))); _g = _m_1 / (_n * System.Math.Pow(_t_1, _n)); _r_0 = _ellipsoid.SemiMajorAxis * _g * System.Math.Pow(System.Math.Abs(_t_0), _n); }
/// <summary> /// Sets the map view. /// </summary> /// <param name="center">Center.</param> /// <param name="mapTilt">Map tilt.</param> /// <param name="mapZoom">Map zoom.</param> void IMapView.SetMapView(GeoCoordinate center, Degree mapTilt, float mapZoom) { MapCenter = center; MapTilt = mapTilt; MapZoom = mapZoom; this.NotifyMovementByInvoke(); }
/// <summary> /// Raises the touch event. /// </summary> /// <param name="v">V.</param> /// <param name="e">E.</param> public bool OnTouch(global::Android.Views.View v, MotionEvent e) { _tagGestureDetector.OnTouchEvent (e); _scaleGestureDetector.OnTouchEvent (e); _rotateGestureDetector.OnTouchEvent (e); _moveGestureDetector.OnTouchEvent (e); if (_deltaX != 0 || _deltaY != 0 || // was there movement? _deltaScale != 1.0 || // was there scale? _deltaDegrees != 0) { // was there rotation? if (_deltaScale != 1.0) { // calculate the scale. double zoomFactor = this.Map.Projection.ToZoomFactor (this.MapZoom); zoomFactor = zoomFactor * _deltaScale; this.MapZoom = (float)this.Map.Projection.ToZoomLevel (zoomFactor); } // stop the animation. this.StopCurrentAnimation(); //OsmSharp.Logging.Log.TraceEvent("OsmSharp.Android.UI.MapView", System.Diagnostics.TraceEventType.Information, // string.Format("OnTouch:[{0},{1}] {2}s {3}d", _deltaX, _deltaY, _deltaScale, _deltaDegrees)); // recreate the view. View2D view = this.CreateView (); // calculate the new center in pixels. double centerXPixels = this.Width / 2.0f - _deltaX; double centerYPixles = this.Height / 2.0f - _deltaY; // calculate the new center from the view. double[] sceneCenter = view.FromViewPort (this.Width, this.Height, centerXPixels, centerYPixles); // convert to the projected center. this.MapCenter = this.Map.Projection.ToGeoCoordinates (sceneCenter [0], sceneCenter [1]); // do the rotation stuff around the new center. if (_deltaDegrees != 0) { View2D rotatedView = view.RotateAroundCenter ((Degree)(-_deltaDegrees)); _mapTilt = (float)((Degree)rotatedView.Rectangle.Angle).Value; } _deltaScale = 1; _deltaDegrees = 0; _deltaX = 0; _deltaY = 0; // notify touch. _mapView.RaiseMapTouched(); this.NotifyMovement (); } return true; }
/// <summary> /// Sets the map view. /// </summary> /// <param name="center">Center.</param> /// <param name="mapTilt">Map tilt.</param> /// <param name="mapZoom">Map zoom.</param> void IMapView.SetMapView(GeoCoordinate center, Degree mapTilt, float mapZoom) { _mapView.SetMapView(center, mapTilt, mapZoom); }
/// <summary> /// Sets the map view. /// </summary> /// <param name="center">Center.</param> /// <param name="mapTilt">Map tilt.</param> /// <param name="mapZoom">Map zoom.</param> /// <param name="invalidate">If set to <c>true</c> invalidate.</param> public void SetMapView(GeoCoordinate center, Degree mapTilt, float mapZoom, bool invalidate) { _mapCenter = center; _mapTilt = mapTilt; this.MapZoom = mapZoom; if(invalidate) { (this.Context as Activity).RunOnUiThread(Invalidate); this.InvalidateMapCenter(); } }