كيفية حساب المربع المحيط معين اللات/الغاز الطبيعي المسال الموقع ؟

StackOverflow https://stackoverflow.com/questions/238260

  •  04-07-2019
  •  | 
  •  

سؤال

لقد أعطيت مكان تحدده خطوط الطول والعرض.الآن أريد لحساب المربع المحيط في مثل10 كيلومتر من تلك النقطة.

المربع المحيط يجب أن يعرف latmin, lngmin و latmax, lngmax.

أحتاج هذه الأشياء من أجل استخدام panoramio API.

هل يعرف أحدا صيغة كيفية الحصول على thos النقاط ؟

تحرير: يا شباب أنا أبحث عن صيغة/وظيفة والتي تأخذ اللات & lng كمدخل وإرجاع المربع المحيط كما latmin & lngmin و latmax & latmin.Mysql, php, c#, جافا سكريبت على ما يرام ولكن أيضا شبة الكود يجب أن يكون حسنا.

تحرير: أنا لا أبحث عن الحل الذي يظهر لي المسافة من 2 نقطة

هل كانت مفيدة؟

المحلول

أقترح لتقريب محليا سطح الأرض باعتبارها المجال مع دائرة نصف قطرها معينة من WGS84 الإهليلجي في إعطاء الحرية.وأظن أن نفس حساب latMin و latMax تتطلب الوظائف الاهليلجيه و لن تسفر عن زيادة ملموسة في دقة (WGS84 هو نفسه تقريبي).

تنفيذ بلدي يلي (إنه مكتوب في بيثون;أنا لم تختبر):

# degrees to radians
def deg2rad(degrees):
    return math.pi*degrees/180.0
# radians to degrees
def rad2deg(radians):
    return 180.0*radians/math.pi

# Semi-axes of WGS-84 geoidal reference
WGS84_a = 6378137.0  # Major semiaxis [m]
WGS84_b = 6356752.3  # Minor semiaxis [m]

# Earth radius at a given latitude, according to the WGS-84 ellipsoid [m]
def WGS84EarthRadius(lat):
    # http://en.wikipedia.org/wiki/Earth_radius
    An = WGS84_a*WGS84_a * math.cos(lat)
    Bn = WGS84_b*WGS84_b * math.sin(lat)
    Ad = WGS84_a * math.cos(lat)
    Bd = WGS84_b * math.sin(lat)
    return math.sqrt( (An*An + Bn*Bn)/(Ad*Ad + Bd*Bd) )

# Bounding box surrounding the point at given coordinates,
# assuming local approximation of Earth surface as a sphere
# of radius given by WGS84
def boundingBox(latitudeInDegrees, longitudeInDegrees, halfSideInKm):
    lat = deg2rad(latitudeInDegrees)
    lon = deg2rad(longitudeInDegrees)
    halfSide = 1000*halfSideInKm

    # Radius of Earth at given latitude
    radius = WGS84EarthRadius(lat)
    # Radius of the parallel at given latitude
    pradius = radius*math.cos(lat)

    latMin = lat - halfSide/radius
    latMax = lat + halfSide/radius
    lonMin = lon - halfSide/pradius
    lonMax = lon + halfSide/pradius

    return (rad2deg(latMin), rad2deg(lonMin), rad2deg(latMax), rad2deg(lonMax))

تحرير:التعليمة البرمجية التالية يحول (درجة ، يعبي, ثانية) إلى درجة + الكسور درجة ، والعكس بالعكس (لم تختبر):

def dps2deg(degrees, primes, seconds):
    return degrees + primes/60.0 + seconds/3600.0

def deg2dps(degrees):
    intdeg = math.floor(degrees)
    primes = (degrees - intdeg)*60.0
    intpri = math.floor(primes)
    seconds = (primes - intpri)*60.0
    intsec = round(seconds)
    return (int(intdeg), int(intpri), int(intsec))

نصائح أخرى

