අක්ෂාංශ-දේශාංශ ලක්ෂ්‍ය දෙකක් අතර දුර ගණනය කරන්න? (හැවර්සින් සූත්‍රය)


926

අක්ෂාංශ හා දේශාංශ මගින් නිශ්චිතව දක්වා ඇති ලක්ෂ්‍ය දෙකක් අතර දුර ගණනය කරන්නේ කෙසේද?

පැහැදිලි කිරීම සඳහා, මම කිලෝමීටරයක දුරට කැමතියි; ලකුණු WGS84 පද්ධතිය භාවිතා කරන අතර පවතින ප්‍රවේශයන්ගේ සාපේක්ෂ නිරවද්‍යතාව තේරුම් ගැනීමට මම කැමතියි.


වඩා හොඳ නිරවද්යතාව සඳහා - බලන්න stackoverflow.com/questions/1420045/...
Lior Kogan

3
WGS 84 වැනි විප්ලවයේ ඉලිප්සොයිඩ් මත ඔබට හැවර්සීන් සූත්‍රයක් යෙදිය නොහැකි බව සලකන්න. ඔබට මෙම ක්‍රමය යෙදිය හැක්කේ අරය සහිත ගෝලයක් මත පමණි.
මයික් ටී

4
මෙහි ඇති බොහෝ පිළිතුරු සරල ගෝලාකාර ත්‍රිකෝණමිතිය භාවිතා කරයි, එබැවින් ජීපීඑස් පද්ධතියේ භාවිතා වන ඩබ්ලිව්ජීඑස් 84 ඉලිප්සොයිඩ් දුර හා සසඳන විට ප්‍රති results ල තරමක් ගොරෝසු ය. සමහර පිළිතුරු වල වින්සෙන්ටිගේ ඉලිප්සොයිඩ් සූත්‍රය ගැන සඳහන් වන නමුත් එම ඇල්ගොරිතම 1960 දශකයේ යුගයේ මේස කැල්කියුලේටර සඳහා භාවිතා කිරීම සඳහා නිර්මාණය කර ඇති අතර එයට ස්ථායිතාව සහ නිරවද්‍යතා ගැටළු ඇත; අපට දැන් වඩා හොඳ දෘඩාංග හා මෘදුකාංග තිබේ. විවිධ භාෂාවලින් ක්‍රියාත්මක කිරීම සහිත උසස් තත්ත්වයේ පුස්තකාලයක් සඳහා කරුණාකර භූගෝලීය ලිබ් බලන්න .
PM 2Ring

Ike මයික්ට් - සත්‍යය මෙහි බොහෝ පිළිතුරු කුඩා දුර ප්‍රමාණයට වඩා ප්‍රයෝජනවත් බව පෙනේ : ඔබ ඩබ්ලිව්ජීඑස් 84 වෙතින් ප්‍රමාද වී / දිගු කාලයක් ගත කර, හැවර්සීන් ගෝලයක් මත ලකුණු කර ඇති ආකාරයට යොදන්නේ නම් , දෝෂ නිසා පමණක් පිළිතුරු ලැබෙන්නේ නැද්ද? පෘථිවියේ සමතලා කිරීමේ සාධකය, එසේනම් වඩාත් නිවැරදි සූත්‍රයකින් 1% ක් ඇතුළත? මේවා කුඩා දුරක් බව අවවාදයෙන්, එක් නගරයක් තුළ කියන්න.
මෙවලම් සාදන්නා

1
මෙම තහඩු සඳහා: මොනෝ / .නෙට් 4.5 / .නෙට් කෝර් / වින්ඩෝස් දුරකථන 8.x / යුනිවර්සල් වින්ඩෝස් වේදිකාව / සැමරින් iOS / සැමරින් ඇන්ඩ්‍රොයිඩ් බලන්න stackoverflow.com/a/54296314/2736742
A. මොරල්

Answers:


1169

දුර ගණනය කිරීම සඳහා හැවර්සීන් සූත්‍රය භාවිතා කරන ආකාරය විස්තර කරන බැවින් මෙම සබැඳිය ඔබට ප්‍රයෝජනවත් විය හැකිය .

උපුටා ගැනීම:

මෙම ස්ක්‍රිප්ට් [ජාවාස්ක්‍රිප්ට් හි] ලක්ෂ්‍ය දෙක අතර විශාල රවුම් දුර ගණනය කරයි - එනම් පෘථිවි පෘෂ් over යට වඩා කෙටිම දුර - 'හැවර්සීන්' සූත්‍රය භාවිතා කරයි.

function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
  var R = 6371; // Radius of the earth in km
  var dLat = deg2rad(lat2-lat1);  // deg2rad below
  var dLon = deg2rad(lon2-lon1); 
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2)
    ; 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c; // Distance in km
  return d;
}

function deg2rad(deg) {
  return deg * (Math.PI/180)
}

51
මෙම ගණනය කිරීම / ක්‍රමය මගින් පෘථිවිය ගෝලාකාර (පරිපූර්ණ ගෝලයක් නොවේ) වීමට හේතු වේද? මුල් ප්‍රශ්නය WGS84 ලෝක ගෝලයෙහි ලකුණු අතර දුරක් ඉල්ලා සිටියේය. පරිපූර්ණ ගෝලයක් භාවිතා කිරීමෙන් කොපමණ දෝෂයක් ඇතිවිය හැකිදැයි විශ්වාස නැත, නමුත් එය ලෝකයේ ඇති ස්ථාන මත පදනම්ව එය බොහෝ සෙයින් විය හැකි යැයි මම සැක කරමි, එබැවින් වෙනස මතක තබා ගැනීම වටී.
redcalx

15
හැවර්සීන් සූත්‍රය පෘථිවිය ගෝලාකාර වීමක් ලෙස ගණන් නොගනී, එම නිසා ඔබට යම් දෝෂයක් හඳුන්වා දෙනු ඇත. එය 0.5% ට වඩා නිවැරදි යැයි සහතික කළ නොහැක. එය පිළිගත හැකි මට්ටමේ දෝෂයක් විය හැකිය හෝ නොවිය හැකිය.
බ්‍රැන්ඩන්

24
විකිපීඩියා ලිපිය භාවිතා කරන සූත්‍රය සෘජුවම ක්‍රියාත්මක කිරීම Math.atan2(Math.sqrt(a), Math.sqrt(1-a))වෙනුවට ඒ වෙනුවට භාවිතා කිරීමට හේතුවක් Math.asin(Math.sqrt(h))තිබේද? එය වඩා කාර්යක්ෂම හා / හෝ සංඛ්‍යාත්මකව ස්ථාවරද?
musiphil

17
S උස්මාන් මුටවාකිල් හොඳයි, ඔබට ලැබෙන සැතපුම් 38 පාරේ දුරයි. මෙම ඇල්ගොරිතම පෘථිවි පෘෂ් on යේ සරල රේඛීය දුරක් ගණනය කරයි. ගූගල් සිතියම් සතුව දුරස්ථ මෙවලමක් ඇත (පහළ වම්පස, "විද්‍යාගාර") එයම කරයි, සංසන්දනය කිරීමට එය භාවිතා කරන්න.
පැස්කල්

