public void setRouteIncreaseForward(LatLng endLatLng)
 {
     if (endLatLng == null)
     {
         return;
     }
     if (_marker != null)
     {
         if (NeedUpdateRotation())
         {
             var heading = SphericalUtil.computeHeading(_marker.Position, endLatLng);
             heading = heading + 180;
             //if (Options.HeadingConverter != null)
             //    heading = Options.HeadingConverter(heading);
             double mapHeading = 0;
             if (_googleMap?.CameraPosition != null)
             {
                 mapHeading = -_googleMap.CameraPosition.Bearing;
             }
             _marker.Rotation     = (float)heading + (float)mapHeading;
             _lastUpdatedLocation = endLatLng;
         }
         _marker.Position = endLatLng;
     }
 }
예제 #2
0
        public void Run()
        {
            long  elapsed = SystemClock.UptimeMillis() - _start;
            float t       = _interpolator.GetInterpolation((float)elapsed
                                                           / (float)_duration);
            double lng = t * _toPosition.Longitude + (1 - t)
                         * _startPosition.Longitude;
            double lat = t * _toPosition.Latitude + (1 - t)
                         * _startPosition.Latitude;

            var endLatLng = new LatLng(lat, lng);

            if (NeedUpdateRotation())
            {
                var heading = SphericalUtil.computeHeading(_marker.Position, endLatLng);
                heading = heading + 180;
                //if (Options.HeadingConverter != null)
                //    heading = Options.HeadingConverter(heading);
                double mapHeading = 0;
                if (_gMap?.CameraPosition != null)
                {
                    mapHeading = -_gMap.CameraPosition.Bearing;
                }
                _marker.Rotation     = (float)heading + (float)mapHeading;
                _lastUpdatedLocation = endLatLng;
            }

            _marker.Position = endLatLng;

            if (t < 1.0)
            {
                // Post again 16ms later.
                _handler.PostDelayed(this, 16);
            }
            else
            {
                _endAction?.Invoke();
            }
            //else
            //{
            //    if (hideMarker)
            //    {
            //        marker.Visible = false;
            //    }
            //    else
            //    {
            //        marker.Visible = true;
            //    }
            //}
        }
예제 #3
0
		/// <summary>
		/// This has a problem, if the same pin updates a couple of times a second pin might jump suddenly to the
		/// 2nd to latest position then smooth animate to the latest position, but I think this is ok logically since
		/// By the time it's animating its final animation position is not really up to date.
		/// </summary>
		/// <param name="pin">Pin.</param>
		private void animateLocationChange(Pin pin)
		{
			#region Simultaneous pin update
			System.Threading.Tasks.Task.Run(async () => {
				// If there exist a pin that caused this update
				if (isPinAnimating)
					return;

				//// Wait for pin position assignment in the same call
				isPinAnimating = true;

				// Get all pins with the same key and same flat value (animatable pins)
				var pinsWithSimilarKey = xMap.pins.Where(
					(Pin arg) => arg.IsCenterAndFlat == pin.IsCenterAndFlat).ToArray();

				Device.BeginInvokeOnMainThread(() => {
					var geoJsonSource = (MGLShapeSource)nStyle.SourceWithIdentifier(mapLockedPinsSourceKey);

					var visibleMovablePinCount = pinsWithSimilarKey.Count(p => p.isVisible);
					var currentHeadingCollection = new double[visibleMovablePinCount];
					var features = new NSObject[visibleMovablePinCount];

					// Update the entire frame
					MapBox.Extensions.MapExtensions.animatePin(
						(double d) => {
							System.Threading.Tasks.Task.Run(() => {
								for (int i = 0; i < visibleMovablePinCount; i++) {
									var p = pinsWithSimilarKey[i];
									Position theCurrentAnimationJump = p.position;
									double theCurrentHeading = p.heading;

									// Only update the pin if it is the pin that cause this animation call
									// OR the if it actually requested for a position update before this current animation has not been finished
									if (pin == p || p.requestForUpdate) {
										theCurrentAnimationJump = SphericalUtil.interpolate(p.previousPinPosition, p.position, d);
										theCurrentHeading = SphericalUtil.computeHeading(p.previousPinPosition, p.position);
									}
									currentHeadingCollection[i] = theCurrentHeading;

									var feature = new MGLPointFeature {
										Coordinate = new CLLocationCoordinate2D(theCurrentAnimationJump.latitude,
																				theCurrentAnimationJump.longitude)
									};
									feature.Attributes = NSDictionary<NSString, NSObject>.FromObjectsAndKeys(
										new object[] {
                                                p.image,
												theCurrentHeading,
												p.imageScaleFactor,
												p.id
										},
										new object[] {
												MapboxRenderer.pin_image_key,
												MapboxRenderer.pin_rotation_key,
												MapboxRenderer.pin_size_key,
												MapboxRenderer.pin_id_key
										});

									// Add to the new animation frame
									features[i] = feature;
								}

								// Update the entire layer
								Device.BeginInvokeOnMainThread(() => geoJsonSource.Shape = MGLShapeCollectionFeature.ShapeCollectionWithShapes(features));
							});
						},
						async (d, b) => {
							// DO NOT REMOVE, this is essential for the simultaneous pin location update to work
							await System.Threading.Tasks.Task.Delay(500);

							isPinAnimating = false;

							// Stabilize the pins, at this moment all the pins are updated
							for (int i = 0; i < visibleMovablePinCount; i++) {
								var p = pinsWithSimilarKey[i];
								// To avoid triggering heading property change event
								p.PropertyChanged -= Pin_PropertyChanged;
								p.requestForUpdate = false;
								p.heading = currentHeadingCollection[i];
								p.PropertyChanged += Pin_PropertyChanged;
							}
						}, 500);
				});
			});
			#endregion
		}
