2011-09-02 27 views
16

द्वारा सीएलएलोकेशन को स्थानांतरित करना मेरे पास एक सीएलएलोकेशन परिभाषित है, और मैं उस बिंदु x मीटर को पूर्व में और दक्षिण में वाई मीटर ले जाना चाहता हूं। मैं इसे कैसे प्राप्त कर सकता हूं?एक्स मीटर

+2

ध्यान रखें कि आप हमेशा उत्तर/दक्षिण को दुनिया के सभी बिंदुओं से नहीं ले जा सकते हैं - उदाहरण के लिए, यदि आप उत्तरी ध्रुव पर हैं, तो आप केवल दक्षिण में जा सकते हैं। आप यहाँ क्या करने की कोशिश कर रहे हैं? – duskwuff

+0

@duskwuff: इसे सरल बनाने के लिए, मैं चाहता हूं कि मेरा उपयोगकर्ता सही से 100 कदम उठाए, और 100 कदम पीछे :-) – Oliver

उत्तर

4

एक सी फ़ंक्शन है जो आप जो पूछ रहे हैं उसके करीब है लेकिन इसमें असर और दूरी लगती है। यह मेरी यूटिलिटीजियो क्लास में github पर है। आप इसे करने के लिए अपने CLLocation से अक्षांश और देशांतर गुजरती हैं और फिर परिणामी lat2 से एक नया CLLocation बना सकते हैं और lon2 कि यह रिटर्न होगा:

/*------------------------------------------------------------------------- 
* Given a starting lat/lon point on earth, distance (in meters) 
* and bearing, calculates destination coordinates lat2/lon2. 
* 
* all params in degrees 
*-------------------------------------------------------------------------*/ 
void destCoordsInDegrees(double lat1, double lon1, 
         double distanceMeters, double bearing, 
         double* lat2, double* lon2); 

आपको लगता है कि उपयोग नहीं कर सकते हैं, तो एल्गोरिदम पर एक नज़र डालें कि यह here और here से लिया गया था और शायद आप इसे संशोधित कर सकते हैं या उन साइटों के पास आपकी आवश्यकताओं के करीब कुछ हो सकता है।

+0

जो कि मैं खोज रहा हूं, बहुत करीब (वास्तव में बिल्कुल सही) दिखता है। असर असर मदद करेगा :-) मैं आज रात कोशिश करूँगा। – Oliver

+0

क्या यह फ़ंक्शन दूरी मीटर को क्षेत्र के सतह पर या क्षेत्र के माध्यम से मीटर के रूप में उपयोग करता है? – Oliver

+0

आप अक्षांश को नहीं मानते हैं और अक्षांश नहीं? – Oliver

16

महान पोस्ट, यहाँ जो लोग कॉपी/पेस्ट प्यार के लिए Obj सी आवरण है:

- (CLLocationCoordinate2D) locationWithBearing:(float)bearing distance:(float)distanceMeters fromLocation:(CLLocationCoordinate2D)origin { 
    CLLocationCoordinate2D target; 
    const double distRadians = distanceMeters/(6372797.6); // earth radius in meters 

    float lat1 = origin.latitude * M_PI/180; 
    float lon1 = origin.longitude * M_PI/180; 

    float lat2 = asin(sin(lat1) * cos(distRadians) + cos(lat1) * sin(distRadians) * cos(bearing)); 
    float lon2 = lon1 + atan2(sin(bearing) * sin(distRadians) * cos(lat1), 
        cos(distRadians) - sin(lat1) * sin(lat2)); 

    target.latitude = lat2 * 180/M_PI; 
    target.longitude = lon2 * 180/M_PI; // no need to normalize a heading in degrees to be within -179.999999° to 180.00000° 

    return target; 
} 
+0

सही तरीके से काम नहीं करता है। एक ही असर के साथ अलग दूरी के लिए अलग-अलग स्थान देता है। – kirander

19

स्विफ्ट के लिए एक रूपांतरण, this answer से लिया:

func locationWithBearing(bearing:Double, distanceMeters:Double, origin:CLLocationCoordinate2D) -> CLLocationCoordinate2D { 
    let distRadians = distanceMeters/(6372797.6) // earth radius in meters 

    let lat1 = origin.latitude * M_PI/180 
    let lon1 = origin.longitude * M_PI/180 

    let lat2 = asin(sin(lat1) * cos(distRadians) + cos(lat1) * sin(distRadians) * cos(bearing)) 
    let lon2 = lon1 + atan2(sin(bearing) * sin(distRadians) * cos(lat1), cos(distRadians) - sin(lat1) * sin(lat2)) 

    return CLLocationCoordinate2D(latitude: lat2 * 180/M_PI, longitude: lon2 * 180/M_PI) 
} 

मॉर्गन चेन यह लिखा :

इस विधि में सभी गणित रेडियंस में किए जाते हैं। विधि की शुरुआत में, इस उद्देश्य के लिए अच्छी तरह से lon1 और lat1 को रेडियंस में परिवर्तित कर दिया गया है। असर रेडियंस में भी है। ध्यान रखें कि यह विधि में पृथ्वी के वक्रता को ध्यान में रखती है, जिसे आपको छोटी दूरी के लिए करने की ज़रूरत नहीं है।

