지구 타원체 상의 좌표 및 거리 계산

구 타원체 상에서 특정 지점 간의 관계를 이용하여 거리나 방향을 구하고 ECEF 좌표계로부터 Geodetic 좌표계로의 변환 등에 대해서 설명합니다.

들어가기 전에

설치 프로그램으로 배포되는 XDL 엔진은 Visual Studio 2022 x64 Release 버전으로, Visual Studio 2022 이상의 버전에서 사용 가능하다.
아래의 설명은 Visual Studio 2022를 기준으로 하겠다.

1 기본 프로그램 작성
1.1 Visual Studio 2022를 실행한다.

1.2 메뉴 [파일]-[새로 만들기]-[프로젝트]를 선택한다.

1.3 [새 프로젝트 만들기] 대화상자 중간의 목록에서 “Windows Forms 앱(.NET Framework)”을 선택한다. “다음” 버튼을 눌러 프로젝트의 이름(XDL_GeoPosition)을 입력하고 [새 프로젝트] 대화상자의 “만들기” 버튼을 클릭한다.

“만들기” 버튼을 누르면 프로젝트가 기본적으로 생성되고, 화면에 Form을 디자인할 수 있는 화면이 생성된다. 만약 아래와 같이 Form 디자인화면이 생성되지 않으면, [솔루션 탐색기] 창에서 “Form1.cs”를 마우스 더블클릭하여 디자인 화면을 연다.


1.4 참조를 통해 NXDL.dll 항목을 추가한다.

솔루션 탐색기의 프로젝트 아래에 있는 참조 아이템의 마우스 오른쪽 버튼을 클릭하여 생성되는 팝업 메뉴에서 “참조 추가” 메뉴를 선택한다.


메뉴를 선택하면 아래와 같이 [참조 관리자] 대화상자가 나타나며, 대화상자 아래쪽에 있는 “찾아보기” 버튼을 클릭한다.


열기 대화상자에서 “C:\Pixoneer\XDL3.0\bin\NXDL.dll” 파일을 선택한 후 “추가”를 클릭하고, [참조 관리자] 대화상자의 “확인” 버튼을 클릭한다. 솔루션 탐색기의 [참조]에 “NXDL”이 추가된 것을 확인할 수 있다.


1.5 프로그램 종료 시 메모리를 해제를 위한 코드를 Form이 닫히는 이벤트에 추가한다.

Form1의 디자인 화면에서 Form을 선택한 후 [속성] 창(Visual Studio 메뉴 [보기]-[속성 창]을 선택하면 된다.)에서 [이벤트] 메뉴를 클릭하고 이벤트 목록 중 “FormClosed”를 선택한 뒤 마우스 더블클릭을 하여 해당 이벤트를 추가한다.


아래와 같이 Form1_FormClosed 함수에 코드를 추가한다.

C#

                                    
namespace XDL_GeoPosition
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            Pixoneer.NXDL.Xfn.Close();	//코드 추가
        }
    }
}
                                    
                                

1.6 다음과 같이 NXDL에 대하여 참조를 설정한다.

C#

                                    
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Pixoneer.NXDL; // 추가
                                    
                                

1.7 [도구 상자] 와 [속성] 창을 사용하여 다음과 같이 Form에 버튼을 올려 디자인한다.
2 지구상의 특정 위치(REFERENCE POSITION)로부터 방위각(AZIMUTH ANGLE)과 거리(DISTANCE)에 해당하는 위치(TARGET POSITION) 구하기 예제

여기에서 거리는 평면상의 거리가 아니고 지구 곡률을 고려한 거리를 의미한다.


2.1 Calc Position By Bearing And Distance 버튼을 더블 클릭하여 함수를 자동생성한다.

C#

                                    
private void CalcPositionByBearingAndDistance_Click(object sender, EventArgs e)
{

}
                                    
                                

2.2 CalcPositionByBearingAndDistance_Click 함수에 다음과 같이 코드를 입력한다. 아래 예제는 임의의 기준점(예를 들어 현재 자신의 위치)로부터 방위각과 특정 거리상에 있는 좌표값을 계산한다.

