4

I'm querying my server for a list of locations that are closest to the user based on his observable portion of the mapview.

I'm not entirely sure on how to do this, but should I send the center lat and long of the mapview's visible region and then search for results based on nearest radius?

I know that MKMapView has two properties called region and visibleMapRect. Should I use one of those, and if so, which one is more appropriate based on my question?

EDIT I'm looking to implement functionality that's identical to the apple maps and Yelp app when you search for nearby locations and it shows you what's relevant based off the visible portion of the map view.

EDIT 2 I have seen a lot of people break up the visible portion of their mapview into quadrants, most commonly NW,NE,SW and SE. However, I'm still not entirely sure why theyr'e doing this. I would like to know the best way to query the back end, which contains a lat and long for each location, to find the locations which exist on the mapview.

I have looked everywhere on stackoverflow and I found a similar question here. However, it doesn't answer my question and there's no mention of visibleMapRect because it's over 5 years old.

Any help is tremendously appreciated.

Community
  • 1
  • 1
Mihado
  • 1,487
  • 3
  • 17
  • 30
  • So do you location manager working at least? – Nicholas Mata Feb 09 '16 at 22:49
  • Of course it works. The list of locations are stored server side in a mysql db. Additionally, my question has nothing to do with whether location manager is set up, it's a matter of how to retrieve locations store server side based on the viewable portion of the mkmapview. – Mihado Feb 09 '16 at 22:50
  • My answer if based off the fact that you have location manager working because you want to display locations that are around there current location right? – Nicholas Mata Feb 09 '16 at 23:18
  • Not necessarily around the current location of the user, but rather wherever he is viewing the map. For example, my location could be in los angeles, but if I scroll up to san francisco, it'll update the locations that i'm viewing. Does that make sense? – Mihado Feb 09 '16 at 23:20

2 Answers2

4

So you would need to provide your server call with these 2 coord bottomleft and topright 4 points all together.

  1. if lat of location > bottomleft.lat and if lat of location < topright.lat
  2. if long of location > bottomleft.long and if long of location < topright.long

iOS Code would look like this the make server call with these four variables as parameters

fun viewDidLoad() {
   super.viewDidLoad()
   self.mapView.delegate = self
}


func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
   // Using region
   var span: MKCoordinateSpan = mapView.region.span
   var center: CLLocationCoordinate2D = mapView.region.center

   // This is the farthest Lat point to the left
   var farthestLeft = center.latitude - span.latitudeDelta * 0.5
   // This is the farthest Lat point to the Right
   var farthestRight = center.latitude + span.latitudeDelta * 0.5
   // This is the farthest Long point in the Upward direction
   var farthestTop = center.longitude - span.longitudeDelta * 0.5
   // This is the farthest Long point in the Downward direction
   var farthestBottom = center.longitude + span.longitudeDelta * 0.5
   var SWCoord = MKCoordinateForMapPoint(farthestBottom, farthestLeft)
   var NECoord = MKCoordinateForMapPoint(farthestTop, farthestRight)


   // Using visibleMapRect
   var mapRect = mapView.visibleMapRect
   // This is the top right Coordinate
   var NECoord = getCoordinateFromMapRectanglePoint(MKMapRectGetMaxX(mapRect), y: mapRect.origin.y)
   // This is the bottom left Coordinate
   var SWCoord = getCoordinateFromMapRectanglePoint(mapRect.origin.x, y: MKMapRectGetMaxY(mapRect))
   // Not needed but could be useful
   // var NWCoord = getCoordinateFromMapRectanglePoint(MKMapRectGetMinX(mapRect), y: mapRect.origin.y)
   // var SECoord = getCoordinateFromMapRectanglePoint(MKMapRectGetMaxX(mapRect), y: MKMapRectGetMaxY(mapRect))


}

func getCoordinateFromMapRectanglePoint(x: Double, y: Double) -> CLLocationCoordinate2D {
   var mapPoint = MKMapPointMake(x, y)
   return MKCoordinateForMapPoint(mapPoint)
}

If you have anymore questions just comment

Nicholas Mata
  • 796
  • 1
  • 9
  • 19
  • Why are you not using visibleMapRect, wouldn't that make it easier? – Mihado Feb 09 '16 at 23:20
  • This property represents the same basic information as the region property but specified as a map rectangle instead of a region. If you like you can you use visibleMapRect instead it is the same thing you will still have to get the 4 bounding points – Nicholas Mata Feb 09 '16 at 23:24
  • Can you please edit the code to use either region or visibleMapRect? Right now you're basing it off of where the user is, which doesn't answer my question. Afterwards I'd be happy to award you the points. – Mihado Feb 09 '16 at 23:33
  • This looks like what I want. I have yet to implement it because I have the flu. But if I have any additional questions i'll let you know. 50 points for you. Thank you Jack! – Mihado Feb 10 '16 at 20:41
1

EDIT 2 I have seen a lot of people break up the visible portion of their mapview into quadrants, most commonly NW,NE,SW and SE. However, I'm still not entirely sure why theyr'e doing this. I would like to know the best way to query the back end, which contains a lat and long for each location, to find the locations which exist on the mapview.

I'm not sure if this is what you're referring to but they could be using quadtrees as a way to efficiently search the locations of a huge amount of coordinates.

This post from Thoughtbot demonstrates how to use quadtrees to display thousands of place coordinates as clusters on the map and it includes gifs that very succinctly explain how it works:

enter image description here enter image description here

A quad tree is a data structure comprising nodes which store a bucket of points and a bounding box. Any point which is contained within the node’s bounding box is added to its bucket. Once the bucket gets filled up, the node splits itself into four nodes, each with a bounding box corresponding to a quadrant of its parents bounding box. All points which would have gone into the parent’s bucket now go into one of its children’s buckets.

Source: How To Efficiently Display Large Amounts of Data on iOS Maps

Benjamin Cheah
  • 1,401
  • 17
  • 23