2008-09-23 16 views
74

मैं दो अलग-अलग बिंदुओं के बीच की दूरी ढूंढना चाहता हूं। यह मुझे महान सर्कल दूरी के साथ पूरा किया जा सकता है। http://www.meridianworlddata.com/Distance-calculation.aspमैं जावा में दो अक्षांश + देशांतर बिंदुओं के आधार पर दूरी को मापने और बाध्यकारी बॉक्स कैसे बना सकता हूं?

एक बार आदेश बिंदु चारों ओर एक बॉक्स बनाने के लिए किया है, एक बिंदु और दूरी मुझे लगता है कि दूरी उत्तर बिंदु मिल चाहते हैं, और कहा कि दूरी पूर्व के साथ।

+1

इस ब्लॉग http://xebee.xebia.in/2010/10/28/working-with-geolocations/ – Robin

उत्तर

20

हमें बहुत अधिक स्थितित्मक डेटा प्लॉट करने के लिए OpenMap का उपयोग करके कुछ सफलता मिली है। LatLonPoint कक्षा है जिसमें दूरी सहित कुछ बुनियादी कार्यक्षमताएं हैं।

+5

संभव ग्रहण करने वालों को चेतावनी का संदर्भ लें: मैं सिर्फ OpenMap के साथ एक बड़ी समस्या में पड़ गए; वे दशमलव अक्षांश/लोन के लिए आंतरिक रूप से फ्लोट का उपयोग करते हैं, जो सटीकता को सीमित करता है कि आप भूमध्य रेखा के करीब कितने करीब हैं। वे संस्करण 4.7 में शुरू होने वाले ओएमजीआरपी कक्षाओं के साथ युगल के विकल्प का समर्थन करने की योजना बना रहे हैं, लेकिन वर्तमान स्थिर केवल 4.6.5 (मार्च 2010 तक) है। स्रोत: http://openmap.bbn.com/mailArchives/openmap-users/2006-01/4522.html – Marc

+0

यह भी ध्यान दें कि वर्तमान ओपनमैप सॉफ्टवेयर लाइसेंस अनुबंध http://openmap.bbn.com/license.html है गैर मुक्त माना जाता है। http://web.archiveorange.com/archive/v/XyE55YoXwS3lME936I0U बीबीएन के साथ कुछ चर्चाएं लाइसेंस बदलने के लिए हुई हैं लेकिन अभी तक कुछ भी नहीं हुआ है। –

+0

LatLonPoint लिंक टूटा हुआ है – Petriborg

7

एक त्वरित Google खोज GeoTools बदल जाती है, जिसकी संभावना है कि आप किस तरह के कार्यों की तलाश कर रहे हैं।

140

यहां Haversine सूत्र का जावा कार्यान्वयन है। मैं इसे एक परियोजना में लेट/लम्बाई के बीच मील की दूरी की गणना करने के लिए उपयोग करता हूं।

public static double distFrom(double lat1, double lng1, double lat2, double lng2) { 
    double earthRadius = 3958.75; // miles (or 6371.0 kilometers) 
    double dLat = Math.toRadians(lat2-lat1); 
    double dLng = Math.toRadians(lng2-lng1); 
    double sindLat = Math.sin(dLat/2); 
    double sindLng = Math.sin(dLng/2); 
    double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2) 
      * Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)); 
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
    double dist = earthRadius * c; 

    return dist; 
    } 
+22