C#

                                    
private void CalcPositionByBearingAndDistance_Click(object sender, EventArgs e)
{
    // 지구의 특정 기준점으로부터 북쪽으로부터 시계방향의 방위각과 임의의 거리에 해당하는 지점을 계산.

    // 1. 기준점 설정
    XAngle lon1 = XAngle.FromDegree(127);
    XAngle lat1 = XAngle.FromDegree(36);

    // 2. 북쪽으로부터 방위각 설정
    XAngle bearing = XAngle.FromDegree(45);

    // 3. 거리 설정(unit : meter)
    double dist = 10000;

    // 4. 결과값에 해당하는 위경도값을 얻을 XAngle생성
    XAngle lon2 = new XAngle();
    XAngle lat2 = new XAngle();

    // 5. CalcPosByBearingAndDist함수를 통해 지점 계산
    XAngle ang = Xfn.CalcPosByBearingAndDist(lon1, lat1, bearing, dist, ref lon2, ref lat2);

    Console.WriteLine("Position : " + lon2.deg.ToString() + " " + lat2.deg.ToString());
    Console.WriteLine("Return Angle : " + ang.deg.ToString());
}
                                    
                                

2.3 컴파일하고 프로그램을 실행하여 Calc Position By Bearing And Distance 버튼을 클릭한다.

2.4 출력창에 값이 프린트됨을 확인한다.

참조 위경도위치 127, 36인 위치로부터 45도 북방위각이고 거리가 10000meter인 결과를 출력한다.

3 지구상의 특점 한 위치(REFERENCE POSITION)와 다른 장소의 한 위치(TARGET POSITION)로부터 방위각도와 거리 구하는 예제

여기에서 거리는 평면상의 거리가 아니고 지구 곡률을 고려한 거리를 의미한다


3.1 Calc Arc Dist and Angle From Two Position 버튼을 더블 클릭하여 함수를 자동생성한다.

C#

                                    
private void CalcArcDistAndAngle_Click (object sender, EventArgs e)
{

}
                                    
                                

3.2 CalcArcDistAndAngle_Click함수에 다음과 같이 코드를 입력한다. 아래 예제는 임의의 2점으로부터 방위각과 특정 거리를 계산한다.

C#

                                    
private void CalcArcDistAndAngle_Click(object sender, EventArgs e)
{
    // 지구의 특정 두지점(기준점과 임의의 지점)으로부터 기준점으로부터 임의의 지점으로의 
    // 방위각(Forward, Backward)값과 지점간의 거리를 얻는다.

    // 1. 기준점 설정
    XAngle lon1 = XAngle.FromDegree(127);
    XAngle lat1 = XAngle.FromDegree(36);

    // 2. 임의의 지점 설정
    XAngle lon2 = XAngle.FromDegree(128);
    XAngle lat2 = XAngle.FromDegree(37);

    // 3. 두 지점간의 Forward, Backward각도를 얻을 객체 생성
    XAngle fwdAz = new XAngle();
    XAngle revAz = new XAngle();

    double dist = 0;

    // 4. 두지점을 입력하여 CalArcDistAndAngle함수를 이용하여 거리와 각도를 얻는다.
    bool bResult = Xfn.CalArcDistAndAngle(lon1, lat1, lon2, lat2, ref dist, ref fwdAz, ref revAz);

    Console.WriteLine("Distance : " + dist.ToString());
    Console.WriteLine("Forward Angle : " + fwdAz.deg.ToString());
    Console.WriteLine("Backward Angle : " + revAz.deg.ToString());
}
                                    
                                

3.3 컴파일하고 프로그램을 실행하여 Calc Arc Dist and Angle From Two Position 버튼을 클릭한다.

3.4 출력창에 값이 프린트됨을 확인한다.

참조 위치 127, 36(경위도)인 위치로부터 128, 37(경위도)위치로부터 거리가 142618.087미터와 38.6195662318174도인 방위각을 얻을 수 있다.

4 GEOGRAPHIC 좌표계로부터 ECEF 좌표계로의 변환 예제

4.1 Geo To ECEF 버튼을 더블클릭하여 함수를 자동생성한다.

C#

                                    
private void GeoToECEF_Click (object sender, EventArgs e)
{

}
                                    
                                

4.2 GeoToECEF_Click 함수에 다음과 같이 코드를 입력한다.

