Author Topic: Haversine Formula  (Read 1280 times)

0 Members and 1 Guest are viewing this topic.

snownut2

  • Swamp Rat
  • Posts: 971
  • Bricscad 22 Ultimate
Haversine Formula
« on: June 12, 2016, 10:40:36 AM »
Using this to approximate latitude or longitude degrees from feet.

Code - Auto/Visual Lisp: [Select]
  1.      (defun dis>deg (lat1 lon1 dis adj / a c d i lond latd var) ; Haversine Formula function
  2.        (defun deg>rad (n)                                       ; degrees to radians conversion
  3.          (* n (/ pi 180))
  4.          )
  5.        (defun km>ft (n)                                         ; kilometers to feet conversion
  6.          (* n 3280.84)
  7.          )
  8.        (setq d 0 latd 0 lond 0
  9.              var (if (= adj 1) 'lond 'latd)
  10.              )
  11.        (while (or (> dis (fix d))(< dis (fix d)))               ; iterating till hitting the correct distance
  12.          (setq dlon  (-(deg>rad (+ lond lon1))(deg>rad lon1))
  13.                dlat  (-(deg>rad (+ latd lat1))(deg>rad lat1))
  14.                a (+(expt (sin(/ dlat 2))2) (*(cos (deg>rad lat1)) (cos (deg>rad (+ latd lat1))) (expt(sin(/ dlon 2))2)))
  15.                c (* (atan (sqrt a) (sqrt(- 1 a)))2)
  16.                d (km>ft (* 6371 c))                             ; 6371 = accepted mean radius in kilometers of earth (as a sphere) according to NASA
  17.                i (if (< (fix d) (- dis 10)) 1.0e-005 1.0e-008)
  18.                )
  19.          (set var  (+ (eval var) i))
  20.          )
  21.        (eval var)
  22.        );
  23.  

