<!DOCTYPE html>
<html lang="zh_CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>计算通信方位角和大圆距离</title>
    <!-- Bootstrap -->
    <link href="https://cdn.ghink.net/assembly/bootstrap/4.6.1/css/bootstrap.min.css" rel="stylesheet">
    <!-- Favicon -->
    <link rel="icon" href="https://cdn.ghink.net/image/avatar/Bigsk.png" type="image/png">
    <script src="https://cdn.ghink.net/js/vue/2.6.14/vue.min.js"></script>
    <script>
      function sgn(n) {
        if (n > 0) {
          return 1;
        } else if (n < 0) {
          return -1;
        } else {
          return 0;
        }
      }

      function fndeg(d, m, s) {
        return d + sgn(d) * (m / 60 + s/ 3600);
      }

      function fnacs(x) {
        return Math.PI / 2 - 2 * Math.atan(x / (1 + Math.sqrt(1 - x * x)));
      }

      function calc(tlongd, tlatd, rlongd, rlatd) {
        let ro = 6370;

        let gcdkm;
        let btrd;
        let brtd;

        let r2d = 180 / Math.PI;
        let d2r = Math.PI / 180;

        let tlong = tlongd * d2r;
        let tlat = tlatd * d2r;
        let rlong = rlongd * d2r;
        let rlat = rlatd * d2r;

        if (tlong < 0) {
          tlong = Math.PI * 2 + tlong;
        }
        if (rlong < 0) {
          rlong = Math.PI * 2 + rlong;
        }

        let dlong = tlong - rlong;
        if (Math.abs(dlong) > Math.PI) {
          dlong = dlong - Math.PI * 2 * sgn(dlong);
        }

        let x = Math.sin(tlat) * Math.sin(rlat) + Math.cos(tlat) * Math.cos(rlat) * Math.cos(dlong);
        let gcd = fnacs(x);

        if (gcd < 0.0000001) {
          gcd = 0.0000001;
        }

        if (Math.cos(tlat) - 0.0000001 <= 0) {
          let btr;
          if (tlat >= 0) {
            btr = 0;
          } else {
            btr = Math.PI;
          }

          if (Math.cos(rlat) - 0.0000001 > 0) {
            x = (Math.sin(tlat) - Math.sin(rlat) * Math.cos(gcd)) / (Math.cos(rlat) * Math.sin(gcd));
            let brt = fnacs(x);
            if (dlong < 0) {
              brt = Math.PI * 2 - brt;
            }
            gcdkm = gcd * ro;
            btrd = btr * r2d;
            brtd = brt * r2d;
          } else {
            let brt;
            if (rlat >= 0) {
              brt = 0;
            } else {
              brt = Math.PI;
            }
            gcdkm = gcd * ro;
            btrd = btr * r2d;
            brtd = brt * r2d;
          }
        } else {
          x = (Math.sin(rlat) - Math.sin(tlat) * Math.cos(gcd)) / (Math.cos(tlat) * Math.sin(gcd));
          let btr = fnacs(x);

          if (dlong > 0) {
            btr = Math.PI * 2 - btr;
          }

          if (Math.cos(rlat) - 0.0000001 > 0) {
            x = (Math.sin(tlat) - Math.sin(rlat) * Math.cos(gcd)) / (Math.cos(rlat) * Math.sin(gcd));
            let brt = fnacs(x);
            if (dlong < 0) {
              brt = Math.PI * 2 - brt;
            }
            gcdkm = gcd * ro;
            btrd = btr * r2d;
            brtd = brt * r2d;
          } else {
            let brt;
            if (rlat >= 0) {
              brt = 0;
            } else {
              brt = Math.PI;
            }
            gcdkm = gcd * ro;
            btrd = btr * r2d;
            brtd = brt * r2d;
          }
        }

        return [gcdkm, btrd, brtd];
      }
    </script>
  </head>
  <body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
      <a class="navbar-brand" href="https://tools.ianxia.com"><b>Ian</b>Tools</a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav ml-auto">
          <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
		      语言
		    </a>
            <div class="dropdown-menu" aria-labelledby="navbarDropdown">
              <a class="dropdown-item" href="en_US.html"><b>English</b></a>
            </div>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="https://www.ianxia.com">首页</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="https://blog.ianxia.com">博客</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="https://demo.ianxia.com">DEMO</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="https://adsb.ianxia.com">ADS-B</a>
          </li>
          <li class="nav-item active">
            <a class="nav-link" href="../zh_CN.html">小工具</a>
          </li>
        </ul>
      </div>
    </nav>
    <section>
      <div class="jumbotron text-center mt-2">
        <div class="container">
          <div class="row">
            <div class="col-12">
              <h1>计算通信方位角和大圆距离</h1>
            </div>
          </div>
        </div>
      </div>
    </section>
    <section>
      <div class="container">
        <div class="row" id="app">
          <div class="col-md-1"></div>
          <div class="col-md-5">
            <form class="form-horizontal" role="form">
              <div class="form-inline">
                <label><b>发信点经度</b>&nbsp;</label>
                <input type="number" class="form-control" v-model="tlongdd" max="180" min="-180" placeholder="度" style="width:70px; height:30px;">&nbsp;度&nbsp;
                <input type="number" class="form-control" v-model="tlongdm" max="60" min="-60" placeholder="分" style="width:70px; height:30px;">&nbsp;分&nbsp;
                <input type="number" class="form-control" v-model="tlongds" max="60" min="-60" placeholder="秒" style="width:70px; height:30px;">&nbsp;秒&nbsp;
              </div>
              <div class="form-inline">
                <label><b>发信点纬度</b>&nbsp;</label>
                <input type="number" class="form-control" v-model="tlatdd" max="90" min="-90" placeholder="度" style="width:70px; height:30px;">&nbsp;度&nbsp;
                <input type="number" class="form-control" v-model="tlatdm" max="60" min="-60" placeholder="分" style="width:70px; height:30px;">&nbsp;分&nbsp;
                <input type="number" class="form-control" v-model="tlatds" max="60" min="-60" placeholder="秒" style="width:70px; height:30px;">&nbsp;秒&nbsp;
              </div>
              <div class="form-inline">
                <label><b>收信点经度</b>&nbsp;</label>
                <input type="number" class="form-control" v-model="rlongdd" max="180" min="-180" placeholder="度" style="width:70px; height:30px;">&nbsp;度&nbsp;
                <input type="number" class="form-control" v-model="rlongdm" max="60" min="-60" placeholder="分" style="width:70px; height:30px;">&nbsp;分&nbsp;
                <input type="number" class="form-control" v-model="rlongds" max="60" min="-60" placeholder="秒" style="width:70px; height:30px;">&nbsp;秒&nbsp;
              </div>
              <div class="form-inline">
                <label><b>收信点纬度</b>&nbsp;</label>
                <input type="number" class="form-control" v-model="rlatdd" max="90" min="-90" placeholder="度" style="width:70px; height:30px;">&nbsp;度&nbsp;
                <input type="number" class="form-control" v-model="rlatdm" max="60" min="-60" placeholder="分" style="width:70px; height:30px;">&nbsp;分&nbsp;
                <input type="number" class="form-control" v-model="rlatds" max="60" min="-60" placeholder="秒" style="width:70px; height:30px;">&nbsp;秒&nbsp;
              </div>
            </form>
          </div>
          <div class="col-md-6">
            <h5>计算结果:</h5>
            <h5>大圆距离为{{gcdkm}}(km)</h5>
            <h5>发信点对收信点的方位角为{{btrdd}}度{{btrdm}}分{{btrds}}秒</h5>
            <h5>收信点对发信点的方位角为{{brtdd}}度{{brtdm}}分{{brtds}}秒</h5>
          </div>
        </div>
        <div class="text-center">
          <hr>
          <h5>算法来源:《业余无线电通信》 童效勇BA1AA 陈方BA4RC 附录18</h5>
          <h5>语言翻译:Bigsk (<a href="https://gitea.ghink.net/bigsk/commu_a_c" target="_blank">Git仓库</a>)</h5>
        </div>
      </div>
    </section>
    <hr>
    <script>
      function result(object) {
        let tlongd = fndeg(parseInt(object.tlongdd), parseInt(object.tlongdm), parseInt(object.tlongds))
        let tlatd = fndeg(parseInt(object.tlatdd), parseInt(object.tlatdm), parseInt(object.tlatds))
        let rlongd = fndeg(parseInt(object.rlongdd), parseInt(object.rlongdm), parseInt(object.rlongds))
        let rlatd = fndeg(parseInt(object.rlatdd), parseInt(object.rlatdm), parseInt(object.rlatds))
        return calc(tlongd, tlatd, rlongd, rlatd)
      }

      new Vue({
        el: '#app',
        data: {
          tlongdd: 103,
          tlongdm: 45,
          tlongds: 0,
          tlatdd: 36,
          tlatdm: 2,
          tlatds: 0,
          rlongdd: 121,
          rlongdm: 29,
          rlongds: 0,
          rlatdd: 31,
          rlatdm: 14,
          rlatds: 0
        },
        computed: {
          gcdkm: function () {
            return result(this)[0]
          },
          btrdd: function () {
            let d = Math.trunc(result(this)[1])
            return d
          },
          btrdm: function () {
            let d = Math.trunc(result(this)[1])
            let m = Math.trunc((result(this)[1] - d) * 60)
            return m
          },
          btrds: function () {
            let d = Math.trunc(result(this)[1])
            let m = Math.trunc((result(this)[1] - d) * 60)
            let s = Math.trunc((result(this)[1] - d - m / 60) * 3600)
            return s
          },
          brtdd: function () {
            let d = Math.trunc(result(this)[2])
            let m = Math.trunc((result(this)[2] - d) * 60)
            return d
          },
          brtdm: function () {
            let d = Math.trunc(result(this)[2])
            let m = Math.trunc((result(this)[2] - d) * 60)
            return m
          },
          brtds: function () {
            let d = Math.trunc(result(this)[2])
            let m = Math.trunc((result(this)[2] - d) * 60)
            let s = Math.trunc((result(this)[2] - d - m / 60) * 3600)
            return s
          }
        }
      })
      
      let date = new Date();
    </script>
    <footer class="text-center">
      <div class="container">
        <div class="row">
          <div class="col-12">
            <p style="color: #516069"><strong>版权所有 © Ian Xia <script>document.write(date.getFullYear().toString());</script> 保留所有权利</strong></p>
          </div>
        </div>
      </div>
    </footer>
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://cdn.ghink.net/js/jquery/jquery-3.6.0.min.js"></script>
    <!-- Grey Filter Detector -->
    <script>
      $.ajax({
        type: "GET",
        url: "https://open.geh.ink/grey_filter",
        dataType: "json",
        success: function(data, textStatus){
          for (let i=0;i<data["content"]["accurate_slot"].length;i++) {
            // Accurate Slot
            if (Date.now()/1000 >= data["content"]["accurate_slot"][i][0] && Date.now()/1000 <= data["content"]["accurate_slot"][i][1]) {
              $("html").css({
                '-webkit-filter': 'grayscale(100%)',
                '-moz-filter': 'grayscale(100%)',
                '-ms-filter': 'grayscale(100%)',
                '-o-filter': 'grayscale(100%)',
                'filter': 'progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)',
                '_filter': 'none'
              });
              break;
            }
          }
          for (let i=0;i<data["content"]["day_slot"].length;i++) {
            // Day Slot
            let begin = new Date(
              date.getFullYear().toString() + "-" + 
              data["content"]["day_slot"][i][0][0].toString() + "-" + 
              data["content"]["day_slot"][i][0][1].toString() + " " + 
              data["content"]["day_slot"][i][0][2].toString() + ":" +
              data["content"]["day_slot"][i][0][3].toString() + ":" +
              data["content"]["day_slot"][i][0][4].toString()
            )
            let end = new Date(
              date.getFullYear().toString() + "-" + 
              data["content"]["day_slot"][i][1][0].toString() + "-" + 
              data["content"]["day_slot"][i][1][1].toString() + " " + 
              data["content"]["day_slot"][i][1][2].toString() + ":" +
              data["content"]["day_slot"][i][1][3].toString() + ":" +
              data["content"]["day_slot"][i][1][4].toString()
            )
            if (Date.now() >= begin.getTime() && Date.now() <= end.getTime()) {
              $("html").css({
                '-webkit-filter': 'grayscale(100%)',
                '-moz-filter': 'grayscale(100%)',
                '-ms-filter': 'grayscale(100%)',
                '-o-filter': 'grayscale(100%)',
                'filter': 'progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)',
                '_filter': 'none'
              });
              break;
            }
          }
        }
      });
    </script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="https://cdn.ghink.net/js/popper/1.16.1/popper.min.js"></script>
    <script src="https://cdn.ghink.net/assembly/bootstrap/4.6.1/js/bootstrap.min.js"></script>
  </body>
</html>