Post

특정 위치의 부채꼴 각도 내 존재 판별

특정 위치의 부채꼴 각도 내 존재 판별

요구사항

XY 평면 상의 지점 A(x, y)가 주어진 부채꼴 범위 내에 존재하는지 판별


논리 및 구현

예시 이미지

입력

  • 목표 지점 A (x, y)
  • 부채꼴 중심점 P (x, y)
  • 부채꼴 중심 방향 벡터 V (x, y)
  • 부채꼴 반지름 r
  • 부채꼴 각도 d (degree)

출력

  • bool : A가 부채꼴안에 있는지 여부

논리

두 조건문 C1, C2에 대하여 return C1 && C2를 처리하면 된다.

1
2
3
4
C1. A와 P 사이의 거리가 r 이내인가?


C2. P → A 벡터(toA)와 V의 각도 차이가 d 이내인가?

이 때, C2의 각도 범위 판별은 내적과 cos를 이용해서 처리할 수 있다.

벡터 v1, v2, 허용 각도(radian) d 에 대하여

v1 · v2 / (|v1|*|v2|) ≥ cos(d)

해당 조건을 만족하면, v1과 v2가 이루는 사잇각이 d 이하라는 소리가 된다.

이유는 다음과 같다

  1. 벡터 v1 · v2 = |v1| * |v2| * cos(사잇각)이다

    → v1 · v2 / ( |v1| * |v2| ) = cos(사잇각)

  2. 닫힌 구간 [-pi, pi]에서 cos(a) ≥ cos(b) 이면 -b ≤ a ≤ b 이다

Desmos에서 수식을 통해 판별을 구현하면 다음과 같다.

P, V, D 를 이용해서 부채꼴을 수정 할 수 있다. 점 A가 부채꼴 범위 안에 있으면 파란색이 되고, 부채꼴 범위 밖에 있으면 빨간 점이 된다.

Desmos 링크 : https://www.desmos.com/calculator/nu4ttennie

구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// targetPos = A
// arcPos = P
// radius = r
// centerDir = V
// rangeDegree = d

public static bool IsPositionInArc(
		Vector2 targetPos, Vector2 arcPos, 
		float radius, Vector2 centerDir, 
		float rangeDegree)
{
    Vector2 toA = targetPos - arcPos;
		
    // sqrt 연산이 무거운 편이라, 기왕이면 제곱수 비교
    float r2 = radius * radius;
    float dist2 = to.sqrMagnitude;
    
    if (dist2 > r2)
    {
        return false;
    }
    
    if (dist2 < 1e-8f)
    {
        // 부동소수점 오차 고려, targetPos와 arcPos값이 근사하면
        // 각도 계산 없이 return true
        return true;
    }

    Vector2 dir = new Vector2(centerDir.x, centerDir.y);
    if (dir.sqrMagnitude < 1e-8f)
    {
        // Vector2.zero 근삿값이 입력되는 경우의 예외처리
        dir = Vector2.right;
    }
    else
    {
        dir.Normalize();
    }

    float halfRad = (rangeDegree * 0.5f) * Mathf.Deg2Rad;
    float cos = Mathf.Cos(halfRad);
    float dot = Vector2.Dot(dir, toA.normalized);
    return dot >= cos; // 경계 포함
}

This post is licensed under CC BY 4.0 by the author.

Trending Tags