4
@ Forte_201092: එය අවශ්‍ය නොවන නිසා - (sin(x))²සමානව(sin(-x))²
ජීන් හෝමිනල්

375

මගේ ව්‍යාපෘතිය සඳහා ලකුණු අතර දුර ප්‍රමාණයක් ගණනය කිරීමට මට අවශ්‍ය විය, එබැවින් මම ඉදිරියට ගොස් කේතය ප්‍රශස්තිකරණය කිරීමට උත්සාහ කළෙමි, මම මෙහි සොයාගෙන ඇත. විවිධ බ්‍රව්සර්වල සාමාන්‍යයෙන් මගේ නව ක්‍රියාත්මක කිරීම වඩාත්ම උත්තරීතර පිළිතුරට වඩා 2 ගුණයක් වේගයෙන් ක්‍රියාත්මක වේ.

function distance(lat1, lon1, lat2, lon2) {
  var p = 0.017453292519943295;    // Math.PI / 180
  var c = Math.cos;
  var a = 0.5 - c((lat2 - lat1) * p)/2 + 
          c(lat1 * p) * c(lat2 * p) * 
          (1 - c((lon2 - lon1) * p))/2;

  return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}

ඔබ මගේ jsPerf සමග සෙල්ලම් සහ දකින්න පුළුවන් මෙතන ප්රතිඵල .

මෑතකදී මට පයිතන් වලදීද එසේ කිරීමට අවශ්‍ය විය, එබැවින් මෙන්න පයිතන් ක්‍රියාත්මක කිරීමකි :

from math import cos, asin, sqrt, pi

def distance(lat1, lon1, lat2, lon2):
    p = pi/180
    a = 0.5 - cos((lat2-lat1)*p)/2 + cos(lat1*p) * cos(lat2*p) * (1-cos((lon2-lon1)*p))/2
    return 12742 * asin(sqrt(a)) #2*R*asin...

සහ සම්පූර්ණත්වය සඳහා: හැවර්සින් විකිය.


14
Ng ඇන්ගුලර් එම් සහ ඔබ දුර ගණන් ගණනය කරන්නේ නම් ඔබ මාර්ග කිහිපයක් මිස සරල රේඛාවක් නොවේ.
සැල්වදෝර් ඩාලි

3
ගූගල් රිය පැදවීමේ දුර ගණනය කරයි, මෙය ගණනය කරන්නේ "කකුළුවා පියාසර කරන විට"
විනෝදාංශය

5
U ඕවාඩි සහ එය වේගය වැඩි කරයිද? බොහෝ විට නැත, නමුත් පැරණි බ්‍රව්සර්වල එය පිටපත් කරන පුද්ගලයින් සඳහා මම 'ඔබේ දේවල් ක්‍රියා නොකරයි'
සැල්වදෝර් ඩාලි

4
හොඳයි, නමුත් එයින් // 2 * R; R = 6371 kmඅදහස් කරන්නේ කුමක්ද? සහ වර්තමාන ක්‍රමය කිලෝමීටර හෝ සැතපුම් වලින් පිළිතුරු සපයයිද? වඩා හොඳ ලියකියවිලි අවශ්‍යයි. ස්තූතියි
කලීල් කලාෆ්

26
Al ඛලීල් කලාෆ් ඔබ විහිළුවක්ද? km යනු කිලෝමීටර වේ. R යනු කුමක් සඳහා යැයි ඔබ සිතන්නේද (විශේෂයෙන් අපි ෂෙපර් ගැන කතා කරන්නේ නම්)? ඔබ දැනටමත් කිලෝමීටරයක් ​​දුටුවහොත් පිළිතුර කුමන ඒකක වලින්දැයි අනුමාන කරන්න. ඔබ මෙහි කුමන ආකාරයේ ලියකියවිලි සොයන්නේද: එහි පේළි 4 ක් ඇත.
සැල්වදෝර් ඩාලි

69

මෙන්න C # ක්‍රියාත්මක කිරීම:

static class DistanceAlgorithm
{
    const double PIx = 3.141592653589793;
    const double RADIUS = 6378.16;

    /// <summary>
    /// Convert degrees to Radians
    /// </summary>
    /// <param name="x">Degrees</param>
    /// <returns>The equivalent in radians</returns>
    public static double Radians(double x)
    {
        return x * PIx / 180;
    }

    /// <summary>
    /// Calculate the distance between two places.
    /// </summary>
    /// <param name="lon1"></param>
    /// <param name="lat1"></param>
    /// <param name="lon2"></param>
    /// <param name="lat2"></param>
    /// <returns></returns>
    public static double DistanceBetweenPlaces(
        double lon1,
        double lat1,
        double lon2,
        double lat2)
    {
        double dlon = Radians(lon2 - lon1);
        double dlat = Radians(lat2 - lat1);

        double a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) + Math.Cos(Radians(lat1)) * Math.Cos(Radians(lat2)) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2));
        double angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
        return angle * RADIUS;
    }

}

14
ඔබ භාවිතා කරන්නේ සමක අරය, නමුත් ඔබ භාවිතා කළ යුත්තේ කිලෝමීටර 6371 ක් වන
මධ්‍ය අරයයි

7
මෙම නොවිය යුතුය double dlon = Radians(lon2 - lon1);හාdouble dlat = Radians(lat2 - lat1);
ක්රිස් Marisic

මම ක්‍රිස් මාරිසික් සමඟ එකඟ වෙමි. මම මුල් කේතය භාවිතා කළ අතර ගණනය කිරීම් වැරදිය. ඩෙල්ටා රේඩියන බවට පරිවර්තනය කිරීම සඳහා මම ඇමතුම එක් කළ අතර එය දැන් නිසි ලෙස ක්‍රියාත්මක වේ. මම සංස්කරණයක් ඉදිරිපත් කළ අතර එය සමපදස්ථ සමාලෝචනයක් සඳහා බලා සිටිමි.
බ්‍රයන් බෙඩාර්ඩ්

Lat1 & lat2 ද රේඩියන් බවට පරිවර්තනය කළ යුතු නිසා මම තවත් සංස්කරණයක් ඉදිරිපත් කළෙමි. මෙහි ඇති සූත්‍රයට හා කේතයට ගැලපෙන පරිදි පැවරුම සඳහා වූ සූත්‍රය ද මම සංශෝධනය කළෙමි: movable-type.co.uk/scripts/latlong.html
බ්‍රයන් බෙඩාර්ඩ්

වේද, RADIUSඅනෙක් පිළිතුරු ලෙස 6371 විය අගය අවශ්ය?
ක්‍රිස් හේස්

67

මෙන්න හැවර්සීන් සූත්‍රයේ ජාවා ක්‍රියාත්මක කිරීමකි.

public final static double AVERAGE_RADIUS_OF_EARTH_KM = 6371;
public int calculateDistanceInKilometer(double userLat, double userLng,
  double venueLat, double venueLng) {

    double latDistance = Math.toRadians(userLat - venueLat);
    double lngDistance = Math.toRadians(userLng - venueLng);

    double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
      + Math.cos(Math.toRadians(userLat)) * Math.cos(Math.toRadians(venueLat))
      * Math.sin(lngDistance / 2) * Math.sin(lngDistance / 2);

    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    return (int) (Math.round(AVERAGE_RADIUS_OF_EARTH_KM * c));
}

