2017年12月26日火曜日

2点間の方位角を求める公式を導出する

地球を球体とみなす場合、球面三角法の公式を変形するだけで導くことができる。球面三角法の導出は地図における数学で解説されている。

2点を\(A\), \(B\)、極を\(C\)、地球の中心を\(O\)とし、頂角も同じ文字で表す。また、\(\angle AOB\), \(\angle BOC\), \(\angle COA\)をそれぞれ\(c\), \(a\), \(b\)とする。なお、地球の半径を\(1\)とすれば、大円の弧\(AB\), \(BC\), \(CA\)はそれぞれ\(c\), \(a\), \(b\)と等しい。

2点の緯度経度から以下の値がわかっていて、求めたいのは\(A\)の値。

\begin{align} a &= (90 - B_{latitude}) \frac{\pi}{180} \\ b &= (90 - A_{latitude}) \frac{\pi}{180} \\ C &= (B_{longitude} - A_{longitude}) \frac{\pi}{180} \end{align}

球面三角法の余弦定理を次のように変形する。

\begin{align} \cos a &= \cos b \cos c + \sin b \sin c \cos A \\ \sin b \sin c \cos A &= \cos a - \cos b \cos c \\ &= \cos a - \cos b (\cos a \cos b + \sin a \sin b \cos C) \\ &= \cos a - \cos a \cos^2 b - \sin a \sin b \cos b \cos C \\ &= \cos a (1 - \cos^2 b) - \sin a \sin b \cos b \cos C \\ &= \cos a \sin^2 b - \sin a \sin b \cos b \cos C \\ \sin c \cos A &= \cos a \sin b - \sin a \cos b \cos C \end{align}

正弦定理も変形する。

\begin{align} \frac{\sin C}{\sin c} &= \frac{\sin A}{\sin a} \\ \sin c \sin A &= \sin a \sin C \end{align}

上式から\(\tan A\)が求まり、\(A\)の値も求まる。

\begin{align} A &= \arctan(\tan A) \\ &= \arctan \left(\frac{\sin c \sin A}{\sin c \cos A} \right) \\ &= \arctan \left(\frac{\sin a \sin C}{\cos a \sin b - \sin a \cos b \cos C} \right) \end{align}

実際の計算では、先に\(\tan A\)を求めると第一象限と第三象限、第二象限と第四象限の区別がつかない。プログラムを書くときはatan2を使う。なお、\(A\)と\(B\)の経度が等しい場合でも正しい値が得られる。

また、

\begin{align} a' &= B_{latitude} \frac{\pi}{180} \\ b' &= A_{latitude} \frac{\pi}{180} \end{align}

と置くと、

\begin{align} A &= \arctan \left(\frac{\cos a' \sin C}{\sin a' \cos b' - \cos a' \sin b' \cos C} \right) \\ &= \arctan \left(\frac{\sin C}{\tan a' \cos b' - \sin b' \cos C} \right) \end{align}

とも書くことができる。

2017年3月29日水曜日

TBS News iの連続動画再生で新しいニュースのみ選択するブックマークレットとユーザースクリプト

News iの連続動画再生ビューアに何ヶ月も前のニュースが混じっていたりして、毎回新しい動画を選択するのが辛いので、ユーザースクリプトとついでにブックマークレットを書いた。テストはFirefox 52 ESRとGreasemonkeyで行ってある。

(2017/12/11 追記)スクリプトが複数回実行された時に正しく選択されないバグを修正。

ブックマークレット

以下のリンクをブックマークに登録して、連続動画再生ビューアのページで普通のブックマークと同じようにクリックすれば、12時間以内のニュースが選択されるはず。

(2017/3/29 追記)属性値のダブルクォートをエスケープし忘れていたのを修正した。

もっと新しいニュースのみ選択したい場合、例えば6時間以内なら、ブックマークのアドレス部分の末尾を(12)から(6)に変更すればいい。

ユーザースクリプト

// ==UserScript==
// @name        news i selector
// @include     http://news.tbs.co.jp/3snewsi/*
// @grant       none
// ==/UserScript==

var HOURS = 12;

setTimeout(function() {
    var expiredAt = Date.now() / 1000 - HOURS * 60 * 60;
    Array.prototype.forEach.call(document.querySelectorAll(".ls-checkItem"), function(item) {
        var checked = item.querySelector("input[type='checkbox']").checked;
        var time = parseInt(item.querySelector(".gs-metaData>span").getAttribute("data-time"), 10);
        var expired = (time < expiredAt);
        if (checked) {
            item.click();
        }
        if (!expired) {
            item.click();
        }
    });
    // setTimeout(function() {
    //     document.querySelector(".md-3snewsiPlayButton .ls-playSelected").click();
    // }, 0);
}, 3000);

(2017/9/20 追記)最近のアップデートで選択のタイミングが合わなくなってしまったので、setTimeoutを使って遅らせるように修正した。

(2017/12/14 追記)GreasemonkeyがWebExtensionになったことで動かなくなったのを修正。。

最後のコメントアウトをはずすと再生も自動でされる。しかし、連続動画再生ビューアはどういうわけか勝手にリロードすることがあり、その場合、また最初の動画から再生されてしまうので使い勝手は良くない。