كتبت مقالا حول العثور على إحاطة الإحداثيات:

http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates

توضح هذه المقالة الصيغ ويوفر أيضا تنفيذ جافا.(كما يبين لماذا فيديريكو صيغة مين/ماكس الطول غير دقيقة.)

هنا يجب تحويلها فيديريكو A.Ramponi الجواب C# على أي شخص مهتم:

public class MapPoint
{
    public double Longitude { get; set; } // In Degrees
    public double Latitude { get; set; } // In Degrees
}

public class BoundingBox
{
    public MapPoint MinPoint { get; set; }
    public MapPoint MaxPoint { get; set; }
}        

// Semi-axes of WGS-84 geoidal reference
private const double WGS84_a = 6378137.0; // Major semiaxis [m]
private const double WGS84_b = 6356752.3; // Minor semiaxis [m]

// 'halfSideInKm' is the half length of the bounding box you want in kilometers.
public static BoundingBox GetBoundingBox(MapPoint point, double halfSideInKm)
{            
    // Bounding box surrounding the point at given coordinates,
    // assuming local approximation of Earth surface as a sphere
    // of radius given by WGS84
    var lat = Deg2rad(point.Latitude);
    var lon = Deg2rad(point.Longitude);
    var halfSide = 1000 * halfSideInKm;

    // Radius of Earth at given latitude
    var radius = WGS84EarthRadius(lat);
    // Radius of the parallel at given latitude
    var pradius = radius * Math.Cos(lat);

    var latMin = lat - halfSide / radius;
    var latMax = lat + halfSide / radius;
    var lonMin = lon - halfSide / pradius;
    var lonMax = lon + halfSide / pradius;

    return new BoundingBox { 
        MinPoint = new MapPoint { Latitude = Rad2deg(latMin), Longitude = Rad2deg(lonMin) },
        MaxPoint = new MapPoint { Latitude = Rad2deg(latMax), Longitude = Rad2deg(lonMax) }
    };            
}

// degrees to radians
private static double Deg2rad(double degrees)
{
    return Math.PI * degrees / 180.0;
}

// radians to degrees
private static double Rad2deg(double radians)
{
    return 180.0 * radians / Math.PI;
}

// Earth radius at a given latitude, according to the WGS-84 ellipsoid [m]
private static double WGS84EarthRadius(double lat)
{
    // http://en.wikipedia.org/wiki/Earth_radius
    var An = WGS84_a * WGS84_a * Math.Cos(lat);
    var Bn = WGS84_b * WGS84_b * Math.Sin(lat);
    var Ad = WGS84_a * Math.Cos(lat);
    var Bd = WGS84_b * Math.Sin(lat);
    return Math.Sqrt((An*An + Bn*Bn) / (Ad*Ad + Bd*Bd));
}

كتبت وظيفة جافا سكريبت التي ترجع أربعة إحداثيات متر مربع الإحاطة ، بالنظر إلى مسافة وزوج من إحداثيات:

'use strict';

/**
 * @param {number} distance - distance (km) from the point represented by centerPoint
 * @param {array} centerPoint - two-dimensional array containing center coords [latitude, longitude]
 * @description
 *   Computes the bounding coordinates of all points on the surface of a sphere
 *   that has a great circle distance to the point represented by the centerPoint
 *   argument that is less or equal to the distance argument.
 *   Technique from: Jan Matuschek <http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates>
 * @author Alex Salisbury
*/

