Microsoft MVP성태의 닷넷 이야기
Graphics: 16. 3D 공간에서 두 점이 이루는 각도 구하기 [링크 복사], [링크+제목 복사],
조회: 30146
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 1개 있습니다.)

3D 공간에서 두 점이 이루는 각도 구하기

예를 들어, 다음과 같이 3D 공간에서 면과 점이 있다고 가정해 보겠습니다.

angle_between_two_0.png
(오른손 좌표계 시스템의 x-y-z 축을 사용하고 있습니다.)

이때 점 C와 점 A가 이루는 각도는 어떻게 될까요? 간단하게 점과 점의 위치를 빼서 벡터를 만들고,

점 C와 카메라의 벡터 = 점 C - 점 A
                    = (-1.4, -2.9, -5)

그 벡터가 이루는 각을 3차원에 따라 각 축 별로 3개의 각도를 구할 수 있습니다.

  • x-축을 기준으로 y-z 평면의 각
  • y-축을 기준으로 x-z 평면의 각
  • z-축을 기준으로 x-y 평면의 각

역시 시각화를 해보는 게 좋겠지요? ^^ GeoGebra 앱에서 "Home" 모양의 아이콘을 누르면,

angle_between_two_1.png

차례대로 "y축을 기준으로 x-z 평면", "z축을 기준으로 x-y 평면", "x축을 기준으로 y-z 평면" 상에서의 물체를 볼 수 있는 기능이 제공됩니다.

자... 멋진 툴이 있으니, 그럼 우선 첫 번째 아이콘인 "y축을 기준으로 x-z 평면"을 다음과 같이 볼 수 있습니다. ^^

angle_between_two_2_y.png

보는 바와 같이 x-z 평면에서 벡터가 이루는 각을 쉽게 확인할 수 있습니다. 점 A에서 x-축으로 수선의 발을 그렸을 때,

angle_between_two_3.png

직각 삼각형이 되고 이때 우리가 아는 벡터 A의 x, z 성분의 값으로 인해 아크 탄젠트 함수를 사용하면 점 A에서 이루는 각도를 구할 수 있습니다.

각 A = arc_tangent(vx, vz);

C# 코드로 구해 보면 다음과 같습니다.

Vector3 v3 = new Vector3(-1.4f, -2.9f, -5f);

{
    double yAngle = Math.Atan2(v3.X, v3.Z);
    Console.WriteLine(RadianToDegree(yAngle));
}

실행해 보면, -164.357753796137도가 나오는데, 벡터가 음의 방향이어서 그런 것일 뿐 180도를 빼면 약 15.6도가 나옵니다. 동일한 각도를 Geogebra 기하를 이용해서도 구해 볼까요? ^^

2차원 좌표계에서 x, z의 성분으로 점을 표시한 후 그와 연결한 벡터를 그리고 그 사잇각을 다음과 같이 구할 수 있습니다.

angle_between_two_4.png

잘 맞아 들어가는군요. ^^




마찬가지 방식으로 "z축을 기준으로 x-y 평면"과,

angle_between_two_2_z.png

"x축을 기준으로 y-z 평면" 상의 모습을 확인하며,

angle_between_two_2_x.png

각도를 구해 보면 이렇습니다.

Vector3 v3 = new Vector3(-1.4f, -2.9f, -5f);
Console.WriteLine("xAngle");
{
    double xAngle = Math.Atan2(v3.Y, v3.Z);
    Console.WriteLine(RadianToDegree(xAngle));
}

Console.WriteLine("yAngle");
{
    double yAngle = Math.Atan2(v3.X, v3.Z);
    Console.WriteLine(RadianToDegree(yAngle));
}

Console.WriteLine("zAngle");
{
    double zAngle = Math.Atan2(v3.Y, v3.X);
    Console.WriteLine(RadianToDegree(zAngle));
}

/*
출력 결과

xAngle
-149.886266031276
yAngle
-164.357753796137
zAngle
-115.769326504636
*/

(첨부 파일은 이 글에서 예제로 사용한 geogebra 파일입니다.)




참고로, 2개의 벡터가 이루는 각은 아크코사인을 이용해 구할 수 있습니다.

vector v1 = ...;
vector v2 = ...;

vector nv1 = normalize(v1);
vector nv2 = normalize(v2);

float angle = acos(mul(nv1, nv2));

일반적으로 acos의 정의역이 -1 ~ 1이기 때문에 정규화된 벡터의 내적 연산으로 NaN 값을 반환하는 경우는 없습니다. 문제는 0 벡터인 경우 normalize 하는 과정에서 NaN이 나온다는 것입니다.

vector v = vector(0, 0, 0, 0);
vector normal = normalize(v); // normal == NaN

왜냐하면 정규화라는 것이 벡터 크기로 나누는 것인데,

${
\hat v = \left ( \frac{ v_x }{ \Vert v \Vert }, \frac{ v_y }{ \Vert v \Vert }, \frac{ v_z }{ \Vert v \Vert } \right )
}$

분모가 0이 되므로 normalize의 결과가 NaN이 나옵니다. 이 때문에 mul 연산도 NaN이 되고, acos까지 NaN으로 끝납니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 8/1/2018]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 166  167  168  169  170  171  172  173  174  175  176  177  [178]  179  180  ...
NoWriterDateCnt.TitleFile(s)
536정성태9/12/200732340.NET Framework: 97. WCF : netTcpBinding에서의 각종 Timeout 값 설명 [11]
535정성태9/11/200729805.NET Framework: 96. WCF - PerSession에서의 클라이언트 연결 관리 [5]
534정성태9/3/200725303개발 환경 구성: 29. VHD 파일 크기 줄이기
533정성태9/2/200727999개발 환경 구성: 28. CA 서비스 - 사용자 정의 템플릿 유형 추가
532정성태9/2/200730530개발 환경 구성: 27. AD CA에서 Code Signing 인증서 유형 추가 방법
531정성태9/2/200726269.NET Framework: 95. WCF에서의 DataTable 사용
530정성태9/1/200722747.NET Framework: 94. WCF 예외에 대한 시행착오
529정성태8/31/200725672.NET Framework: 93. WCF - DataContract와 KnownType 특성 [1]
528정성태8/30/200720322오류 유형: 47. VPC - 네트워크 어댑터 MAC 주소 중복 오류
527정성태8/30/200730419Team Foundation Server: 20. 잠긴 파일을 강제로 해제 [2]
526정성태8/29/200720300오류 유형: 46. VS.NET 2008 - ASP.NET 디버깅 : Strong name validation failed.
525정성태8/27/200722558VS.NET IDE: 54. VS.NET 2008 - 새롭게 도입되는 XSD Schema Designer
524정성태8/23/200740065오류 유형: 45. 요청한 작업은, 사용자가 매핑한 구역이 열려 있는...
523정성태8/16/200722685VS.NET IDE: 53. VS.NET 2008 - 서비스 참조 시 기존 데이터 컨테이너 DLL 사용
522정성태8/13/200726353VS.NET IDE: 52. VS.NET 2008 - WCF를 위한 디버깅 환경 개선
521정성태8/8/200726379.NET Framework: 92. XmlSerializer 생성자의 실행 속도를 올리는 방법 - 두 번째 이야기 [3]
520정성태8/7/200721567VS.NET IDE: 51. Visual Studio 2008 베타 2 설치
519정성태7/27/200727933오류 유형: 44. System.BadImageFormatException [2]
518정성태7/26/200728970오류 유형: 43. System.ComponentModel.LicenseException [1]
517정성태7/19/200717233개발 환경 구성: 26. VPC - 일반 사용자 계정으로 구동
516정성태7/19/200720368오류 유형: 42. TFS - Error loading menu: Index was outside the bounds of the array [2]
515정성태7/18/200728091오류 유형: 41. SSL 서버 자격 증명을 만드는 동안 심각한 오류가 발생했습니다.
514정성태7/14/200720791Team Foundation Server: 19. Orcas에서 개선되는 TFS 기능들
513정성태7/4/200731769.NET Framework: 91. Foreground Thread / Background Thread [1]
512정성태6/27/200721719오류 유형: 40. error PRJ0050: Failed to register output.
511정성태6/25/200729708.NET Framework: 90. XmlSerializer 생성자의 실행 속도를 올리는 방법 [2]
... 166  167  168  169  170  171  172  173  174  175  176  177  [178]  179  180  ...