1

Here is the scenario that I need to implement:

Assume that I have a database table that contains Latitudes and Longitudes of all the restaurants of my city, say 500 restaurants. Now I am standing somewhere in the city using my app and want to know my nearby restaurants, say within 10 miles radius.

To achieve this, the app must first know my current location (I have done that). Once my location is known, the app needs to put markers on all the restaurants that are within 10 miles (assume only 25 out of the total 500). I do not need to show the markers for those which are farther than that. Now when I click on any marker I will see the InfoWindow and then clicking on it I need to navigate to a new activity and show some details like address, name, phone number (these all come from database) and its distance from my current location.

Now my two questions:

  1. I need to show markers only within the given radius and not the rest of those. I too don't want to draw a circle on map. Do I have to traverse all locations and see which lie within the radius or is there a faster and more efficient way?
  2. Can I have the option of getting both straight-line as well as road distances for all my markers?
Ahmed Salman Tahir
  • 1,783
  • 1
  • 17
  • 26

2 Answers2

1

Write a method in your BI that gives you all the restaurants between the bounds of the Map (or within a given distance from the center (LatLon) of the Map. I used to do it embedding a custom function in Sqlite

[SqliteFunctionAttribute(Name = "distance", Arguments = 4, FuncType = FunctionType.Scalar)]
class SqliteDistance : SqliteFunction
{
    public override object Invoke(object[] args)
    {
       double latA = System.Convert.ToDouble(args[0]);
       double lonA = System.Convert.ToDouble(args[1]);
       double latB = System.Convert.ToDouble(args[2]);
       double lonB = System.Convert.ToDouble(args[3]);



       const double R = 6371;
       const double pigreco = 3.1415927;
       double lat_alfa, lat_beta;
       double lon_alfa, lon_beta;
       double fi;
       double p, d;
       /* Converte i gradi in radianti */
       lat_alfa = pigreco * latA / 180;
       lat_beta = pigreco * latB / 180;
       lon_alfa = pigreco * lonA / 180;
       lon_beta = pigreco * lonB / 180;
       /* Calcola l'angolo compreso fi */
       fi = Math.Abs(lon_alfa - lon_beta);
       /* Calcola il terzo lato del triangolo sferico */
       p = Math.Acos(Math.Sin(lat_beta) * Math.Sin(lat_alfa) +
         Math.Cos(lat_beta) * Math.Cos(lat_alfa) * Math.Cos(fi));
       /* Calcola la distanza sulla superficie 
       terrestre R = ~6371 km */
       d = p * R;
       return (d);

    }

}

then in your query :

Public List<Restaurant> GiveMeRestaurants(double fromLat, double fromLon)
{
String sql="Select * from restaurants where distance('" + fromLat.ToString() + "','" + fromLon.ToString() + "',restaurants.Latitude,restaurants.Longitude) <= 100 )";


}

This can give you also the straight line distance.

  1. For road distance maybe you can call google play services using the center map and the coordinates or the restaurant
Luca V
  • 26
  • 6
  • Thanks Luca for this. First, can you please change the comments in your code to English so that I can understand it a bit more? :) Secondly, if I write this in my BI, I will have to call it 500 times, i.e. for every restaurant, and then see whether it lies within my radius or not, correct? – Ahmed Salman Tahir Dec 30 '13 at 17:04
  • Don't mind the comments, they simply explain the steps for calculate geodetic distance between two points on the hearth :) No, you haven't to call it 500 times. Is a single query that returns all the restaurants in a range (of 100 km in this case) from the center point you set(the ceneter of the map showed). When the user pan the map, the center will change, and you'll have to re-execute the query and show the new restaurants on the map. :) – Luca V Dec 31 '13 at 09:30
  • But as this method is in BI instead of database, won't I always have to fetch all 500 restaurants from database and then filter them on BI (i.e. actually calling this method for all of them) and then the web service handing over the filtered list to the app? – Ahmed Salman Tahir Dec 31 '13 at 09:55
  • In sqlite the only way to attach a custom function (i.e. the distance function) is to write it in a class. (if you don't want to recompile sqlite..), so, from your class that reads from the db you will return a list of restaurants to the map (no need to fetch all restaurants).Write a method that gives you only the restaurants returned by the query. It's not a good approach to maintain all the restaurants in memory. If you have all your restaurant in memory take a look to LINQ, you can achieve the same result. – Luca V Dec 31 '13 at 14:18
  • As I'm not using sqlite at all in my app so I guess I will always have to call the method for every restaurant, right? By the way, I am assuming that the returned distance is in km, correct? – Ahmed Salman Tahir Dec 31 '13 at 14:22
  • Uh, you said that you have a database table :). Yes the distance are in Km in this case, where do you you store the 500 restaurants? – Luca V Dec 31 '13 at 14:24
  • Oh sorry for the confusion. I do have an online database that contains those restaurants' LatLng. I have written web service over that database – Ahmed Salman Tahir Dec 31 '13 at 14:26
0

So you can move this logic in the webservice or do it via LINQ

take a look here Is there a simple way to write a custom function in LINQ to Entities?

Community
  • 1
  • 1
Luca V
  • 26
  • 6