অক্ষাংশ / দ্রাঘিমাংশের ভিত্তিতে দুটি পয়েন্টের মধ্যে দূরত্ব অর্জন করা


156

আমি এই সূত্রটি বাস্তবায়নের চেষ্টা করেছি: http://andrew.hedges.name/experiments/haversine/ অ্যাপলেটটি যে দুটি পয়েন্ট আমি পরীক্ষা করছি তার জন্য ভাল কাজ করে:

এখানে চিত্র বর্ণনা লিখুন

তবুও আমার কোড কাজ করছে না।

from math import sin, cos, sqrt, atan2

R = 6373.0

lat1 = 52.2296756
lon1 = 21.0122287
lat2 = 52.406374
lon2 = 16.9251681

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))
distance = R * c

print "Result", distance
print "Should be", 278.546

এটির দূরত্ব 5447.05546147 । কেন?

উত্তর:


206

সম্পাদনা: ঠিক একটি নোট হিসাবে, যদি আপনার কেবল দুটি পয়েন্টের মধ্যে দূরত্ব সন্ধানের দ্রুত এবং সহজ উপায়ের প্রয়োজন হয় তবে আমি হ্যাভারসাইনকে পুনরায় বাস্তবায়নের পরিবর্তে নীচের কার্টের উত্তরে বর্ণিত পদ্ধতির ব্যবহারের দৃ strongly় পরামর্শ দিচ্ছি - যুক্তির জন্য তার পোস্টটি দেখুন see

এই উত্তরটি কেবলমাত্র নির্দিষ্ট বাগের ওপিতে উত্তর দেওয়ার উপর দৃষ্টি নিবদ্ধ করে।


এটি পাইথনের কারণেই, সমস্ত ট্রিগ ফাংশন ডিগ্রি নয়, রেডিয়ান ব্যবহার করে

আপনি হয় সংখ্যাটিকে ম্যানুয়ালি রেডিয়ানে রূপান্তর করতে পারেন, বা radiansগণিত মডিউল থেকে ফাংশনটি ব্যবহার করতে পারেন :

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

# approximate radius of earth in km
R = 6373.0

lat1 = radians(52.2296756)
lon1 = radians(21.0122287)
lat2 = radians(52.406374)
lon2 = radians(16.9251681)

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

distance = R * c

print("Result:", distance)
print("Should be:", 278.546, "km")

দূরত্বটি এখন কিমিটির সঠিক মানটি ফিরিয়ে দিচ্ছে 278.545589351


13
এটি কোনও প্রোগ্রামিং ভাষায় এবং ডিফারেনশিয়াল ক্যালকুলাসেও সত্য। ডিগ্রি ব্যবহার করা ব্যতিক্রম, এবং কেবলমাত্র মানুষের বাক্যে ব্যবহৃত হয়।
ব্লুজমুন

11
বুদ্ধিমানদের কাছে কথা, এই সূত্রটির জন্য সমস্ত ডিগ্রি ধনাত্মক হওয়া দরকার। radians(abs(52.123))কৌশলটি করা উচিত ...
রিচার্ড ডান

1
আপনি কি সব ডিগ্রি (কোণ?) ইতিবাচক হওয়ার বিষয়ে নিশ্চিত? আমি মনে করি এটি ভুল। ল্যাট 1, লোন 1 = 10, 10 (ডিগ্রি) এবং ল্যাট 2, লোন 2 = -10, -10 (ডিগ্রি) বিবেচনা করুন। ডিগ্রির চারপাশে একটি অ্যাবস () যুক্ত করে, দূরত্বটি শূন্য হবে, যা ভুল। সম্ভবত আপনি ড্লোন এবং / বা ড্ল্যাটের পরম মানটি বোঝাতে চেয়েছিলেন, তবে আপনি যদি ডিলোন, একটি এর গণনায় ড্ল্যাট মানগুলি দেখেন তবে সাইন একটি সমান ফাংশন, এবং কোসাইন স্কোয়ার্ড একটি সমান ফাংশন, তাই আমি করি না dlat বা dlon এর নিরঙ্কুশ মান গ্রহণের জন্য কোনও উপকারিতা দেখুন।
ডেভ লেকম্পটে

238