getBoundingBox = function (centerPoint, distance) {
  var MIN_LAT, MAX_LAT, MIN_LON, MAX_LON, R, radDist, degLat, degLon, radLat, radLon, minLat, maxLat, minLon, maxLon, deltaLon;
  if (distance < 0) {
    return 'Illegal arguments';
  }
  // helper functions (degrees<–>radians)
  Number.prototype.degToRad = function () {
    return this * (Math.PI / 180);
  };
  Number.prototype.radToDeg = function () {
    return (180 * this) / Math.PI;
  };
  // coordinate limits
  MIN_LAT = (-90).degToRad();
  MAX_LAT = (90).degToRad();
  MIN_LON = (-180).degToRad();
  MAX_LON = (180).degToRad();
  // Earth's radius (km)
  R = 6378.1;
  // angular distance in radians on a great circle
  radDist = distance / R;
  // center point coordinates (deg)
  degLat = centerPoint[0];
  degLon = centerPoint[1];
  // center point coordinates (rad)
  radLat = degLat.degToRad();
  radLon = degLon.degToRad();
  // minimum and maximum latitudes for given distance
  minLat = radLat - radDist;
  maxLat = radLat + radDist;
  // minimum and maximum longitudes for given distance
  minLon = void 0;
  maxLon = void 0;
  // define deltaLon to help determine min and max longitudes
  deltaLon = Math.asin(Math.sin(radDist) / Math.cos(radLat));
  if (minLat > MIN_LAT && maxLat < MAX_LAT) {
    minLon = radLon - deltaLon;
    maxLon = radLon + deltaLon;
    if (minLon < MIN_LON) {
      minLon = minLon + 2 * Math.PI;
    }
    if (maxLon > MAX_LON) {
      maxLon = maxLon - 2 * Math.PI;
    }
  }
  // a pole is within the given distance
  else {
    minLat = Math.max(minLat, MIN_LAT);
    maxLat = Math.min(maxLat, MAX_LAT);
    minLon = MIN_LON;
    maxLon = MAX_LON;
  }
  return [
    minLon.radToDeg(),
    minLat.radToDeg(),
    maxLon.radToDeg(),
    maxLat.radToDeg()
  ];
};

كنت تبحث عن الاهليلجي الصيغة.

أفضل مكان وجدت لبدء الترميز مبني على Geo::الإهليلجي المكتبة من CPAN.فهو يوفر لك الأساس لإنشاء الاختبارات الخاصة بك من ومقارنة النتائج مع النتائج.أنا استخدامها كأساس مماثلة مكتبة PHP في بلدي صاحب العمل السابق.

جيو::الإهليلجي

نلقي نظرة على location الأسلوب.يطلق عليه مرتين و كنت قد حصلت الخاص بك bbox.

لم بعد ما اللغة التي تستخدمها.قد تكون هناك أخطاء التكويد المكتبة المتاحة لك.

و إذا لم ترد عليها حتى الآن ، خرائط جوجل يستخدم WGS84 الإهليلجي.

منذ أنا في حاجة إلى تقدير تقريبي جدا ، لذلك لتصفية بعض وغني عن وثائق ونحن الاستعلام العاملين للصيغة التالية:

Min.lat = Given.Lat - (0.009 x N)
Max.lat = Given.Lat + (0.009 x N)
Min.lon = Given.lon - (0.009 x N)
Max.lon = Given.lon + (0.009 x N)

N = kms بالشكل المطلوب مكان معين.لقضيتك N=10

ليست دقيقة ولكن مفيد.

لقد تكيفت السيناريو PHP وجدت للقيام بذلك فقط.يمكنك استخدامه للعثور على زوايا مربع حول نقطة (20 كم خارج).بلدي محددة مثال على خرائط جوجل API:

http://www.richardpeacock.com/blog/2011/11/draw-box-around-coordinate-google-maps-based-miles-or-kilometers

هنا هي لعبة بسيطة التنفيذ باستخدام جافا سكريبت الذي يقوم على تحويل خط العرض درجة كيلومترا حيث 1 degree latitude ~ 111.2 km.

أنا حساب حدود الخريطة من خطوط الطول والعرض مع 10 دقيقة بالسيارة من العرض.

