지구를 중심으로 하는 공간 데이터를 다루려고 하니, 생소한 용어가 한둘이 아니다. 정리를 해야 겠다.
WGS84
한 지점의 좌표 값은 어떤 측지계를 기준으로 하느냐에 따라 달라진다. 과거 우리나라에서 사용하던 측지계는 Tokyo를 중심으로 사용했다. 최근에는 WGS84(1984년에 만든 최신 Word Geodetic System 이다. WGS 1984 혹은 EPSG:4326이라고 부르기도 한다)라고 부르는 세계측지계를 사용한다.
WGS84의 좌표 원점은 지구 질량 중심에 있다. 위치는 2cm 보다 작다고 한다.
투영
지도를 제작하기 위해서는 지구를 일정한 기준에서 봐야 하는데, 지구는 완벽한 원형 혹은 타원형이 아니다. 실제 울퉁불퉁한 표면을 가지고 있기 때문에 수학적으로 구현하기에 무리가 따른다. 그래서 수학적으로 쉽게 계산하기 위한 유사타원체(Geoid)를 만들었다. 지도의 좌표체계의 차이는 지오이드를 정하는 방법의 차이다.
Bessel 타원체 : 동경좌표계(Tokyo Datum)를 사용.
WGS84 : 미국방성이 1984년 채택한 GPS용 타원체
이 타원체는 3차원 곡면좌표를 가지는데, 이를 우리가 사용하는 2차원 평면좌표에 표현하기 위해서 투영이라는 과정을 거친다.
투영법(도법)은 나라와 지역별로 다양하다. 베셀타원체의 투영법으로는 TM 도법을 사용하고, WGS84 타원체의 경우 UTM 도법을 사용한다. 우리나라는 TM과 UTM을 모두 사용한다.
Spatial 데이터 저장
Mysql, ElasticSearch 혹은 Solr, MongoDB등 많은 RDBMS혹은 NoSQL 애플리케이션들이 spatial 쿼리를 지원한다.
나는 Postgresql의 spatial 기능 확장인 PostGIS로 공간 데이터를 저장하기로 했다. 이유는 기능과 안정성 모든 측면에서 독보적이라는 평가가 많아서이다. 상용 DBMS인 Oracle과 비교해서도 그렇다는 많은 글들을 읽을 수 있었다.
PostGIS 설치 및 간단한 사용
역시 우분투 이미 패키징 돼 있다.
# apt-cache search postgis
...
postgis - Geographic objects support for PostgreSQL
postgis-doc - Geographic objects support for PostgreSQL -- documentation
postgis-gui - Geographic objects support for PostgreSQL -- GUI programs
postgresql-9.6-pgrouting - Routing functionality support for PostgreSQL/PostGIS
postgresql-9.6-pgrouting-doc - Routing functionality support for PostgreSQL/PostGIS (Documentation)
postgresql-9.6-pgrouting-scripts - Routing functionality support for PostgreSQL/PostGIS - scripts
postgresql-9.6-postgis-2.3 - Geographic objects support for PostgreSQL 9.6
postgresql-9.6-postgis-2.3-scripts - Geographic objects support for PostgreSQL 9.6 -- scripts
....
GUI 프로그램도 제공하는 것 같은데, 일단은 "postgresql-9.6-postgis-2.3"만 설치했다.
$ apt-get install postgresql-9.6-postgis-2.3
postgres 사용 문서는 아니다. 유저를 만들거나 하는 것들을 여기에서 하고 싶지 않다. 그냥 슈퍼유저인 "postgres" 계정으로 su(switch user) 한 다음에, 작업을 하자.
postgres로 su 한다음 테스트를 위한 데이터 베이스를 만든다.
$ sudo su - postgres
$ createdb mygis
$ psql mygis
mygis=# \conninfo
You are connected to database "mygis" as user "postgres" via socket in "/var/run/postgresql" at port "5432".
PostGIS는 postgresql의 확장기능이다. spatial function을 이용하기 위해서는 postgis 확장을 로딩해야 한다.
이제 mygis 데이터베이스에서 spatial functions를 사용할 수 있게 됐다. 서울 시청(126.9778923,37.5654808)에서 광주광역시청(126.8491083,35.1600765)까지의 직선거리를 구해보자. "ST_DistanceSphere" 함수를 이용하면 두 지점(경도,위도)의 거리를 구 할 수 있다. st_makepoint함수는 입력한 두개의 float값을 경도,위도로 변환한다.
Contents
용어 정리
WGS84
투영
- Bessel 타원체 : 동경좌표계(Tokyo Datum)를 사용.
- WGS84 : 미국방성이 1984년 채택한 GPS용 타원체
이 타원체는 3차원 곡면좌표를 가지는데, 이를 우리가 사용하는 2차원 평면좌표에 표현하기 위해서 투영이라는 과정을 거친다. 투영법(도법)은 나라와 지역별로 다양하다. 베셀타원체의 투영법으로는 TM 도법을 사용하고, WGS84 타원체의 경우 UTM 도법을 사용한다. 우리나라는 TM과 UTM을 모두 사용한다.Spatial 데이터 저장
PostGIS 설치 및 간단한 사용
mygis=# select ST_DistanceSphere(st_makepoint(126.9778923,37.5654808),st_makepoint(126.8491083,35.1600765)); st_distancesphere ------------------- 267717.5019854Geometric Types
Geometry 함수들
예제 테이블
INSERT INTO restaurant VALUES('푸켓쌀국수', '기타', 37.499851, 127.026272, 3 ); INSERT INTO restaurant VALUES('메드포갈릭', '이탈리안', 37.497774, 127.026615, 4 ); INSERT INTO restaurant VALUES('아리랑', '한식', 37.499587, 127.027098, 5 ); INSERT INTO restaurant VALUES('참치공방', '한식', 37.497868, 127.028428, 5 ); INSERT INTO restaurant VALUES('베이징', '중식', 37.496395, 127.029297, 3 );Geometry
- POINT 는 postgresql이 제공하는 Geometry Types 중 하나로 평면에서 점을 표현할 때 사용한다.
- SRID는 spatial reference identifier는 평면 지구, 혹운 둥근지구 매핑에 사용되는 특정 타원면을 기준으로 하는 공간 참조 시스템이다. rastaurant 테이블은 SRID 4326이라는 투영체를 사용하는데, 이는 WGS84를 의미한다.
latitude, longitude 컬럼 데이터를 이용해서 gemoetry 필드를 업데이트 했다.mygis=# select * from restaurant ; name | category | latitude | longitude | point | geom ------------+----------+-----------+------------+-------+---------------------------------------------------- 푸켓쌀국수 | 기타 | 37.499851 | 127.026272 | 3 | 0101000020E61000003C33C170AEC15F40BBEF181EFBBF4240 메드포갈릭 | 이탈리안 | 37.497774 | 127.026615 | 4 | 0101000020E610000051A5660FB4C15F404966F50EB7BF4240 아리랑 | 한식 | 37.499587 | 127.027098 | 5 | 0101000020E61000005EF23FF9BBC15F40DD408177F2BF4240 참치공방 | 한식 | 37.497868 | 127.028428 | 5 | 0101000020E61000009B92ACC3D1C15F40CADC7C23BABF4240 베이징 | 중식 | 37.496395 | 127.029297 | 3 | 0101000020E6100000BD378600E0C15F40EF7211DF89BF4240 (5 rows)mygis=# SELECT name, latitude, longitude, ST_AsText(geom), ST_AsEwkt(geom), ST_X(geom), ST_Y(geom) FROM restaurant ; name | latitude | longitude | st_astext | st_asewkt | st_x | st_y ------------+-----------+------------+-----------------------------+---------------------------------------+------------+----------- 푸켓쌀국수 | 37.499851 | 127.026272 | POINT(127.026272 37.499851) | SRID=4326;POINT(127.026272 37.499851) | 127.026272 | 37.499851 메드포갈릭 | 37.497774 | 127.026615 | POINT(127.026615 37.497774) | SRID=4326;POINT(127.026615 37.497774) | 127.026615 | 37.497774 아리랑 | 37.499587 | 127.027098 | POINT(127.027098 37.499587) | SRID=4326;POINT(127.027098 37.499587) | 127.027098 | 37.499587 참치공방 | 37.497868 | 127.028428 | POINT(127.028428 37.497868) | SRID=4326;POINT(127.028428 37.497868) | 127.028428 | 37.497868 베이징 | 37.496395 | 127.029297 | POINT(127.029297 37.496395) | SRID=4326;POINT(127.029297 37.496395) | 127.029297 | 37.496395mygis=# SELECT * FROM restaurant WHERE ST_DistanceSphere(geom, ST_MakePoint(127.026993,37.497933)) <= 150; name | category | latitude | longitude | point | geom ------------+----------+-----------+------------+-------+---------------------------------------------------- 메드포갈릭 | 이탈리안 | 37.497774 | 127.026615 | 4 | 0101000020E610000051A5660FB4C15F404966F50EB7BF4240 참치공방 | 한식 | 37.497868 | 127.028428 | 5 | 0101000020E61000009B92ACC3D1C15F40CADC7C23BABF4240 (2 rows)SELECT name, latitude, longitude, ST_DistanceSphere(geom, ST_MakePoint(127.026993,37.497933)) FROM restaurant WHERE ST_DistanceSphere(geom, ST_MakePoint(127.026993,37.497933)) <= 150; name | latitude | longitude | st_distancesphere ------------+-----------+------------+------------------- 메드포갈릭 | 37.497774 | 127.026615 | 37.74392799 참치공방 | 37.497868 | 127.028428 | 126.80109399 (2 rows)기타 참고할 만한 Spatial 데이터베이스
위치 데이터 저장 애플리케이션 예제
- google map 상에서 Point를 찍고, 음식점 정보 몇 가지를 입력하고 submit 하면 데이터베이스에 저장한다.
- 자신의 위치에서, 가장 가까운 음식점을 검색한다. 위치는 HTML5 GEO API를 이용한다.
... 계속참고
Recent Posts
Archive Posts
Tags