Linux 在bash中计算中点、初始方位角和距离

Linux 在bash中计算中点、初始方位角和距离,linux,bash,awk,Linux,Bash,Awk,已解决: 我正在尝试编写一个脚本,计算给定一对lat-lon坐标的距离、方位和中点 我发现这个公式很简单,但我得到了错误的答案。这可能只是一个数学错误,但我已经看了很多遍,我遗漏了一些东西。 我遵循这个网站的公式: 这是我得到的,输出是距离,方位,中点纬度,中点长 script.bash 1-80-3-79.2 453.58158.22,68.1258,95.390 这是我应该得到的: script.bash 1-80-3-79.2 453.6 168.7-1-79.6 所以,距离看起来不错。但

已解决:

我正在尝试编写一个脚本,计算给定一对lat-lon坐标的距离、方位和中点

我发现这个公式很简单,但我得到了错误的答案。这可能只是一个数学错误,但我已经看了很多遍,我遗漏了一些东西。 我遵循这个网站的公式:

这是我得到的,输出是距离,方位,中点纬度,中点长

script.bash 1-80-3-79.2

453.58158.22,68.1258,95.390

这是我应该得到的:

script.bash 1-80-3-79.2

453.6 168.7-1-79.6

所以,距离看起来不错。但是其他人都走了。有什么想法吗

这是我的密码:

#!/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

对于shell脚本来说,这是一项完全不合适的工作,您应该将其作为单个awk(或类似的,例如perl、ruby、python)脚本来完成。顺便说一句,将变量命名为与命令相同的(
cat
)会混淆代码并使其更容易出错

以下是您的出发点应该是什么(检查数学/转换,因为我几乎可以肯定的是,当使用
-s
-c
将字符串输送到bc等时,我并不总是正确地解释您试图执行的操作,正如我猜测的那样):


对于shell脚本来说,这是一项完全不合适的工作,您应该将其作为单个awk(或类似的,例如perl、ruby、python)脚本来完成。顺便说一句,将变量命名为与命令相同的(
cat
)会混淆代码并使其更容易出错

以下是您的出发点应该是什么(检查数学/转换,因为我几乎可以肯定的是,当使用
-s
-c
将字符串输送到bc等时,我并不总是正确地解释您试图执行的操作,正如我猜测的那样):



只是为什么?使用一种实际执行浮点运算的语言,而不是将整个进程分叉来处理单个操作。是否缺少任何实际的脚本编写培训?我喜欢awk解决方案,不知道你可以用awk做这么多。根本不要给你的问题添加一个有效的解决方案。感兴趣的人可以在Ed的答案中看到它。我把它改回来了。shell是一种环境,可以在其中操纵(创建/销毁)文件和进程,并使用一种语言对调用进行排序。如果您想做更多的事情,例如操纵文本或数学计算,那么您需要找出哪个工具可以做任何您想做的事情(首先开始查看awk,因为它是所有UNIX安装中唯一的标准工具),并使用它,而不是尝试使用shell构造来完成。只是。。。为什么?使用一种实际执行浮点运算的语言,而不是将整个进程分叉来处理单个操作。是否缺少任何实际的脚本编写培训?我喜欢awk解决方案,不知道你可以用awk做这么多。根本不要给你的问题添加一个有效的解决方案。感兴趣的人可以在Ed的答案中看到它。我把它改回来了。shell是一种环境,可以在其中操纵(创建/销毁)文件和进程,并使用一种语言对调用进行排序。如果您想做更多的事情,例如操纵文本或数学计算,那么您需要找出哪个工具可以做任何您想做的事情(首先看看awk,因为它是所有UNIX安装中唯一的标准工具)并使用它,而不是尝试使用shell构造。s和c分别是正弦和cos。我正在尝试,但得到了完全不同的答案。如果我把它恢复到原始结果或正确的结果,我会更新我的帖子。那么你只想对-s和-c后面的值调用sin()和cos()?好的,我更新了我的“答案”。再次检查我解释和写的内容是否符合您的意图。您应该会发现,调试比原来的shell脚本容易得多。谢谢,我现在能够找到错误,并且可以正常工作。我想,如果您将lonmidr的行更改为lonmidr=lon1r+atan2(atc3,atc4),那么脚本将正常工作,这是我最初的错误,并且非常确定它们是我从这里更改的唯一内容。哇,我也更改了打印行,第三个值应该是latmid,而不是latmidr,这是弧度值。我得到453.581168.696-1.00002-79.6002,-s和-c分别是正弦和cos。我正在尝试,但得到了完全不同的答案。如果我把它恢复到原始结果或正确的结果,我会更新我的帖子。那么你只想对-s和-c后面的值调用sin()和cos()?好的,我更新了我的“答案”。再次检查我解释和写的内容是否符合您的意图。您应该会发现,调试比原来的shell脚本容易得多。谢谢,我现在能够找到错误,并且可以正常工作。我想,如果您将lonmidr的行更改为lonmidr=lon1r+atan2(atc3,atc4),那么脚本将正常工作,这是我最初的错误,并且非常确定它们是我从这里更改的唯一内容。哇,我也更改了打印行,第三个值应该是latmid,而不是latmidr,这是弧度值。我得到453.581168.696-1.00002-79.6002。
$ 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