আপডেট: 04/2018: নোট করুন যে ভিনসেন্টির দূরত্ব জিওপাই সংস্করণ 1.13 থেকে অবনতি হয়েছে - পরিবর্তে আপনার জিওপি.ডেসটেন্স.ডেসটেন্স () ব্যবহার করা উচিত!


উপরের উত্তরগুলি হ্যাভারসাইন সূত্রের উপর ভিত্তি করে তৈরি হয়েছে , যা ধরে নেয় পৃথিবীটি একটি গোলক, যার ফলশ্রুতিতে প্রায় 0.5% পর্যন্ত ত্রুটি রয়েছে (অনুযায়ী help(geopy.distance))। Vincenty দূরত্ব যেমন ব্যবহারসমূহ আরো সঠিক ellipsoidal মডেলের WGS-84 , এবং বাস্তবায়িত হয় geopy । উদাহরণ স্বরূপ,

import geopy.distance

coords_1 = (52.2296756, 21.0122287)
coords_2 = (52.406374, 16.9251681)

print geopy.distance.vincenty(coords_1, coords_2).km

279.352901604ডিফল্ট উপবৃত্তাকার WGS-84 ব্যবহার করে কিলোমিটারের দূরত্ব মুদ্রণ করবে । (আপনি .milesঅন্যান্য কয়েকটি দূরত্বের ইউনিটগুলির মধ্যে একটি বা চয়ন করতে পারেন )।


1
ধন্যবাদ। আপনি দয়া করে নিউপোর্ট এবং ক্লিভল্যান্ডের পরিবর্তে প্রশ্নে আমি যে স্থানাঙ্কগুলি দিয়েছি সেগুলি দিয়ে আপনার উত্তর আপডেট করতে পারেন। এটি ভবিষ্যতের পাঠকদের আরও ভাল বোঝাপড়া দেবে।
gwaramadze

1
নিউপোর্ট এবং ক্লেভল্যান্ডের স্বেচ্ছাসেবী অবস্থানগুলি পাইপিআই তালিকাতে ভূ-সংক্রান্ত ডকুমেন্টেশন থেকে এসেছে: পিপিআইপিথন.আরপিপি
জেসন পারহাম

আমাকে এটির জন্য কার্ট পিকের উত্তরটি সংশোধন করতে হয়েছিল: মূলধন প্রয়োজনীয়:print geopy.distance.VincentyDistance(coords_1, coords_2).km 279.352901604
জিম

4
আপনার সম্ভবত সম্ভবত geopy.distance.distance(…)কোডটি ব্যবহার করা উচিত যা বর্তমানে সেরা (= সবচেয়ে নির্ভুল) দূরত্বের সূত্রের একটি উপনাম। (এই মুহুর্তে
ভিনসেন্টি

10
জিওপি-ডিস্টেন্স.ভান্সটি ব্যবহার করে জিওপি -১.১১.১ আউটপুটগুলিতে: ভিনসেন্টি অবমূল্যায়ন করা হয়েছে এবং জিওপি ২.০ এ অপসারণ করা যাচ্ছে। ব্যবহারের geopy.distance.geodesic(অথবা ডিফল্ট geopy.distance.distance) পরিবর্তে, যা আরো সঠিক এবং সবসময় এগোয় হয়।
জুয়ানমাহ

88

লোকেরা (আমার মতো) সার্চ ইঞ্জিনের মাধ্যমে এখানে আসছেন এবং বাক্স থেকে কার্যকর এমন একটি সমাধান খুঁজছেন, আমি ইনস্টল করার পরামর্শ দিচ্ছি mpu। এটির মাধ্যমে ইনস্টল করুন pip install mpu --userএবং হ্যাসারসিন দূরত্ব পেতে এটি ব্যবহার করুন :

import mpu

# Point one
lat1 = 52.2296756
lon1 = 21.0122287

# Point two
lat2 = 52.406374
lon2 = 16.9251681

# What you were looking for
dist = mpu.haversine_distance((lat1, lon1), (lat2, lon2))
print(dist)  # gives 278.45817507541943.

একটি বিকল্প প্যাকেজ হ'ল gpxpy

আপনি যদি নির্ভরতা না চান তবে আপনি ব্যবহার করতে পারেন:

import math


def distance(origin, destination):
    """
    Calculate the Haversine distance.

    Parameters
    ----------
    origin : tuple of float
        (lat, long)
    destination : tuple of float
        (lat, long)

    Returns
    -------
    distance_in_km : float

    Examples
    --------
    >>> origin = (48.1372, 11.5756)  # Munich
    >>> destination = (52.5186, 13.4083)  # Berlin
    >>> round(distance(origin, destination), 1)
    504.2
    """
    lat1, lon1 = origin
    lat2, lon2 = destination
    radius = 6371  # km

    dlat = math.radians(lat2 - lat1)
    dlon = math.radians(lon2 - lon1)
    a = (math.sin(dlat / 2) * math.sin(dlat / 2) +
         math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) *
         math.sin(dlon / 2) * math.sin(dlon / 2))
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    d = radius * c

    return d


