ArcGIS DEsktop और / या R का उपयोग करके निकटतम बिंदुओं (अक्षांश / लंबे समय में दिए गए) से किमी में दूरी की गणना करें?


10

आर्कजीआईएस में मेरे पास दो बिंदु डेटासेट हैं, दोनों को डब्ल्यूजीएस84 लैट / लोन को-ऑर्डिनेट्स में दिया गया है और अंक पूरी दुनिया में फैले हुए हैं। मैं डेटासेट ए में प्रत्येक बिंदु पर डेटासैट ए में निकटतम बिंदु खोजना चाहता हूं, और किलोमीटर में उनके बीच की दूरी प्राप्त करना चाहता हूं।

यह नियर टूल के सही उपयोग की तरह लगता है, लेकिन इससे मुझे इनपुट पॉइंट्स के को-ऑर्डिनेट सिस्टम में परिणाम मिलते हैं: यानी दशमलव डिग्री। मुझे पता है कि मैं डेटा को फिर से प्रोजेक्ट कर सकता हूं, लेकिन मैं ( इस सवाल से ) इकट्ठा करता हूं कि यह एक प्रक्षेपण खोजना मुश्किल है (यदि असंभव नहीं है) जो पूरी दुनिया में सटीक दूरी देगा।

उस प्रश्न के उत्तर सीधे अक्षांश-देशांतर सह-निर्देशांक का उपयोग करके दूरियों की गणना करने के लिए हैवरसाइन सूत्र का उपयोग करने का सुझाव देते हैं। क्या ऐसा करने का एक तरीका है और ArcGIS का उपयोग करके किमी में परिणाम प्राप्त करना है? यदि नहीं, तो इसके लिए सबसे अच्छा तरीका क्या है?

जवाबों:


6

हालांकि यह एक आर्कगिस समाधान नहीं है, आपकी समस्या को आर्क से अपने अंक निर्यात करके और पैकेज spDists से फ़ंक्शन का उपयोग करके आर में हल किया जा सकता है sp। यदि आप सेट करते हैं तो फ़ंक्शन एक संदर्भ बिंदु (बिंदु) और बिंदुओं के एक मैट्रिक्स के बीच की दूरी को पाता है longlat=T

यहाँ एक त्वरित और गंदा उदाहरण है:

library(sp)
## Sim up two sets of 100 points, we'll call them set a and set b:
a <- SpatialPoints(coords = data.frame(x = rnorm(100, -87.5), y = rnorm(100, 30)), proj4string=CRS("+proj=longlat +datum=WGS84"))
b <- SpatialPoints(coords = data.frame(x = rnorm(100, -88.5), y = rnorm(100, 30.5)), proj4string=CRS("+proj=longlat +datum=WGS84"))

## Find the distance from each point in a to each point in b, store
##    the results in a matrix.
results <- spDists(a, b, longlat=T)

धन्यवाद - यह सबसे यथार्थवादी समाधान की तरह लगता है। डॉक्स को देखकर ऐसा लगता है कि मैं केवल एक संदर्भ बिंदु और अन्य बिंदुओं के एक सेट के बीच ऐसा कर सकता हूं, इसलिए मुझे अपने सभी बिंदुओं के माध्यम से जाने के लिए इसे लूप में करना होगा। क्या आप R में ऐसा करने का अधिक कुशल तरीका जानते हैं?
रोबिन्ट

कोई लूपिंग की आवश्यकता नहीं है, आप फ़ंक्शन को दो सेट अंक दे सकते हैं और यह प्रत्येक संयोजन के बीच की दूरी के साथ एक मैट्रिक्स लौटाएगा। उदाहरण कोड को शामिल करने के लिए संपादित उत्तर।
एलन

3

यह एक आर्कगिस समाधान नहीं है, लेकिन एक स्थानिक डेटाबेस में एक गोल पृथ्वी डेटा मॉडल का उपयोग करके चाल करना होगा। इसका समर्थन करने वाले डेटाबेस में पृथ्वी की दूरी की गणना करना बहुत आसान होगा। मैं आपको दो रीडिंग सुझा सकता हूं:

http://postgis.net/workshops/postgis-intro/geography.html

http://blog.safe.com/2012/08/round-earth-data-in-oracle-postgis-and-sql-server/


2

आपको एक दूरी गणना की आवश्यकता है जो लाट / लांग के साथ काम करती है। विन्सेंटी वह है जिसका मैं उपयोग करूँगा (0.5 मिमी सटीकता)। मैंने पहले भी इसके साथ खेला है, और इसका उपयोग करना बहुत कठिन नहीं है।

