Search code examples
c#geographygeographic-distance

Calculate SW & NE Lat/Longs of Square X miles from a Centre Lat/Long


I am working on getting data out of the Noaa API.

When talking to the Noaa API you can get a list of weather stations within a square. They call them "extents" and they are a 2 sets of lat/longs. The bottom left lat/long and the top right lat/long

As detailed here:

http://www.ncdc.noaa.gov/cdo-web/webservices/v2#stations

I have been given a list of lat/longs for a number of cities in the US and I am trying to work out the best way of putting a box around.

So, my first guess would be to take the central lat/long, work out the lat/long 75 miles to the West, then work out the lat/long of the point 75 miles South of that point.

Ideally I would like to have this as a c# function.

Has anyone got any ideas on the best way to code this please?

Thanks


Solution

  • Yippee! - found the solution...

    First a simple class:

    public class LatLonAlt
        {
            public double Latitude { get; set; }
            public double Longitude { get; set; }
            public double Altitude { get; set; }
        }
    

    Then a function to calculate a new position:

    public static HelpersModel.LatLonAlt CalculateDerivedPosition(HelpersModel.LatLonAlt source, double range, double bearing)
        {
            double latA = Convert.ToDouble(source.Latitude) * (Math.PI / 180);
            double lonA = Convert.ToDouble(source.Longitude) * (Math.PI / 180);
            double angularDistance = range / 6371;
            double trueCourse = bearing * (Math.PI / 180);
    
            double lat = Math.Asin(
                Math.Sin(latA) * Math.Cos(angularDistance) +
                Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse));
    
            double dlon = Math.Atan2(
                Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA),
                Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat));
    
            double lon = ((lonA + dlon + Math.PI) % (Math.PI * 2)) - Math.PI;
    
            HelpersModel.LatLonAlt results = new HelpersModel.LatLonAlt();
            results.Latitude = lat * (180 / Math.PI);
            results.Longitude = lon * (180 / Math.PI);
            results.Altitude = source.Altitude;
    
            return results;
        }
    

    Then, and I know I can do this better.. but it works for now...

    2 functions that work out the bottmleft and topright extent:

    public static HelpersModel.LatLonAlt FindBottomLeftExtent(HelpersModel.LatLonAlt startpoint)
        {
            // first move left
            HelpersModel.LatLonAlt movedleft = CalculateDerivedPosition(startpoint, 72.42, 270);
            // move down
            HelpersModel.LatLonAlt moveddown = CalculateDerivedPosition(movedleft, 72.42, 180);
    
            return moveddown;
        }
        public static HelpersModel.LatLonAlt FindTopRightExtent(HelpersModel.LatLonAlt startpoint)
        {
            // first move right
            HelpersModel.LatLonAlt movedright = CalculateDerivedPosition(startpoint, 72.42, 90);
            // move up
            HelpersModel.LatLonAlt movedup = CalculateDerivedPosition(movedright, 72.42, 0);
    
            return movedup;
        }
    

    HTH!

    Trev