दो अक्षांश-देशांतर बिंदुओं के बीच की दूरी की गणना करें? (हैवरसाइन सूत्र)


905

मैं अक्षांश और देशांतर द्वारा निर्दिष्ट दो बिंदुओं के बीच की दूरी की गणना कैसे करूं?

स्पष्टीकरण के लिए, मुझे किलोमीटर में दूरी पसंद है; अंक WGS84 प्रणाली का उपयोग करते हैं और मैं उपलब्ध दृष्टिकोणों के सापेक्ष सटीकता को समझना चाहूंगा।


बेहतर सटीकता के लिए - stackoverflow.com/questions/1420045/…
लियो कोगन

3
ध्यान दें कि आप डब्ल्यूजीएस 84 की तरह क्रांति के दीर्घवृत्त पर एक हेवर्सिन फार्मूला लागू नहीं कर सकते। आप केवल इस पद्धति को एक दायरे के साथ लागू कर सकते हैं।
माइक टी।

3
यहां अधिकांश उत्तर सरल गोलाकार त्रिकोणमिति का उपयोग कर रहे हैं, इसलिए परिणाम जीपीएस सिस्टम में उपयोग किए गए WGS84 दीर्घवृत्त दूरी की तुलना में कच्चे हैं। कुछ उत्तर दीर्घवृत्त के लिए विन्सेन्टी के सूत्र का उल्लेख करते हैं, लेकिन उस एल्गोरिथ्म को 1960 के युग के डेस्क कैलकुलेटर पर उपयोग के लिए डिज़ाइन किया गया था और इसमें स्थिरता और सटीकता के मुद्दे हैं; अब हमारे पास बेहतर हार्डवेयर और सॉफ्टवेयर हैं। कृपया विभिन्न भाषाओं में कार्यान्वयन के साथ एक उच्च गुणवत्ता वाले पुस्तकालय के लिए जियोग्राफिकलिब देखें ।
PM 2Ring

@ माइक - सच है, हालांकि यहाँ कई उत्तर छोटी दूरी पर उपयोगी लगते हैं : यदि आप डब्ल्यूजीएस 84 से लेट / लॉन्ग लेते हैं, और हैवेरसाइन को लागू करते हैं जैसे कि वे एक गोले पर बिंदु थे , तो क्या आपको ऐसे उत्तर नहीं मिलते हैं जिनकी त्रुटियां केवल उसी के कारण हैं पृथ्वी का समतल कारक, तो शायद 1% अधिक सटीक सूत्र के भीतर? इस चेतावनी के साथ कि ये छोटी दूरियां हैं, एक शहर के भीतर कहें।
टूलमेकरसेव

1
इन प्लेटफॉर्मों के लिए: मोनो / .NET 4.5 / .NET कोर / विंडोज फोन 8.x / यूनिवर्सल विंडोज प्लेटफॉर्म / एक्समरीन iOS / Xamarin एंड्रॉयड देखें stackoverflow.com/a/54296314/2736742
ए। मोरेल

जवाबों:


1145

यह लिंक आपके लिए मददगार हो सकता है, क्योंकि यह दूरी की गणना करने के लिए हैवरसाइन सूत्र के उपयोग का विवरण देता है ।

अंश:

यह स्क्रिप्ट [जावास्क्रिप्ट में] दो बिंदुओं के बीच महान-सर्कल दूरी की गणना करती है - अर्थात, पृथ्वी की सतह पर सबसे छोटी दूरी - 'हैवरसाइन' सूत्र का उपयोग करना।

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)), जो विकिपीडिया लेख का उपयोग करने वाले सूत्र का प्रत्यक्ष कार्यान्वयन होगा? क्या यह अधिक कुशल और / या अधिक संख्यात्मक रूप से स्थिर है?
मुशीफिल

16
@UsmanMutawakil खैर, आपको मिलने वाली 38 मील सड़क पर दूरी है। यह एल्गोरिथ्म पृथ्वी की सतह पर एक सीधी रेखा की दूरी की गणना करता है। Google मैप्स में एक दूरी उपकरण (नीचे बाईं ओर, "लैब्स") है जो समान है, तुलना करने के लिए इसका उपयोग करें।
पास्कल

4
@ Forte_201092: क्योंकि यह आवश्यक नहीं है - (sin(x))²बराबर(sin(-x))²
जीन होमिनल

359

