'국가교통정보센터'에 해당되는 글 1건

  1. 2009.06.24 OSM 작업노트 #11: 도로 3

OSM 작업노트 #11: 도로

GPS 2009. 6. 24. 20:52
작년 10월부터 OSM 간보기를 하다가 올 3월초부터 OSM 작업을 시작했는데, 4개월만 더 있으면  OSM 작업하겠다고 생각한지 만 1년이 된다.

저번 주와 마찬가지로 이번 주에도 작업을 그리 많이 하지 못했다. 이번 주는 화요일, 수요일 합쳐 약 7시간 정도 작업. 이 기사 쓰는데 쓰는 시간이 더 걸리는 것 같다. 국가교통정보센터의 지도가 내년에 업데이트 되어도 그것을 손쉽게 업데이트할 방법을 찾다보니... 도로 작업에 너무 많은 시간을 까먹고 있다.

국가교통정보센터의 지도에서 추출한 도로로 다음 네 단계로 작업으로 나눴다. 라우팅은 미심쩍은 것들이 많아 이번 주 작업에서 뺐다.

1. 노이즈 제거

사용자 삽입 이미지
왼쪽: 원본 데이터, 오른쪽: 노이즈 제거 후

아마도
프로젝션에 따른 오차를 보정하다가(추측임) 위와 같은 노이즈가 원치않게 끼어든 것 같다. polygon 처리에 사용하던 이동평균 보간으로 노이즈를 없애버리면 유의미한 vertex도 날아가므로 노이즈의 성향을 살펴 연직 및 수평 이동이 발견될 때에만 제한적으로 보정 했다.

이런 노이즈의 '크기'는 대략 1-4m 정도. 2점/3점까지 수평/연직이 발견되면 한 점이나 두 점을 삭제하고 2점/3점의 평균 거리로 첫 번째 위치를 이동하여 보정했다.
 
2. 선로 합치기
 
국도 및 지방도는 고속도로처럼 뚜렷한 경계선에 의해 구분되지 않으므로 2개의 라인이 서로 다른 방향을 가진 벡터로 진행할 필요가 없다. 물론 국도나 지방도 중에서 4/8차선이 없는 것은 아니지만, 2개의 라인으로 표현되면 파일 크기가 커지고, 굳이 그렇게 도로 폭을 크게 묘사할 필요가 없다고 판단해 국도와 지방도의 선로를 합치기로 했다.
 
선로를 합치기 위한 조건은, 두 벡터의 시작점/끝점이 일정 거리 내에 인접해 있고 벡터의 방향만 반대일 때이다. 아울러 polyline의 이름과 타잎이 일치해야 한다.
 
시작점, 끝점은 경위도좌표로 나타나므로 두 좌표의 거리를 재어 파라미터로 정한 거리 안에 들어오면 인접했다고 판단할 수 있다. 평면 상의 두 점의 거리는 sqrt( (x2 - x1)^2 + (y2 - y1)^2 ). 물론 경위도로 표현되는 두 좌표는 구체인 지구 구면의 거리가 되어야 하므로 평면 거리는 쓸모없다. 구면 상의 두 점의 거리는 구면기하 삼각함수를 이용한 Haversine 공식을 사용해 계산:
 
d = acos(sin(lat1) * sin(lat2) +  cos(lat1) * cos(lat2) * cos(lon2 - lon1)) * R
R(지구반지름) = 6371000m
 
자전 및 공전을 하는 지구가 완전한 구체는 아니라서(WGS-84 ellipsoid 모델에서 적도 반지름은 6378km, 극 반지름은 6357km) Haversine식은 0.3% 가량의 오차를 가진다(즉, 1km 거리에서 3m 가량의 오차). 오차를 줄이려면Vincenty 공식을 사용하면 되지만(오차가 무려 1mm), 좌표간 거리가 대단한 정밀도를 가질 필요가 없고 계산량도 많아 Haversine 공식을 사용하기로 했다. 지구면의 두 지점에 관한 여러 종류의 수식은 여기를 참조.
 
사용자 삽입 이미지
왼쪽: 작업 전, 오른쪽: 작업 후

국도 및 지방도에 좌표 거리를 25m 이내로 했다. 선로 합치기는 비교적 잘 되었다. 예상대로 파일 크기는 1/2로 줄었다.
 
3. 인접 차선 결합
 
국가교통정보센터의 도로는 대부분 잘게 토막나 있다. 이것들을 하나의 긴 도로로 묶어 놓는다. 선로 합치기와 마찬가지로 벡터의 시작점/끝점이 일정 거리 내에 인접해 있으면 합친다. 경우의 수는 네 가지다.
 
vector1: B1 ---->---->---->---- E1
vector2: B2 ---->---->---->---- E2
 
E1, B2 인접: vector2의 B2를 지우고(공통) vector2를 vector1뒤에 연결한 다음 vector2 삭제(공통)
B1, E2 인접: 위와 비슷
B1, B2 인접: vector2의 방향을 바꿔 vector1에 연결
E1, E2 인접: 위와 비슷.

사용자 삽입 이미지
왼쪽: 떨어져서 별개로 선택되는 도로들, 오른쪽: 연결된 도로

4. 벡터 평탄화
 
벡터가 완만하게 변화하는 구간에서만 평탄화를 실시한다. 평탄화를 하면 지점의 갯수가 줄어든다. 변화폭은 일정 갯수의 지점에서 벡터 방향(bearing)의 각도 변화의 총합을 측정하여 파라미터로 결정한다. 예: 10점 동안 각도 변화가 10도 미만이면 평탄화.

평탄화는 급격한 변화 구간(예를 들면 도로의 인터체인지의 원형 진입로)은 그대로 놔 두고 완만한 변화 구간을 압축하는 효과가 있어 파일 크기를 줄일 수 있다. 3점 각도 변화 15도에서 원래 데이터를 크게 손상시키지 않으며 그 크기를 대략 1/2로 줄였다.

잘 뒤져보면 위에 언급한 네 가지 작업에 적합한 좋은 알고리즘이 있을 법하지만, 굳이 속도나 효율을 요구하는게 아니라서 일단 이대로 프로그래밍하기로 했다.

네 가지 작업의 효과(또는 취약점)을 확인할 수 있도록 파라미터를 선택하여 처리할 수 있도록 GUI 프로그램을 짰다.

사용자 삽입 이미지
이전의 해안선 처리에 사용하던 프로그램과 통합하고, polygon 처리할 때도 smoothing을 넣으니까 vertex 수가 10% 가량 줄었다. 빙고.

프로그램을 돌려보니 출력 파일의 크기가 원본의 24~30% 정도 밖에 되지 않는다. 원래 계획했던, 350MB를 100MB 이내로 줄이는 것이 가능하다. 한동안은 한가하게 출력 파일을 검증하는 작업을 할 것이다. 더디긴 하지만 작업은 계획대로 진행되고 있다.

 

 
,