इस पर बस एक नोट, यह मील में दूरी लौटाएगा (पृथ्वी की गति के कारण)। अन्य इकाइयों के लिए धरती को बदलें (अधिक के लिए http://en.wikipedia.org/wiki/Earth_radius देखें) –

+0

क्या कोई कारण है कि आप युगल के बजाय फ्लोट का उपयोग कर रहे हैं? अगर मैं सही ढंग से समझता हूं तो आप अपने इनपुट पैरामीटर प्रकारों को बदलकर अपने परिणामों की शुद्धता बढ़ा सकते हैं – Hamy

+0

आधे डेल्टा के साइन की गणना करने की आवश्यकता नहीं है। इसे एक बार गणना करें और इसे अपने साथ गुणा करें। यह निश्चित रूप से एक तंग पाश में लायक है। –

43

या आप SimpleLatLng का उपयोग कर सकते हैं। अपाचे 2.0 लाइसेंस प्राप्त और एक उत्पादन प्रणाली में उपयोग किया जाता है जिसे मैं जानता हूं: मेरा।

लघु कहानी:

मैं एक साधारण भू पुस्तकालय के लिए खोज रहा था और एक मेरी जरूरतों फिट करने के लिए नहीं मिल सका। और जो हर एप्लिकेशन में बार-बार इन छोटे भौगोलिक उपकरणों को लिखना और परीक्षण करना और डिबग करना चाहते हैं? एक बेहतर तरीका होना चाहिए!

तो SimpleLatLng अक्षांश-देशांतर डेटा को स्टोर करने, दूरी की गणना करने और आकार की सीमाएं बनाने के तरीके के रूप में पैदा हुआ था।

मुझे पता है कि मैं मूल पोस्टर की मदद करने में बहुत देर हो चुकी हूं, लेकिन मेरा लक्ष्य उन लोगों की मदद करना है जो इस प्रश्न को खोज में ढूंढते हैं। मुझे कुछ लोग इसका इस्तेमाल करना पसंद करेंगे और इस छोटी हल्के उपयोगिता के परीक्षण और दृष्टि में योगदान देंगे।

+0

इससे मेरी मदद हो सकती है! क्या आपने इसे बनाया क्या आप दूरी गणना के लिए हावर्सिन फॉर्मूला का उपयोग करते हैं ??अगर मुझे समय मिल जाए तो मैं कूदने की कोशिश करूंगा! – Gevorg

+0

सही, यह हावर्सिन का उपयोग दूरी की गणना के लिए करता है (हालांकि स्वीकार्य रूप से एक जुनून नहीं) गति और कम स्मृति प्रोफ़ाइल। मुझे लगता है कि इसमें कुछ अन्य अच्छी संख्या-हैंडलिंग गुण भी हैं, जैसे निर्देशांक पर विचार करना जो "वास्तव में करीब" बराबर हैं। – JavadocMD

1

आप Java Geodesy Library for GPS का उपयोग कर सकते हैं, यह Vincenty's formulae का उपयोग करता है जो पृथ्वी की सतह वक्रता का खाता लेता है।

कार्यान्वयन इस प्रकार है:

import org.gavaghan.geodesy.*; 
... 
GeodeticCalculator geoCalc = new GeodeticCalculator(); 
Ellipsoid reference = Ellipsoid.WGS84; 
GlobalPosition pointA = new GlobalPosition(latitude, longitude, 0.0); 
GlobalPosition userPos = new GlobalPosition(userLat, userLon, 0.0); 
double distance = geoCalc.calculateGeodeticCurve(reference, userPos, pointA).getEllipsoidalDistance(); 

जिसके परिणामस्वरूप दूरी मीटर में है।

11

एक और अधिक सटीक दूरी (0.5mm) आप भी Vincenty सन्निकटन उपयोग कर सकते हैं:

/** 
* Calculates geodetic distance between two points specified by latitude/longitude using Vincenty inverse formula 
* for ellipsoids 
* 
* @param lat1 
*   first point latitude in decimal degrees 
* @param lon1 
*   first point longitude in decimal degrees 
* @param lat2 
*   second point latitude in decimal degrees 
* @param lon2 
*   second point longitude in decimal degrees 
* @returns distance in meters between points with 5.10<sup>-4</sup> precision 
* @see <a href="http://www.movable-type.co.uk/scripts/latlong-vincenty.html">Originally posted here</a> 
*/ 
public static double distVincenty(double lat1, double lon1, double lat2, double lon2) { 
    double a = 6378137, b = 6356752.314245, f = 1/298.257223563; // WGS-84 ellipsoid params 
    double L = Math.toRadians(lon2 - lon1); 
    double U1 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat1))); 
    double U2 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat2))); 
    double sinU1 = Math.sin(U1), cosU1 = Math.cos(U1); 
    double sinU2 = Math.sin(U2), cosU2 = Math.cos(U2); 

    double sinLambda, cosLambda, sinSigma, cosSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM; 
    double lambda = L, lambdaP, iterLimit = 100; 
    do { 
     sinLambda = Math.sin(lambda); 
     cosLambda = Math.cos(lambda); 
     sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) 
       + (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda)); 
     if (sinSigma == 0) 
      return 0; // co-incident points 
     cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda; 
     sigma = Math.atan2(sinSigma, cosSigma); 
     sinAlpha = cosU1 * cosU2 * sinLambda/sinSigma; 
     cosSqAlpha = 1 - sinAlpha * sinAlpha; 
     cos2SigmaM = cosSigma - 2 * sinU1 * sinU2/cosSqAlpha; 
     if (Double.isNaN(cos2SigmaM)) 
      cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (§6) 
     double C = f/16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha)); 
     lambdaP = lambda; 
     lambda = L + (1 - C) * f * sinAlpha 
       * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM))); 
    } while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0); 

    if (iterLimit == 0) 
     return Double.NaN; // formula failed to converge 

    double uSq = cosSqAlpha * (a * a - b * b)/(b * b); 
    double A = 1 + uSq/16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq))); 
    double B = uSq/1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq))); 
    double deltaSigma = B 
      * sinSigma 
      * (cos2SigmaM + B 
        /4 
        * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B/6 * cos2SigmaM 
          * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM))); 
    double dist = b * A * (sigma - deltaSigma); 

    return dist; 
} 

इस कोड को स्वतंत्र रूप से http://www.movable-type.co.uk/scripts/latlong-vincenty.html

6

सही Haversine दूरी सूत्र से अनुकूलित किया गया था ....

