Search code examples
iosobjective-ccllocationmanagercllocationcoordinate2d

Create perpendicular lat long from single cllocation coordinate of X meter


I have user current location i.e. CLLocation Coordinate (location lat & long) and user is on race track pointing to one direction with the help of user current location i created one region now I want some more race track coordinate(say 2m , 4m , 6m away from race track in perpendicular direction) and the track is 10 m long. Please check the image and the red points are on the track. Please check this image


Solution

  • /**
     * Returns the destination point from initial point having travelled the given distance on the
     * given initial bearing (bearing normally varies around path followed).
     *
     * @param   {double} distance - Distance travelled, in same units as earth radius (default: metres).
     * @param   {double} bearing - Initial bearing in degrees from north.
     *
     * @returns {CLLocationCoordinate} Destination point.
     */
    
    #define kEarthRadius 6378137
    
    - (CLLocationCoordinate2D)destinationPointWithStartingPoint:(MKMapPoint)initialPoint distance:(double)distance andBearing:(double)bearing {
      CLLocationCoordinate2D location = MKCoordinateForMapPoint(initialPoint);
    
      double delta = distance / kEarthRadius;
      double omega = [self degreesToRadians:bearing];
    
      double phi1 = [self degreesToRadians:location.latitude];
      double lambda1 = [self degreesToRadians:location.longitude];
    
      double phi2 = asin(sin(phi1)*cos(delta) + cos(phi1) * sin(delta) * cos(omega));
      double x = cos(delta) - sin(phi1) * sin(phi2);
      double y = sin(omega) * sin(delta) * cos(phi1);
      double lambda2 = lambda1 + atan2(y, x);
    
      return CLLocationCoordinate2DMake([self radiansToDegrees:phi2], ([self radiansToDegrees:lambda2]+540)%360-180);
    }
    
    - (CLLocationCoordinate2D)rhumbDestinationPointForInitialPoint:(MKMapPoint)initialPoint distance:(double)distance andBearing:(double)bearing {
      CLLocationCoordinate2D location = MKCoordinateForMapPoint(initialPoint);
    
      double delta = distance / kEarthRadius;
      double omega = [self degreesToRadians:bearing];
    
      double phi1 = [self degreesToRadians:location.latitude];
      double lambda1 = [self degreesToRadians:location.longitude];
    
      double delta_phi = delta * cos(omega);
      double phi2 = phi1 + delta_phi;
    
      // check for some daft bugger going past the pole, normalise latitude if so
      if (fabs(phi2) > M_PI / 2) {
        phi2 = phi2 > 0 ? M_PI-phi2 : -M_PI-phi2;
      }
    
      double delta_gamma = log(tan(phi2/2+M_PI/4)/tan(phi1/2+M_PI/4));
      double q = fabs(delta_gamma) > 10e-12 ? delta_phi / delta_gamma : cos(phi1);
    
      double delta_lambda = delta*sin(omega)/q;
      double lambda2 = lambda1 + delta_lambda;
    
      return CLLocationCoordinate2DMake([self radiansToDegrees:phi2], ([self radiansToDegrees:lambda2]+540)%360-180);
    }
    
    - (double)degreesToRadians:(double)degrees {
      return degrees * M_PI / 180.0;
    }
    
    - (double)radiansToDegrees:(double)radians {
      return radians * 180.0 / M_PI;
    }
    

    Adapted from : http://www.movable-type.co.uk/scripts/latlong.html
    More information on bearing : https://en.wikipedia.org/wiki/Bearing_(navigation)
    And rhumb line : https://en.wikipedia.org/wiki/Rhumb_line