Check answer as follows;
Code - Auto/Visual Lisp: [Select]
  1.  
  2. (setq lat-degrees  (dis>deg 43.1234565 -71.2345657  30 0)
  3. (setq lon-degrees (dis>deg 43.1234565 -71.2345657  30 1)
  4.  
  5.  

This is for short distances only between 20-100 feet.

Anyone have any other thoughts on accomplishing this deed?

Bruce


ymg

  • Guest
Re: Haversine Formula
« Reply #1 on: June 12, 2016, 11:32:56 AM »
Bruce,

I had done Vincenty's Formula in lisp a while back.

This is good for long distance.

Code - Auto/Visual Lisp: [Select]
  1. ;------------------------------------------------------------------------------------------------------;
  2. ; InvVincenty                  by ymg                                                                  ;
  3. ;                                                                                                      ;
  4. ; Calculates geodetic distance between two points specified by latitude/longitude using                ;
  5. ; Vincenty inverse formula for ellipsoids                                                              ;
  6. ;                                                                                                      ;
  7. ; Arguments:  lat1, Latitude of First Point in Decimal Degrees.                                        ;
  8. ;             lon1, Longitude of First Point in Decimal Degrees.                                       ;
  9. ;             lat2, Latitude of Second Point in Decimal Degrees.                                       ;
  10. ;             lon2, Longitude of Second Point in Decimal Degrees.                                      ;
  11. ;                                                                                                      ;
  12. ; Returns:    List (Distance Forward_Azimut Reverse_Azimut)                                            ;
  13. ;                                                                                                      ;
  14. ; Translated  from Vincenty Inverse Solution of Geodesics on the Ellipsoid (c) Chris Veness 2002-2012  ;
  15. ; Some modifications as per Wikipedia on Calculation of MajA and MajB                                  ;
  16. ;------------------------------------------------------------------------------------------------------;
  17. (defun InvVincenty (lat1 lon1 lat2 lon2 /)
  18.  
  19.    ; // WGS-84 ellipsoid params
  20.    (setq    a 6378137.0    
  21.             f (/ 1 298.257223563)
  22.             b (* a (- f 1)  -1)  ; eq. 6356752.314245179              
  23.           eSq (* f (- 2 f))      ; eq. (/ (- (* a a) (* b b)) (* a a))
  24.          e*Sq (/ eSq (- 1 eSq))  ; eq. (/ (- (* a a) (* b b)) (* b b))
  25.             L (dtr (- lon2 lon1))
  26.            u1 (atan (* (- 1 f) (tan (dtr lat1))))
  27.            u2 (atan (* (- 1 f) (tan (dtr lat2))))          
  28.         sinu1 (sin u1)   sinu2 (sin u2)
  29.         cosu1 (cos u1)   cosu2 (cos u2)            
  30.       lambdas L   iterlimit 100
  31.    )                
  32.  
  33.    (while (and (> (abs (- lambdas lambdaP)) 0.00000000000001) (> iterLimit 0))
  34.  
  35.        (setq sinLambda (sin lambdas)
  36.              cosLambda (cos lambdas)
  37.               sinSigma (sqrt (+ (* cosU2 sinLambda cosU2 sinLambda) (* (- (* cosU1 sinU2) (* sinU1 cosU2 cosLambda)) (- (* cosU1 sinU2) (* sinU1 cosU2 cosLambda)))))
  38.        )      
  39.        (if (/= sinSigma 0)
  40.           (progn         
  41.               (setq cosSigma (+ (* sinU1 sinU2) (* cosU1 cosU2 cosLambda))
  42.                        sigma (atan sinSigma cosSigma)
  43.                     sinAlpha (/ (* cosU1 cosU2 sinLambda) sinSigma)
  44.                   cosSqAlpha (- 1 (* sinAlpha sinAlpha))
  45.                   cos2SigmaM (- cosSigma (/ (* 2 sinU1 sinU2) cosSqAlpha))
  46.               )      
  47.               (if (not (numberp cos2SigmaM)) (setq cos2SigmaM 0))
  48.               (setq       c (* (/ f 16) cosSqAlpha (+ 4 (* f (- 4 (* 3 cosSqAlpha)))))
  49.                     lambdaP lambdas
  50.                     lambdas (+ L (* (- 1 c) f sinAlpha (+ sigma (* c sinSigma (+ cos2SigmaM (* c cosSigma (- (* 2 cos2SigmaM cos2SigmaM) 1)))))))
  51.                   iterLimit (1- iterLimit)
  52.              )
  53.           )
  54.           (setq iterlimit 0) ; Else sinSigma is equal to 0 so we  exit the loop.
  55.        )  
  56.    )
  57.  
  58.    (cond
  59.       ((= 0 sinSigma) (list 0.0 nil nil)) ; Returns List (0 nil nil)
  60.       ((= iterLimit 0) (alert "The Equations Did Not Nonverge In\n" (atoi iterlimit) "Iterations.")) ; Returns nil  
  61.       (t  (setq    uSq (* cosSqAlpha e*Sq)
  62.                     k1 (/ (- (sqrt (+ 1 uSq)) 1) (+ (sqrt (+ 1 uSq)) 1))
  63.                   MajA (/ (+ 1 (* k1 k1 0.25)) (- 1 k1))  
  64.                   MajB (* k1 (- 1 (* k1 k1 0.375)))      
  65.             deltaSigma (* majB  sinSigma  (+ cos2SigmaM (*  (/ majB 4) (- (* cosSigma  (- (* 2. cos2SigmaM cos2SigmaM) 1.))  (* (/ majB 6.) cos2SigmaM (- (* 4. sinSigma sinSigma) 3.) (- (* 4. cos2SigmaM cos2SigmaM) 3.))))))
  66.                      s (* b  MajA  (- sigma deltaSigma))
  67.                  fwdAz (rtd (atan (* cosU2 sinLambda) (- (* cosU1 sinU2) (* sinU1 cosU2 cosLambda))))
  68.                  revAz (rtd (atan (* cosU1 sinLambda) (+ (* sinU1 cosU2 -1) (* cosU1 sinU2 cosLambda))))
  69.           )        
  70.           (list s fwdAz revAz) ; Returns List (Distance Forward_Azimut Reverse_Azimut)
  71.       )  
  72.    )
  73. )
  74.  
  75.  
  76. ;------------------------------------------------------------------------------------------------------;
  77. ;  DirVincenty                  by ymg                                                                 ;
  78. ;                                                                                                      ;
  79. ;  Calculates Destination Point Given Start Point lat/long, Initial Azimut & Distance,                 ;
  80. ;  using Vincenty inverse formula for ellipsoids.                                                      ;
  81. ;                                                                                                      ;
  82. ;   Arguments:  lat1, Latitude of Origin Point in Decimal Degrees.                                     ;
  83. ;               lon1, Longitude of Origin Point in Decimal Degrees.                                    ;
  84. ;             InitAz, Initial Azimut of Travel in Decimal Degrees.                                     ;
  85. ;               dist, Distance along bearing in metres.                                                ;
  86. ;                                                                                                      ;
  87. ;   Returns:    A List (Latitude Longitude FinalAzimut)                                                ;
  88. ;                                                                                                      ;
  89. ; Translated  from Vincenty Inverse Solution of Geodesics on the Ellipsoid (c) Chris Veness 2002-2012  ;
  90. ; Some modifications as per Wikipedia on Calculation of MajA and MajB                                  ;
  91. ; See http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html                               ;
  92. ;------------------------------------------------------------------------------------------------------;
  93.                
  94. (defun dirVincenty (lat1 lon1 InitAz dist /)
  95.  
  96.    ; // WGS-84 ellipsoid params
  97.    (setq    a 6378137.0    
  98.             f (/ 1 298.257223563)
  99.             b (* a (- f 1) -1)   ; eq. 6356752.314245179              
  100.           eSq (* f (- 2 f))      ; eq. (/ (- (* a a) (* b b)) (* a a))
  101.          e*Sq (/ eSq (- 1 eSq))  ; eq. (/ (- (* a a) (* b b)) (* b b))
  102.             s dist
  103.            U1 (atan (* (- 1 f) (tan (dtr lat1))))
  104.         sinU1 (sin U1)
  105.         cosU1 (cos U1)
  106.         tanU1 (/ sinU1 cosU1)
  107.        alpha1 (dtr InitAz)
  108.     sinAlpha1 (sin alpha1)
  109.     cosAlpha1 (cos alpha1)     
  110.        sigma1 (atan tanU1 cosAlpha1)
  111.      sinAlpha (* cosU1 sinAlpha1)
  112.    cosSqAlpha (- 1 (* sinAlpha sinAlpha))
  113.           uSq (* cosSqAlpha e*Sq)
  114.            k1 (/ (- (sqrt (+ 1 uSq)) 1) (+ (sqrt (+ 1 uSq)) 1))
  115.          MajA (/ (+ 1 (* k1 k1 0.25)) (- 1 k1))  
  116.          MajB (* k1 (- 1 (* k1 k1 0.375)))
  117.         sigma (/ s (* b MajA))
  118.        sigmaP (* 2 pi)          
  119.    )        
  120.    (while (> (abs (- sigma sigmaP)) 0.00000000000001)
  121.        (setq cos2SigmaM (cos (+ (* 2 sigma1) sigma))
  122.                sinSigma (sin sigma)
  123.                cosSigma (cos sigma)
  124.              deltaSigma (* majB  sinSigma  (+ cos2SigmaM (*  (/ majB 4) (- (* cosSigma  (- (* 2. cos2SigmaM cos2SigmaM) 1.))  (* (/ majB 6.) cos2SigmaM (- (* 4. sinSigma sinSigma) 3.) (- (* 4. cos2SigmaM cos2SigmaM) 3.))))))
  125.                  sigmaP sigma
  126.                   sigma (+ (/ s (* b MajA)) deltaSigma)                  
  127.        )        
  128.    )
  129.            
  130.    (setq   tmp (- (* sinU1 sinSigma) (* cosU1 cosSigma cosAlpha1))
  131.           lat2 (rtd (atan (+ (* sinU1 cosSigma) (* cosU1 sinSigma cosAlpha1))  (* (- 1 f) (sqrt (+ (* sinAlpha sinAlpha) (* tmp tmp))))))
  132.        lambdas (atan (* sinSigma sinAlpha1) (- (* cosU1 cosSigma) (* sinU1 sinSigma cosAlpha1)))
  133.              C (* (/ f 16) cosSqAlpha (+ 4 (* f (- 4 (* 3 cosSqAlpha)))))
  134.              L (- lambdas (* (- 1 C) f sinAlpha (+ sigma (* C sinSigma (+ cos2SigmaM (* C cosSigma (- (* 2 cos2SigmaM cos2SigmaM) 1)))))))
  135.           lon2 (rtd (+ (dtr lon1) L))
  136.        FinalAz (rtd (atan sinAlpha (* tmp -1)))
  137.    )
  138.    (list lat2 lon2 FinalAz)
  139. )
  140.              
  141. ; Helper Functions                                                                 ;
  142. (defun tan (a) (/ (sin a) (cos a)))
  143. (defun dtr (a) (* pi (/ a 180.0)))
  144. (defun rtd (a) (/ (* a 180.0) pi))
  145.  
  146.  


snownut2

  • Swamp Rat
  • Posts: 971
  • Bricscad 22 Ultimate
Re: Haversine Formula
« Reply #2 on: June 12, 2016, 04:51:32 PM »
Thanks ymg, the amount of error is far less utilizing the Vincenty method.