본문 바로가기
개발/Unity

유니티 - 3차원에서 점과 직선 사이의 수선의 발 구하기 (Find a Point Perpendicular to a Line)

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

Unity 전체 링크

 

참고 

- 3차원에서 점과 직선의 거리

- 임의의 다각형을 포함하는 사각형 구하기

 

위의 링크에서 점과 직선 사이의 거리를 구하였다.

점 A점 B로 구성된 직선 AB점 D의 가장 가까운 경로를 만드는 점 H가 있다.

여기서 점과 직선 사이의 수선의 발(H)을 구해보자.

 

직선 AB = line1, 직선 BD를 line2라고 하자.

이때 line1과 line2의 각도는 θ다.

 

벡터의 내적에 의하면 다음 공식이 성립한다.

 

 

따라서 cosθ는 다음과 같다.

 

 

cosθ와 직선 BD의 길이를 알면 직선 BH의 길이를 알 수 있다.

 

 

즉, 점 H 점 B에서 점 A의 벡터 방향으로 길이 BH의 크기를 빼면 된다.

 

위의 설명을 그대로 구현하면 아래와 같다.

    Vector3 getPerpendicularOntoLine(Vector3 A, Vector3 B, Vector3 D)
    {
        Vector3 line1 = A - B;
        Vector3 line2 = D - B;

        float cos = Vector3.Dot(line1, line2) / (line1.magnitude * line2.magnitude);
        float lengthBD = Vector3.Distance(B, D);
        float projectionLength = lengthBD * cos;

        Vector3 normalAB = (B - A).normalized;

        return (B - normalAB * projectionLength);
    }

 

빈 오브젝트에 스크립트를 추가해서 위의 코드를 확인해보자.

 

빨간색 점직선 사이에서 가장 가까운 점(수선의 발)을 찾는 것을 알 수 있다.

 

전체 코드는 다음과 같다.

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

public class PointToLine : MonoBehaviour
{
    public Transform pointA, pointB, target, perpendicular;

    public GameObject lineRenderer;
    LineRenderer[] lrs;

    // 참고, 점과 직선 사이의 거리
    float getDistancePointAndLine(Vector3 A, Vector3 B, Vector3 point)
    {
        Vector3 AB = B - A;
        return (Vector3.Cross(point - A, AB)).magnitude / AB.magnitude;
    }

    Vector3 getPerpendicularOntoLine(Vector3 A, Vector3 B, Vector3 D)
    {
        Vector3 line1 = A - B;
        Vector3 line2 = D - B;

        float cos = Vector3.Dot(line1, line2) / (line1.magnitude * line2.magnitude);
        float lengthBD = Vector3.Distance(B, D);
        float projectionLength = lengthBD * cos;

        Vector3 normalAB = (B - A).normalized;

        return (B - normalAB * projectionLength);
    }

    void setLineRenderer(LineRenderer lr, Color color)
    {
        lr.startWidth = lr.endWidth = .2f;
        lr.material.color = color;
        lr.positionCount = 2;
    }

    void Start()
    {
        lrs = lineRenderer.GetComponentsInChildren<LineRenderer>();

        setLineRenderer(lrs[0], Color.red);
        setLineRenderer(lrs[1], Color.black);
    }

    void Update()
    {
        lrs[0].SetPosition(0, pointA.position);
        lrs[0].SetPosition(1, pointB.position);
        
        lrs[1].SetPosition(0, target.position);
        lrs[1].SetPosition(1, perpendicular.position);

        perpendicular.position 
            = getPerpendicularOntoLine(pointA.position, pointB.position, target.position);
    }
}

 

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

Perpendicular.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

반응형

댓글