벡터의 방향 (Orientation) 에 대해서 알아보자.
3차원 방향과 크기를 가리키는 벡터의 표현 방식은 (x, y, z)로 나타낼수 있다.
3차원 좌표도 동일하게 (x, y, z)로 나타낼수 있기 때문에 혼동하면 안된다.
A(x1, y1) , B(x2, y2), C(x3, y3) 3개의 좌표가 있다.
- AB 벡터는 (x2 - x1, y2 - y1)
- BA 벡터는 (x1 - x2, y1 - y2)
벡터는 방향이 반대로 되면, x, y의 부호도 반대로 된다.
AB가 선분 (line segment)을 이룬다고 가정할때, AB 선분을 기준으로 C가 어디에
있는지 확인할 수 있는 방법이 있다.
모든 위치의 경우의 수는 다음과 같다.
1) C가 선분 AB의 왼쪽에 있다.
2) C가 선분 AB의 오른쪽에 있다.
3) C가 선분 AB의 윗쪽에 있다.
4) C가 선분 AB의 아랫쪽에 있다.
5) C는 A 혹은 B와 동일하다.
6) C는 선분 AB 사이에 있다.
AB 벡터, AC 벡터를 생각해 봅시다.
AB, AC 외적의 결과는 AB, AC와 수직인 벡터입니다.
이 수직인 벡터의 크기가 AB, AC벡터가 이루는 사각형의 크기입니다.
오른손의 법칙을 생각해 보면,
AB 벡터와 AC 벡터의 외적 값이 > 0, 양수 라면 반시계방향(CCW) 이며,
AB 벡터와 AC 벡터의 외적 값이 < 0, 음수 라면 시계방향(CW) 입니다.
1) C가 선분 AB의 왼쪽에 있다.
=> AB벡터 X AC벡터 > 0
2) C가 선분 AB의 오른쪽에 있다.
=> AB벡터 X AC벡터 < 0
3) C가 선분 AB의 윗쪽에 있다.
=> AB벡터의 크기 < AC벡터의 크기
4) C가 선분 AB의 아랫쪽에 있다.
=> AB.x * AC.x < 0 && AB.y * AC.y < 0
벡터의 방향이 반대로 되려면, 부호를 반대로 해주면 된다.
AB벡터 (x, y)의 방향이 반대 벡터는 (-x, -y) 이다.
방향이 다른 두벡터의 각 요소를 곱하면 음수가 나오게 하면 된다.
5) C는 A 혹은 B와 동일하다.
=> A == C or B == C
6) C는 선분 AB 사이에 있다.
=> 1~5 해당이 되지 않는 경우.
AreaTriangle2D 함수는 외적을 사용해서 AB벡터와 AC벡터가 이루는 삼각형의 넓이는 구한다.
public double AreaTriangle2D(Point2d a, Point2d b, Point2d c)
{
var ab = b - a;
var ac = c - a;
var result = Vector2f.CrossProduct2D(ab, ac);
return result / 2;
}
public RelativePosition Oridentation2d(Point2d a, Point2d b, Point2d c)
{
var area = AreaTriangle2D(a, b, c);
if (area > 0 && area < TOLERANCE) area = 0;
if (area < 0 && area > TOLERANCE) area = 0;
Vector2f ab = b - a;
Vector2f ac = c - a;
if (area > 0) return RelativePosition.Left;
if (area < 0) return RelativePosition.Right;
if (ab.x * ac.x < 0 || ab.y * ac.y < 0) return RelativePosition.Behind;
if (ab.Magnitude() < ac.Magnitude()) return RelativePosition.Beyond;
if (a == c) return RelativePosition.origin;
if (b == c) return RelativePosition.destination;
return RelativePosition.Beetween;
}
2차원의 경우 벡터 AB, AC를 만들어서 외적을 통해 스칼라 값을 사용했지만,
3차원의 경우 벡터 AB, AC 외적을 하면 스칼라 값이 나오지 않고 벡터가 나옵니다.
해당 벡터를 다시 내적을 통해 스칼라 값을 만들어 줍니다.
기하학적으로는 Update 예정.!
3차원 케이스입니다.
private double OrientationXY3D(Point3d a, Point3d b, Point3d c)
{
var ab = b - a;
var ac = c - a;
var crossProduct = Vector3f.CrossProduct3D(ab, ac);
var up = new Vector3f(0, -1, 0);
return Vector3f.DotProduct(up, crossProduct);
}
public RelativePosition Orientation3d(Point3d a, Point3d b, Point3d c)
{
var area = OrientationXY3D(a, b, c);
if (area > 0 && area < TOLERANCE) area = 0;
if (area < 0 && area > TOLERANCE) area = 0;
Vector3f ab = b - a;
Vector3f ac = c - a;
if (area > 0f) { return RelativePosition.Left; }
if (area < 0f) { return RelativePosition.Right; }
if (ab.x * ac.x < 0f || ab.z * ac.z < 0f) { return RelativePosition.Behind; }
if (ab.Magnitude() < ac.Magnitude()) { return RelativePosition.Beyond; }
if (a == c) { return RelativePosition.origin; }
if (b == c) { return RelativePosition.destination; }
return RelativePosition.Beetween;
}
'Computation Geography' 카테고리의 다른 글
6. 면 (Plane) (0) | 2023.09.11 |
---|---|
5. 선 (Line), 선과 선의 교차점 체크하기 (0) | 2023.09.09 |
1. 벡터의 기본 (덧셈, 뺄셈, Magnitude, Normalize) (0) | 2023.09.02 |
3. 외적 ( Cross Product ) (0) | 2023.09.01 |
2. 내적 ( Dot Product ) (0) | 2023.08.31 |