पाइथन में हैवरसाइन फॉर्मूला (दो जीपीएस बिंदुओं के बीच असर और दूरी)


119

संकट

मैं जानना चाहूंगा कि 2 जीपीएस बिंदुओं के बीच दूरी और असर कैसे प्राप्त करें । मैंने ह्वरसाइन सूत्र पर शोध किया है। किसी ने मुझे बताया कि मैं भी उसी डेटा का उपयोग करके असर पा सकता हूं।

संपादित करें

सब कुछ ठीक काम कर रहा है लेकिन असर अभी बहुत काम नहीं करता है। असर नकारात्मक उत्पन्न करता है, लेकिन 0 - 360 डिग्री के बीच होना चाहिए। सेट डेटा को क्षैतिज असर बनाना चाहिए 96.02166666666666 और यह है:

Start point: 53.32055555555556 , -1.7297222222222221   
Bearing:  96.02166666666666  
Distance: 2 km  
Destination point: 53.31861111111111, -1.6997222222222223  
Final bearing: 96.04555555555555

यहाँ मेरा नया कोड है:

from math import *

Aaltitude = 2000
Oppsite  = 20000

lat1 = 53.32055555555556
lat2 = 53.31861111111111
lon1 = -1.7297222222222221
lon2 = -1.6997222222222223

lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * atan2(sqrt(a), sqrt(1-a))
Base = 6371 * c


Bearing =atan2(cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon2-lon1), sin(lon2-lon1)*cos(lat2)) 

Bearing = degrees(Bearing)
print ""
print ""
print "--------------------"
print "Horizontal Distance:"
print Base
print "--------------------"
print "Bearing:"
print Bearing
print "--------------------"


Base2 = Base * 1000
distance = Base * 2 + Oppsite * 2 / 2
Caltitude = Oppsite - Aaltitude

a = Oppsite/Base
b = atan(a)
c = degrees(b)

distance = distance / 1000

print "The degree of vertical angle is:"
print c
print "--------------------"
print "The distance between the Balloon GPS and the Antenna GPS is:"
print distance
print "--------------------"

पायथन हावरिन कार्यान्वयन को कोडेकोडेक्स . com/wiki/… पाया जा सकता है । हालाँकि छोटी दूरी की गणना के लिए बहुत सरल तरीके मौजूद हैं। अब, आपकी अधिकतम दूरी क्या है? क्या आप कुछ स्थानीय कार्टेशियन समन्वय प्रणाली में अपने समन्वय प्राप्त करने में सक्षम हैं?
खाएं

अजगर में कुछ कार्यान्वयन: - code.activestate.com/recipes/… - platoscave.net/blog/2009/oct/5/…
Fábio Diniz

1
@ जेम्स डायसन: 15 किमी की दूरी के साथ, जीव चक्र कुछ भी नहीं गिनता है। मेरा सुझाव: यूक्लिडियन दूरियों के साथ पहले समाधान का पता लगाएं! यह आपको एक कार्यशील समाधान देगा और फिर बाद में यदि आपकी दूरियां बहुत अधिक हो जाएंगी, तो अपने आवेदन को समायोजित करें। साभार
खाएं

1
@ जेम्स डायसन: यदि आपकी उपरोक्त टिप्पणी का उद्देश्य मुझे (और मेरे पहले सुझाव पर) था, तो इसका उत्तर निश्चित रूप से (और साथ ही काफी 'तुच्छ' है)। मैं कुछ उदाहरण कोड देने में सक्षम हो सकता हूं, लेकिन यह त्रिकोणमिति का उपयोग नहीं करेगा, बल्कि ज्यामिति (इसलिए मैं अनिश्चित हूं अगर यह आपको बिल्कुल मदद करेगा। क्या आप वेक्टर की अवधारणा से बिल्कुल परिचित हैं? आपके मामले में स्थिति? दिशाओं को वैक्टर के साथ सबसे सरल तरीके से संभाला जा सकता है)।
खाना खाएं

1
atan2(sqrt(a), sqrt(1-a))के रूप में ही हैasin(sqrt(a))
user102008

जवाबों:


241

यहाँ एक पायथन संस्करण है:

from math import radians, cos, sin, asin, sqrt