C#

                                    
private void GeoToECEF_Click (object sender, EventArgs e)
{
    // Lat/Lon(위경도)좌표계로 부터 ECEF좌표계로 변환하기

    // 1. 위경도 좌표값을 설정.
    XGeoPoint geo = new XGeoPoint();
    XVertex3d ecr = new XVertex3d();
    geo.lond = 127;
    geo.latd = 36;
    geo.hgt = 1200;

    // 2. ECEF값을 얻는다.
    Xfn.GeoToEcr(geo, ref ecr);

	// 3. 결과값을 프린트한다.
    Console.WriteLine("X : " + ecr.x.ToString() + " Y : " + ecr.y.ToString() + " Z : " + ecr.z.ToString());
}
                                    
                                

4.3 컴파일하고 프로그램을 실행하여 Geo To ECEF 버튼을 클릭한다.

4.4 출력창에 값이 프린트됨을 확인한다.

참조 위치 127, 36(경위도)이고 고도가 1200meter인 위치의 ECEF값은 X : -3109559.92819602 Y : 4126525.40023087 Z : 3728897.01809016임을 확인할 수 있다.

5 ECEF 좌표계로부터 GEOGRAPHIC 좌표계로의 변환 예제

5.1 ECEF To Geo 버튼을 더블클릭하여 함수를 자동생성한다.

C#

                                    
private void ECEFToGeo_Click (object sender, EventArgs e)
{

}
                                    
                                

5.2 ECEFToGeo_Click 함수에 다음과 같이 코드를 입력한다.

C#

                                    
private void ECEFToGeo_Click (object sender, EventArgs e)
{
    // ECEF좌표계로부터 Lat/Lon(위경도)좌표계로 변환하기

    //  1. ECEF값을 설정
    XGeoPoint geo = new XGeoPoint();
    XVertex3d ecr = new XVertex3d();
    ecr.x = -3109559.9281960232;
    ecr.y = 4126525.4002308655;
    ecr.z = 3728897.0180901629;

    //  2. 위경도값을 얻는다
    Xfn.EcrToGeo(ecr, ref geo);

    // 3. 결과값을 프린트한다.
    Console.WriteLine("lat : " + geo.lat.deg.ToString() + " lon : " + geo.lon.deg.ToString() + " Height : " + geo.hgt.ToString());
}
                                    
                                

5.3 컴파일하고 프로그램을 실행하여 ECEF To Geo 버튼을 클릭한다.

5.4 출력창에 값이 프린트됨을 확인한다.

참조 위치 ECEF 값이 X : -3109559.92819602 Y : 4126525.40023087 Z : 3728897.01809016인 Geographic 좌표계 값은 127, 36(경위도)이고 고도가 1200meter인 위치임을 확인할 수 있다.

1 기본 프로그램 작성
1.1 Visual Studio 2022를 실행한다.

1.2 메뉴 [파일]-[새로 만들기]-[프로젝트]를 선택한다.

1.3 [새 프로젝트 만들기] 대화상자 중간의 목록에서 “WPF 앱(.NET Framework)”을 선택하고 “다음” 버튼을 클릭한다. [새 프로젝트 구성] 창에서 프로젝트 이름(XDL_GeoPosition)을 입력하고 사용자가 원하는 프로젝트 경로를 입력한 다음 “만들기” 버튼을 클릭한다.

“만들기” 버튼을 누르면 프로젝트가 기본적으로 생성되고, 화면에 Window을 디자인할 수 있는 화면이 뜬다. 만약 아래와 같은 Window 창이 생성되지 않으면, [솔루션 탐색기] 창에서 MainWindow.xaml”를 마우스 더블클릭을 하여 창을 연다.


1.4 참조를 통해 NXDL.dll 항목을 추가한다.

솔루션 탐색기의 프로젝트 아래에 있는 참조 아이템의 마우스 오른쪽 버튼을 클릭하여 생성되는 팝업메뉴에서 “참조추가” 메뉴를 선택한다.


메뉴를 선택하면 아래와 같이 [참조 관리자] 대화상자가 나타나며, 대화상자 아래쪽에 있는 “찾아보기” 버튼을 클릭한다.



“C:\Pixoneer\XDL3.0\bin\NXDL.dll” 파일을 선택한다. “추가” 를 클릭하고, [참조 관리자] 대화상자의 “확인” 버튼을 클릭한다. [참조] 에 “NXDL”이 추가된 것을 확인할 수 있다.


1.5 프로그램 종료 시 메모리를 해제를 위한 코드를 Window창이 닫히는 이벤트에 추가한다.