कोड थोड़ा लंबा है, लेकिन यह काम करता है। डब्ल्यूजीएस में दो बिंदुओं को देखते हुए, यह मीटर में दूरी लौटाएगा।

आप इसे आर्कगिस में पायथन स्क्रिप्ट के रूप में उपयोग कर सकते हैं, या इसे किसी अन्य स्क्रिप्ट के चारों ओर लपेट सकते हैं जो बस दो पॉइंट शेपफाइल्स पर पुनरावृत्त करता है और आपके लिए एक दूरी मैट्रिक्स बनाता है। या, 2-3 निकटतम सुविधाओं (पृथ्वी की वक्रता की जटिलताओं से बचने के लिए) को खोजने के साथ GENERATE_NEAR_TABLE के परिणामों को खिलाना शायद आसान है।

import math

ellipsoids = {
    #name        major(m)   minor(m)            flattening factor
    'WGS-84':   (6378137,   6356752.3142451793, 298.25722356300003),
    'GRS-80':   (6378137,   6356752.3141403561, 298.25722210100002),
    'GRS-67':   (6378160,   6356774.5160907144, 298.24716742700002),

}

def distanceVincenty(lat1, long1, lat2, long2, ellipsoid='WGS-84'):
    """Computes the Vicenty distance (in meters) between two points
    on the earth. Coordinates need to be in decimal degrees.
    """
    # Check if we got numbers
    # Removed to save space
    # Check if we know about the ellipsoid
    # Removed to save space
    major, minor, ffactor = ellipsoids[ellipsoid]
    # Convert degrees to radians
    x1 = math.radians(lat1)
    y1 = math.radians(long1)
    x2 = math.radians(lat2)
    y2 = math.radians(long2)
    # Define our flattening f
    f = 1 / ffactor
    # Find delta X
    deltaX = y2 - y1
    # Calculate U1 and U2
    U1 = math.atan((1 - f) * math.tan(x1))
    U2 = math.atan((1 - f) * math.tan(x2))
    # Calculate the sin and cos of U1 and U2
    sinU1 = math.sin(U1)
    cosU1 = math.cos(U1)
    sinU2 = math.sin(U2)
    cosU2 = math.cos(U2)
    # Set initial value of L
    L = deltaX
    # Set Lambda equal to L
    lmbda = L
    # Iteration limit - when to stop if no convergence
    iterLimit = 100
    while abs(lmbda) > 10e-12 and iterLimit >= 0:
        # Calculate sine and cosine of lmbda
        sin_lmbda = math.sin(lmbda)
        cos_lmbda = math.cos(lmbda)
        # Calculate the sine of sigma
        sin_sigma = math.sqrt(
                (cosU2 * sin_lmbda) ** 2 + 
                (cosU1 * sinU2 - 
                 sinU1 * cosU2 * cos_lmbda) ** 2
        )
        if sin_sigma == 0.0:
            # Concident points - distance is 0
            return 0.0
        # Calculate the cosine of sigma
        cos_sigma = (
                    sinU1 * sinU2 + 
                    cosU1 * cosU2 * cos_lmbda
        )
        # Calculate sigma
        sigma = math.atan2(sin_sigma, cos_sigma)
        # Calculate the sine of alpha
        sin_alpha = (cosU1 * cosU2 * math.sin(lmbda)) / (sin_sigma)
        # Calculate the square cosine of alpha
        cos_alpha_sq = 1 - sin_alpha ** 2
        # Calculate the cosine of 2 sigma
        cos_2sigma = cos_sigma - ((2 * sinU1 * sinU2) / cos_alpha_sq)
        # Identify C
        C = (f / 16.0) * cos_alpha_sq * (4.0 + f * (4.0 - 3 * cos_alpha_sq))
        # Recalculate lmbda now
        lmbda = L + ((1.0 - C) * f * sin_alpha * (sigma + C * sin_sigma * (cos_2sigma + C * cos_sigma * (-1.0 + 2 * cos_2sigma ** 2)))) 
        # If lambda is greater than pi, there is no solution
        if (abs(lmbda) > math.pi):
            raise ValueError("No solution can be found.")
        iterLimit -= 1
    if iterLimit == 0 and lmbda > 10e-12:
        raise ValueError("Solution could not converge.")
    # Since we converged, now we can calculate distance
    # Calculate u squared
    u_sq = cos_alpha_sq * ((major ** 2 - minor ** 2) / (minor ** 2))
    # Calculate A
    A = 1 + (u_sq / 16384.0) * (4096.0 + u_sq * (-768.0 + u_sq * (320.0 - 175.0 * u_sq)))
    # Calculate B
    B = (u_sq / 1024.0) * (256.0 + u_sq * (-128.0 + u_sq * (74.0 - 47.0 * u_sq)))
    # Calculate delta sigma
    deltaSigma = B * sin_sigma * (cos_2sigma + 0.25 * B * (cos_sigma * (-1.0 + 2.0 * cos_2sigma ** 2) - 1.0/6.0 * B * cos_2sigma * (-3.0 + 4.0 * sin_sigma ** 2) * (-3.0 + 4.0 * cos_2sigma ** 2)))
    # Calculate s, the distance
    s = minor * A * (sigma - deltaSigma)
    # Return the distance
    return s

