大円距離で求めるk個の最近傍点
空間データベースを用意せず、指定座標に最も近い地理的な地点を検索できます。検索元の緯度と経度、候補座標の一覧、必要な件数を指定してください。各候補までの大円距離を計算し、近い順に並べ、先頭のk件を元のインデックスおよび任意のラベルとともに返します。決定的な並び順になるため、店舗検索、経路計算の前処理、近接判定、再現可能なデータ処理に適しています。
無料で実行
検索座標と候補一覧を準備します
検索元の座標を十進度で指定し、候補を1件以上10000件以下で用意してください。緯度は-90から90、経度は-180から180の範囲です。候補にも同じ条件が適用され、店舗名、倉庫コード、センサーID、都市名などのラベルを任意で付けられます。ラベルは結果へコピーされますが、順位には影響しません。kには候補数以下の正の整数を指定します。この明確な入力規則により、不完全な検索を避け、不正なレコードを分かりやすい入力エラーとして早期に検出できます。座標はWeb地図やGPS出力で一般的な十進度へ統一してください。度分秒や投影座標系のデータは、呼び出し前に変換する必要があります。距離が同じ候補については元の入力順を維持するため、実行環境や呼び出し回数が変わっても結果を再現できます。
大円距離による順位を理解します
地球を平均半径6,371.0088キロメートルの球として扱います。各候補にハーサインの関係式とatan2による中心角計算を適用するため、非常に短い距離でも、ほぼ反対側にある地点でも安定します。distance_kmは小数点以下6桁に丸め、その後で昇順に並べます。これは地表に沿った距離であり、地球内部を通る直線、道路経路、ローカルな地図投影上の距離ではありません。日付変更線付近の経度の切り替わりや両極も自然に処理されます。球面モデルは、世界規模の検索、候補発見、おおまかな配車、絞り込みに適しています。測量級の楕円体距離、道路、標高、境界、障害物が必要な場合は、この結果を一次候補として専門的な計算を続けてください。元のインデックスが返るため、ラベルがない場合や重複する場合でも入力レコードへ確実に結び付けられます。
順位付き候補を後続処理へつなげます
最近傍検索は、多くの場合、判断の終点ではなく始点です。店舗検索では近い5店舗を取得してから、営業時間や在庫で絞り込めます。物流サービスでは近隣の拠点を選び、その少数だけを道路経路エンジンへ渡せます。環境ダッシュボードでは観測値を近いセンサーへ関連付け、品質確認用に距離を保持できます。この関数はネットワーク、乱数、保存状態、現在時刻を使わないため、同じ入力から常に同じ出力が得られます。そのため、キャッシュ、固定例による結合テスト、監査時の順位再現が容易です。上限も明示されており、各候補を1回測定して有限の集合を並べるので処理量を予測できます。巨大または頻繁に変化する集合には空間インデックスが適しています。要求ごとに渡す小規模な一覧なら、索引設定を省き、次の処理へ直接渡せる明確なJSONを得られます。
活用例
近隣店舗を絞り込みます
在庫、営業時間、予約枠で絞る前に、近い店舗やサービス拠点を取得できます。
観測値をセンサーへ対応付けます
近い観測局を探し、後の検証に使う距離と元インデックスを保持できます。
経路候補を準備します
高コストな道路経路を求める前に、倉庫や経由点を近い候補だけへ減らせます。
よくある質問
1回の料金はいくらですか?
APIリクエスト1回は$0.002です。同じ決定的な計算をブラウザーでも実行できます。
どの距離式を使いますか?
平均地球半径6,371.0088キロメートルを用いる、ハーサインに基づく大円距離計算です。
同じ距離はどのように並びますか?
同距離では、0から始まる元インデックスに従い、候補の入力順を維持します。
kを候補数より大きくできますか?
できません。kは正の整数で、指定した候補点の数以下でなければなりません。
道路距離を計算しますか?
いいえ。球面上の距離であり、道路、移動時間、標高、境界、障害物は考慮しません。
開発者向け — APIアクセス
このページの機能はすべてAPIからも利用できます。自社システムに組み込みたいチーム向けのセクションです。それ以外の方は上のツールをそのままお使いください。
エンドポイント
Bearerトークンで認証し、POST1回でタスクをキューに登録します。結果はWebhookまたは署名付きリンクで受け取れます。
お使いのスタックから呼び出す
curl -X POST https://api.kit.forhosting.com/geo/k-nearest-neighbors \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"lat":40.4168,"lon":-3.7038,"points":[{"label":"Toledo","lat":39.8628,"lon":-4.0273},{"label":"Segovia","lat":40.9429,"lon":-4.1088},{"label":"Guadalajara","lat":40.6337,"lon":-3.1674}],"k":2}'const res = await fetch("https://api.kit.forhosting.com/geo/k-nearest-neighbors", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"lat": 40.4168,
"lon": -3.7038,
"points": [
{
"label": "Toledo",
"lat": 39.8628,
"lon": -4.0273
},
{
"label": "Segovia",
"lat": 40.9429,
"lon": -4.1088
},
{
"label": "Guadalajara",
"lat": 40.6337,
"lon": -3.1674
}
],
"k": 2
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/geo/k-nearest-neighbors",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"lat": 40.4168,
"lon": -3.7038,
"points": [
{
"label": "Toledo",
"lat": 39.8628,
"lon": -4.0273
},
{
"label": "Segovia",
"lat": 40.9429,
"lon": -4.1088
},
{
"label": "Guadalajara",
"lat": 40.6337,
"lon": -3.1674
}
],
"k": 2
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/geo/k-nearest-neighbors", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"lat":40.4168,"lon":-3.7038,"points":[{"label":"Toledo","lat":39.8628,"lon":-4.0273},{"label":"Segovia","lat":40.9429,"lon":-4.1088},{"label":"Guadalajara","lat":40.6337,"lon":-3.1674}],"k":2}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"lat":40.4168,"lon":-3.7038,"points":[{"label":"Toledo","lat":39.8628,"lon":-4.0273},{"label":"Segovia","lat":40.9429,"lon":-4.1088},{"label":"Guadalajara","lat":40.6337,"lon":-3.1674}],"k":2}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/geo/k-nearest-neighbors", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)リクエスト例
{
"lat": 40.4168,
"lon": -3.7038,
"points": [
{
"label": "Toledo",
"lat": 39.8628,
"lon": -4.0273
},
{
"label": "Segovia",
"lat": 40.9429,
"lon": -4.1088
},
{
"label": "Guadalajara",
"lat": 40.6337,
"lon": -3.1674
}
],
"k": 2
}レスポンス例
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "geo.k_nearest_neighbors",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}非同期APIです。task_idは即時に返ります。ポーリングは1秒あたり1リクエストまでです。
料金
単価はすべて公開しています。トークン換算や独自クレジットはありません。失敗したタスクは課金されません。
制限
max_items | 10000 |
エラー
| HTTP | コード | 意味 |
|---|---|---|
401 | unauthorized | APIキーが無効か、指定されていません。Authorizationヘッダーを確認してください。 |
402 | insufficient_balance | 残高が不足しています。チャージ後に再度お試しください。 |
404 | unknown_type | 指定されたタスクタイプは存在しません。タイプ名を確認してください。 |
429 | rate_limited | リクエストが多すぎます。しばらく待ってから再度お試しください。 |