මෙන්න අපි ළඟම ඇති කිලෝමීටරයට පිළිතුර වටකරමින් සිටින බව සලකන්න.


2
මීටර වලින් ලකුණු දෙකක් අතර දුර ගණනය කිරීමට අපට අවශ්‍ය නම්, වඩාත් නිවැරදි ක්‍රමය කුමක්ද? 6371000පෘථිවියේ අරය ලෙස භාවිතා කිරීමට ? (පෘථිවියේ අරය මීටර 6371000 කි) හෝ ඔබේ ශ්‍රිතයෙන් කිලෝමීටර මීටර බවට පරිවර්තනය කරන්න?
මයික්‍රෝ

ඔබට සැතපුම් අවශ්‍ය නම්, 0.621371
ප්‍රති result ලය අනුව ගුණ කරන්න

42

මේ සියල්ලටම බොහොම ස්තූතියි. මගේ Objective-C iPhone යෙදුමේ මම පහත කේතය භාවිතා කළෙමි:

const double PIx = 3.141592653589793;
const double RADIO = 6371; // Mean radius of Earth in Km

double convertToRadians(double val) {

   return val * PIx / 180;
}

-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {

        double dlon = convertToRadians(place2.longitude - place1.longitude);
        double dlat = convertToRadians(place2.latitude - place1.latitude);

        double a = ( pow(sin(dlat / 2), 2) + cos(convertToRadians(place1.latitude))) * cos(convertToRadians(place2.latitude)) * pow(sin(dlon / 2), 2);
        double angle = 2 * asin(sqrt(a));

        return angle * RADIO;
}

අක්ෂාංශ සහ දේශාංශ දශමයෙන් පවතී. ඇසින් () ඇමතුම සඳහා මම මිනි () භාවිතා නොකළ අතර මා භාවිතා කරන දුර ප්‍රමාණය ඉතා කුඩා බැවින් ඔවුන්ට එය අවශ්‍ය නොවේ.

මම රේඩියන්ස් හි අගයන් පසු කරන තෙක් එය වැරදි පිළිතුරු ලබා දී ඇත - දැන් එය ඇපල් සිතියම් යෙදුමෙන් ලබාගත් අගයන්ට සමාන ය :-)

අමතර යාවත්කාලීන කිරීම:

ඔබ iOS4 හෝ ඊට පසු භාවිතා කරන්නේ නම් ඇපල් විසින් මෙය සිදු කිරීම සඳහා ක්‍රම කිහිපයක් ලබා දෙයි.

-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {

    MKMapPoint  start, finish;


    start = MKMapPointForCoordinate(place1);
    finish = MKMapPointForCoordinate(place2);

    return MKMetersBetweenMapPoints(start, finish) / 1000;
}

1
: iOS SDK එහි ම ක්රියාත්මක කර developer.apple.com/library/ios/documentation/CoreLocation/... :
tuler

මම හිතන්නේ අවට වරහන් pow(sin(dlat / 2), 2) + cos(convertToRadians(place1.latitude))වැරදියි. ඒවා ඉවත් කරන්න, මෙම පිටුවේ වෙනත් ක්‍රියාත්මක කිරීම් භාවිතා කරන විට ලැබෙන ප්‍රති result ලය මට ගැලපේ, නැතහොත් මුල සිටම විකිපීඩියාවෙන් හැවර්සීන් සූත්‍රය ක්‍රියාත්මක කරන්න .
zanedp

NYC සඳහා ඛණ්ඩාංක (40.7127837, -74.0059413) සහ LA සඳහා (34.052234, -118.243685) භාවිතා කරමින්, ()එම මුදල සමඟ මට 3869.75 ක් ලැබේ. ඔවුන් නොමැතිව, මට 3935.75 ක් ලැබේ, එය වෙබ් සෙවුමකට වඩා වැඩි ය.
zanedp

40

මෙය සරල PHP ශ්‍රිතයක් වන අතර එය ඉතා සාධාරණ දළ විශ්ලේෂණයක් ලබා දෙනු ඇත (+/- 1% දෝෂ ආන්තිකය යටතේ).

<?php
function distance($lat1, $lon1, $lat2, $lon2) {

    $pi80 = M_PI / 180;
    $lat1 *= $pi80;
    $lon1 *= $pi80;
    $lat2 *= $pi80;
    $lon2 *= $pi80;

    $r = 6372.797; // mean radius of Earth in km
    $dlat = $lat2 - $lat1;
    $dlon = $lon2 - $lon1;
    $a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlon / 2) * sin($dlon / 2);
    $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
    $km = $r * $c;

    //echo '<br/>'.$km;
    return $km;
}
?>

කලින් කී පරිදි; පෘථිවිය ගෝලයක් නොවේ. එය මාක් මැක්විවර් සමඟ පුහුණුවීමට තීරණය කළ පැරණි, පැරණි බේස්බෝල් ක්‍රීඩාවක් වැනි ය - එය දත් හා ගැටිති වලින් පිරී ඇත. සරල ගණනය කිරීම් (මේ වගේ) එය ගෝලයක් ලෙස සලකයි.

මෙම අක්‍රමවත් ඩිම්බකෝෂයේ ඔබ සිටින්නේ කොතැනද යන්න සහ ඔබේ ලකුණු කොතරම් දුරින් තිබේද යන්න අනුව විවිධ ක්‍රම වැඩි හෝ අඩු නිරවද්‍ය විය හැකිය (ඒවා සමීප වන විට නිරපේක්ෂ දෝෂ ආන්තිකය කුඩා වේ). ඔබේ අපේක්ෂාව වඩාත් නිවැරදිව, ගණිතය වඩාත් සංකීර්ණ වේ.

වැඩි විස්තර සඳහා: විකිපීඩියා භූගෝලීය දුර


4
මෙය පරිපූර්ණව ක්රියා කරයි! මම දැන් එකතු කළේ $ distance_miles = $ km * 0.621371; සැතපුම් දුරක් සඳහා මට අවශ්‍ය වූයේ එපමණයි! ස්තූතියි ටෝනි.

31

මගේ වැඩ කරන ආදර්ශය මම මෙහි පළ කරමි.

නියම කරන ලද ලක්ෂ්‍යයක් අතර දුරක් ඇති වගුවේ ඇති සියලුම ලකුණු ලැයිස්තුගත කරන්න (අපි අහඹු ලක්ෂ්‍යයක් භාවිතා කරමු - lat: 45.20327, දිග: 23.7806) 50 KM ට අඩු අක්ෂාංශ හා දේශාංශ සමඟ MySQL හි (වගු ක්ෂේත්‍රය coord_lat සහ coord_long):

කිලෝමීටරයක DISTANCE <50 ඇති සියල්ල ලැයිස්තුගත කරන්න (පෘථිවි අරය 6371 KM ලෙස සැලකේ):

SELECT denumire, (6371 * acos( cos( radians(45.20327) ) * cos( radians( coord_lat ) ) * cos( radians( 23.7806 ) - radians(coord_long) ) + sin( radians(45.20327) ) * sin( radians(coord_lat) ) )) AS distanta 
FROM obiective 
WHERE coord_lat<>'' 
    AND coord_long<>'' 