MainWindow.xaml 창에서 Window을 선택한 후 [속성] 창에서 [이벤트] 메뉴를 클릭하고 이벤트 목록 중 “Closed”를 마우스 더블클릭을 하여 해당 이벤트를 추가한다.


아래와 같이 Window_Closed 함수에 코드를 추가한다.

C#

                                        
namespace XDL_GeoPosition
{
    
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            Pixoneer.NXDL.Xfn.Close(); //코드추가
        }
                                        
                                

1.6 다음과 같이 NXDL에 대하여 참조를 설정한다.

C#

                                        
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using Pixoneer.NXDL;  //추가
                                        
                                

1.7 다음과 같이 도구상자에서 버튼을 Window 창에 올려 디자인한다.
2 지구상의 특정 위치(REFERENCE POSITION)로부터 방위각(AZIMUTH ANGLE)과 거리(DISTANCE)에 해당하는 위치(TARGET POSITION) 구하기 예제

여기에서 거리는 평면상의 거리가 아니고 지구 곡률을 고려한 거리를 의미한다.


2.1 Calc Position By Bearing And Distance 버튼을 더블 클릭하여 함수를 자동생성한다.

C#

                                        
private void buttonCalcPositionByBearingAndDistance_Click(object sender, RoutedEventArgs e)
{

}
                                        
                                

2.2 buttonCalcPositionByBearingAndDistance_Click 함수에 다음과 같이 코드를 입력한다. 아래 예제는 임의의 기준점(예를 들어 현재 자신의 위치)로부터 방위각과 특정 거리상에 있는 좌표값을 계산한다.

C#

                                        
private void buttonCalcPositionByBearingAndDistance_Click(object sender, RoutedEventArgs e)
{
    // 지구의 특정 기준점으로부터 북쪽으로부터 시계방향의 방위각과 임의의
    // 거리에 해당하는 지점을 계산

    // 1. 기준점 설정
    XAngle lon1 = XAngle.FromDegree(127);
    XAngle lat1 = XAngle.FromDegree(36);

    // 2. 북쪽으로부터 방위각 설정
    XAngle bearing = XAngle.FromDegree(45);

    // 3. 거리 설정 (unit : meter)
    double dist = 10000;

    // 4. 결과값에 해당하는 위경도 값을 얻을 XAngle생성
    XAngle lon2 = new XAngle();
    XAngle lat2 = new XAngle();

    // 5. CalcPosByBearingAndDist함수를 통해 지점 계산
    XAngle ang = Xfn.CalcPosByBearingAndDist(lon1, lat1, bearing, dist,ref lon2, ref lat2);

    Console.WriteLine("Position : " + lon2.deg.ToString() + " " + lat2.deg.ToString());
    Console.WriteLine("Return Angle : " + ang.deg.ToString());
}
                                        
                                

2.3 컴파일하고 프로그램을 실행하여 Calc Position By Bearing And Distance 버튼을 클릭한다.

2.4 출력창에 값이 프린트됨을 확인한다.

참조 위경도 위치 127, 36인 위치로부터 45도 북방위각이고 거리가 10000meter인 결과를 출력한다.

3 지구상의 특점 한 위치(REFERENCE POSITION)와 다른 장소의 한 위치(TARGET POSITION)로부터 방위각도와 거리 구하는 예제

여기에서 거리는 평면상의 거리가 아니고 지구 곡률을 고려한 거리를 의미한다


3.1 Cal Arc Dist and Angle From Two Position 버튼을 더블 클릭하여 함수를 자동생성한다.

C#

                                        
private void buttonCalcArcDistAndAngle_Click(object sender, RoutedEventArgs e)
{

}
                                        
                                

3.2 buttonCalcArcDistAndAngle_Click함수에 다음과 같이 코드를 입력한다. 아래 예제는 임의의 2점으로부터 방위각과 특정 거리를 계산한다.