function getBoundsFromLatLng(lat, lng){
     var lat_change = 10/111.2;
     var lon_change = Math.abs(Math.cos(lat*(Math.PI/180)));
     var bounds = { 
         lat_min : lat - lat_change,
         lon_min : lng - lon_change,
         lat_max : lat + lat_change,
         lon_max : lng + lon_change
     };
     return bounds;
}

التوضيح @جان فيليب المطعم العائلي المأكولات العالمية الرفيعة شرح ممتاز.(يرجى متابعة-التصويت جوابه ، وليس هذا ؛ أنا مضيفا ان هذا كما أخذت بعض الوقت في فهم الجواب الأصلية)

المربع المحيط الأسلوب الأمثل في العثور على أقرب الجيران سوف تحتاج إلى استخلاص الحد الأدنى والحد الأقصى أزواج خطوط الطول ودوائر العرض ، ف نقطة في المسافة d .جميع النقاط التي تقع خارج هذه هي بالتأكيد على مسافة أكبر من د من نقطة.شيء واحد أن نلاحظ هنا هو حساب خط التقاطع كما هو مبين في يناير فيليب المطعم العائلي المأكولات العالمية الرفيعة التفسير.خط عرض تقاطع ليست على خط عرض النقطة P ولكن تعويض قليلا من ذلك.هذا هو في كثير من الأحيان غاب ولكن جزء مهم في تحديد الصحيح الأدنى والحد الأقصى إحاطة الطول نقطة P على المسافة d.وهذا هو أيضا مفيدة في التحقق.

على haversine المسافة بين (تقاطع خط العرض وخط الطول عالية) إلى (خطوط الطول والعرض) من P تساوي المسافة d.

بيثون جوهر هنا https://gist.github.com/alexcpn/f95ae83a7ee0293a5225

enter image description here

كنت أعمل على المربع المحيط المشكلة باعتبارها قضية جانبية إلى إيجاد جميع النقاط داخل SrcRad نصف قطرها ثابت اللات, نقطة منذ فترة طويلة.كان هناك عدد غير قليل من العمليات الحسابية التي تستخدم

maxLon = $lon + rad2deg($rad/$R/cos(deg2rad($lat)));
minLon = $lon - rad2deg($rad/$R/cos(deg2rad($lat)));

لحساب الطول حدود ، ولكن وجدت أن هذا لا يعطي كل الأجوبة اللازمة.لأن ما كنت حقا تريد القيام به هو

(SrcRad/RadEarth)/cos(deg2rad(lat))

أنا أعرف الجواب يجب أن يكون نفسه ، ولكن وجدت أن هذا لم يكن.ويبدو أن عدم التأكد من كنت أفعله (SRCrad/RadEarth) أولا ثم قسمة لأن الجزء الأول كان يترك بعض نقاط الموقع.

بعد أن تحصل على كل ما تبذلونه من المربع المحيط نقطة ، إذا كان لديك دالة تقوم بحساب نقطة على بعد نقطة معينة lat, long فمن السهل أن تحصل فقط على تلك النقاط التي هي مسافة معينة الشعاع من نقطة ثابتة.هنا هو ما فعلته.أعلم أن الأمر استغرق بضع خطوات إضافية ولكن من ساعدني

-- GLOBAL Constants
gc_pi CONSTANT REAL := 3.14159265359;  -- Pi

-- Conversion Factor Constants
gc_rad_to_degs          CONSTANT NUMBER := 180/gc_pi; -- Conversion for Radians to Degrees 180/pi
gc_deg_to_rads          CONSTANT NUMBER := gc_pi/180; --Conversion of Degrees to Radians

lv_stat_lat    -- The static latitude point that I am searching from 
lv_stat_long   -- The static longitude point that I am searching from 

-- Angular radius ratio in radians
lv_ang_radius := lv_search_radius / lv_earth_radius;
lv_bb_maxlat := lv_stat_lat + (gc_rad_to_deg * lv_ang_radius);
lv_bb_minlat := lv_stat_lat - (gc_rad_to_deg * lv_ang_radius);

