やり方
近くにあるもの、近づく時刻
ある日付に、ある天体にいちばん近い天体を、空の見かけの角度か宇宙での距離でさがします。2つの天体がいちばん近づく時刻も、JPL Horizons と秒の単位で比べて確かめています。
/nearest は、太陽・惑星・準惑星・衛星について、3つのことに答えます。「この日、この天体のとなりには何がある?」「この2つはいつ、いちばん近づく?」「この2つは今どれだけ離れていて、どこまで離れる?」です。ゲーム (「今夜、月はどの惑星のとなり?」)、合 (ごう) のカレンダー、星図のラベルに使えます。ブラウザなしでどこでも動き、このパッケージ自身の位置を使います。
import { closestApproach, conjunctions, distance, distanceRange, nearest, within } from "@johnmorrisdotca/wakusei-planets/nearest";
const date = Date.UTC(2026, 11, 27, 16);
console.log(nearest("moon", { kind: "planet", count: 2, date }).map((row) => `${row.id} ${row.angle.toFixed(2)} degrees`).join(", "));
console.log(within("jupiter", 1.5, { date }).map((row) => row.id).join(", "));
console.log(nearest("earth", { by: "space", kind: "planet", count: 1, date })[0]?.distanceAu.toFixed(2), "au");
const great = closestApproach("jupiter", "saturn", { from: Date.UTC(2020, 11, 1), to: Date.UTC(2021, 0, 1) });
console.log(great.time.toISOString(), great.angle?.toFixed(2), "degrees");
console.log(distance("earth", "mars", date).distanceAu.toFixed(2), "au now apart");
console.log(distanceRange("earth", "mars", { from: Date.UTC(1900, 0, 1), to: Date.UTC(2100, 0, 1) }).max.distanceAu.toFixed(2), "au at most");
console.log(conjunctions({ from: Date.UTC(2023, 0, 1), to: Date.UTC(2024, 0, 1), bodies: ["venus", "jupiter"], within: 2 }).length, "close approaches");jupiter 1.41 degrees, mars 13.46 degrees
io, europa, ganymede, callisto, moon
0.62 au
2020-12-21T18:25:35.939Z 0.10 degrees
0.95 au now apart
2.68 au at most
1 close approaches6つの関数
| 関数 | 返すもの |
|---|---|
nearest(target, options) | ある日付に target にいちばん近い天体を、近い順に |
within(target, radius, options) | ある半径の中にあるすべての天体を、近い順に |
closestApproach(a, b, { from, to }) | 期間の中で2つの天体がいちばん近づく時刻と、そのときの近さ |
conjunctions({ from, to, within, bodies }) | 期間の中のすべての天体の組の近づきを、早い順に |
distance(a, b, date) | ある日付の2つの天体のあいだの直線距離を、kmとauで |
distanceRange(a, b, { from, to }) | 期間の中で2つの天体がいちばん近い距離といちばん遠い距離を、それぞれの時刻つきで |
天体は "mars"、"moon"、"io" のような名前で、パッケージのほかの部分と同じ名前です。太陽、惑星、準惑星、衛星のすべてが対象です。恒星は /stars にあります。恒星はここでは target にできません。
オプション
どの関数でも同じオプションは同じ意味です。ファミリーのほかのパッケージが同じものに使う名前でもあります。
| オプション | 意味 |
|---|---|
by | "sky" (初期値): 観測者の空で、2つの天体のあいだの角度。"space": 2つの中心のあいだの距離 |
date | Date か、1970年からのミリ秒 (UTC)。初期値は今 |
count | いくつ返すか。初期値は5。within があるときは、その中のすべて |
within | これより近いものだけ。by: "sky" では度、by: "space" ではキロメートル |
kind | この種類だけ ("planet" 惑星、"dwarf-planet" 準惑星、"moon" 衛星、"star" は太陽)。種類の配列も可 |
bodies | これらの天体だけをさがす |
observer | 空を見る場所。初期値は地球の中心。{ latitude, longitude, heightM } で地球上の場所、天体の名前 ("mars") でその天体の空 |
恒星には /stars に magnitude (等級) の絞りこみがあります。このパッケージの天体には明るさのデータがないので、ここに magnitude オプションはありません。
空で
by: "sky" は、観測者から見た2つの天体の方向のあいだの角度で、0度から180度です。外積と内積のアークタンジェントで求めるので、0度 (合) や180度 (衝) の近くでも、90度のときと同じ精度です。方向は天文測位 (astrometric) で、JPL Horizons の赤経・赤緯と同じ考え方です。それぞれの天体は光が出たときの場所にあり (月は1秒あまり前、海王星は何時間も前)、観測者は今の場所にいます。光行差と光の曲がりは足していません。近くにある2つの天体は、ほとんど同じだけずれるからです。
月は近いので、立っている場所で答えが最大で1度ほど変わります。月には場所を渡してください。2026年12月27日、ガニメデは地球の中心から見ると月から1.4度、バンクーバーから見ると2.3度です。
import { nearest } from "@johnmorrisdotca/wakusei-planets/nearest";
const date = Date.UTC(2026, 11, 27, 16);
const centre = nearest("moon", { bodies: ["ganymede"], date })[0];
const vancouver = nearest("moon", { bodies: ["ganymede"], date, observer: { latitude: 49.28, longitude: -123.12 } })[0];
console.log(centre?.angle.toFixed(2), vancouver?.angle.toFixed(2));
console.log(nearest("earth", { observer: "mars", count: 1, date })[0]?.id, "is next to the Earth in the sky of Mars");1.40 2.30
moon is next to the Earth in the sky of Mars天体は自分の空には出てきません。target 自身と、空を見ている天体 (地球上の観測者なら地球) は結果に入りません。空の target が観測者自身の天体だと RangeError を投げます。
宇宙で
by: "space" は、その日付の2つの中心を結ぶ直線の距離で、キロメートル (distanceKm) と天文単位 (distanceAu) で返します。光の到着時間は入っていません。ある一瞬の形です。観測者は関係ないので、無視されます。
いちばん近づく時刻と合
closestApproach と conjunctions は、2つの天体のあいだの近さが時間でどう変わるかを見ます。期間をあらい刻みで調べます。刻みは、いちばん速い天体の公転周期の40分の1で、2日を超えません (イオは1.8日で1周するので、イオを入れると約1時間刻みです。火星や木星は2日刻みです)。近さが下がってから上がるところを見つけたら、黄金分割探索で最小の時刻を約1秒の単位まで絞ります (範囲が0.5秒より小さくなったら止めます)。
closestApproach(a, b, { from, to }) は、期間の中でいちばん小さい近さを返します。期間を通して近さが下がるだけ、または上がるだけのときは、小さいほうの端を返し、atEdge が true になります。conjunctions は、bodies のすべての組の最小のうち、within の中にあるものを早い順に返します (空では初期値が5度、宇宙ではすべて)。bodies の初期値は太陽と水星から海王星で、空を見ている天体は除きます。最小になるのは2つの中心の近さなので、一方がもう一方の前を横切る場合 (通過や掩蔽) も、0にはならず、小数点以下の度になります。
import { conjunctions } from "@johnmorrisdotca/wakusei-planets/nearest";
const found = conjunctions({ from: Date.UTC(2026, 0, 1), to: Date.UTC(2027, 0, 1), within: 1 });
for (const one of found.slice(0, 5)) console.log(one.a, one.b, one.time.toISOString().slice(0, 16), one.angle?.toFixed(2));sun venus 2026-01-06T06:24 0.70
venus mars 2026-01-08T03:12 0.17
sun mars 2026-01-09T09:36 0.94
mercury mars 2026-01-18T06:33 0.96
mercury venus 2026-01-29T13:55 0.68距離と、2つの天体が離れる範囲
distance(a, b, date) は、どの2つの天体でも使える by: "space" を1回の呼び出しにしたもので、{ a, b, time, distanceKm, distanceAu, uncertaintyKm } を返します。日付は Date かミリ秒で、省略すると今です。distanceRange(a, b, { from, to }) は closestApproach と同じように期間を調べ、{ a, b, min, max } を返します。それぞれ { time, distanceKm, distanceAu, uncertaintyKm, atEdge } です。どちらの折り返し点も、同じ黄金分割探索で約1秒の単位まで絞ります。最大は、距離にマイナスをつけたものの最小です。期間を通して距離が下がるだけ、または上がるだけのときは、その極値になる端を atEdge: true で返します。
import { distance, distanceRange } from "@johnmorrisdotca/wakusei-planets/nearest";
const { min, max } = distanceRange("earth", "mars", { from: Date.UTC(1900, 0, 1), to: Date.UTC(2100, 0, 1) });
console.log(min.time.toISOString().slice(0, 10), min.distanceAu.toFixed(3), "au;", max.time.toISOString().slice(0, 10), max.distanceAu.toFixed(3), "au");
console.log(Math.round(distance("jupiter", "io", Date.UTC(2026, 10, 8)).distanceKm), "km from Jupiter to Io");2003-08-27 0.373 au; 2066-08-25 2.676 au
422312 km from Jupiter to Io惑星、1900年から2100年
200年のあいだの、惑星の各組のいちばん近い距離といちばん遠い距離と、それぞれの年です (node scripts/distance-table.ts が表を出力します)。単位は天文単位です。年のあとの星印は、期間の中の折り返し点ではなく、期間の端が極値だという意味です。地球と火星は、2003年8月27日に0.373 auまで近づき、2066年に2.676 auまで離れます。
| 組 | 最小 (au) | 年 | 最大 (au) | 年 |
|---|---|---|---|---|
| 水星と金星 | 0.261 | 2085 | 1.187 | 2059 |
| 水星と地球 | 0.549 | 2061 | 1.452 | 2034 |
| 水星と火星 | 0.966 | 1918 | 2.080 | 1908 |
| 水星と木星 | 4.595 | 2010 | 5.810 | 2075 |
| 水星と土星 | 8.705 | 1915 | 10.379 | 1900 |
| 水星と天王星 | 17.897 | 2051 | 20.486 | 2010 |
| 水星と海王星 | 29.483 | 2041 | 30.656 | 1958 |
| 金星と地球 | 0.264 | 2093 | 1.736 | 1960 |
| 金星と火星 | 0.654 | 2052 | 2.394 | 2002 |
| 金星と木星 | 4.223 | 2070 | 6.182 | 2005 |
| 金星と土星 | 8.295 | 1914 | 10.788 | 1900 |
| 金星と天王星 | 17.564 | 2050 | 20.818 | 2092 |
| 金星と海王星 | 29.083 | 2042 | 31.055 | 1959 |
| 地球と火星 | 0.373 | 2003 | 2.676 | 2066 |
| 地球と木星 | 3.949 | 1951 | 6.456 | 1945 |
| 地球と土星 | 8.030 | 1914 | 11.051 | 1900 |
| 地球と天王星 | 17.290 | 2051 | 21.093 | 2093 |
| 地球と海王星 | 28.814 | 2041 | 31.324 | 1958 |
| 火星と木星 | 3.516 | 2000 | 6.887 | 1994 |
| 火星と土星 | 7.418 | 1915 | 11.663 | 2019 |
| 火星と天王星 | 16.621 | 2049 | 21.759 | 2093 |
| 火星と海王星 | 28.304 | 1900 | 31.838 | 1983 |
| 木星と土星 | 4.033 | 1921 | 15.241 | 1990 |
| 木星と天王星 | 12.849 | 2052 | 25.454 | 1920 |
| 木星と海王星 | 24.745 | 1907 | 35.393 | 1990 |
| 土星と天王星 | 9.234 | 1988 | 29.633 | 2100* |
| 土星と海王星 | 20.178 | 1989 | 40.007 | 2079 |
| 天王星と海王星 | 10.570 | 1994 | 49.879 | 2084 |
どの距離も、結果の不確かさの範囲で正しいと考えてください。内惑星で数千km、木星より外で数万kmです。JPL Horizons との比較は3つの組 (地球と火星、金星と地球、木星と土星) で行います。test/nearest.test.ts は、1900年から2100年のそれぞれの組の最小と最大の距離について、Horizons の表 (一方の惑星の中心からもう一方の中心への幾何学的なベクトルで、折り返し点の前後10日を6時間刻み。scripts/fetch-horizons-distance.py が問い合わせを test/data/horizons-distance.json に記録します) を使い、放物線を当てはめて極値を求めます。
| 組 | Horizons | このパッケージ | 距離の差 | 時刻の差 |
|---|---|---|---|---|
| 地球と火星、最小 | 2003-08-27 09:41、0.37272 au | 09:51、0.37271 au | 1,410 km | 10分 |
| 地球と火星、最大 | 2066-08-25 00:36、2.67633 au | 00:28、2.67631 au | 2,145 km | 8分 |
| 金星と地球、最小 | 2093-12-17 10:40、0.26433 au | 10:40、0.26432 au | 1,020 km | 1秒 |
| 金星と地球、最大 | 1960-06-21 23:15、1.73598 au | 23:27、1.73599 au | 1,095 km | 12分 |
| 木星と土星、最小 | 1921-07-26 20:13、4.03311 au | 21:21、4.03309 au | 3,950 km | 69分 |
| 木星と土星、最大 | 1990-10-01 07:59、15.24084 au | 09:44、15.24086 au | 2,025 km | 105分 |
距離の差は、毎回、示した不確かさの中に入っています (その3分の1から10分の1)。時刻の差は、数分から1、2時間です。折り返し点では距離がほとんど変わらない (1時間に数km) ので、位置のわずかな差で、頂点が少し早くなったり遅くなったりします。
結果に入っているもの
空の結果は { id, kind, angle, uncertaintyArcseconds }、宇宙の結果は { id, kind, distanceKm, distanceAu, uncertaintyKm } です。近づきは { a, b, time, atEdge, uncertaintySeconds } に、角度と uncertaintyArcseconds、または距離と uncertaintyKm がつきます。time は Date です。
不確かさ (uncertainty) は上限ではなく、理論から期待できる大きさです。精度テストが天体ごとに守らせている限度 (惑星は太陽から見た方向、衛星は惑星から見た方向) を、その天体の距離でキロメートルにして、合わせたものです。2つの天体が共有する誤差は打ち消されます。衛星とその惑星は惑星の誤差を共有するので、木星とイオは、木星自身の位置が3.6秒角の精度でも、1秒角に満たない精度になります。地球から見るときの地球自身の誤差も、空で近くにある2つの天体のあいだでは打ち消されます。uncertaintySeconds は、角度の不確かさを、2つが横を通りすぎる速さで割ったものです。そのため、ゆっくりすれちがう木星と土星 (1秒に0.01秒角) は数分、月と惑星は数秒になります。tables を読み込まないと、木星と土星の衛星は当てはめた軌道なので、不確かさにもそれが出ます。
JPL Horizons との比較
test/nearest.test.ts は、すべての出来事を Horizons 自身の表と比べます。表は一度だけ取得してあり (scripts/fetch-horizons-approach.py が、それぞれの問い合わせを test/data/horizons-approach.json に記録します)、テストにネットワークは使いません。Horizons の赤経・赤緯は天文測位で、地球の中心から、1分刻み (金星と木星は5分刻み) です。2つの近さの最小は、表の最小のまわりで、近さの2乗に当てはめた放物線の頂点です。2026年11月8日の測定です。
| 出来事 | Horizons | このパッケージ | 時刻の差 | 角度の差 |
|---|---|---|---|---|
| 木星と土星、大合 | 2020-12-21 18:21:06、0.10176度 | 18:25:36、0.10184度 | 270秒 | 0.27秒角 |
| 金星と木星 | 2023-03-02 05:05:18、0.48915度 | 05:05:41、0.48900度 | 23秒 | 0.54秒角 |
| 月と水星、2026年12月 | 12-07 19:49:59、5.70071度 | 19:50:00、5.70086度 | 1秒 | 0.55秒角 |
| 月と金星 | 12-05 05:04:49、6.59375度 | 05:04:48、6.59392度 | 1秒 | 0.61秒角 |
| 月と火星 | 12-28 13:29:22、4.73649度 | 13:29:29、4.73689度 | 7秒 | 1.45秒角 |
| 月と木星 | 12-27 16:26:11、1.38067度 | 16:26:11、1.38056度 | 0.2秒 | 0.40秒角 |
| 月と土星 | 12-18 04:37:58、6.17202度 | 04:37:50、6.17212度 | 7秒 | 0.33秒角 |
| 月と天王星 | 12-22 02:49:30、5.16230度 | 02:49:24、5.16253度 | 7秒 | 0.80秒角 |
| 月と海王星 | 12-17 16:59:52、4.62811度 | 16:59:51、4.62788度 | 1秒 | 0.85秒角 |
角度の差はどれも1.5秒角以内で、これは惑星自身の精度です。時刻の差は、1時間に0.5度動く月では数秒、大合では270秒です。木星と土星は1秒に0.01秒角しか近づかないので、0.27秒角が270秒になります。テストは、これらより少しだけ大きい限度を守らせ、示した不確かさが差をおおっているかも確かめます。地球上の場所も確かめています。バンクーバーから見た月と金星を30分刻みの25点で比べると、Horizons の地上観測者の表との差は0.9秒角以内で、地球の中心から見たものだと0.85度ずれます。距離は、1800年から2200年の60の日付で Horizons のベクトルと比べています。地球から各惑星までの距離は、すべての日付で示した不確かさの中に入り、いちばん悪い日でもその3分の2です。
探索そのものは、同じ近さを1分刻みでしらみつぶしに調べた結果と比べています (最小の時刻は1分以内、角度は10万分の1度以内)。conjunctions の一覧は、6時間刻みの調べ直しと同じものを見つけます。
かかる時間
node scripts/bench-nearest.ts が、それぞれの探索の時間を測ります。1台のマシン (Node 24、Apple のノートパソコン) で5回の中央値です。
| 探索 | 時間 |
|---|---|
nearest、1つの天体と、ほかの46個すべて、ある日付 | 1 ms |
closestApproach、金星と木星、1年 | 2 ms |
conjunctions、太陽と惑星 (28組)、1年 | 18 ms |
conjunctions、月・金星・火星・木星、1年 | 46 ms |
conjunctions、木星と4つの衛星、1年 | 1.1 s |
どの天体も、1刻みにつき1回だけ計算します。いくつの組に入っていても同じです。なので、天体の数が増えると、時間はその数に比例して増え、2乗では増えません。時間がかかるのは刻みの細かさです。イオの刻みのせいで、ガリレオ衛星の1年の探索は、惑星の探索の100倍ほどかかります。質問に合った within、短い bodies、衛星なら数年までの期間を使ってください。
限界
- 精度はパッケージの精度です。惑星は数秒角、衛星は軌道の上で1度か2度なので、2つの衛星のあいだの角度は、それより良くはなりません (精度を見てください)。
- 1つの組の2つの最小が刻みより近いと、見落とすことがありますが、これらの天体にそういう組はありません。逆行のある組 (火星と木星) は、2日以下の刻みで調べます。
- 距離には光の到着時間がなく、空の角度には光行差と光の曲がりがありません。
- 1800年から2200年の外では位置が悪くなります。準惑星は、表の年の外では1つの時点の接触軌道要素になります。不確かさにそれが出ます (秒角ではなく度)。
targetはこのパッケージの天体でなければなりません。惑星にいちばん近い恒星や、惑星がいる星座は、/starsや星座を持つパッケージの仕事です。
この日本語は、まだ日本語を母語とする方の確認を受けていません。訂正を歓迎します。