두개의 위도 경도가 있고 그 사이의 거리를 구해야하는 일이 발생하여 찾아보았다.
하버사인공식
하버사인 공식을 볼 수 있는 홈페이지 www.movable-type.co.uk/scripts/latlong.html
내용의 스크린샷은 아래와 같다.
하버사인공식 mysql 적용 예시
select
ROUND(6371 * ACOS(COS(RADIANS(latitude2)) * COS(RADIANS(latitude1)) * COS(RADIANS(longitude1) - RADIANS(longitude2)) + SIN(RADIANS(latitude2)) * SIN(RADIANS(latitude1))), 1) AS distance
from
location
having distance < 1
6371을 사용하면 km단위의 값이 나오고, 3959를 사용하면 miles단위의 값이 나온다고 한다.
실제 프로젝트 사용 예시
실제 프로젝트에서는 지도의 zoom in, zoom out레벨을 이용하여 각 레벨마다 불러오는 아이템의 수를 제한하는데 사용했다. 현재 정 중앙의 점, 줌 레벨을 가져오고 각 줌 레벨 별로 특정 거리 만큼 거리가 있는 아이템만 출력한다.
*2021-05-21추가
이 글이 유일하게 유입자가 많은 글이다...신기하게 이거를 찾는 분이 있을줄은 음...
그래서 위의 예시를 php(codeigniter)에서 사용한 코드를 첨부 하였다.
function getItem($zl = '', $lat = '129.1234567', $lng = '35.1234567'){
$maxDistance = array(0,9000,8000,7000,6000,5000,2000,1050,550,290,130,65,33,16.5,7.7,4,2,1,0.5,0.2,0.1);
$this->db->select("*");
$this->db->select("ROUND(6371 * ACOS(COS(RADIANS($lat)) * COS(RADIANS(latitude)) * COS(RADIANS(longitude) - RADIANS($lng)) + SIN(RADIANS($lat)) * SIN(RADIANS(latitude))), 1) AS distance2");//added
$this->db->from("location");
$this->db->where("latitude !=",0);
$this->db->where("longitude !=",0);
$zl = floor($zl);
$this->db->having("distance <= $maxDistance[$zl]");//added
$query = $this->db->get();
return $query->result();
}
지도에 따라 좀 다르겠지만 zoom level마다 표시해야하는 거리를 설정하고 zoom in, zoom out할때마다 새로 불러오도록 사용했다. floor($zl)을 넣었는데 저거는 zoom level이 실수로 나오게 기능이 좀 바껴서 추가를 했다.
'DATABASE' 카테고리의 다른 글
MySQL ogr2ogr(공간정보 저장에 대해서) (0) | 2021.07.28 |
---|---|
varchar타입에 order by를 써야하는 경우 (0) | 2021.07.20 |
date, datetime 속도 이슈 정리(feat timestamp를 쓰도록...) (0) | 2021.06.08 |
mysql union과 union all의 차이 (0) | 2021.05.31 |
mysql 인덱스 확인, 추가, 삭제 (0) | 2021.04.21 |
댓글