폴리곤의 구성 좌표가 시계방향인지 반시계방향인지 검사하기

폴리곤이 오목한지 볼록한지에 대한 각각의 경에 대해서, 좌표가 시계방향으로 되어 있는지, 반시계 방향으로 되어 있는지를 검사하기 위한 방법입니다. GIS에서 폴리곤 도형에 대해 시계방향인지 반시계방향인지에 따라 폴리곤에 대한 구멍(Hole)인지의 여부를 결정짓는 경우가 있습니다. 이외에 폴리곤의 앞면인지 뒷면인지의 여부도 시계방향인지의 여부에 따라 결정됩니다.

먼저 폴리곤의 구성하는 좌표의 개수가 N개라고 하고, 구성 좌표를 아래처럼 표기합니다.

사용자 삽입 이미지

볼록한 폴리곤에 대해서 좌표의 방향에 대한 간단한 검사는 인접한 좌표들이 이루는 선분(벡터)에 대한 외적(Cross Product)을 통해 가능합니다. 만약에 외적이 양수이면 수직벡터가 폴리곤이 이루는 평면(z축이 평면의 위쪽으로 향한다고 가정) 윗 방향이고, 음수이면 평면의 안쪽 즉 평면에 대해 아래 방향으로 향합니다.

사용자 삽입 이미지
오목한 폴리곤의 경우는 폴리곤의 면적을 계산함으로써 알 수가 있습니다. 면적을 계산하는 공식은 다음과 같습니다. (왜 이렇게 되는지는 블로그의 다른 글을 통해 곧 소개 하겠습니다)

사용자 삽입 이미지
위의 값이 양수이면 폴리곤의 구성 좌표의 구성 순서가 시계 반대 방향이고, 음수이면 시계 방향임을 나타냅니다.

이제 그렇다면, 뒤집어서…. 폴리곤이 오목한지 볼록한지는 어떻게 알 수 있을까요? 그것은 볼록한 폴리곤을 이루는 인접한 선분 벡터들은 모두 같은 부호이지만, 오목한 폴리곤의 경우는 부호가 섞여 있다는 것으로 알 수 있습니다.

평면상의 세 점으로부터 평면의 방정식 구하기

평면의 방정식은 아래처럼 기술할 수 있으며, (A, B, C)는 평면에 대한 법선(수직) 백터이고.. D는 이 법선 백터의 길이(크기)입니다. (x,y,z)는 평면상의 임이의 점입니다.

사용자 삽입 이미지
평면은 최소한 점 3개가 정해지면 평면의 방정식이 명확히 정의됩니다. 즉, 평면 상의 (x1,y1,z1)과 (x2, y2, z2) 그리고 (x3, y3, z3)가 정해지면 위의 공식에서 A, B, C, D의 값이 정해진다는 의미입니다. 각 A,B,C,D는 정해진 점들에 대해서 다음과 같은 행렬식으로 정의되며…

사용자 삽입 이미지
위의 행렬식은 다음과 같이 다시 한번 전개가 됩니다.

사용자 삽입 이미지
결국 이렇게 구한 A,B,C,D로부터 평면의 방정식이 결정되게 됩니다.

평면과 선의 교차점 구하기

