본문 바로가기
개발/Unity

유니티 - 삼각형 안에 있는 점 판단하기 (How to Check If a Point Is Inside a Triangle)

by 피로물든딸기 2022. 10. 29.
반응형

Unity 전체 링크

 

참고

- 사각형 안에 있는 점 판단하기

- 다각형 안에 있는 점 판단하기

 

삼각형 안에 한 점이 있다는 것은 삼각형의 넓이를 이용해서 판단할 수 있다.

 

삼각형의 꼭짓점 dot1, 2, 3과 내부에 있는지 검사해야할 점이 있다고 하자.

그러면 dot1, 2, 3가 만드는 삼각형의 넓이

dot12, dot23, dot31 내부의 점에 의해 만들어진 삼각형의 넓이와 같아야 한다.

 

삼각형의 넓이는 아래의 함수로 구할 수 있다.

    float getAreaOfTriangle(Vector3 dot1, Vector3 dot2, Vector3 dot3)
    {
        Vector3 a = dot2 - dot1;
        Vector3 b = dot3 - dot1;
        Vector3 cross = Vector3.Cross(a, b);

        return cross.magnitude / 2.0f;
    }

 

그리고 전체 삼각형의 넓이(=area)와 각각의 삼각형 넓이의 합을 비교해서 area와 같다면 truereturn한다.

이때 약간의 오차를 허용하였다. (=0.1f)

    bool checkTriangleInPoint(Vector3 dot1, Vector3 dot2, Vector3 dot3, Vector3 checkPoint)
    {
        float area = getAreaOfTriangle(dot1, dot2, dot3);
        float dot12 = getAreaOfTriangle(dot1, dot2, checkPoint);
        float dot23 = getAreaOfTriangle(dot2, dot3, checkPoint);
        float dot31 = getAreaOfTriangle(dot3, dot1, checkPoint);

        return (dot12 + dot23 + dot31) <= area + 0.1f /* 오차 허용 */;
    }

실제 게임에서 확인해보기 위해 아래와 같이 CheckInTriangle.cs를 빈 오브젝트에 추가한다.

그리고 dot1, 2, 3로 만들 삼각형을 그리기 위해 라인 렌더러를 추가한다.

삼각형 내부에 Cube가 있다면 파란색, 외부라면 빨간색으로 교체하기 위해 아래의 오브젝트를 추가하였다.

 

큐브의 Material을 교체하기 위해 Renderer를 할당한다.

그리고 라인 렌더러를 아래와 같이 설정한다.

public class CheckInTriangle : MonoBehaviour
{
    Renderer rd;
    LineRenderer lr;

    void Start()
    {
        rd = checkCube.GetComponent<Renderer>();
        lr = this.GetComponent<LineRenderer>();

        lr.startWidth = lr.endWidth = .1f;
        lr.material.color = Color.red;

        lr.positionCount = 3;
        lr.loop = true;
    }
}

 

Update에서 라인 렌더러를 갱신하고 큐브가 삼각형 안에 있는지 판단한 후 Material을 교체한다.

    void Update()
    {
        Vector3 dot1Pos, dot2Pos, dot3Pos, cubePos;

        dot1Pos = dot1.transform.position;
        dot2Pos = dot2.transform.position;
        dot3Pos = dot3.transform.position;
        cubePos = checkCube.transform.position;

        lr.SetPosition(0, dot1Pos);
        lr.SetPosition(1, dot2Pos);
        lr.SetPosition(2, dot3Pos);

        if(checkTriangleInPoint(dot1Pos, dot2Pos, dot3Pos, cubePos))
        {
            rd.material = blue;
        }
        else
        {
            rd.material = red;
        }
    }

 

큐브를 움직여서 삼각형 밖으로 내보내거나, 꼭짓점을 옮기면 큐브의 색깔이 변하는 것을 알 수 있다.

 

최종 코드는 다음과 같다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CheckInTriangle : MonoBehaviour
{
    Renderer rd;
    public Material red, blue;
    public GameObject dot1, dot2, dot3, checkCube;
    LineRenderer lr;

    float getAreaOfTriangle(Vector3 dot1, Vector3 dot2, Vector3 dot3)
    {
        Vector3 a = dot2 - dot1;
        Vector3 b = dot3 - dot1;
        Vector3 cross = Vector3.Cross(a, b);

        return cross.magnitude / 2.0f;
    }

    bool checkTriangleInPoint(Vector3 dot1, Vector3 dot2, Vector3 dot3, Vector3 checkPoint)
    {
        float area = getAreaOfTriangle(dot1, dot2, dot3);
        float dot12 = getAreaOfTriangle(dot1, dot2, checkPoint);
        float dot23 = getAreaOfTriangle(dot2, dot3, checkPoint);
        float dot31 = getAreaOfTriangle(dot3, dot1, checkPoint);

        return (dot12 + dot23 + dot31) <= area + 0.1f /* 오차 허용 */;
    }

    void Start()
    {
        rd = checkCube.GetComponent<Renderer>();
        lr = this.GetComponent<LineRenderer>();

        lr.startWidth = lr.endWidth = .1f;
        lr.material.color = Color.red;

        lr.positionCount = 3;
        lr.loop = true;
    }

    void Update()
    {
        Vector3 dot1Pos, dot2Pos, dot3Pos, cubePos;

        dot1Pos = dot1.transform.position;
        dot2Pos = dot2.transform.position;
        dot3Pos = dot3.transform.position;
        cubePos = checkCube.transform.position;

        lr.SetPosition(0, dot1Pos);
        lr.SetPosition(1, dot2Pos);
        lr.SetPosition(2, dot3Pos);

        if(checkTriangleInPoint(dot1Pos, dot2Pos, dot3Pos, cubePos))
        {
            rd.material = blue;
        }
        else
        {
            rd.material = red;
        }
    }
}

 

위의 실행결과는 아래의 unitypackage에서 확인 가능하다.

TriangleCheck.unitypackage
0.03MB

 

Unity Plus:

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Unity Pro:

 

Unity Pro

The complete solutions for professionals to create and operate.

unity.com

 

Unity 프리미엄 학습:

 

Unity Learn

Advance your Unity skills with live sessions and over 750 hours of on-demand learning content designed for creators at every skill level.

unity.com

반응형

댓글