--Here's the tricky part, accounting for the Longitude getting smaller as we move up the latitiude scale
-- I seperated the parts of the equation to make it easier to debug and understand
-- I may not be a smart man but I know what the right answer is... :-)

lv_int_calc := gc_deg_to_rads * lv_stat_lat;
lv_int_calc := COS(lv_int_calc);
lv_int_calc := lv_ang_radius/lv_int_calc;
lv_int_calc := gc_rad_to_degs*lv_int_calc;

lv_bb_maxlong := lv_stat_long + lv_int_calc;
lv_bb_minlong := lv_stat_long - lv_int_calc;

-- Now select the values from your location datatable 
SELECT *  FROM (
SELECT cityaliasname, city, state, zipcode, latitude, longitude, 
-- The actual distance in miles
spherecos_pnttopntdist(lv_stat_lat, lv_stat_long, latitude, longitude, 'M') as miles_dist    
FROM Location_Table 
WHERE latitude between lv_bb_minlat AND lv_bb_maxlat
AND   longitude between lv_bb_minlong and lv_bb_maxlong)
WHERE miles_dist <= lv_limit_distance_miles
order by miles_dist
;

أنها بسيطة جدا فقط اذهب الى موقع panoramio ثم فتح خريطة العالم من موقع panoramio.ثم انتقل إلى الموقع المحدد which's خطوط الطول والعرض المطلوب.

ثم يمكنك العثور على خطوط الطول والعرض في شريط العنوان على سبيل المثال في هذا العنوان.

http://www.panoramio.com/map#lt=32.739485&ln=70.491211&z=9&k=1&a=1&tab=1&pl=all

lt=32.739485 =>خطوط ln=70.491211 =>خط الطول

هذا Panoramio جافا سكريبت API القطعة إنشاء مربع الإحاطة حول lat/long الزوج ومن ثم العودة جميع الصور في تلك الحدود.

نوع آخر من Panoramio جافا سكريبت API القطعة التي يمكنك أيضا تغيير لون الخلفية مع مثال ورمز هنا.

فإنه لا تظهر في تأليف المزاج.تظهر بعد النشر.

<div dir="ltr" style="text-align: center;" trbidi="on">
<script src="https://ssl.panoramio.com/wapi/wapi.js?v=1&amp;hl=en"></script>
<div id="wapiblock" style="float: right; margin: 10px 15px"></div>
<script type="text/javascript">
var myRequest = {
  'tag': 'kahna',
  'rect': {'sw': {'lat': -30, 'lng': 10.5}, 'ne': {'lat': 50.5, 'lng': 30}}
};
  var myOptions = {
  'width': 300,
  'height': 200
};
var wapiblock = document.getElementById('wapiblock');
var photo_widget = new panoramio.PhotoWidget('wapiblock', myRequest, myOptions);
photo_widget.setPosition(0);
</script>
</div>

هنا يجب تحويلها فيديريكو A.Ramponi الجواب PHP إذا كان أي شخص مهتم:

<?php
# deg2rad and rad2deg are already within PHP

# Semi-axes of WGS-84 geoidal reference
$WGS84_a = 6378137.0;  # Major semiaxis [m]
$WGS84_b = 6356752.3;  # Minor semiaxis [m]

# Earth radius at a given latitude, according to the WGS-84 ellipsoid [m]
function WGS84EarthRadius($lat)
{
    global $WGS84_a, $WGS84_b;

    $an = $WGS84_a * $WGS84_a * cos($lat);
    $bn = $WGS84_b * $WGS84_b * sin($lat);
    $ad = $WGS84_a * cos($lat);
    $bd = $WGS84_b * sin($lat);

    return sqrt(($an*$an + $bn*$bn)/($ad*$ad + $bd*$bd));
}