1

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

लेकिन यह दृष्टिकोण आपके डेटासेट में अंकों की मात्रा पर निर्भर करेगा। यह बड़े डेटासेट के साथ ठीक से काम नहीं कर सकता है।


सलाह के लिये धन्यवाद। हालाँकि, मैं यह नहीं देख सकता कि यह कैसे मेरी मदद करेगा। डॉक्स ( help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//… ) के अनुसार "दूरी इनपुट सुविधाओं के लीनियर यूनिट में समन्वय प्रणाली है।", जो इनपुट के रूप में हैं। in lat / lon मुझे निश्चित रूप से दशमलव डिग्री में परिणाम देगा? (मैं परीक्षण करने के लिए यहां पर
आर्कजीआईएस के

इस स्थिति में, मैं शायद आपके डेटा योग्य में X और Y फ़ील्ड जोड़कर "त्वरित और गंदे" समाधान का उपयोग करूंगा और मीटर में X और Y चुनने वाले परिकलित ज्यामिति पर क्लिक करूंगा। यदि इस विकल्प को चुनना संभव नहीं है, तो अपने MXD के समन्वय प्रणाली को बदलें। मैं इससे पहले एक प्रोजेक्ट पर काम कर रहा था, जहाँ मेरे क्लाइंट को लॉन्ग / लेट, एक्स / वाई और गॉस-क्रुगेर आर / एच की वैल्यू हर एक शेप फाइल में चाहिए थी। जटिल गणना से बचने के लिए, बस अनुमानों को बदलना और ज्यामिति की गणना करना सबसे आसान तरीका था जिससे यह काम किया।
बस्तो

0

यदि आपको उच्च-सटीक और मजबूत जियोडेसिक मापों की आवश्यकता है, तो जियोग्राफिकलिब का उपयोग करें , जो मूल रूप से कई प्रोग्रामिंग भाषाओं में लिखा गया है, जिसमें सी ++, जावा, मैटलैब, पायथन, आदि शामिल हैं।

साहित्यिक संदर्भ के लिए CFF Karney (2013) "एल्गोरिदम के लिए एल्गोरिदम" देखें । ध्यान दें कि ये एल्गोरिदम विन्सेन्ट्स के एल्गोरिदम की तुलना में अधिक मजबूत और सटीक हैं, उदाहरण के लिए एंटीपोड्स के पास।

दो बिंदुओं के बीच मीटर में दूरी की गणना करने के लिए, व्युत्क्रम जियोडेसिक समाधानs12 से दूरी विशेषता प्राप्त करें । जैसे, पायथन के लिए भौगोलिक भौगोलिक पैकेज

from geographiclib.geodesic import Geodesic
g = Geodesic.WGS84.Inverse(-41.32, 174.81, 40.96, -5.50)
print(g)  # shows:
{'a12': 179.6197069334283,
 'azi1': 161.06766998615873,
 'azi2': 18.825195123248484,
 'lat1': -41.32,
 'lat2': 40.96,
 'lon1': 174.81,
 'lon2': -5.5,
 's12': 19959679.26735382}

या एक सुविधा फ़ंक्शन करें, जो मीटर से किलोमीटर तक भी परिवर्तित होता है:

dist_km = lambda a, b: Geodesic.WGS84.Inverse(a[0], a[1], b[0], b[1])['s12'] / 1000.0
a = (-41.32, 174.81)
b = (40.96, -5.50)
print(dist_km(a, b))  # 19959.6792674 km

अब सूचियों के बीच निकटतम बिंदु खोजने के लिए Aऔर B, प्रत्येक 100 अंक के साथ:

from random import uniform
from itertools import product
A = [(uniform(-90, 90), uniform(-180, 180)) for x in range(100)]
B = [(uniform(-90, 90), uniform(-180, 180)) for x in range(100)]
a_min = b_min = min_dist = None
for a, b in product(A, B):
    d = dist_km(a, b)
    if min_dist is None or d < min_dist:
        min_dist = d
        a_min = a
        b_min = b

print('%.3f km between %s and %s' % (min_dist, a_min, b_min))

22.481 किमी (84.57916462672875, 158.67545706102192) और (84.70326937581333, 156.9784597422855) के बीच

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