HAVING distanta<50 
ORDER BY distanta desc

ඉහත උදාහරණය MySQL 5.0.95 සහ 5.5.16 (ලිනක්ස්) වලින් පරීක්ෂා කරන ලදී.


මම හිතන්නේ හොඳ ප්‍රවේශයක් ප්‍රති ro ල පෙරනිමිත්තක් භාවිතයෙන් පෙරීම විය හැකිය, එබැවින් බර සූත්‍රය අදාළ වන්නේ සමහර අවස්ථාවල පමණි. ඔබට වෙනත් කොන්දේසි තිබේ නම් විශේෂයෙන් ප්‍රයෝජනවත් වේ. ආරම්භක ඇප්‍රොක්ස් සඳහා මම මෙය භාවිතා කරමි: stackoverflow.com/questions/1253499/…
පැටෝ

29

අනෙක් පිළිතුරු තුළ ක්‍රියාත්මක කිරීම අතුරුදහන්.

පැකේජයේ distmක්‍රියාකාරිත්වය සමඟ ලක්ෂ්‍ය දෙකක් අතර දුර ගණනය කිරීම තරමක් සරල ය geosphere:

distm(p1, p2, fun = distHaversine)

කොහේද:

p1 = longitude/latitude for point(s)
p2 = longitude/latitude for point(s)
# type of distance calculation
fun = distCosine / distHaversine / distVincentySphere / distVincentyEllipsoid 

පෘථිවිය පරිපූර්ණ ගෝලාකාර නොවන බැවින්, ඉලිප්සොයිඩ් සඳහා වින්සන්ටි සූත්‍රය දුර ගණනය කිරීමට හොඳම ක්‍රමය විය හැකිය. මේ අනුව geosphereඔබ භාවිතා කරන පැකේජයේ:

distm(p1, p2, fun = distVincentyEllipsoid)

ඇත්ත වශයෙන්ම ඔබට geosphereපැකේජයක් භාවිතා කිරීමට අවශ්‍ය නැත , ඔබට Rශ්‍රිතයක් සමඟ පාදමේ දුර ගණනය කළ හැකිය :

hav.dist <- function(long1, lat1, long2, lat2) {
  R <- 6371
  diff.long <- (long2 - long1)
  diff.lat <- (lat2 - lat1)
  a <- sin(diff.lat/2)^2 + cos(lat1) * cos(lat2) * sin(diff.long/2)^2
  b <- 2 * asin(pmin(1, sqrt(a))) 
  d = R * b
  return(d)
}

ඔබ පැවසූ දේ පිළිබඳව මට පැහැදිලි බව සහතික කර ගැනීම සඳහා: ඔබ තනතුර අවසානයේ දෙන කේතය: එය වින්සන්ටි සූත්‍රය ක්‍රියාත්මක කිරීමක්ද? ඔබ දන්නා පරිදි, එය භූගෝලයේ වින්සෙන්ටි ඇමතීමට සමාන පිළිතුරක් දිය යුතුද? [මට භූගෝලයක් හෝ වෙනත් පුස්තකාලයක් නොමැත; හරස් වේදිකා යෙදුමකට ඇතුළත් කිරීම සඳහා යම් කේතයක් සොයමින් සිටී. දන්නා හොඳ කැල්කියුලේටරයකට එරෙහිව සමහර පරීක්ෂණ අවස්ථා මම සත්‍යාපනය කරමි.]
මෙවලම් සාදන්නා

1
Answ ටූල්මේකර් මගේ පිළිතුර අවසානයේ ඇති කාර්යය හැවර්සීන් ක්‍රමය ක්‍රියාත්මක කිරීමකි
ජාප්

හායි a ජාප් මට සූත්‍රය සඳහා මිනුම් ඒකකය කුමක්දැයි විමසිය හැකිද? එය මීටර වලින්ද?
ජැක්සන්

11

හැවර්සීන් අනිවාර්යයෙන්ම බොහෝ අවස්ථාවන් සඳහා හොඳ සූත්‍රයක් වන අතර, වෙනත් පිළිතුරු දැනටමත් එයට ඇතුළත් කර ඇති බැවින් මම අවකාශය ගැනීමට යන්නේ නැත. නමුත් කුමන සූත්‍රයක් භාවිතා කළත් (ඔව් එකක් පමණක් නොවේ) බව සැලකිල්ලට ගැනීම වැදගත්ය. හැකි තරම් විශාල නිරවද්‍යතාව මෙන්ම ගණනය කිරීමේ කාලය නිසා. සූත්‍රය තේරීම සඳහා සරල මොළයක් නැති පිළිතුරකට වඩා ටිකක් වැඩි සිතුවිල්ලක් අවශ්‍ය වේ.

නාසා හි පුද්ගලයෙකුගෙන් මෙම පළ කිරීම, විකල්පයන් සාකච්ඡා කිරීමේදී මා සොයාගත් හොඳම එකයි

http://www.cs.nyu.edu/visual/home/proj/tiger/gisfaq.html

උදාහරණයක් ලෙස, ඔබ සැතපුම් 100 ක අරයක් තුළ දුරින් පේළි වර්ග කරන්නේ නම්. පැතලි පෘථිවි සූත්‍රය හැවර්සීන් වලට වඩා වේගවත් වනු ඇත.

HalfPi = 1.5707963;
R = 3956; /* the radius gives you the measurement unit*/

a = HalfPi - latoriginrad;
b = HalfPi - latdestrad;
u = a * a + b * b;
v = - 2 * a * b * cos(longdestrad - longoriginrad);
c = sqrt(abs(u + v));
return R * c;

එක් කොසයින් හා වර්ග මූලයක් පමණක් ඇති බව සැලකිල්ලට ගන්න. හේවර්සීන් සූත්‍රයේ 9 වන Vs.


1
එය හොඳ හැකියාවක්. සාකච්ඡාවේ නිර්දේශිත උපරිම දුර සැතපුම් 12 ක් මිස 100 ක් නොවන බවත්, එසේ වුවද, දෝෂයන් ලෝකයේ පිහිටීම අනුව මීටර් 30 (අඩි 100) දක්වා ගමන් කළ හැකි බවත් මතක තබා ගන්න.
එරික් වු

8

තවත් පිළිතුරක් එක් කිරීමට මා කැමති නැත, නමුත් ගූගල් සිතියම් API v.3 හි ගෝලාකාර ජ්‍යාමිතිය ඇත (සහ තවත්). ඔබේ WGS84 දශම අංශක බවට පරිවර්තනය කිරීමෙන් පසු ඔබට මෙය කළ හැකිය:

<script src="http://maps.google.com/maps/api/js?sensor=false&libraries=geometry" type="text/javascript"></script>  

distance = google.maps.geometry.spherical.computeDistanceBetween(
    new google.maps.LatLng(fromLat, fromLng), 
    new google.maps.LatLng(toLat, toLng));