if __name__ == '__main__':
    import doctest
    doctest.testmod()

অন্য বিকল্প প্যাকেজটি হ'ল [haversine][1]

from haversine import haversine, Unit

lyon = (45.7597, 4.8422) # (lat, lon)
paris = (48.8567, 2.3508)

haversine(lyon, paris)
>> 392.2172595594006  # in kilometers

haversine(lyon, paris, unit=Unit.MILES)
>> 243.71201856934454  # in miles

# you can also use the string abbreviation for units:
haversine(lyon, paris, unit='mi')
>> 243.71201856934454  # in miles

haversine(lyon, paris, unit=Unit.NAUTICAL_MILES)
>> 211.78037755311516  # in nautical miles

তারা দুটি ভেক্টরের সমস্ত পয়েন্টের মধ্যে দূরত্বের জন্য পারফরম্যান্স অপ্টিমাইজেশন রয়েছে বলে দাবি করে

from haversine import haversine_vector, Unit

lyon = (45.7597, 4.8422) # (lat, lon)
paris = (48.8567, 2.3508)
new_york = (40.7033962, -74.2351462)

haversine_vector([lyon, lyon], [paris, new_york], Unit.KILOMETERS)

>> array([ 392.21725956, 6163.43638211])

বিন্দুগুলির প্রদত্ত হিহিটকে পরিবর্তন করার কোনও উপায় আছে কি?
ইয়েভেল কোহেন

আপনি কেবল দূরত্বে উচ্চতার পার্থক্যটি যুক্ত করতে পারেন। যদিও আমি তা করব না।
মার্টিন থোমা

16

আমি অনেক সহজ এবং শক্তসমর্থ সমাধান যা ব্যবহার করছে আগত geodesicথেকে geopyপ্যাকেজ যেহেতু আপনি অত্যন্ত সম্ভবত হতে আপনার প্রকল্পের কোন পথে তাই কোন অতিরিক্ত প্যাকেজ ইনস্টলেশনের প্রয়োজন মধ্যে এটি ব্যবহার করব।

এখানে আমার সমাধান:

from geopy.distance import geodesic


origin = (30.172705, 31.526725)  # (latitude, longitude) don't confuse
dist = (30.288281, 31.732326)

print(geodesic(origin, dist).meters)  # 23576.805481751613
print(geodesic(origin, dist).kilometers)  # 23.576805481751613
print(geodesic(origin, dist).miles)  # 14.64994773134371

geopy


5
import numpy as np


def Haversine(lat1,lon1,lat2,lon2, **kwarg):
    """
    This uses the ‘haversine’ formula to calculate the great-circle distance between two points – that is, 
    the shortest distance over the earth’s surface – giving an ‘as-the-crow-flies’ distance between the points 
    (ignoring any hills they fly over, of course!).
    Haversine
    formula:    a = sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2)
    c = 2 ⋅ atan2( √a, √(1−a) )
    d = R ⋅ c
    where   φ is latitude, λ is longitude, R is earth’s radius (mean radius = 6,371km);
    note that angles need to be in radians to pass to trig functions!
    """
    R = 6371.0088
    lat1,lon1,lat2,lon2 = map(np.radians, [lat1,lon1,lat2,lon2])

    dlat = lat2 - lat1
    dlon = lon2 - lon1
    a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2) **2
    c = 2 * np.arctan2(a**0.5, (1-a)**0.5)
    d = R * c
    return round(d,4)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.