2拠点間の距離を求める方法を備忘録として残りておきます。
計算で算出する
/**
* 変数は下記が入っているものとする。
* $lat:現在地の緯度
* $lng:現在地の経度
* $comparisonLat:距離を比較する緯度
* $comparisonLng:距離を比較する経度
*/
// 緯度、経度の移動量を計算
$latDistance = $lat - $comparisonLat;
if ($latDistance < 0) {
$latDistance *= -1;
}
$lngDistance = $lng - $comparisonLng;
if ($lngDistance < 0) {
$latDistance *= -1;
}
// 緯度位置における経度量を計算
$latitude = 30.9221438 * cos($lat / 180 * pi());
if ($latitude < 0) {
$latitude *= -1;
}
/**
* 緯度や赤道での経度の場合0.00027778度 = 30.9221438mになるので
* 移動量÷0.00027778*30.9221438の値で三角関数を使う
*/
$distance = (int)(sqrt((abs($latDistance / 0.00027778 * 30.9221438) ** 2) + (abs($lngDistance / 0.00027778 * $latitude) ** 2)));
SQLで求める
Laravel8, MySQL8を使用しています。
SQLで計算する場合は経度と緯度をgeometry
型にしておく必要があります。
/**
* @return \Illuminate\Database\Eloquent\Builder
*/
public function newQuery()
{
$raw = '';
foreach ($this->geoFields as $column) {
$raw .= ' ST_AsText(' . $column . ') as ' . $column . ' ';
}
return parent::newQuery()->addSelect('*', DB::raw($raw));
}
/**
* 現在地から〇m以内のデータを返す
* @param float $lat 緯度
* @param float $lng 経度
* @param int $distance 距離
* @return mixed
*/
public function getData(float $lat, float $lng, int $distance)
{
return $this
->query()
->addSelect(DB::raw("ROUND(
ST_LENGTH(
ST_GeomFromText(
CONCAT(
'LineString( " . $lat . " " . $lng . " , ', ST_X(position), ' ', ST_Y(position), ')'))) * 111000) AS distance "))
->whereRaw("ROUND(
ST_LENGTH(
ST_GeomFromText(
CONCAT(
'LineString( " . $lat . " " . $lng . " , ', ST_X(position), ' ', ST_Y(position), ')'))) * 111000) < " . $distance)
->orderBy('distance')
->get();
}