# Bounding box surrounding the point at given coordinates,
# assuming local approximation of Earth surface as a sphere
# of radius given by WGS84
function boundingBox($latitudeInDegrees, $longitudeInDegrees, $halfSideInKm)
{
    $lat = deg2rad($latitudeInDegrees);
    $lon = deg2rad($longitudeInDegrees);
    $halfSide = 1000 * $halfSideInKm;

    # Radius of Earth at given latitude
    $radius = WGS84EarthRadius($lat);
    # Radius of the parallel at given latitude
    $pradius = $radius*cos($lat);

    $latMin = $lat - $halfSide / $radius;
    $latMax = $lat + $halfSide / $radius;
    $lonMin = $lon - $halfSide / $pradius;
    $lonMax = $lon + $halfSide / $pradius;

    return array(rad2deg($latMin), rad2deg($lonMin), rad2deg($latMax), rad2deg($lonMax));
}
?>

شكرا @Fedrico A.بالنسبة Phyton التنفيذ ، لقد استدار إلى الهدف C فئة الدرجة.هنا هو:

#import "LocationService+Bounds.h"

//Semi-axes of WGS-84 geoidal reference
const double WGS84_a = 6378137.0; //Major semiaxis [m]
const double WGS84_b = 6356752.3; //Minor semiaxis [m]

@implementation LocationService (Bounds)

struct BoundsLocation {
    double maxLatitude;
    double minLatitude;
    double maxLongitude;
    double minLongitude;
};

+ (struct BoundsLocation)locationBoundsWithLatitude:(double)aLatitude longitude:(double)aLongitude maxDistanceKm:(NSInteger)aMaxKmDistance {
    return [self boundingBoxWithLatitude:aLatitude longitude:aLongitude halfDistanceKm:aMaxKmDistance/2];
}

#pragma mark - Algorithm 

+ (struct BoundsLocation)boundingBoxWithLatitude:(double)aLatitude longitude:(double)aLongitude halfDistanceKm:(double)aDistanceKm {
    double radianLatitude = [self degreesToRadians:aLatitude];
    double radianLongitude = [self degreesToRadians:aLongitude];
    double halfDistanceMeters = aDistanceKm*1000;


    double earthRadius = [self earthRadiusAtLatitude:radianLatitude];
    double parallelRadius = earthRadius*cosl(radianLatitude);

    double radianMinLatitude = radianLatitude - halfDistanceMeters/earthRadius;
    double radianMaxLatitude = radianLatitude + halfDistanceMeters/earthRadius;
    double radianMinLongitude = radianLongitude - halfDistanceMeters/parallelRadius;
    double radianMaxLongitude = radianLongitude + halfDistanceMeters/parallelRadius;

    struct BoundsLocation bounds;
    bounds.minLatitude = [self radiansToDegrees:radianMinLatitude];
    bounds.maxLatitude = [self radiansToDegrees:radianMaxLatitude];
    bounds.minLongitude = [self radiansToDegrees:radianMinLongitude];
    bounds.maxLongitude = [self radiansToDegrees:radianMaxLongitude];

    return bounds;
}

+ (double)earthRadiusAtLatitude:(double)aRadianLatitude {
    double An = WGS84_a * WGS84_a * cosl(aRadianLatitude);
    double Bn = WGS84_b * WGS84_b * sinl(aRadianLatitude);
    double Ad = WGS84_a * cosl(aRadianLatitude);
    double Bd = WGS84_b * sinl(aRadianLatitude);
    return sqrtl( ((An * An) + (Bn * Bn))/((Ad * Ad) + (Bd * Bd)) );
}

+ (double)degreesToRadians:(double)aDegrees {
    return M_PI*aDegrees/180.0;
}

+ (double)radiansToDegrees:(double)aRadians {
    return 180.0*aRadians/M_PI;
}



@end

لقد اختبرت ذلك و يبدو أن العامل لطيفة.البنية BoundsLocation يجب أن يتم استبدال من قبل فئة ، لقد استخدمت فقط أن حصة هنا.