public static double HaverSineDistance(double lat1, double lng1, double lat2, double lng2) 
{ 
    // mHager 08-12-2012 
    // http://en.wikipedia.org/wiki/Haversine_formula 
    // Implementation 

    // convert to radians 
    lat1 = Math.toRadians(lat1); 
    lng1 = Math.toRadians(lng1); 
    lat2 = Math.toRadians(lat2); 
    lng2 = Math.toRadians(lng2); 

    double dlon = lng2 - lng1; 
    double dlat = lat2 - lat1; 

    double a = Math.pow((Math.sin(dlat/2)),2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(dlon/2),2); 

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

    return EARTH_RADIUS * c; 
} 
+0

पृथ्वी एक सही क्षेत्र नहीं है –

+0

सही, कभी-कभी ** बंद ** पर्याप्त अच्छा है। आईई: क्यों श्रीमान इमान ने इसे बनाया। मैं उसे बताउंगा कि वह गलत है, लेकिन वह मर चुका है। : ओ (यदि आपको दुनिया के आबादी के आकार की गणना करने की आवश्यकता है, तो उसके लिए बेहतर सूत्र हैं। कुछ महान अपाचे लाइब्रेरी भी हैं जिनका आप उपयोग भी कर सकते हैं। अगर आपको बस कुछ सरल चाहिए, तो यह एक अच्छा त्वरित उदाहरण है :) –

+0

हां, हावर्सिन फॉर्मूला 'करीबी पर्याप्त है' प्रिंसिपल पर बनाया गया है। उस समय हम दूरी को माप रहे थे जो <50 मील की दूरी पर एक स्थान से दूसरे स्थान पर 'हेरिस्टिक' के रूप में निर्धारित करने के लिए थे। –

0

मैं आम तौर पर Mapping Toolbox साथ MATLAB का उपयोग करें, और उसके बाद मेरे जावा में कोड MATLAB Builder JA. का उपयोग कर यह मेरे जीवन बहुत आसान बना देता है का उपयोग करें। अधिकांश विद्यालयों में यह मुफ्त छात्र पहुंच के लिए है, आप इसे आजमा सकते हैं (या अपने काम को पाने के लिए परीक्षण संस्करण प्राप्त करें)।

2

http://www.movable-type.co.uk/scripts/latlong.html

public static Double distanceBetweenTwoLocationsInKm(Double latitudeOne, Double longitudeOne, Double latitudeTwo, Double longitudeTwo) { 
     if (latitudeOne == null || latitudeTwo == null || longitudeOne == null || longitudeTwo == null) { 
      return null; 
     } 

     Double earthRadius = 6371.0; 
     Double diffBetweenLatitudeRadians = Math.toRadians(latitudeTwo - latitudeOne); 
     Double diffBetweenLongitudeRadians = Math.toRadians(longitudeTwo - longitudeOne); 
     Double latitudeOneInRadians = Math.toRadians(latitudeOne); 
     Double latitudeTwoInRadians = Math.toRadians(latitudeTwo); 
     Double a = Math.sin(diffBetweenLatitudeRadians/2) * Math.sin(diffBetweenLatitudeRadians/2) + Math.cos(latitudeOneInRadians) * Math.cos(latitudeTwoInRadians) * Math.sin(diffBetweenLongitudeRadians/2) 
       * Math.sin(diffBetweenLongitudeRadians/2); 
     Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 
     return (earthRadius * c); 
    } 
1

मैं जानता हूँ कि बहुत-से उत्तर देखते हैं कि, लेकिन इस विषय पर कुछ शोध करने में, मैंने पाया है कि सबसे जवाब यहां Haversine सूत्र का उपयोग करें, लेकिन Vincenty सूत्र वास्तव में अधिक सटीक है। एक पोस्ट था जो जावास्क्रिप्ट संस्करण से गणना को अनुकूलित करता था, लेकिन यह बहुत ही कमजोर है। मुझे एक संस्करण मिला जो बेहतर है क्योंकि:

  1. इसमें एक खुला लाइसेंस भी है।
  2. यह ओओपी सिद्धांतों का उपयोग करता है।
  3. आपके द्वारा उपयोग किए जाने वाले एलीपसॉइड को चुनने के लिए इसमें अधिक लचीलापन है।
  4. इसमें भविष्य में विभिन्न गणनाओं की अनुमति देने के लिए और अधिक विधियां हैं।
  5. यह अच्छी तरह से प्रलेखित है।

VincentyDistanceCalculator

1

यह विधि आपको किमी में भौगोलिक स्थान पर बीच की दूरी को खोजने में मदद मिलेगी।

private double getDist(double lat1, double lon1, double lat2, double lon2) 
{ 
    int R = 6373; // radius of the earth in kilometres 
    double lat1rad = Math.toRadians(lat1); 
    double lat2rad = Math.toRadians(lat2); 
    double deltaLat = Math.toRadians(lat2-lat1); 
    double deltaLon = Math.toRadians(lon2-lon1); 

    double a = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) + 
      Math.cos(lat1rad) * Math.cos(lat2rad) * 
      Math.sin(deltaLon/2) * Math.sin(deltaLon/2); 
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 

    double d = R * c; 
    return d; 
} 
संबंधित मुद्दे