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.