मुझे अपनी परियोजना के लिए बिंदुओं के बीच बहुत अधिक दूरी की गणना करने की आवश्यकता थी, इसलिए मैंने आगे बढ़कर कोड को अनुकूलित करने का प्रयास किया, मैंने यहां पाया है। अलग-अलग ब्राउज़रों में औसतन मेरा नया कार्यान्वयन सबसे अधिक उत्तर वाले उत्तर की तुलना में 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...

और पूर्णता के लिए: विकी पर हैवरसाइन


13
@AngularM और इस बात की बहुत अधिक संभावना है कि Google दूरी की गणना करता है यदि आप कुछ सड़कें ले रहे होंगे और एक सीधी रेखा नहीं होगी।
साल्वाडोर डाली

3
Google ड्राइविंग दूरी की गणना करता है, यह "कौवा मक्खियों के रूप में" की गणना करता है
होबिस्ट

4
@Ouadie और क्या यह गति में सुधार करेगा? सबसे शायद नहीं, लेकिन मैं बहुत से लोगों के लिए समाप्त हो जाऊंगा, जो आपके सामान को काम नहीं करते हैं जो पुराने ब्राउज़रों में इसे कॉपी करते हैं
सल्वाडोर डाली

4
अच्छी तरह से हाँ, लेकिन क्या करता // 2 * R; R = 6371 kmहै? और वर्तमान विधि किमी या मील में उत्तर प्रदान करती है? बेहतर प्रलेखन की जरूरत है। धन्यवाद
खलील खलफ

20
@KhalilKhalaf क्या आप मज़ाक कर रहे हैं या यहाँ ट्रोल करने की कोशिश कर रहे हैं? किमी किलोमीटर के लिए खड़ा है। आपको क्या लगता है R का मतलब है (विशेषकर यदि हम एक shpere के बारे में बोलते हैं)? यदि आप पहले से ही किमी को देखते हैं तो उत्तर क्या होगा। आप यहाँ किस तरह के दस्तावेज़ देख रहे हैं: वहाँ सचमुच 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);
क्रिस मैरिसिक

मैं क्रिस मैरिसिक से सहमत हूं। मैंने मूल कोड का उपयोग किया और गणना गलत थी। मैंने डेल्टास को रेडियंस में बदलने के लिए कॉल जोड़ा और यह अब ठीक से काम करता है। मैंने एक संपादन प्रस्तुत किया है और इसके लिए सहकर्मी की समीक्षा की प्रतीक्षा कर रहा हूं।
ब्रायन बेडार्ड

मैंने एक और संपादन प्रस्तुत किया क्योंकि lat1 और lat2 को भी रेडियन में बदलना होगा। मैंने असाइनमेंट के फॉर्मूले को संशोधित करने के लिए फॉर्मूले और कोड का मिलान यहाँ पाया: movable-type.co.uk/scripts/latlong.html
ब्रायन बेडार्ड

क्या RADIUSअन्य उत्तरों की तरह मूल्य 6371 होना चाहिए?
क्रिस हेस

66

यहाँ हैवर्सिन सूत्र का एक जावा कार्यान्वयन है।

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
lasec0203

42

इस सब के लिए बहुत बहुत धन्यवाद। मैंने अपने ऑब्जेक्टिव-सी 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 या बाद में उपयोग कर रहे हैं तो Apple इसे करने के लिए कुछ विधियाँ प्रदान करता है ताकि उसी कार्यक्षमता को प्राप्त किया जा सके:

-(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))गलत है। उन लोगों को निकालें, और जब मैं इस पृष्ठ पर अन्य कार्यान्वयन का उपयोग करता हूं, तो परिणाम मुझे मिलता है, या स्क्रैच से विकिपीडिया से हैवरसाइन सूत्र को लागू करता है ।
ज़नदीप

NYC के लिए निर्देशांक (40.7127837, -74.0059413) और LA के लिए (34.052234, -118.243685) का उपयोग करते हुए, ()उस राशि के आसपास, मुझे 3869.75 मिलता है। उनके बिना, मुझे ३ ९ ३५. ,५ मिलता है, जो कि एक वेब खोज में बदल जाता है।
ज़नदीप

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
यह पूरी तरह से काम करता है! मैंने अभी $ दूरी_मीलों = $ किमी * 0.621371 जोड़ी है; और वह सब मुझे मील में अनुमानित दूरी के लिए आवश्यक है! धन्यवाद टोनी।

