Ejemplo n.º 1
0
		// Must be true if from new instance of collection
		private void removeAllPins(bool isFromNewCollection)
		{
			if (xMap.pins == null)
				return;

			// Get the segregated pin type by flat value to avoid multiple instance of the same pin to be added
			var mapLockedFeatureCollection = xMap.pins.Where((Pin pin) => pin.IsCenterAndFlat);
			var normalFeatureCollection = xMap.pins.Where((Pin pin) => !pin.IsCenterAndFlat);

			var flatPinsSource = (MGLShapeSource)nStyle.SourceWithIdentifier(mapLockedPinsSourceKey);
			var normalPinsSource = (MGLShapeSource)nStyle.SourceWithIdentifier(normalPinsSourceKey);

			// Just set to empty pins, this will also refreshes with the latest pin and the old pins removed
			flatPinsSource.Shape = MGLShapeCollectionFeature.ShapeCollectionWithShapes(mapLockedFeatureCollection.toShapeSourceArray());
			normalPinsSource.Shape = MGLShapeCollectionFeature.ShapeCollectionWithShapes(normalFeatureCollection.toShapeSourceArray());

			// Usubscribe each pin to change monitoring
			if (xMap.oldPins != null) {
				foreach (var pin in xMap.oldPins)
					pin.PropertyChanged -= Pin_PropertyChanged;
				xMap.oldPins.CollectionChanged -= Pins_CollectionChanged;
			}
			if (isFromNewCollection)
				xMap.pins.CollectionChanged += Pins_CollectionChanged;

			// Subcribe each new pin to change monitoring
			foreach (var pin in xMap.pins)
				pin.PropertyChanged += Pin_PropertyChanged;
		}
        void DrawPolyline()
        {
            var     jsonPath = NSBundle.MainBundle.PathForResource("example", "geojson");
            NSData  data     = NSFileManager.DefaultManager.Contents(jsonPath);
            NSError err;
            MGLShapeCollectionFeature shapeCollectionFeature = (MGLShapeCollectionFeature)MGLShape.ShapeWithData(data, (uint)NSStringEncoding.UTF8, out err);
            MGLPolylineFeature        polyline = (MGLPolylineFeature)shapeCollectionFeature.Shapes.First();

            mapView.AddAnnotation(polyline);
        }
Ejemplo n.º 3
0
		private void updatePins(Pin pin)
		{
			// The image is the type/class key
            string key = pin.image;
            // Find a source that has the same image as this pin
			var uiImage = nStyle.ImageForName(key);
			// Get all pins with the same flat value
			var pinsWithSimilarKey = xMap.pins.Where((Pin arg) => arg.IsCenterAndFlat == pin.IsCenterAndFlat);

			// If there are existing image of the same type the reuse
			if (uiImage != null) {
				MGLShapeSource geoJsonSource;

				// Edit the proper source
				if (pin.IsCenterAndFlat)
					geoJsonSource = (MGLShapeSource)nStyle.SourceWithIdentifier(mapLockedPinsSourceKey);
				else
					geoJsonSource = (MGLShapeSource)nStyle.SourceWithIdentifier(normalPinsSourceKey);

				// Refresh entire source when a pin is added to a specific source
				geoJsonSource.Shape = MGLShapeCollectionFeature.ShapeCollectionWithShapes(pinsWithSimilarKey.toShapeSourceArray());
			}
		}
Ejemplo n.º 4
0
		private void addAllPins()
		{
			if (xMap.pins == null)
				return;

			// Subscribe all pins to their respective changes
			foreach (var pin in xMap.pins)
				pin.PropertyChanged += Pin_PropertyChanged;

			// Add the mapLocked pins first
			// Select all pins where it has heading setter activated
			var mapLockedFeatureCollection = xMap.pins.Where((Pin pin) => pin.IsCenterAndFlat).toShapeSourceArray();

			var mapLockedPinSource = (MGLShapeSource)nStyle.SourceWithIdentifier(mapLockedPinsSourceKey);
			mapLockedPinSource.Shape = MGLShapeCollectionFeature.ShapeCollectionWithShapes(mapLockedFeatureCollection);

			// Add the normal pins after
			// Select all pins where it has heading disabled
			var normalFeatureCollection = xMap.pins.Where((Pin pin) => !pin.IsCenterAndFlat).toShapeSourceArray();

			var normalPinSource = (MGLShapeSource)nStyle.SourceWithIdentifier(normalPinsSourceKey);
			normalPinSource.Shape = MGLShapeCollectionFeature.ShapeCollectionWithShapes(normalFeatureCollection);
		}
Ejemplo n.º 5
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
		}
Ejemplo n.º 6
0
 public static MGLShapeCollectionFeature toShapeCollectionFeature(this IEnumerable <Route> routes)
 {
     return(MGLShapeCollectionFeature.ShapeCollectionWithShapes(routes.toFeatureList().ToArray()));
 }