특정 위치의 부채꼴 각도 내 존재 판별
특정 위치의 부채꼴 각도 내 존재 판별
요구사항
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 이하라는 소리가 된다.
이유는 다음과 같다
벡터 v1 · v2 = |v1| * |v2| * cos(사잇각)이다
→ v1 · v2 / ( |v1| * |v2| ) = cos(사잇각)
닫힌 구간 [-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.