31

मैं यहां अपना काम करने का उदाहरण देता हूं।

तालिका के सभी बिंदुओं को निर्दिष्ट बिंदु के बीच की दूरी पर सूचीबद्ध करें (हम एक यादृच्छिक बिंदु का उपयोग करते हैं - lat: 45.20327, लंबी: 23.7806) 50 KM से कम अक्षांश और देशांतर के साथ, MySQL में (तालिका फ़ील्ड ord_lat और ord_long हैं):

सभी की सूची सूची <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 (लिनक्स) में परीक्षण किया गया था।


मुझे लगता है कि एक अच्छा तरीका पूर्व-प्रक्रिया का उपयोग करके परिणामों को फ़िल्टर करने से पहले हो सकता है, इसलिए भारी फॉर्मूला केवल कुछ मामलों के लिए लागू किया जाता है। यदि आपके पास अन्य स्थितियां हैं तो विशेष रूप से उपयोगी है। मैं प्रारंभिक aprox के लिए इसका उपयोग कर रहा हूं: stackoverflow.com/questions/1253499/…
Pato

28

अन्य उत्तर में एक कार्यान्वयन लापता है।

दो बिंदुओं के बीच की दूरी की गणना पैकेज 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
मेरे जवाब के अंत में @ToolmakerSteve हवेर्सिन पद्धति का कार्यान्वयन है
जाप

हाय @ जप मैं पूछ सकता हूं कि सूत्र के लिए माप की इकाई क्या है? क्या यह मीटर में है?
जैक्सन

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 हवार्सिन सूत्र पर।


यह एक अच्छी संभावना है। बस इस बात से अवगत रहें कि चर्चा में अनुशंसित अधिकतम दूरी 12 मील है, 100 नहीं है , और यह भी कि, त्रुटियां 30 मीटर (100 फीट) तक रेंग सकती हैं, जो कि विश्व की स्थिति पर निर्भर करती है।
एरिक वू

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

मुझे अभी तक एक और उत्तर जोड़ना पसंद नहीं है, लेकिन Google मैप्स एपीआई 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));

Google की गणनाएँ कितनी सटीक हैं या यहां तक ​​कि किस मॉडल का उपयोग किया गया है, इसके बारे में कोई शब्द नहीं है (हालांकि यह "जियोइड के बजाय" गोलाकार "कहता है। वैसे," स्ट्रेट लाइन "दूरी स्पष्ट रूप से दूरी से अलग होगी यदि कोई यात्रा करता है। पृथ्वी की सतह जो सभी को प्रतीत होती है।


दूरी मीटर में है। वैकल्पिक रूप से एक कम्प्यूटरीकृत () का उपयोग कर सकते हैं
इलेक्ट्रोबैबे

7

पायथन निहितार्थ उत्पत्ति सन्निहित संयुक्त राज्य अमेरिका का केंद्र है।

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

किलोमीटर में उत्तर प्राप्त करने के लिए बस मील = गलत सेट करें।


1
आप एक गैर-मानक पैकेज आयात कर रहे हैं जो सभी काम करता है। मुझे नहीं पता कि क्या यह सब उपयोगी है।
तेईपेमम

पैकेज PyPI, Python Package Index में, अजगर 3 पैकेज के साथ-साथ सुकुमार और स्किकिट-लर्न के रूप में है। निश्चित नहीं है कि पैकेजों के लिए अपील क्यों की जाती है। वे काफी उपयोगी होते हैं। खुले स्रोत के रूप में, कोई निहित विधियों की भी जांच कर सकता है। मुझे लगता है कि कई लोगों को यह पैकेज उपयोगी लगेगा इसलिए मैं पद छोड़ने के बावजूद पद छोड़ दूंगा। चीयर्स। :)
invoketheshell

7

एक सरल समाधान हो सकता है, और अधिक सही: भूमध्य रेखा पर पृथ्वी की परिधि 40,000Km है, ग्रीनविच (या किसी देशांतर) चक्र पर लगभग 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 से विभाजित करें। Geeky लग रहा है, आप इसे Ris में बदल सकते हैं, लगभग 7 से गुणा कर सकते हैं या पैरासांग पर, 2.2 से विभाजित कर सकते हैं ;-)
Meymann