예제 #4
0
        /// <summary>
        /// This has a problem, if the same pin updates a couple of times a second pin might jump suddenly to the
        /// 2nd to latest position then smooth animate to the latest position, but I think this is ok logically since
        /// By the time it's animating its final animation position is not really up to date.
        /// </summary>
        /// <param name="pin">Pin.</param>
        private void animateLocationChange(Pin pin)
        {
            #region Simultaneous pin update
            System.Threading.Tasks.Task.Run(async() => {
                // If there exist a pin that caused this update
                if (isPinAnimating)
                {
                    return;
                }

                // Wait for pin position assignment in the same call
                isPinAnimating = true;

                // Get all pins with the same key and same flat value (animatable pins)
                var pinsWithSimilarKey = xMap.pins.Where(
                    (Pin arg) => arg.IsCenterAndFlat == pin.IsCenterAndFlat).ToArray();

                Device.BeginInvokeOnMainThread(() => {
                    var geoJsonSource = (GeoJsonSource)nMap.GetSource(mapLockedPinsSourceKey);

                    var visibleMovablePinCount   = pinsWithSimilarKey.Count(p => p.isVisible);
                    var currentHeadingCollection = new double[visibleMovablePinCount];
                    var features = new Feature[visibleMovablePinCount];

                    // Update the entire frame
                    MapBox.Extensions.MapExtensions.animatePin(
                        (double d) => {
                        System.Threading.Tasks.Task.Run(() => {
                            for (int i = 0; i < visibleMovablePinCount; i++)
                            {
                                var p = pinsWithSimilarKey[i];
                                Position theCurrentAnimationJump = p.position;
                                double theCurrentHeading         = p.heading;

                                // Only update the pin if it is the pin that cause this animation call
                                // OR the if it actually requested for a position update before this current animation has not been finished
                                if (pin == p || p.requestForUpdate)
                                {
                                    theCurrentAnimationJump = SphericalUtil.interpolate(p.previousPinPosition, p.position, d);
                                    theCurrentHeading       = SphericalUtil.computeHeading(p.previousPinPosition, p.position);
                                }
                                currentHeadingCollection[i] = theCurrentHeading;

                                var feature = Feature.FromGeometry(
                                    Com.Mapbox.Geojson.Point.FromLngLat(theCurrentAnimationJump.longitude,
                                                                        theCurrentAnimationJump.latitude));
                                feature.AddStringProperty(MapboxRenderer.pin_image_key, p.image);
                                feature.AddNumberProperty(MapboxRenderer.pin_rotation_key, (Java.Lang.Number)theCurrentHeading);
                                feature.AddNumberProperty(MapboxRenderer.pin_size_key, (Java.Lang.Number)p.imageScaleFactor);
                                feature.AddStringProperty(MapboxRenderer.pin_id_key, p.id);

                                // Add to the new animation frame
                                features[i] = feature;
                            }

                            // Extension method bypass, fromFeatures accepts IList as parameter
                            var featureCollection = FeatureCollection.FromFeatures(features);

                            // Update the entire layer
                            Device.BeginInvokeOnMainThread(() => geoJsonSource.SetGeoJson(featureCollection));
                        });
                    },
                        async(d, b) => {
                        // DO NOT REMOVE, this is essential for the simultaneous pin location update to work
                        await System.Threading.Tasks.Task.Delay(500);

                        isPinAnimating = false;

                        // Stabilize the pins, at this moment all the pins are updated
                        for (int i = 0; i < visibleMovablePinCount; i++)
                        {
                            var p = pinsWithSimilarKey[i];
                            // To avoid triggering heading property change event
                            p.PropertyChanged -= Pin_PropertyChanged;
                            p.requestForUpdate = false;
                            p.heading          = currentHeadingCollection[i];
                            p.PropertyChanged += Pin_PropertyChanged;
                        }
                    }, 500);
                });
            });
            #endregion
        }