ගූගල් ගණනය කිරීම් කෙතරම් නිවැරදිද යන්න හෝ කුමන ආකෘතියක් භාවිතා කරන්නේද යන්න ගැන වචනයක්වත් නැත (එය "භූමි" යන්නට වඩා "ගෝලාකාර" යැයි පැවසුවද, මාර්ගය වන විට, "සරල රේඛාව" දුර යමෙකු ගමන් කරන්නේ නම් දුරට වඩා වෙනස් වනු ඇත. සෑම කෙනෙකුම උපකල්පනය කරන පරිදි පෘථිවි පෘෂ් surface ය.


දුර මීටර වලින්. විකල්පයක් ලෙස එක් computeLength () භාවිතා කළ හැක
electrobabe

8

සරල විසඳුමක් තිබිය හැකි අතර වඩාත් නිවැරදි ය: පෘථිවියේ පරිමිතිය සමකයට කිලෝමීටර 40,000 ක් ද ග්‍රීන්විච් (හෝ ඕනෑම දේශාංශ) චක්‍රයක 37,000 ක් ද වේ. මේ අනුව:

pythagoras = function (lat1, lon1, lat2, lon2) {
   function sqr(x) {return x * x;}
   function cosDeg(x) {return Math.cos(x * Math.PI / 180.0);}

   var earthCyclePerimeter = 40000000.0 * cosDeg((lat1 + lat2) / 2.0);
   var dx = (lon1 - lon2) * earthCyclePerimeter / 360.0;
   var dy = 37000000.0 * (lat1 - lat2) / 360.0;

   return Math.sqrt(sqr(dx) + sqr(dy));
};

එය ඉලිප්සොයිඩ් බව මා විසින්ම පැවසූ බැවින් එය මනාව සකස් කළ යුතු බව මම එකඟ වෙමි, එබැවින් කොසයින් මගින් ගුණ කළ යුතු අරය වෙනස් වේ. නමුත් එය ටිකක් නිවැරදි ය. ගූගල් සිතියම් සමඟ සසඳන විට එය දෝෂය සැලකිය යුතු ලෙස අඩු කළේය.


මෙම ශ්‍රිතය ආපසු පැමිණීමේ දුර කිලෝමීටරයක්ද?
විකී

එය සමකයට හා දේශාංශ චක්‍රයට කි.මී. සැතපුම් සඳහා, 40000 සහ 37000 1.6 න් බෙදන්න. භූගෝලීය බවක් දැනෙන විට, ඔබට එය රිස් බවට පරිවර්තනය කළ හැකිය, 7 කින් පමණ ගුණ කළ හැකිය, නැතහොත් පරසැන්ග් විය හැකිය, 2.2
න් බෙදන්න

මෙය මෙහි දී ඇති හොඳම පිළිතුර බව පෙනේ. මම එය භාවිතා කිරීමට කැමති නමුත් මෙම ඇල්ගොරිතමයේ නිරවද්‍යතාවය සත්‍යාපනය කිරීමට ක්‍රමයක් තිබේදැයි මම කල්පනා කරමි. මම f (50,5,58,3) පරීක්ෂා කළා. ඇති ෙහයින්ද එය, 832km දෙන movable-type.co.uk/scripts/latlong.html වන 'haversine' සූත්රය භාවිතා 899km ලබා දෙයි. එතරම් විශාල වෙනසක් තිබේද?
චොං ලිප් ෆැන්ග්

එපමණක් නොව, ඉහත කේතය මඟින් ආපසු ලබා දුන් අගය කි.මී. නොව m වේ.
චොං ලිප් ෆැන්ග්

1
මෙම සූත්‍රයේ සාවද්‍ය අංකයක් ඇත. ධ්‍රැව හරහා වට ප්‍රමාණය 6356.752 නාසා * 2 පී = 39940.651 කි. 37000 නොවේ. එබැවින් චොං දුටු පරිදි අක්ෂාංශ වල වෙනස්කම් සඳහා අඩු පිළිතුරු සපයයි. "37000000.0" "39940651.0" සමඟ ප්රතිස්ථාපනය කරන්න. මෙම නිවැරදි කිරීමත් සමඟ, මගේ අනුමානය 100 සිට 1 කොටස දක්වා නිරවද්‍යතාවය, එක් අංශකයකට වඩා වැඩි දුරක්. (සත්‍යාපනය කර නැත.)
මෙවලම් සාදන්නා

8

ඉහත සියලු පිළිතුරු උපකල්පනය කරන්නේ පෘථිවිය ගෝලයක් බවයි. කෙසේ වෙතත්, වඩාත් නිවැරදි තක්සේරුවක් වනුයේ ඕලෙට් ස්පීරොයිඩ් ය.

a= 6378.137#equitorial radius in km
b= 6356.752#polar radius in km

def Distance(lat1, lons1, lat2, lons2):
    lat1=math.radians(lat1)
    lons1=math.radians(lons1)
    R1=(((((a**2)*math.cos(lat1))**2)+(((b**2)*math.sin(lat1))**2))/((a*math.cos(lat1))**2+(b*math.sin(lat1))**2))**0.5 #radius of earth at lat1
    x1=R*math.cos(lat1)*math.cos(lons1)
    y1=R*math.cos(lat1)*math.sin(lons1)
    z1=R*math.sin(lat1)

    lat2=math.radians(lat2)
    lons2=math.radians(lons2)
    R1=(((((a**2)*math.cos(lat2))**2)+(((b**2)*math.sin(lat2))**2))/((a*math.cos(lat2))**2+(b*math.sin(lat2))**2))**0.5 #radius of earth at lat2
    x2=R*math.cos(lat2)*math.cos(lons2)
    y2=R*math.cos(lat2)*math.sin(lons2)
    z2=R*math.sin(lat2)

    return ((x1-x2)**2+(y1-y2)**2+(z1-z2)**2)**0.5

7

මෙය ගණනය කිරීම සඳහා ඔබට CLLocationDistance හි ගොඩනැගීම භාවිතා කළ හැකිය:

CLLocation *location1 = [[CLLocation alloc] initWithLatitude:latitude1 longitude:longitude1];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:latitude2 longitude:longitude2];
[self distanceInMetersFromLocation:location1 toLocation:location2]

- (int)distanceInMetersFromLocation:(CLLocation*)location1 toLocation:(CLLocation*)location2 {
    CLLocationDistance distanceInMeters = [location1 distanceFromLocation:location2];
    return distanceInMeters;
}

ඔබේ නඩුවේදී ඔබට කිලෝමීටර අවශ්‍ය නම් 1000 න් බෙදන්න.


7

පයිතන් ආවේගකරණය සම්භවය එක්සත් ජනපදයේ කේන්ද්‍රස්ථානයයි.

from haversine import haversine
origin = (39.50, 98.35)
paris = (48.8567, 2.3508)
haversine(origin, paris, miles=True)

කිලෝමීටර වලින් පිළිතුර ලබා ගැනීම සඳහා සැතපුම් = අසත්‍යය සකසන්න.


2
ඔබ ආනයනය කරන්නේ සම්මත නොවන පැකේජයක් වන අතර එය සියලු කටයුතු කරයි. ඒ සියල්ල ප්‍රයෝජනවත් දැයි මම නොදනිමි.
Teepeemm