यह यहां प्रस्तुत सबसे अच्छा जवाब लगता है। मैं इसका उपयोग करना चाहता हूं लेकिन मुझे आश्चर्य है कि क्या इस एल्गोरिथ्म की शुद्धता को सत्यापित करने का कोई तरीका है। मैंने f (50,5,58,3) का परीक्षण किया। यह 832 किमी देता है, जबकि मूवेबल-type.co.uk/scripts/latlong.html 'हैवरसाइन' फॉर्मूला का उपयोग करके 899 किमी देता है। क्या इतना बड़ा अंतर है?
चोंग लिप फांग

इसके अलावा, मुझे लगता है कि उपरोक्त कोड द्वारा लौटाया गया मूल्य मीटर में है, न कि किमी।
चोंग लिप फांग

@ChongLipPhang - चेतावनी: पायथागॉरियन प्रमेय केवल छोटे क्षेत्रों के लिए उचित अनुमान है , क्योंकि यह प्रमेय मानता है कि पृथ्वी सपाट है। एक चरम मामले के रूप में, भूमध्य रेखा पर शुरू करें, और 90 डिग्री पूर्व और 90 डिग्री उत्तर की ओर बढ़ें। पाठ्यक्रम का अंतिम परिणाम उत्तरी ध्रुव है, और 0 डिग्री पूर्व और 90 डिग्री उत्तर की ओर बढ़ने के समान है; ऐसा करना sqrt (sqr (dx) + sqr (dy)) पहले मामले में बेतहाशा बंद होगा। ~ sqrt (10 किमी sqr + 10km sqr) ~ = 14.4 किमी बनाम सही दूरी ~ 10 किमी।
टूलमेकरसैट

7

उपरोक्त सभी उत्तर मानते हैं कि पृथ्वी एक क्षेत्र है। हालांकि, एक अधिक सटीक सन्निकटन एक गोलाकार गोलाकार होगा।

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

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

यहाँ हैवरसाइन सूत्र का एक टाइपस्क्रिप्ट कार्यान्वयन है

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;
}

5

जैसा कि कहा गया है, एक सटीक गणना को ध्यान में रखना चाहिए कि पृथ्वी एक आदर्श क्षेत्र नहीं है। यहां पेश किए गए विभिन्न एल्गोरिदम की कुछ तुलनाएं यहां दी गई हैं:

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

छोटी दूरी पर, Keerthana का एल्गोरिथ्म Google मैप्स के साथ मेल खाता है। Google मानचित्र किसी भी सरल एल्गोरिथ्म का पालन नहीं करता है, यह सुझाव देता है कि यह यहां सबसे सटीक तरीका हो सकता है।

वैसे भी, यहाँ कीर्तन के एल्गोरिथ्म का एक जावास्क्रिप्ट कार्यान्वयन है:

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));
}

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 पा सकते हैं । इसके ओपन सोर्स के रूप में इसका एक उपयोगी गाइड है कि कैसे proj.dll लाइब्रेरी का उपयोग किया जाए, जो कोर ओपन सोर्स प्रोजेक्शन लाइब्रेरी प्रतीत होती है।


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 या Miles में परिणाम देगा जो आपके द्वारा पास किए गए Enum मान पर आधारित है।

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

"A" की गणना करने पर, क्या आपने गलती से Math.Sin ( dLat ..) दो बार लिखा था ?
मार्को ओटिना

2

मैंने सूत्र को सरल करके गणना की निंदा की।

यहाँ यह रूबी में है:

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

यहाँ कुछ खोज के बाद दशमलव डिग्री के माध्यम से गणना दूरी के लिए मेरा जावा कार्यान्वयन है। मैंने किमी में दुनिया के विकीपीडिया (विकिपीडिया से) का उपयोग किया। İयदि आप परिणाम मील चाहते हैं तो मील में विश्व त्रिज्या का उपयोग करें।

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

उपयोग के रूप में मापदंडों का उपयोग करें 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

यहाँ पोस्टग्रेज एसक्यूएल में एक उदाहरण है (किमी में, मील संस्करण के लिए, 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

1

PHP http://www.geodatasource.com/developers/php के साथ दूरी की गणना करने के लिए यहां एक अच्छा उदाहरण है :

 function distance($lat1, $lon1, $lat2, $lon2, $unit) {

     $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 == "N") {
          return ($miles * 0.8684);
     } else {
          return $miles;
     }
 }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.