Math - 3D

[TOC]

좌표계

엄지, 검지, 중지를 x, y, z축으로 가정한다.


평면

평면의 활용
평면의 조건

법선 벡터(Normal Vector)

한 평면이나 직선에 대하여 수직인 벡터를 말한다.

법선 벡터를 알면 평면의 기울기를 알 수 있다.

법선 벡터와 평면 상의 한 점으로 평면을 정의할 수 있다.

법선 벡터로 평면의 앞, 뒤를 알 수 있다.


평면 방정식

평면은 평면 위의 점과 평면에 수직인 법선으로 정의할 수 있다.

이는 평면 위의 점을 지나고 법선 벡터에 수직인 벡터를 구하는 방정식으로 해석할 수 있고 이를 구하는 방정식이 평면의 방정식이다.

\[\text{평면의 벡터 방정식} \\ \begin{matrix} O &:& 원점 \\ \vec{n}(a, b, c) &:& \text{평면에 수직인 법선 벡터} \\ A(x_1, y_1, z_1) &:& \text{평면상의 점} \\ P(x, y, z) &:& \text{평면상의 점} \\ \\ \end{matrix} \\ \begin{matrix} \vec{AP} \cdot \vec{n} = 0 \\ (\vec{OP} - \vec{OA}) \cdot \vec{n} = 0 \\ (\vec{p} - \vec{a}) \cdot \vec{n} = 0 \\ \\ \end{matrix} \\ \text{위 평면상의 벡터 방정식을 성분에 의한 내적으로 표현한다} \\ \begin{matrix} (x - x_1, y - y_1, z - z_1) \cdot (a, b, c) = 0 \\ a(x - x_1) + b(y - y_1) + c(z - z_1) = 0 \\ \\ \text{위 식은 } A(x_1, y_1, z_1)\text{를 지나고(시작점으로 하고) } \vec{n}(a, b, c)\text{에 수직인 벡터를 구하는 평면의 방정식이다.} \\ \\ \end{matrix} \\\]
평면 방정식 결과의 의미

점의 좌표를 평면 방정식에 대입했을 때

결과 점의 위치
0 평면 상에 있다.
양수 법선 벡터쪽에 있다.
음수 법선 벡터 반대쪽에 있다.
평면 방정식의 일반형

평면의 법선 벡터 : N(a, b, c) 평면 위의 좌표 : Q(x₁, y₁, z₁)

\[\begin{matrix} 0 &=& a(x-x_1) + b(y-y_1) + c(z-z_1) \\ &=& ax + by + cz +(-ax_1 - by_1 - cz_1) \\\\ d &=& (-ax_1 - by_1 - cz_1) \\ &=& -(ax_1 + by_1 + cz_1) \\ &=& -N \cdot Q \\\\ & \therefore& ax + by + cz + d = 0 \\ \end{matrix}\] \[\begin{matrix} \text{x, y, z에 대한 일차식으로 표현} \\ \text{x, y, z의 계수인 a, b, c가 평면의 법선 벡터} \\ \text{이 방정식을 만족하는 해는 평면상에 있다} \end{matrix}\] \[\begin{matrix} a = 0, b \ne 0, c \ne 0 \\ \text{x축에 대해 평행인 평면이 만들어진다.} \\ \\ a = 0, b = 0, c \ne 0 \\ \text{xy 평면에 대해 평행인 평면이 만들어진다.} \\ \\ \end{matrix}\]

위 방정식에 따라 평면은 a, b, c, d 4개의 수로 만들 수 있고 벡터는 3개의 수로 만들 수 있다.

확실하게 평면상에 있는 좌표

확실하게 평면상에 있는 좌표

\[(-\frac{d}{3a}, -\frac{d}{3b}, -\frac{d}{3c})\]

증명 : 평면 방정식에 좌표 대입

\[\require{cancel} \begin{matrix} ax + by + cz + d &=& a(-\frac{d}{3a}) + b(-\frac{d}{3b}) + c(-\frac{d}{3c}) + d \\ &=& \cancel{a}(-\frac{d}{3\cancel{a}}) + \cancel{b}(-\frac{d}{3\cancel{b}}) + \cancel{c}(-\frac{d}{3\cancel{c}}) + d \\ &=& -\frac{d}{3} -\frac{d}{3} -\frac{d}{3} + d \\ &=& -d + d \\ &=& 0 \end{matrix}\]
평면과 점 사이의 거리

평면의 법선 벡터 : N

공간 상의 한 점 : P

평면 위의 한 점 : Q

P → Q 벡터 : V

평면과 좌표 사이의 가장 짧은 거리 벡터 : W