def haversine(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points 
    on the earth (specified in decimal degrees)
    """
    # convert decimal degrees to radians 
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    r = 6371 # Radius of earth in kilometers. Use 3956 for miles
    return c * r

10
Pi / 180 से गुणा करने के बजाय math.radians () फ़ंक्शन का उपयोग कर सकता है - समान प्रभाव, लेकिन थोड़ा अधिक स्व-दस्तावेजीकरण।
ह्यूग बोथवेल

4
आप कर सकते हैं, लेकिन यदि आप कहते हैं import mathतो आपको निर्दिष्ट करना होगा math.pi, math.sinआदि के साथ from math import *आपको सभी मॉड्यूल सामग्री तक सीधे पहुंच प्राप्त होगी। एक अजगर ट्यूटोरियल में "नामस्थान" की जाँच करें (जैसे docs.python.org/tutorial/modules.html )
माइकल डन

2
आप केवल असिन (sqrt (a)) के बजाय atan2 (sqrt (a), sqrt (1-a)) का उपयोग कैसे करते हैं? क्या इस मामले में atan2 अधिक सटीक है?
ईयूल

4
यदि मीन त्रिज्या को 6371 किमी के रूप में परिभाषित किया गया है, तो वह 3959 मील के बराबर है, न कि 3956 मील। इन मूल्यों की गणना करने के विभिन्न तरीकों के लिए वैश्विक औसत त्रैमासिक देखें ।
ekhumoro

3
यह क्या लौट रहा है? असर या दूरी?
aesculusMaximus

11

इनमें से अधिकांश उत्तर पृथ्वी की त्रिज्या को "गोल" कर रहे हैं। यदि आप अन्य दूरी परिकलकों (जैसे जियोफाई) के खिलाफ इनकी जांच करते हैं, तो ये कार्य बंद हो जाएंगे।

यह अच्छी तरह से काम करता है:

from math import radians, cos, sin, asin, sqrt

def haversine(lat1, lon1, lat2, lon2):

      R = 3959.87433 # this is in miles.  For Earth radius in kilometers use 6372.8 km

      dLat = radians(lat2 - lat1)
      dLon = radians(lon2 - lon1)
      lat1 = radians(lat1)
      lat2 = radians(lat2)

      a = sin(dLat/2)**2 + cos(lat1)*cos(lat2)*sin(dLon/2)**2
      c = 2*asin(sqrt(a))

      return R * c

# Usage
lon1 = -103.548851
lat1 = 32.0004311
lon2 = -103.6041946
lat2 = 33.374939

print(haversine(lat1, lon1, lat2, lon2))

2
यह एक बहुत अधिक सटीक है तो ऊपर दिए गए उदाहरण!
एलेक्स वैन Es

यह ध्रुवों पर R. 6356.752 किमी के अंतर को भूमध्य रेखा पर 6378.137 किमी तक संबोधित नहीं करता है
ldmtwo

3
क्या वह त्रुटि आपके आवेदन के लिए वास्तव में मायने रखती है? cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
तेजस काले

8

एक सदिशीकृत कार्यान्वयन भी है , जो निर्देशांक के लिए स्केलर मानों के बजाय 4 संख्यात्मक सरणियों का उपयोग करने की अनुमति देता है:

def distance(s_lat, s_lng, e_lat, e_lng):

   # approximate radius of earth in km
   R = 6373.0

   s_lat = s_lat*np.pi/180.0                      
   s_lng = np.deg2rad(s_lng)     
   e_lat = np.deg2rad(e_lat)                       
   e_lng = np.deg2rad(e_lng)  

   d = np.sin((e_lat - s_lat)/2)**2 + np.cos(s_lat)*np.cos(e_lat) * np.sin((e_lng - s_lng)/2)**2

   return 2 * R * np.arcsin(np.sqrt(d))

4

असर गणना गलत है, आपको इनपुट को atan2 में स्वैप करने की आवश्यकता है।

    bearing = atan2(sin(long2-long1)*cos(lat2), cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(long2-long1))
    bearing = degrees(bearing)
    bearing = (bearing + 360) % 360

यह आपको सही असर देगा।


मैं वास्तव में यह समझने के लिए संघर्ष कर रहा हूं कि ये समीकरण कैसे बने थे क्योंकि मैं एक पेपर पढ़ रहा हूं। आपने मुझे एक संकेत दिया है: haversine formulaयह सुनने के लिए पहली बार, धन्यवाद।
अरिलवन

4

आप निम्नलिखित की कोशिश कर सकते हैं:

from haversine import haversine
haversine((45.7597, 4.8422),(48.8567, 2.3508), unit='mi')
243.71209416020253

इसे Django की ORM क्वेरी में कैसे उपयोग किया जा सकता है?
गोस्ट

3

यहाँ @Michael Dunn द्वारा दिया गया हैवेर्सिन फॉर्मूला का एक सुस्पष्ट वेक्टर कार्यान्वयन, सामान्य डॉक्टरों पर 10-50 बार सुधार देता है।

from numpy import radians, cos, sin, arcsin, sqrt

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

    #Convert decimal degrees to Radians:
    lon1 = np.radians(lon1.values)
    lat1 = np.radians(lat1.values)
    lon2 = np.radians(lon2.values)
    lat2 = np.radians(lat2.values)

    #Implementing Haversine Formula: 
    dlon = np.subtract(lon2, lon1)
    dlat = np.subtract(lat2, lat1)

    a = np.add(np.power(np.sin(np.divide(dlat, 2)), 2),  
                          np.multiply(np.cos(lat1), 
                                      np.multiply(np.cos(lat2), 
                                                  np.power(np.sin(np.divide(dlon, 2)), 2))))
    c = np.multiply(2, np.arcsin(np.sqrt(a)))
    r = 6371

    return c*r

2

आप 360 ° जोड़कर नकारात्मक असर वाली समस्या को हल कर सकते हैं। दुर्भाग्य से, इसका परिणाम सकारात्मक बीयरिंग के लिए 360 ° से बड़ा बीयरिंग हो सकता है। यह मॉडुलो ऑपरेटर के लिए एक अच्छा उम्मीदवार है, इसलिए सभी में आपको लाइन जोड़ना चाहिए

Bearing = (Bearing + 360) % 360

अपनी विधि के अंत में।


1
मुझे लगता है कि यह सिर्फ: असर = असर% 360
Holger Bille

1

डिफ़ॉल्ट रूप से Y, atan2 पहला पैरामीटर है। यहाँ प्रलेखन है । सही असर कोण प्राप्त करने के लिए आपको अपने इनपुट को स्विच करना होगा।

bearing = atan2(sin(lon2-lon1)*cos(lat2), cos(lat1)*sin(lat2)in(lat1)*cos(lat2)*cos(lon2-lon1))
bearing = degrees(bearing)
bearing = (bearing + 360) % 360

1

इस लिंक का संदर्भ लें: /gis/84885/whats-the-difference-between-vincenty-and-great-circle-distance-calculations

यह वास्तव में दूरी पाने के दो तरीके देता है। वे हैवरसाइन और विन्सेन्ट हैं। मेरे शोध से मुझे पता चला कि विन्सेंट अपेक्षाकृत अपेक्षाकृत सटीक है। कार्यान्वयन करने के लिए आयात विवरण का भी उपयोग करें।


0

दूरी और असर की गणना करने के लिए यहां दो कार्य हैं, जो पिछले संदेशों और https://gist.github.com/jeromer/2005586 में कोड पर आधारित हैं (अक्षांश में भौगोलिक बिंदुओं के लिए जोड़ा गया प्रकार, स्पष्टता के लिए दोनों कार्यों के लिए अकेला प्रारूप )। मैंने दोनों कार्यों का परीक्षण किया और वे सही काम करने लगते हैं।

#coding:UTF-8
from math import radians, cos, sin, asin, sqrt, atan2, degrees

def haversine(pointA, pointB):

    if (type(pointA) != tuple) or (type(pointB) != tuple):
        raise TypeError("Only tuples are supported as arguments")

    lat1 = pointA[0]
    lon1 = pointA[1]

    lat2 = pointB[0]
    lon2 = pointB[1]

    # convert decimal degrees to radians 
    lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2]) 

    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    r = 6371 # Radius of earth in kilometers. Use 3956 for miles
    return c * r


def initial_bearing(pointA, pointB):

    if (type(pointA) != tuple) or (type(pointB) != tuple):
        raise TypeError("Only tuples are supported as arguments")

    lat1 = radians(pointA[0])
    lat2 = radians(pointB[0])

    diffLong = radians(pointB[1] - pointA[1])

    x = sin(diffLong) * cos(lat2)
    y = cos(lat1) * sin(lat2) - (sin(lat1)
            * cos(lat2) * cos(diffLong))

    initial_bearing = atan2(x, y)

    # Now we have the initial bearing but math.atan2 return values
    # from -180° to + 180° which is not what we want for a compass bearing
    # The solution is to normalize the initial bearing as shown below
    initial_bearing = degrees(initial_bearing)
    compass_bearing = (initial_bearing + 360) % 360

    return compass_bearing

pA = (46.2038,6.1530)
pB = (46.449, 30.690)

print haversine(pA, pB)

print initial_bearing(pA, pB)

यह विधि उपरोक्त सभी अन्य विधियों की तुलना में अन्य परिणाम देती है!
बेसिलिस्क
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.