하나의 평면에 대해서 2가지의 평면공식이 도출되는데, 이 2가지 평면의 공식에 대해서.. 선과 평면에 대한 교차점을 구하는 방법에 대해서 논의해 보겠습니다. 이 자료는 1991년에 작성된 Paul Bourke(http://local.wasp.uwa.edu.au)님의 글을 좀더 알기 쉽게 풀어 쓴 글입니다.
사용자 삽입 이미지방법 1.

점 P는 평면 위의 임이의 점이고, N은 법선벡터이며 P3는 이미 알고 있는 평면상의 점이라고 하면 평면의 공식은 우리가 고등학교때 배운 평면의 방정식의 형태인, 다음처럼 기술됩니다.

사용자 삽입 이미지
평면을 수학적으로 기술했으니, 이제는 선에 대한 공식을 알아볼 차례입니다. 이제 앞에서 언급한 점 P를 평면과 선과의 교차점이라고 하면, 점 P는 선에 대한 점입니다. 그리고 선이 지나는 이미 알고 있는 2개의 점을 각각 P1, P2라고 하면 선에 대한 공식은 수학적으로 다음과 같습니다.

사용자 삽입 이미지
위에서 u는 선에 대한 기울기 값이 되겠지요. 이제.. 평면의 공식에서 P에 선의 공식을 대입할 수 있는 형태입니다. 대입해 보면 아래와 같습니다.

사용자 삽입 이미지
위의 식을 u에 대해서 전개해 보면 아래와 같은 공식이 됩니다.

사용자 삽입 이미지

이제 u값을 구했으니.. 이 u값을 선에 대한 공식에 대입하여 교차점 P를 구할 수 있습니다. 다음은 주의할 점입니다.

  • 만약 u에 대한 식에서 분모가 0이면, 주어진 선과 평면의 법선은 수직이라는 의미입니다. 즉, 이말은 평면과 선은 서로 만나지 않는다는 의미입니다.
  • 교점 P가 P1과 P2 사이에 있는지 검사해야한다면, u값이 0~1사이의 값인지 확인해 보면 됩니다.

방법 2.

이제 평면에 대한 공식으로, 고등학교때 배운 또 다른 형태는 다음과 같습니다.

사용자 삽입 이미지
(x,y,z)는 평면상의 점이고 (A,B,C)는 평면에 대한 법선벡터이며 D는 이 법선벡터의 길이값입니다. 이 형태의 평면방정식은 임이의 점에 대해서 위의 공식에 대입하여 그 값이 양수인경우 평면을 경계로 법선벡터가 향하는 부분에 존재하는 것이고, 음수인경우는 그 반대방향에 존재하는 것을 간단히 판단할 수 있습니다.

P1(x1,y1,z1)과 P2(x2,y2,z2)를 지나는 선에 대한 공식을 방법1에서의 선에 대한 공식… 다시 언급해 보면 아래와 같습니다.

사용자 삽입 이미지
위의 선 공식을 방법2에서의 평면의 공식에 대입해 보면 다음과 같은 형태로 전개됩니다.

사용자 삽입 이미지
위의 식을 u에 대해서 정리해 보면…

사용자 삽입 이미지
이제 u를 구했으니, 방법1과 마찬가지로 교점을 구할 수 있습니다. 이 방법에 대해 주의할 점은 방법 1과 동일합니다.

[GIS] DBF 필드값 최적화시켜 용량 대폭 줄여주는 툴, OptimizeDBF

간혹, 사실은 거의 대부분.. 가지고 있는 Shape 파일의 속성 정보인 DBF 파일이 내용에 비해 그 용량이 매우 크게 느껴질때가 있습니다. 하나의 예로 아래는 제가 가지고 있는 62MB 크기의 DBF 파일의 덤프 내용입니다. 가장 윗부분에 필드 이름이 정의되어져 있고, 그 아래로 쭈욱~ 값들이 기록되어져 있는데.. 실제 내용보다는 빈문자열이 훨씬 많습니다. 이렇게 된 이유는, 특히 문자열 필드의 경우 길이를 기본적으로 255자로 정의하고 DBF를 생성했기 때문입니다.

사용자 삽입 이미지
아래는 이런 불성실한 ^^; DBF 파일의 용량을 줄여주는 툴입니다. 필드값을 저장할 수 있는 필드의 최대 길이를 자동으로 계산해 줌으로써 사용자가 따로 계산할 필요가 없습니다. 또한 저장할 필드를 따로 선택해 저장시킬 수 있습니다.

사용자 삽입 이미지
위의 툴을 이용해 생성된 DBF 파일의 덤프 내용은 아래와 같습니다. 용량이 62MB에서 3.45MB로 꽤나 많이 줄었습니다.

사용자 삽입 이미지
이 툴을 만들게 된 목적은 개발중인 맵 엔진(XGE)에 데이터를 제공하는 웹방식의 데이터서버가 관리하고 있는 속성 데이터를 최적화시킬 목적으로 만들게 되었습니다. XGE 지도 엔진을 만들기 위한 Core 라이브러리를 이용해 제작했습니다.

[GIS] DXF를 ESRI Shape로 변환해주는 툴, DXF to SHP

DXF를 ESRI의 SHP 파일로 변환해주는 툴입니다. 수치지도 DXF 파일과 내보낼 레이어를 선택하고, 변환될 Shape의 종류를 선택해주면 Shape 파일로 생성해 주는 간단한 툴입니다. 개발중인 맵 엔진에 DXF 수치지도를 표시하는 기능에 대비해, 회사에서 DXF를 Shape 파일로 변환해야할 일이 생겨서 겸사 겸사 만들어 보았습니다. Shape의 속성은 Layer 명 하나만 만들어 집니다.

사용자 삽입 이미지
사용하기 전에 알면 좋은 점이.. DXF 수치지도를 Point나 Polyline, Polygon으로 내보기기 할때 DXF에서 이용할 Enitity입니다.

  • Point : CAD의 INSERT 엔티티를 사용
  • Polyline : CAD의 POLYLINE 엔티티를 사용
  • Polygon : CAD의 POLYLINE 엔티티를 사용하며, 폐합된 엔티티만을 Polygon으로 내보냄(만약 Force Close-Polygon을 체크하면 강제로 폐합시키고 모든 엔티티를 내보냄)

아래는 화면은 이 툴을 이용해 실제 수치지도를 등고선 레이어 7XXX 대를 폴리라인으로 내보내기 해서 ArcMap으로 살펴본 화면입니다.

사용자 삽입 이미지
이 툴은 XGE 지도 엔진을 이용하지 않고, XGE 지도 엔진을 구현하기 위한 Core 라이브러리를 이용해 개발하였습니다. C++로 개발된지라 .NET 2.0 역시 필요치 않습니다.