简体   繁体   中英

Calculating midpoint, initial bearing, and distance in bash

SOLVED:

I'm trying to write a script that calculates the distance, bearing, and mid-point given a pair of lat lon coords.

I found the formula's easily enough, but I'm getting the wrong answers. It might just be a math mistake, but I've looked it over multiple times and I'm missing something. I'm following this website's formulas: http://www.movable-type.co.uk/scripts/latlong-nomodule.html

Here's what I get, output is dist, bearing, midpoint lat, midpoint long

script.bash 1 -80 -3 -79.2

453.58,158.22,68.1258,95.390

this is what I should get:

script.bash 1 -80 -3 -79.2

453.6 168.7 -1 -79.6

So, distance looks good. But the others are all off. Any thoughts?

Here is my code:

#!/bin/bash

lat1=$1
lat2=$3
lon1=$2
lon2=$4

#some basic info

R=6371

lat1r=`echo "$lat1*3.14159/180" | bc -l`
lat2r=`echo "$lat2*3.14159/180" | bc -l`
lon1r=`echo "$lon1*3.14159/180" | bc -l`
lon2r=`echo "$lon2*3.14159/180" | bc -l`

dLat=`echo "$lat2r - $lat1r" | bc -l`
dLon=`echo "$lon2r - $lon1r" | bc -l`

#Distance calculations
a=`echo "-s ($dLat/2) * -s ($dLat/2) + -c ($lat1r) * -c ($lat2r) * -s ($dLon/2) * -s ($dLon/2)" | bc -l`
c1=`echo "sqrt($a) " | bc -l`
c2=`echo "sqrt(1 - $a)" | bc -l`
cat=`echo "$c1,$c2"| awk -F',' '{ print atan2($1,$2) }'`
c=`echo "2*$cat" | bc -l`
d=`echo "$R*$c" | bc -l`

#Bearing calculation 

y=`echo "-s ($dLon) * -c ($lat2r)" | bc -l`
x=`echo "-c ($lat1r) * -s ($lat2r) - -s ($lat1r) * -c ($lat2r) * -c ($dLon)" | bc -l`

brng=`echo "$y,$x"| awk -F',' '{ print atan2($1,$2) }'`
brn=`echo "$brng * 180 / 3.14159" | bc -l`
echo "$brng * 180 / 3.14159" 

#Mid point calculation

Bx=`echo "-c ($lat2r) * -c ($dLon)" | bc -l`
By=`echo "-c ($lat2r) * -s ($dLon)" | bc -l`
atc1=`echo " -s ($lat1r) + -s ($lat2r)" | bc -l`
atc2=`echo " sqrt( ( -c ($lat1r) + $Bx )^2 + $By^2 ) "  | bc -l`

latmidr=`echo "$atc1,$atc2"| awk -F',' '{ print atan2($1,$2) }'`
latmid=`echo "$latmidr * 180 / 3.14159" | bc -l`

atc3=$By
atc4=`echo " -c ($lat1r) + $Bx" | bc -l`

lonmidr=`echo "$atc3,$atc4"| awk -F',' '{ print atan2($1,$2) }'`
lonmid=`echo "$lonmidr * 180 / 3.14159" | bc -l`

echo $d,$brn,$latmidr,$lonmid

That's a completely inappropriate job for a shell script, you should have done it as a single awk (or similar, eg perl, ruby, python) script. Btw naming a variable the same as a command ( cat ) obfuscates your code and makes it more error prone.

Here's what your starting point should be (check the math/conversions as I almost certainly didn't always interpret what you were trying to do when piping strings with -s and -c to bc etc. correctly as I was guessing):

$ cat tst.sh
#!/usr/bin/env bash

awk -v lat1="$1" -v lat2="$3" -v lon1="$2" -v lon2="$4" '
BEGIN {
    #some basic info

    pi = 3.14159
    R  = 6371

    lat1r = lat1 * pi / 180
    lat2r = lat2 * pi / 180
    lon1r = lon1 * pi / 180
    lon2r = lon2 * pi / 180

    dLat = lat2r - lat1r
    dLon = lon2r - lon1r

    #Distance calculations
    a   = sin(dLat/2) * sin(dLat/2) + cos(lat1r) * cos(lat2r) * sin(dLon/2) * sin(dLon/2)
    c1  = sqrt(a)
    c2  = sqrt(1 - a)
    cat = atan2(c1,c2)
    c   = 2 * cat
    d   = R * c

    #Bearing calculation
    x = cos(lat1r) * sin(lat2r) - sin(lat1r) * cos(lat2r) * cos(dLon)
    y = sin(dLon) * cos(lat2r)

    brng = atan2(y,x)
    brn  = brng * 180 / pi
    print brng * 180 / pi

    #Mid point calculation

    Bx = cos(lat2r) * cos(dLon)
    By = cos(lat2r) * sin(dLon)
    atc1 = sin(lat1r) + sin(lat2r)
    atc2 = sqrt( (cos(lat1r) + Bx )^2 + By^2 )

    latmidr = atan2(atc1,atc2)
    latmid  = latmidr * 180 / pi

    atc3 = By
    atc4 = cos(lat1r) + Bx

    lonmidr = lon1r + atan2(atc3,atc4)
    lonmid  = lonmidr * 180 / pi

    print d, brn, latmid, lonmid
}
'

.

$ ./tst.sh 1 -80 -3 -79.2
168.696
453.581 168.696 -1.00002 -79.6002

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM