1

I want to be able to display a Bing map in a Windows 8/Store app with an array of pushpins/waypoints at a zoom setting that will show every location, but no more than that - IOW, I want as much detail as possible while still showing all of the locations/coordinates.

I have this pseudocode:

public static int GetMapZoomSettingForCoordinates(List<String> coordinatesList)
{
    string furthestNorth = GetFurthestNorth(coordinatesList);
    string furthestSouth = GetFurthestSouth(coordinatesList);
    string furthestEast = GetFurthestEast(coordinatesList);
    string furthestWest = GetFurthestWest(coordinatesList);
    int milesBetweenNorthAndSouthExtremes = GetMilesBetween(furthestNorth, furthestSouth);
    int milesBetweenEastAndWestExtremes = GetMilesBetween(furthestEast, furthestWest);
    int greaterCardinalDistance = Math.Max(milesBetweenNorthAndSouthExtremes, milesBetweenEastAndWestExtremes);
    return GetZoomSettingForDistance(greaterCardinalDistance);
}

...but the "sticking point" (the hard part) are the "milesBetween" functions. Is there an existing algorithm for computing the miles between two coordinates?

I do realize this is a U.S.-centric bunch of code for now (miles vs. kilometers); that is, for now, as designed.

UPDATE

This is my new pseudocode (actual compiling code, but untested):

public static int GetMapZoomSettingForCoordinates(List<string> coordinatePairsList)
{
    List<double> LatsList = new List<double>();
    List<double> LongsList = new List<double>();
    List<string> tempList = new List<string>();

    foreach (string s in coordinatePairsList)
    {
        tempList.AddRange(s.Split(';'));
        double dLat;
        double.TryParse(tempList[0], out dLat);
        double dLong;
        double.TryParse(tempList[0], out dLong);
        LatsList.Add(dLat);
        LongsList.Add(dLong);
        tempList.Clear();
    }

    double furthestNorth = GetFurthestNorth(LatsList);
    double furthestSouth = GetFurthestSouth(LatsList);
    double furthestEast = GetFurthestEast(LongsList);
    double furthestWest = GetFurthestWest(LongsList);
    int milesToDisplay = 
        HaversineInMiles(furthestWest, furthestNorth, furthestEast, furthestSouth);
    return GetZoomSettingForDistance(milesToDisplay);
}

private static double GetFurthestNorth(List<double> longitudesList)
{
    double northernmostVal = 0.0;
    foreach (double d in longitudesList)
    {
        if (d > northernmostVal)
        {
            northernmostVal = d;
        }
    }
    return northernmostVal;
}

...I still don't know what GetZoomSettingForDistance() should be/do, though...

UPDATE 2

This is "more better":

public static int GetMapZoomSettingForCoordinates(List<Tuple<double, double>> coordinatePairsList)
{
    var LatsList = new List<double>();
    var LongsList = new List<double>();

    foreach (Tuple<double,double> tupDub in coordinatePairsList)
    {
        LatsList.Add(tupDub.Item1);
        LongsList.Add(tupDub.Item2);
    }

    double furthestNorth = GetFurthestNorth(LongsList);
    double furthestSouth = GetFurthestSouth(LongsList);
    double furthestEast = GetFurthestEast(LatsList);
    double furthestWest = GetFurthestWest(LatsList);
    int milesToDisplay =
        HaversineInMiles(furthestWest, furthestNorth, furthestEast, furthestSouth); 
    return GetZoomSettingForDistance(milesToDisplay);
}

UPDATE 3

I realized that my logic was backwards, or wrong, at any rate, regarding meridians of longitude and parallels of latitude. While it's true that meridians of longitude are the vertical lines ("drawn" North-to-South or vice versa) and that parallels of latitude are the horizontal lines ("drawn" East-to-West), points along those line represent the North-South location based on parallels of latitude, and represent East-West locations based on meridians of longitude. This seemed backwards in my mind until I visualized the lines spinning across (longitude) and up and over (latitude) the earth, rather than simply circling the earth like the rings of Saturn do; what also helped get my perception right was reminding myself that it is the values of the meridians of longitude that determine in which time zone one finds themselves. SO, the code above should change to pass latitudes to determine furthest North and furthest South, and conversely pass longitudes to determine furthest East and furthest West.

rbrundritt
  • 16,570
  • 2
  • 21
  • 46
B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • 1
    Just to make sure, you're looking for a "straight line" distance between two points, not the length of a path using roads from location A to location B? – emartel Nov 21 '12 at 19:35
  • 1
    Are these coordinates in the form of latitude and longitude? If so: http://stackoverflow.com/questions/365826/calculate-distance-between-2-gps-coordinates – Jeff Nov 21 '12 at 19:56
  • emartel: yes, straight line. Jeff E: Yes. Thanks. – B. Clay Shannon-B. Crow Raven Nov 21 '12 at 22:56
  • I don't think you mean straight line. You mean arc across the surface of the earth? :) – Kieren Johnstone Nov 21 '12 at 23:13
  • What I actually mean is "as the crow flies." I don't really care about the exact distance, I just want to show all of the locations on the map while also showing as much detail as possible - narrowing in to the point where the furthest points in each direction are as close to the edges of the map as possible. – B. Clay Shannon-B. Crow Raven Nov 22 '12 at 15:14

2 Answers2

2

You can use the Haversine formula to compute the distance along the surface of a sphere.

Here's a C++ function to compute the distance using the Earth as the size of the sphere. It would easily be convertible to C#.

Note that the formula can be simplified if you want to just find the distance either latitudinally or longitudinally (which it sounds like you are trying to do).

Gabe
  • 84,912
  • 12
  • 139
  • 238
D Stanley
  • 149,601
  • 11
  • 178
  • 240
-6

To get the straight line distance you use the Pythagorean Theorem to find the hypotenuse.

d = ((delta x)^2 + (delta y)^2)^.5

Basically square both the changes in the x direction and the y direction, add them, then take the square root.

in your pseudo code it looks like you could have many points and you want to find a maximum distance that should encompass all of them, which makes sense if you are trying to figure out a scale for the zoom of the map. The same formula should work, just use milesBetweenEastAndWestExtremes for delta x, and milesBetweenNorthAndSouthExtremes for delta y. You may opt to add a fixed amount to this just to make sure you don't have points right on the very edge of the map.

GC78
  • 126
  • 9