2

So I am working on a project that includes many uses placing annotations all around a map. The annotation, (which is a custom image with a much larger circular range) appears on the screen and, ideally, I would like for a user to be:

  1. Notified if they are within the range of a annotation and
  2. Not be allowed to place another annotation within the range of another one if the circular pins overlap by, say, more than 25%

I think this is a pretty unique question and should be fun for somebody to help out with, so have fun! Thanks everybody!

Ethan
  • 1,905
  • 2
  • 21
  • 50
  • 1
    As a general pointer, look up GeoFencing – LuigiPower Jul 22 '16 at 17:14
  • 1
    Or, more specifically, with MapKit, look at [Monitoring Geographical Regions](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/RegionMonitoring/RegionMonitoring.html#//apple_ref/doc/uid/TP40009497-CH9-SW2) in the _Location and Maps Programming Guide._ Note, I believe there are a finite number of regions that you can simultaneously monitor, but it's a possible approach. But the right solution, as discussed by others, is likely to be just using `CLLocation`'s `distanceFromLocation` method. – Rob Jul 22 '16 at 19:17
  • Thanks for chiming in @Rob I'll take a look at this now! – Ethan Jul 22 '16 at 19:19

2 Answers2

5

You can check the distance from each annotation using

- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location

This method measures the distance between the two locations by tracing a line between them that follows the curvature of the Earth. The resulting arc is a smooth curve and does not take into account specific altitude changes between the two locations.

For more details refer Link

AtWork
  • 1,283
  • 1
  • 14
  • 34
  • @user154248 Updated – AtWork Jul 22 '16 at 17:22
  • Hmmm this may work. The problem is that all of the annotation coordinates are going to be coming from a server. This would mean that there would be no constant second set of coordinates to measure the distance with. I wonder if this can be adapted into some sort of scanner to check for for annotations within the screen only. – Ethan Jul 22 '16 at 17:26
  • You can draw a circle with whatever range you want to set initially mark its center point and then every time you get new location object from server , you pass it in the above method using your center location object and server location object. _**CLLocationDistance distance = [centerInitialLocation distanceFromLocation:serverLocation];**_ – AtWork Jul 22 '16 at 17:38
  • Okay, I'm making it work. How can I take all of the pins within the range at once? Like is there some way I can pass something like `Annotation.withReuseIdentifiyer("pin")` into the second parameter? – Ethan Jul 22 '16 at 18:28
  • Or even by checking the title of the annotation, because the titles are all the same – Ethan Jul 22 '16 at 18:28
  • Title doesn't matter for dropping the annotation, its the CLLocationCoordinate2D object that contains the value for **CLLocationDegrees latitude; CLLocationDegrees longitude**. – AtWork Jul 22 '16 at 18:38
  • I know, but the issue is that I could have 4 or 5 annotations on the screen at any one time. Any they all need to be measured at once when a button is pressed. – Ethan Jul 22 '16 at 18:39
  • Store all the annotations in an array and run the loop checking all the annotation one at a a time on single button click. – AtWork Jul 22 '16 at 18:40
  • I'm having trouble appending the coordinate to a `Double` array. The main issue is that `append, insert, +=` etc isn't working – Ethan Jul 22 '16 at 19:18
  • Can you try collecting the **CLLocationCoordinate2D** object into **NSMutableArray** and not individual lat-long values. This way you can access them when you want to by **CLLocationCoordinate2D** coordinate property. – AtWork Jul 22 '16 at 19:25
  • Well what I was actually doing was trying to append the center of the users location to the array, and then factor in the overall size of the annotation into the measured distance. The center is acquired by doing this: `let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)` – Ethan Jul 22 '16 at 21:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/118067/discussion-between-user154248-and-atwork). – Ethan Jul 22 '16 at 22:37
1

Try this:

let location = CLLocation(latitude: 1, longitude: 1)//Or user's location
let distance = location.distance(from: anotherLocation)

Edit:

As mentioned in the comments, you wanted to create an equidistant point. I suggest manually doing that:

Subtract the annotation's location from he user's location. Then add your distance back to the original one. For example:

The user's location = (1, 1)

The annotation's location = (3, 2)

Vertical difference would be 2

Horizontal difference would be 1

Then:

(3 + 2, 2 + 1)

Your result: (5, 3)

Now you would have two points (the one you just created and the user's location) at each end with a center point (original annotation)

Pranav Wadhwa
  • 7,666
  • 6
  • 39
  • 61
  • I think location and distance would have to be var's, and I wonder if I can set the distance equal to an annotation within the location coordinates plus a tolerance with a specific reusable identifier? Maybe? – Ethan Jul 22 '16 at 17:31
  • You don't need them to be vars. This would be called every time you update the location (locationDidUpdate method). I edited my question based on the new point. – Pranav Wadhwa Jul 22 '16 at 19:32