+0

प्रिय पीटर, त्वरित समाधान के लिए धन्यवाद, लेकिन मुझे एक चीज़ को सही करने की आवश्यकता है। असर रेडियन में डबल नहीं होना चाहिए। मैं इसे एक उत्तर के रूप में पोस्ट करूंगा क्योंकि मैं यहां कोड पेस्ट नहीं कर सकता। –

+7

यदि यह किसी के लिए अस्पष्ट है, तो असर उस दिशा को संदर्भित करता है जिसे आप अग्रिम करना चाहते हैं, डिग्री के लिए, तो उत्तर के लिए: असर = 0, पूर्व के लिए: असर = 9 0, दक्षिणपश्चिम के लिए: असर = 225, आदि ... –

14

पीटर्स उत्तर के लिए त्वरित त्वरित समाधान। गणना केवल तभी होती है जब गणना की जाती है। @CocoaChris जवाब देने के लिए

func locationWithBearing(bearing:Double, distanceMeters:Double, origin:CLLocationCoordinate2D) -> CLLocationCoordinate2D { 
    let distRadians = distanceMeters/(6372797.6) 

    var rbearing = bearing * M_PI/180.0 

    let lat1 = origin.latitude * M_PI/180 
    let lon1 = origin.longitude * M_PI/180 

    let lat2 = asin(sin(lat1) * cos(distRadians) + cos(lat1) * sin(distRadians) * cos(rbearing)) 
    let lon2 = lon1 + atan2(sin(rbearing) * sin(distRadians) * cos(lat1), cos(distRadians) - sin(lat1) * sin(lat2)) 

    return CLLocationCoordinate2D(latitude: lat2 * 180/M_PI, longitude: lon2 * 180/M_PI) 
} 
+0

मैं ' आपने अपना समाधान लागू किया है। ज्यादातर यह ठीक काम करता है लेकिन कुछ विक्षेपण भी हो रहा है। ऐसा क्यों है। यहां पूछा गया: http://stackoverflow.com/questions/36382149/moving-gmsmarker-by-x-meters-deflects –

3

मामूली समायोजन: अब CLLocation पर एक वर्ग है, और का उपयोग कर निर्मित इकाइयों।

#import <CoreLocation/CoreLocation.h> 


@interface CLLocation (Movement) 

- (CLLocation *)locationByMovingDistance:(double)distanceMeters withBearing:(CLLocationDirection)bearingDegrees; 

@end 


@implementation CLLocation (Movement) 

- (CLLocation *)locationByMovingDistance:(double)distanceMeters withBearing:(CLLocationDirection)bearingDegrees 
{ 
    const double distanceRadians = distanceMeters/(6372797.6); // earth radius in meters 
    const double bearingRadians = bearingDegrees * M_PI/180; 

    float lat1 = self.coordinate.latitude * M_PI/180; 
    float lon1 = self.coordinate.longitude * M_PI/180; 

    float lat2 = asin(sin(lat1) * cos(distanceRadians) + cos(lat1) * sin(distanceRadians) * cos(bearingRadians)); 
    float lon2 = lon1 + atan2(sin(bearingRadians) * sin(distanceRadians) * cos(lat1), 
           cos(distanceRadians) - sin(lat1) * sin(lat2)); 

    return [[CLLocation alloc] initWithLatitude:lat2 * 180/M_PI 
             longitude:lon2 * 180/M_PI]; 
} 

@end 
1

स्विफ्ट कार्यान्वयन Measurement struct का उपयोग कर डिग्री और रेडियन के बीच रूपांतरण करने के लिए।

class GPSLocation { 

public class func degreesToRadians(degrees: Double) -> Double { 
     return Measurement(value: degrees, unit: UnitAngle.degrees).converted(to: .radians).value 
    } 

    public class func radiansToDegrees(radians: Double) -> Double { 
     return Measurement(value: radians, unit: UnitAngle.radians).converted(to: .degrees).value 
    } 

    public class func location(location: CLLocation, byMovingDistance distance: Double, withBearing bearingDegrees:CLLocationDirection) -> CLLocation { 
     let distanceRadians: Double = distance/6372797.6 
     let bearingRadians: Double = GPSLocation.degreesToRadians(degrees: bearingDegrees) 

     let lat1 = GPSLocation.degreesToRadians(degrees: location.coordinate.latitude) 
     let lon1 = GPSLocation.degreesToRadians(degrees: location.coordinate.longitude) 

     let lat2 = GPSLocation.radiansToDegrees(radians:asin(sin(lat1) * cos(distanceRadians) + cos(lat1) * sin(distanceRadians) * cos(bearingRadians))) 
     let lon2 = GPSLocation.radiansToDegrees(radians:lon1 + atan2(sin(bearingRadians) * sin(distanceRadians * cos(lat1)), cos(distanceRadians) - sin(lat1) * sin(lat2))) 

     return CLLocation(latitude: lat2, longitude: lon2) 
    } 

} 
संबंधित मुद्दे