C#

                                        
private void buttonCalcArcDistAndAngle_Click(object sender, RoutedEventArgs e)
{
    // 지구의 특정 두지점(기준점과 임의의 지점)을 이용하여 기준점으로부터 임의의
    // 지점까지의 방위각(Forward, Backward) 값과 지점간의 거리를 얻는다.

    // 1. 기준점 설정
    XAngle lon1 = XAngle.FromDegree(127);
    XAngle lat1 = XAngle.FromDegree(36);

    // 2. 임의의 지점 설정
    XAngle lon2 = XAngle.FromDegree(128);
    XAngle lat2 = XAngle.FromDegree(37);

    // 3. 두 지점간의 Forward, Backward각도를 얻을 객체 생성
    XAngle fwdAz = new XAngle();
    XAngle revAz = new XAngle();

    double dist = 0;

    // 4. 두지점을 입력하여 CalArcDistAndAngle함수를 이용하여 거리와 각도를 얻는다.
    bool bResult = Xfn.CalArcDistAndAngle(lon1, lat1, lon2, lat2, ref dist, ref fwdAz, ref revAz);

    Console.WriteLine("Distance : " + dist.ToString());
    Console.WriteLine("Forward Angle : " + fwdAz.deg.ToString());
    Console.WriteLine("Backward Angle : " + revAz.deg.ToString());
}
                                        
                                

3.3 컴파일하고 프로그램을 실행하여 Calc Arc Dist and Angle From Two Position 버튼을 클릭한다.

3.4 출력창에 값이 프린트됨을 확인한다.

참조 위치 127, 36(경위도)인 위치로부터 128, 37(경위도)위치로부터 거리가 142618.087미터와 38.6195662318174도인 방위각을 얻을 수 있다.

4 GEOGRAPHIC 좌표계로부터 ECEF 좌표계로의 변환 예제

4.1 Geo To ECEF버튼을 더블클릭하여 함수를 자동생성한다.

C#

                                        
private void buttonGeoToECEF_Click (object sender, RoutedEventArgs e)
{

}
                                        
                                

4.2 buttonGeoToECEF_Click 함수에 다음과 같이 코드를 입력한다.

C#

                                        
private void buttonGeoToECEF_Click (object sender, RoutedEventArgs e)
{
    // Lat/Lon(위경도)좌표계로 부터 ECEF좌표계로 변환하기

    // 1. 위경도 좌표값을 설정.
    XGeoPoint geo = new XGeoPoint();
    XVertex3d ecr = new XVertex3d();
    geo.lond = 127;
    geo.latd = 36;
    geo.hgt = 1200;

    // 2. ECEF값을 얻는다.
    Xfn.GeoToEcr(geo, ref ecr);

    // 3. 결과값을 프린트한다.
    Console.WriteLine("X : " + ecr.x.ToString() + " Y : " + ecr.y.ToString() + " Z : " + ecr.z.ToString());
}
                                        
                                

4.3 컴파일하고 프로그램을 실행하여 Geo To ECEF 버튼을 클릭한다.

4.4 출력창에 값이 프린트됨을 확인한다.

참조 위치 127, 36(경위도)이고 고도가 1200meter인 위치의 ECEF값은 X : -3109559.92819602 Y : 4126525.40023087 Z : 3728897.01809016임을 확인할 수 있다.

5 ECEF 좌표계로부터 GEOGRAPHIC 좌표계로의 변환 예제

5.1 ECEF To Geo 버튼을 더블클릭하여 함수를 자동생성한다.

C#

                                        
private void buttonECEFToGeo_Click (object sender, RoutedEventArgs e)
{

}
                                        
                                

5.2 buttonECEFToGeo_Click 함수에 다음과 같이 코드를 입력한다.

C#

                                        
private void buttonECEFToGeo_Click (object sender, RoutedEventArgs e)
{
    // ECEF좌표계로부터 Lat/Lon(위경도)좌표계로 변환하기

    //  1. ECEF값을 설정
    XGeoPoint geo = new XGeoPoint();
    XVertex3d ecr = new XVertex3d();
    ecr.x = -3109559.9281960232;
    ecr.y = 4126525.4002308655;
    ecr.z = 3728897.0180901629;

    //  2. 위경도값을 얻는다
    Xfn.EcrToGeo(ecr, ref geo);

    // 3. 결과값을 프린트한다.
    Console.WriteLine("Longitude : " + geo.lond.ToString() + " Latitude : " + geo.latd.ToString() + " Height : " + geo.hgt.ToString());
}
                                        
                                

5.3 컴파일하고 프로그램을 실행하여 ECEF To Geo 버튼을 클릭한다.

5.4 출력창에 값이 프린트됨을 확인한다.

참조 위치 ECEF 값이 X : -3109559.92819602 Y : 4126525.40023087 Z : 3728897.01809016인 Geographic 좌표계 값은 127, 36(경위도)이고 고도가 1200meter인 위치임을 확인할 수 있다.