පැකේජය පයිපී 3, පයිතන් පැකේජ දර්ශකයේ, පයිතන් 3 පැකේජයක් ලෙස අංකිත හා ස්කිකිට්-ලර්න් සමඟ ඇත. එකක් ඇසුරුම් සඳහා යොදවන්නේ ඇයිදැයි විශ්වාස නැත. ඒවා බෙහෙවින් ප්‍රයෝජනවත් වේ. විවෘත මූලාශ්‍රයක් ලෙස යමෙකුට එහි අඩංගු ක්‍රම පරීක්ෂා කළ හැකිය. මම හිතන්නේ බොහෝ දෙනෙකුට මෙම පැකේජය ප්‍රයෝජනවත් වේවි, එබැවින් පහත වැටීම නොතකා මම තනතුරෙන් ඉවත් වෙමි. චියර්ස්. :)
invoketheshell

6

පෙන්වා දුන් පරිදි, නිවැරදි ගණනය කිරීමකින් පෘථිවිය පරිපූර්ණ ගෝලයක් නොවන බව සැලකිල්ලට ගත යුතුය. මෙහි ඉදිරිපත් කර ඇති විවිධ ඇල්ගොරිතමයන්ගේ සැසඳීම් කිහිපයක් මෙන්න:

geoDistance(50,5,58,3)
Haversine: 899 km
Maymenn: 833 km
Keerthana: 897 km
google.maps.geometry.spherical.computeDistanceBetween(): 900 km

geoDistance(50,5,-58,-3)
Haversine: 12030 km
Maymenn: 11135 km
Keerthana: 10310 km
google.maps.geometry.spherical.computeDistanceBetween(): 12044 km

geoDistance(.05,.005,.058,.003)
Haversine: 0.9169 km
Maymenn: 0.851723 km
Keerthana: 0.917964 km
google.maps.geometry.spherical.computeDistanceBetween(): 0.917964 km

geoDistance(.05,80,.058,80.3)
Haversine: 33.37 km
Maymenn: 33.34 km
Keerthana: 33.40767 km
google.maps.geometry.spherical.computeDistanceBetween(): 33.40770 km

කුඩා දුරින්, කීර්තානාගේ ඇල්ගොරිතම ගූගල් සිතියම් සමඟ සමපාත වන බව පෙනේ. ගූගල් සිතියම් කිසිදු සරල ඇල්ගොරිතමයක් අනුගමනය කරන බවක් නොපෙනේ, එය මෙහි වඩාත්ම නිවැරදි ක්‍රමය විය හැකි යැයි යෝජනා කරයි.

කෙසේ වෙතත්, මෙන්න කීර්තිනාගේ ඇල්ගොරිතමයේ ජාවාස්ක්‍රිප්ට් ක්‍රියාත්මක කිරීමකි:

function geoDistance(lat1, lng1, lat2, lng2){
    const a = 6378.137; // equitorial radius in km
    const b = 6356.752; // polar radius in km

    var sq = x => (x*x);
    var sqr = x => Math.sqrt(x);
    var cos = x => Math.cos(x);
    var sin = x => Math.sin(x);
    var radius = lat => sqr((sq(a*a*cos(lat))+sq(b*b*sin(lat)))/(sq(a*cos(lat))+sq(b*sin(lat))));

    lat1 = lat1 * Math.PI / 180;
    lng1 = lng1 * Math.PI / 180;
    lat2 = lat2 * Math.PI / 180;
    lng2 = lng2 * Math.PI / 180;

    var R1 = radius(lat1);
    var x1 = R1*cos(lat1)*cos(lng1);
    var y1 = R1*cos(lat1)*sin(lng1);
    var z1 = R1*sin(lat1);

    var R2 = radius(lat2);
    var x2 = R2*cos(lat2)*cos(lng2);
    var y2 = R2*cos(lat2)*sin(lng2);
    var z2 = R2*sin(lat2);

    return sqr(sq(x1-x2)+sq(y1-y2)+sq(z1-z2));
}

6

කිලෝමීටරයක දුර ගණනය කිරීම සඳහා SQL ක්‍රියාත්මක කිරීම මෙන්න,

SELECT UserId, ( 3959 * acos( cos( radians( your latitude here ) ) * cos( radians(latitude) ) * 
cos( radians(longitude) - radians( your longitude here ) ) + sin( radians( your latitude here ) ) * 
sin( radians(latitude) ) ) ) AS distance FROM user HAVING
distance < 5  ORDER BY distance LIMIT 0 , 5;

ක්‍රමලේඛන භාෂාමය මඟින් ක්‍රියාත්මක කිරීම පිළිබඳ වැඩි විස්තර සඳහා, ඔබට මෙහි දී ඇති php ස්ක්‍රිප්ට් එක හරහා යා හැකිය


5

මෙන්න මෙය නම් typescript මෙම Haversine සූත්රය ක්රියාත්මක කිරීම

static getDistanceFromLatLonInKm(lat1: number, lon1: number, lat2: number, lon2: number): number {
    var deg2Rad = deg => {
        return deg * Math.PI / 180;
    }

    var r = 6371; // Radius of the earth in km
    var dLat = deg2Rad(lat2 - lat1);   
    var dLon = deg2Rad(lon2 - lon1);
    var a =
        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(deg2Rad(lat1)) * Math.cos(deg2Rad(lat2)) *
        Math.sin(dLon / 2) * Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = r * c; // Distance in km
    return d;
}

4

මෙම ස්ක්‍රිප්ට් එක [PHP හි] ලකුණු දෙක අතර දුර ගණනය කරයි.

public static function getDistanceOfTwoPoints($source, $dest, $unit='K') {
        $lat1 = $source[0];
        $lon1 = $source[1];
        $lat2 = $dest[0];
        $lon2 = $dest[1];

        $theta = $lon1 - $lon2;
        $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
        $dist = acos($dist);
        $dist = rad2deg($dist);
        $miles = $dist * 60 * 1.1515;
        $unit = strtoupper($unit);

        if ($unit == "K") {
            return ($miles * 1.609344);
        }
        else if ($unit == "M")
        {
            return ($miles * 1.609344 * 1000);
        }
        else if ($unit == "N") {
            return ($miles * 0.8684);
        } 
        else {
            return $miles;
        }
    }

4

හැවර්සින් සූත්‍රයට අනුව ජාවා ක්‍රියාත්මක කිරීම

double calculateDistance(double latPoint1, double lngPoint1, 
                         double latPoint2, double lngPoint2) {
    if(latPoint1 == latPoint2 && lngPoint1 == lngPoint2) {
        return 0d;
    }

    final double EARTH_RADIUS = 6371.0; //km value;

    //converting to radians
    latPoint1 = Math.toRadians(latPoint1);
    lngPoint1 = Math.toRadians(lngPoint1);
    latPoint2 = Math.toRadians(latPoint2);
    lngPoint2 = Math.toRadians(lngPoint2);

    double distance = Math.pow(Math.sin((latPoint2 - latPoint1) / 2.0), 2) 
            + Math.cos(latPoint1) * Math.cos(latPoint2)
            * Math.pow(Math.sin((lngPoint2 - lngPoint1) / 2.0), 2);
    distance = 2.0 * EARTH_RADIUS * Math.asin(Math.sqrt(distance));

    return distance; //km value
}

3

ගෝලයක ලකුණු දෙකක් අතර දුර ගණනය කිරීම සඳහා ඔබ මහා කවය ගණනය කිරීම කළ යුතුය යුතුය.