كل ما سبق الجواب جزئيا فقط الصحيح.خاصة في المنطقة مثل أستراليا ، وهي تشمل دائما القطب حساب كبير جدا المستطيل حتى 10kms.

خصيصا الخوارزمية من قبل جان فيليب المطعم العائلي المأكولات العالمية الرفيعة في http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates#UsingIndex وشملت كبير جدا المستطيل من (-37, -90, -180, 180) من أجل كل نقطة تقريبا في أستراليا.هذا يضرب كبيرة من المستخدمين في قاعدة البيانات والمسافة يجب أن يحسب لجميع المستخدمين في ما يقرب من نصف البلاد.

وجدت أن دروبال API الأرض الخوارزمية من قبل معهد روتشستر للتكنولوجيا يعمل بشكل أفضل حول القطب وكذلك في أماكن أخرى و هو أسهل بكثير لتنفيذ.

https://www.rit.edu/drupal/api/drupal/sites%21all%21modules%21location%21earth.inc/7.54

استخدام earth_latitude_range و earth_longitude_range من فوق خوارزمية لحساب مستطيل إحاطة

واستخدام حساب المسافة معادلة موثقة من قبل خرائط جوجل لحساب المسافة

https://developers.google.com/maps/solutions/store-locator/clothing-store-locator#outputting-data-as-xml-using-php

البحث عن طريق كيلومترا بدلا من ميل محل 3959 مع 6371.على (اللات, الغاز الطبيعي المسال) = (37, -122) و علامات الجدول مع الأعمدة اللات و الغاز الطبيعي المسال, الصيغة هي:

SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance FROM markers HAVING distance < 25 ORDER BY distance LIMIT 0 , 20;

قراءة إجابة مفصلة في https://stackoverflow.com/a/45950426/5076414

هنا هو فيديريكو Ramponi الجواب في الذهاب.ملاحظة:لا تدقيق الأخطاء :(

import (
    "math"
)

// Semi-axes of WGS-84 geoidal reference
const (
    // Major semiaxis (meters)
    WGS84A = 6378137.0
    // Minor semiaxis (meters)
    WGS84B = 6356752.3
)

// BoundingBox represents the geo-polygon that encompasses the given point and radius
type BoundingBox struct {
    LatMin float64
    LatMax float64
    LonMin float64
    LonMax float64
}

// Convert a degree value to radians
func deg2Rad(deg float64) float64 {
    return math.Pi * deg / 180.0
}

// Convert a radian value to degrees
func rad2Deg(rad float64) float64 {
    return 180.0 * rad / math.Pi
}

// Get the Earth's radius in meters at a given latitude based on the WGS84 ellipsoid
func getWgs84EarthRadius(lat float64) float64 {
    an := WGS84A * WGS84A * math.Cos(lat)
    bn := WGS84B * WGS84B * math.Sin(lat)

    ad := WGS84A * math.Cos(lat)
    bd := WGS84B * math.Sin(lat)

    return math.Sqrt((an*an + bn*bn) / (ad*ad + bd*bd))
}

// GetBoundingBox returns a BoundingBox encompassing the given lat/long point and radius
func GetBoundingBox(latDeg float64, longDeg float64, radiusKm float64) BoundingBox {
    lat := deg2Rad(latDeg)
    lon := deg2Rad(longDeg)
    halfSide := 1000 * radiusKm

    // Radius of Earth at given latitude
    radius := getWgs84EarthRadius(lat)

    pradius := radius * math.Cos(lat)

    latMin := lat - halfSide/radius
    latMax := lat + halfSide/radius
    lonMin := lon - halfSide/pradius
    lonMax := lon + halfSide/pradius

    return BoundingBox{
        LatMin: rad2Deg(latMin),
        LatMax: rad2Deg(latMax),
        LonMin: rad2Deg(lonMin),
        LonMax: rad2Deg(lonMax),
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top