V와 W의 내각 : α

\[\require{cancel} \begin{matrix} &&\text{법선 벡터가 정규화 됐을 경우} \\ \lVert W \rVert &=& \cos \alpha \lVert V \rVert \\ &=& \hat{V} \cdot \hat{N} \times \lVert V \rVert \\ &=& \frac{V}{\sqrt{V_x^2+V_y^2+V_z^2}} \cdot \hat{N} \times \sqrt{V_x^2+V_y^2+V_z^2} \\ &=& \frac{V}{\cancel{\sqrt{V_x^2+V_y^2+V_z^2}}} \cdot \hat{N} \times \cancel{\sqrt{V_x^2+V_y^2+V_z^2}} \\ &=& V \cdot \hat{N} \\ && \text{(V벡터를 N벡터에 투영한 값과 같다)} \\\\ &=& V_x\hat{N}_x + V_y\hat{N}_y + V_z\hat{N}_z \\ &=& (P_x-Q_x)\hat{N}_x + (P_y-Q_y)\hat{N}_y + (P_z-Q_z)\hat{N}_z \\ &=& (P_x\hat{N}_x + P_y\hat{N}_y + P_z\hat{N}_z) - (Q_x\hat{N}_x + Q_y\hat{N}_y + Q_z\hat{N}_z) \\ &=& (P_x\hat{N}_x + P_y\hat{N}_y + P_z\hat{N}_z) - \hat{N} \cdot Q \\ &=& (P_x\hat{N}_x + P_y\hat{N}_y + P_z\hat{N}_z) + d \\\\ && \therefore \text{d를 구하고 }P_x, P_y, P_z\text{에 공간상의 점의 좌표를 대입하면 거리를 구할 수 있다.} \end{matrix}\] \[\text{법선 벡터가 정규화되지 않았을 경우} \\ d = -N \cdot Q \\ \lVert W \rVert = \frac{(P_xN_x + P_yN_y + P_zN_z) + d}{\lVert N \rVert}\]
평면에 수직으로 선분 그리기 구현
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlaneEquation : MonoBehaviour {
    public Transform Plane;
    public Transform SpacePoint;

    // 공간상의 한 점에서 평면에 수직으로 선분 그리기
    private void OnDrawGizmos()
    {
        /*
        법선 벡터 : N(Nx, Ny, Nz)
        평면상의 한 점 : P(Px, Py, Pz)
        평면의 방정식 : Nx*x + Ny*y + Nz*z + d = 0
                      d = -N·Q = -(Nx*Px + Ny*Py + Nz*Pz)
         */
        Vector3 n = Plane.up.normalized; // 평면의 법선 벡터
        Vector3 p = Plane.position; // 평면상의 한 점
        Vector3 s = SpacePoint.position; // 공간상의 한 점

        // d값은 변하지 않기 때문에 미리 계산하는게 좋다.
        float d = -(n.x * p.x + n.y * p.y + n.z * p.z);
        // 공간 상의 점과 평면의 거리
        float distance = n.x * s.x + n.y * s.y + n.z * s.z + d;
        // 공간 상의 점과 평면을 연결하는 가장 짧은 벡터
        Vector3 shortestVector = -n * distance;

        Debug.Log(distance);

        if (distance > 0)
        {
            Gizmos.color = Color.red;
        } else if (distance < 0)
        {
            Gizmos.color = Color.blue;
        } else
        {
            Gizmos.color = Color.white;
        }
        Gizmos.DrawWireSphere(SpacePoint.position, SpacePoint.localScale.x);
        Gizmos.DrawLine(SpacePoint.position, SpacePoint.position + shortestVector);
    }
}

두 평면이 이루고 있는 각
\[\begin{matrix} n1, n2 &:& \text{평면 법선 벡터} \\ \cos\theta &:& \text{두 평면이 이루는 각} \\ \\ \end{matrix} \\ \begin{matrix} \cos\theta = \frac{n1 \cdot n2}{\rVert n1 \lVert \times \rVert n2 \lVert} \\ \cos, \sin \text{값의 절대값은 항상 예각(직각보다 작은 각)을 나타내므로 다음과 같이 쓸 수 있다.} \\ \cos\theta = \frac{\rvert n1 \cdot n2 \lvert}{\rVert n1 \lVert \times \rVert n2 \lVert} \\ \\ \end{matrix} \\\]
두 평면의 평행, 수직 조건
\[\begin{gather*} n1, n2: \text{평면 법선 벡터} \\ 평행\ :\ n1\cdotp n2\ =\ 1\\ 수직\ :\ n1\cdotp n2\ =\ 0 \end{gather*}\]