MapTools හි සිතියම් ප්‍රක්ෂේපණයට සහාය වීම සඳහා C / C ++ පුස්තකාල ගණනාවක් තිබේඔබේ දුර පැතලි මතුපිටකට ප්‍රතික්ෂේප කිරීමට අවශ්‍ය නම් තිබේ. මෙය සිදු කිරීම සඳහා ඔබට විවිධ ඛණ්ඩාංක පද්ධතිවල ප්‍රක්ෂේපණ නූල අවශ්‍ය වේ.

ලකුණු දෘශ්‍යමාන කිරීම සඳහා ඔබට MapWindow ප්‍රයෝජනවත් මෙවලමක් ද සොයාගත හැකිය . එහි විවෘත මූලාශ්‍රය ලෙස එය ප්‍රොජෙඩ් ඩීඑල් පුස්තකාලය භාවිතා කරන්නේ කෙසේද යන්න පිළිබඳ ප්‍රයෝජනවත් මාර්ගෝපදේශයකි.


3

ඕනෑම කෙනෙකුට අවශ්‍ය නම් ජාවා වෙත පිළිගත් පිළිතුරු ක්‍රියාත්මක කිරීම මෙන්න.

package com.project529.garage.util;


/**
 * Mean radius.
 */
private static double EARTH_RADIUS = 6371;

/**
 * Returns the distance between two sets of latitudes and longitudes in meters.
 * <p/>
 * Based from the following JavaScript SO answer:
 * http://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula,
 * which is based on https://en.wikipedia.org/wiki/Haversine_formula (error rate: ~0.55%).
 */
public double getDistanceBetween(double lat1, double lon1, double lat2, double lon2) {
    double dLat = toRadians(lat2 - lat1);
    double dLon = toRadians(lon2 - lon1);

    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
                    Math.sin(dLon / 2) * Math.sin(dLon / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double d = EARTH_RADIUS * c;

    return d;
}

public double toRadians(double degrees) {
    return degrees * (Math.PI / 180);
}

2

VB.NET ක්‍රියාත්මක කිරීම මෙන්න, මෙම ක්‍රියාත්මක කිරීම මඟින් ඔබ සමත් වූ එනුම් අගය මත පදනම්ව KM හෝ සැතපුම් වලින් ප්‍රති result ලය ලබා දෙනු ඇත.

Public Enum DistanceType
    Miles
    KiloMeters
End Enum

Public Structure Position
    Public Latitude As Double
    Public Longitude As Double
End Structure

Public Class Haversine

    Public Function Distance(Pos1 As Position,
                             Pos2 As Position,
                             DistType As DistanceType) As Double

        Dim R As Double = If((DistType = DistanceType.Miles), 3960, 6371)

        Dim dLat As Double = Me.toRadian(Pos2.Latitude - Pos1.Latitude)

        Dim dLon As Double = Me.toRadian(Pos2.Longitude - Pos1.Longitude)

        Dim a As Double = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(Me.toRadian(Pos1.Latitude)) * Math.Cos(Me.toRadian(Pos2.Latitude)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2)

        Dim c As Double = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a)))

        Dim result As Double = R * c

        Return result

    End Function

    Private Function toRadian(val As Double) As Double

        Return (Math.PI / 180) * val

    End Function

End Class

"අ" ගණනය කිරීමෙන් පසු, ඔබ Math.Sin ( dLat ..) දෙවරක් වැරදීමකින් ලියා තිබේද?
මාකෝ ඔටිනා

2

සූත්‍රය සරල කිරීමෙන් මම ගණනය කිරීම ensed නීභවනය කළෙමි.

මෙන්න එය රූබි හි ඇත:

include Math
earth_radius_mi = 3959
radians = lambda { |deg| deg * PI / 180 }
coord_radians = lambda { |c| { :lat => radians[c[:lat]], :lng => radians[c[:lng]] } }

# from/to = { :lat => (latitude_in_degrees), :lng => (longitude_in_degrees) }
def haversine_distance(from, to)
  from, to = coord_radians[from], coord_radians[to]
  cosines_product = cos(to[:lat]) * cos(from[:lat]) * cos(from[:lng] - to[:lng])
  sines_product = sin(to[:lat]) * sin(from[:lat])
  return earth_radius_mi * acos(cosines_product + sines_product)
end

2
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2,units) {
  var R = 6371; // Radius of the earth in km
  var dLat = deg2rad(lat2-lat1);  // deg2rad below
  var dLon = deg2rad(lon2-lon1); 
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2)
    ; 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c; 
  var miles = d / 1.609344; 

if ( units == 'km' ) {  
return d; 
 } else {
return miles;
}}

චක්ගේ විසඳුම සැතපුම් ගණනක් සඳහා වලංගු වේ.


2

යම් සෙවීමකින් පසු දශම අංශක හරහා දුර ගණනය කිරීම සඳහා මගේ ජාවා ක්‍රියාත්මක කිරීම මෙන්න. මම ලෝකයේ මධ්‍ය අරය (විකිපීඩියාවේ සිට) කි.මී. ඔබට ප්‍රති result ල සැතපුම් අවශ්‍ය නම් ලෝක අරය සැතපුම් වලින් භාවිතා කරන්න.

public static double distanceLatLong2(double lat1, double lng1, double lat2, double lng2) 
{
  double earthRadius = 6371.0d; // KM: use mile here if you want mile result

  double dLat = toRadian(lat2 - lat1);
  double dLng = toRadian(lng2 - lng1);

  double a = Math.pow(Math.sin(dLat/2), 2)  + 
          Math.cos(toRadian(lat1)) * Math.cos(toRadian(lat2)) * 
          Math.pow(Math.sin(dLng/2), 2);

  double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

  return earthRadius * c; // returns result kilometers
}

public static double toRadian(double degrees) 
{
  return (degrees * Math.PI) / 180.0d;
}

2

Mysql හි පහත දැක්වෙන ශ්‍රිතය භාවිතා කරන පරාමිතීන් පසු කරන්න POINT(LONG,LAT)

CREATE FUNCTION `distance`(a POINT, b POINT)
 RETURNS double
    DETERMINISTIC
BEGIN

RETURN

GLength( LineString(( PointFromWKB(a)), (PointFromWKB(b)))) * 100000; -- To Make the distance in meters

END;

2
function getDistanceFromLatLonInKm(position1, position2) {
    "use strict";
    var deg2rad = function (deg) { return deg * (Math.PI / 180); },
        R = 6371,
        dLat = deg2rad(position2.lat - position1.lat),
        dLng = deg2rad(position2.lng - position1.lng),
        a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
            + Math.cos(deg2rad(position1.lat))
            * Math.cos(deg2rad(position1.lat))
            * Math.sin(dLng / 2) * Math.sin(dLng / 2),
        c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    return R * c;
}

console.log(getDistanceFromLatLonInKm(
    {lat: 48.7931459, lng: 1.9483572},
    {lat: 48.827167, lng: 2.2459745}
));

2

postgres sql හි උදාහරණයක් මෙහි දැක්වේ (කි.මී., සැතපුම් අනුවාදය සඳහා, 1.609344 වෙනුවට 0.8684 අනුවාදය)

CREATE OR REPLACE FUNCTION public.geodistance(alat float, alng float, blat  

float, blng  float)
  RETURNS float AS
