반응형
참고
위의 링크에서 점과 직선 사이의 거리를 구하였다.
점 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에서 확인 가능하다.
Unity Plus:
Unity Pro:
Unity 프리미엄 학습:
반응형
'개발 > Unity' 카테고리의 다른 글
유니티 - 스톱워치로 실행시간 확인하기 (Unity Stopwatch Timer) (1) | 2022.12.16 |
---|---|
유니티 - 임의의 다각형을 포함하는 사각형 구하기 (Polygon in a Rectangle) (1) | 2022.12.10 |
유니티 - 3차원에서 점과 직선의 거리 (Find Distance between a Point and a Line) (0) | 2022.12.10 |
유니티 - OnGUI, ProfilerRecorder로 런타임 드로우 콜 확인하기 (How to Get Draw Call Count at Runtime) (0) | 2022.12.10 |
유니티 - 드로우 콜 횟수 최적화하기 (Optimizing Draw Calls, Batches) (0) | 2022.11.30 |
댓글