Question

I have an application with a sqlite database that contains 7000+ records in it with city names, longitudes and latitudes.. also these "cities" are connected to relevant city fields on the database too.

What my app doing is, query the current location with core location, fetch the lon and lat values, and then find the closest location from the database.

The result doesn't have to be super accurate (i just want to match cities), so I want to use Hypotenuse formula for finding the closest point:

closest city in db: min((x1-x2)^2 +(y1-y2)^2)^(1/2)

x1, y1: lon and lat for user
x2, y2: lon and lat for points in database. 

If I was using ms-sql or sqlite database, I could easily create a query but when it comes to core data, I'm out of ideas.

I don't want to fetch all the data (and fill the memory) then aggregate this formula on all fields so is there a way to create a query and get the result from the db?

Am I overthinking this problem, and missing a simple solution?

Was it helpful?

Solution

If I'm understanding your problem correctly, you're wanting to find the closest "n" cities to your current location.

I had something similar and here's how I approached it.

In essence, you probably need to take each city's lat/lon and hash it into some index. We use a Mercator Projection to convert the lat/lon to x/y, then hash that value in a manner similar to how Google/Bing/Apple Maps hash their map tiles. Fortunately, MapKit has a built-in Mercator Projection function.

In pseudocode:

for each city's lat/lon {
    CLLocationCoordinate2D coordinate = (CLLocationCoordinate2D){lat, lon};
    MKMapPoint point = MKMapPointForCoordinate(coordinate);
    //256 represents the size of a map tile at zoomLevel 20.  You can use whatever zoomLevel 
    //you want here, but we need something to quickly lookup close-by cities.
    //this is the formula you can use to determine how granular your index is
    //(256 * pow(2, (20 - zoomLevel)))
    NSInteger x = point.x/256.0;
    NSInteger y = point.y/256.0;
    save x & y in a CityHashIndex table
}

Now, you get the current location's lat/lon, hash that into the index as above, and just simply write a query against this CityHashIndex table.

So say that, for simplicity sake, you're current location is indexed at 1000, 1000. So to find close by cities, maybe you search for cities with indexes in the range of `900-1100, 900-1100'.

From there, you're now only pulling in a much smaller set of cities and the memory requirements to process your Hypotenuse Formula isn't so bad.

I can elaborate more if you're interested.

OTHER TIPS

This is directly related to a commonly asked question about Core Data.

Searching for surrounding suburbs based on latitude & longitude using Objective C

Calculate a bounding box around the point you need (min lat/long max lat/long) then use an NSPredicate against those values to find everything within the box. From there you can do a distance calculation on the results that return and sort them.

I would suggest setting this up so that it can search at multiple distances then you can see if a city is within 10 miles, 100 miles, etc. Slowly increasing the bounding box until you get one or more results back.

I would use NSPredicate to define my search criteria it will act as a filter. I'm not sure how optimized is this and if it will pull all your registers but I'm assuming that coreData has some kind of indexing mechanism that will optimize the search.

You can take a look of this document

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdFetching.html

Check the section named

Retrieving Specific Objects

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top