$BODY$
DECLARE
    v_distance float;
BEGIN

    v_distance = asin( sqrt(
            sin(radians(blat-alat)/2)^2 
                + (
                    (sin(radians(blng-alng)/2)^2) *
                    cos(radians(alat)) *
                    cos(radians(blat))
                )
          )
        ) * cast('7926.3352' as float) * cast('1.609344' as float) ;


    RETURN v_distance;
END 
$BODY$
language plpgsql VOLATILE SECURITY DEFINER;
alter function geodistance(alat float, alng float, blat float, blng float)
owner to postgres;

2

මෙන්න තවත් එකක් රූබි කේතයට පරිවර්තනය කර ඇත :

include Math
#Note: from/to = [lat, long]

def get_distance_in_km(from, to)
  radians = lambda { |deg| deg * Math.PI / 180 }
  radius = 6371 # Radius of the earth in kilometer
  dLat = radians[to[0]-from[0]]
  dLon = radians[to[1]-from[1]]

  cosines_product = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(radians[from[0]]) * Math.cos(radians[to[1]]) * Math.sin(dLon/2) * Math.sin(dLon/2)

  c = 2 * Math.atan2(Math.sqrt(cosines_product), Math.sqrt(1-cosines_product)) 
  return radius * c # Distance in kilometer
end

2

මෙය වඩාත් ජනප්‍රිය සාකච්ඡාව බැවින් මම 2019 අග සිට 2020 මුල සිට මගේ අත්දැකීම් මෙහි එක් කරමි. පවතින පිළිතුරු වලට එකතු කිරීම සඳහා - මගේ අවධානය යොමු වූයේ නිවැරදි හා දෛශික විසඳුමක් සොයා ගැනීම සඳහා ය.

හැවර්සීන් ප්‍රවේශය වේගවත්ම විකල්පය වන අතර දෛශිකකරණය පහසුය, පහත උදාහරණය බලන්න.

def haversine(lat1, lon1, lat2, lon2):
    """
    Calculate the great circle distance between two points
    on the earth (specified in decimal degrees)

    All args must be of equal length.
    Distances are in meters.

    Ref:
    /programming/29545704/fast-haversine-approximation-python-pandas
    https://ipython.readthedocs.io/en/stable/interactive/magics.html
    """
    Radius = 6.371e6
    lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])

    dlon = lon2 - lon1
    dlat = lat2 - lat1

    a = np.sin(dlat/2.0)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2.0)**2

    c = 2 * np.arcsin(np.sqrt(a))
    s12 = Radius * c

    # initial azimuth in degrees
    y = np.sin(lon2-lon1) * np.cos(lat2)
    x = np.cos(lat1)*np.sin(lat2) - np.sin(lat1)*np.cos(lat2)*np.cos(dlon)
    azi1 = np.arctan2(y, x)*180./math.pi

    return {'s12':s12, 'azi1': azi1}

නිරවද්‍යතාව අනුව එය අවම වශයෙන් නිවැරදි ය. විකිපීඩියාව පවසන්නේ කිසිදු ප්‍රභවයක් නොමැතිව 0.5% හොඳම බවයි. මගේ අත්හදා බැලීම් වලින් අඩු අපගමනය පෙන්නුම් කරයි (මෙන්න එය මගේ දෛශිකකරණය කළ වින්සෙන්ටි ක්‍රියාත්මක කිරීම හා සැසඳේ):

np.random.seed(42)
lats1 = np.random.uniform(-90,90,100000)
lons1 = np.random.uniform(-180,180,100000)
lats2 = np.random.uniform(-90,90,100000)
lons2 = np.random.uniform(-180,180,100000)
r1 = inverse(lats1, lons1, lats2, lons2)
r2 = haversine(lats1, lons1, lats2, lons2)
print("Max absolute error: {:4.2f}m".format(np.max(r1['s12']-r2['s12'])))
print("Mean absolute error: {:4.2f}m".format(np.mean(r1['s12']-r2['s12'])))
print("Max relative error: {:4.2f}%".format(np.max((r2['s12']/r1['s12']-1)*100)))
print("Mean relative error: {:4.2f}%".format(np.mean((r2['s12']/r1['s12']-1)*100)))
Max absolute error: 26671.47m
Mean absolute error: -2499.84m
Max relative error: 0.55%
Mean relative error: -0.02%

මෙහි සඳහන් කර ඇති පරිදි, වින්සන්ටිගේ සූත්‍ර ඔබේ අභිසාරීතා නිර්ණායක මත පදනම්ව මිලිමීටර දක්වා නිවැරදි වන අතර එය දෛශිකකරණය කළ හැකිය. ප්‍රතිදේහ ලක්ෂ්‍ය අසල අභිසාරී වීම පිළිබඳ ගැටළුව එයට ඇත. අභිසාරී නිර්ණායක ලිහිල් කිරීමෙන් එම ස්ථානවල එය අභිසාරී වීමට ඉඩ ඇත, නමුත් නිරවද්‍යතාව 0.25% දක්වා පහත වැටෙන අතර භූගෝලීය ලිබ් එදිරිව එදිරිව මෙහි සඳහන් කර ඇති අතර එය මේ මොහොතේ හොඳම විසඳුම යැයි මම විශ්වාස කරමි. මගේ සංඛ්‍යාත්මක අත්හදා බැලීම් වලදී, ප්‍රති-පොඩල් ලකුණු වලින් පිටත වින්සෙන්ටි සාමාන්‍යයෙන් 1.e-6 ට අඩු සාපේක්ෂ දෝෂයක් තුළ භූගෝලීය ලිබ්ට ආසන්න ප්‍රති results ල ලබා දෙන බව මම දුටුවෙමි.

භූගෝලීය ලිබ් තරමක් වේගවත් ය, විශේෂයෙන් ඔබ C ++ ක්‍රියාත්මක කිරීම භාවිතා කරන්නේ නම්. ලකුණු 10 ට වඩා වැඩි යමක් සඳහා ඔබ පයිතන් භාවිතා කිරීමට අදහස් කරන්නේ නම්, දෛශිකකරණය කිරීම ක්‍රියාත්මක කිරීමට සලකා බැලීමට මම යෝජනා කරමි. මගේ අවශ්‍යතාවයන් සඳහා මම දෛශිකකරණය කළ වින්සෙන්ටි පුරුද්දක් සහිත භූ-භූමි පුස්තකාලයක් නිර්මාණය කළෙමි . මෙන්න 100k ලකුණු සඳහා Geographiclib එදිරිව සංසන්දනය. ඔබට පෙනෙන පරිදි එය ප්‍රතිලෝම සඳහා 20x දක්වා සහ 100k ලකුණු සඳහා සෘජු ක්‍රම සඳහා 100x දක්වා වැඩි දියුණු කිරීමක් සපයන අතර පරතරය ලකුණු ගණන සමඟ වර්ධනය වේ. නිරවද්‍යතාව අනුව එය 1.e-5 rtol තුළ වේ.

Direct method for 100,000 points
94.9 ms ± 25 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
9.79 s ± 1.4 s per loop (mean ± std. dev. of 7 runs, 1 loop each)

Inverse method for 100,000 points
1.5 s ± 504 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
24.2 s ± 3.91 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.