欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

点到某三角形的最短距离

程序员文章站 2021-12-23 19:42:54
...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MathPoint2Panel : MonoBehaviour
{
    public Vector3 p1 = Vector3.zero;
    public Vector3 p2 = new Vector3(50, 0, 0);
    public Vector3 p3 = new Vector3(50, 0, 50);

    public Transform point;
    public Vector3 pt = Vector3.zero;

    public float t0;
    public float t1;

    public float test1;
    public Vector3 docNormal;

    public void Update()
    {
        Debug.DrawLine(transform.position + p1, transform.position + p2);
        Debug.DrawLine(transform.position + p2, transform.position + p3);
        Debug.DrawLine(transform.position + p3, transform.position + p1);
        
        Vector3 pa = transform.position + p1;
        Vector3 pb = transform.position + p2;
        Vector3 pc = transform.position + p3;

        // [V0, V1]
        Vector3 V0 = pb - pa;
        Vector3 V1 = pc - pa;
        // Pt = pa + (V0 * t0 + V1 * t1) // 任意一点都能如此表达

        Vector3 p = point.position;


        // p - pt = p - pa - (V0 * t0 + V1 * t1) 
        // 法向量于V0基 垂直 为 0
        // Vector3.Dot(p - pt, V0) = 0  
        // Vector3.Dot(p - pt, V1) = 0
        // (p - pa) * V0 = V0 * V0 * t0 + V1 * V0 * t1 
        // (p - pa) * V1 = V0 * V1 * t0 + V1 * V1 * t1 
        // Pt = P0 + t0 * v0 + t1 * v1 

        float A = Vector3.Dot((p - pa) , V0);
        float B = Vector3.Dot((p - pa) , V1);
        float C = Vector3.Dot(V1, V0);
        float D = Vector3.Dot(V0, V1);
        float E = Vector3.Dot(V0, V0);
        float F = Vector3.Dot(V1, V1);

        // A = V0 * V0 * t0 + V1 * V0 * t1 
        // B = V0 * V1 * t0 + V1 * V1 * t1 

        // A = E * t0 + C * t1;
        // B = D * t0 + F * t1;
        // t0 = (A - C * t1) / E;

        // B = D * (A - C * t1) / E + F * t1;
        // B * E = D * (A - C * t1) + F * E * t1;
        // B * E - D * A = F * E * t1 - D * C * t1 ;

        t1 = (B * E - D * A) / (F * E - C * D);
        t0 = (A - C * t1) / E;
		
		// 判断是否在三角形内
        if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1 && t0 + t1 < 1)
        {
            pt = pa + (t0 * V0 + t1 * V1);  // 带入公式
        }
        else
        {
            Vector3 closed1 = Vector3.zero;
            Vector3 closed2 = Vector3.zero;
            Vector3 closed3 = Vector3.zero;
			
			// 分别求出对三条边的最短距离
            float c1 = FindDistance2Segment(p, pa, pb, out closed1);
            float c2 = FindDistance2Segment(p, pa, pc, out closed2);
            float c3 = FindDistance2Segment(p, pb, pc, out closed3);

            float min = Mathf.Min(c1, c2, c3);

            if (min == c1)
            {
                pt = closed1;
            }
            else if(min == c2)
            {
                pt = closed2;
            }
            else
            {
                pt = closed3;
            }
        }

        Debug.DrawLine(pt, p);
    }

    private float FindDistance2Segment(Vector3 pt, Vector3 p1, Vector3 p2, out Vector3 closedP)
    {
        //float radio = projection / segmentLength;
        Vector3 vSegment = p2 - p1;
        float radio = Vector3.Dot(vSegment, pt - p1) / vSegment.magnitude / vSegment.magnitude;
        if (radio <= 0)
        {
            closedP = p1;
        }
        else if (radio >= 1)
        {
            closedP = p2;
        }
        else
        {
            closedP = p1 + radio * vSegment;
        }

        return (pt - closedP).magnitude;
    }
}

相关标签: Unity 几何学