美文网首页
2021-12-28【Math】空间圆切线计算

2021-12-28【Math】空间圆切线计算

作者: 持刀的要迟到了 | 来源:发表于2021-12-28 23:59 被阅读0次

    在空间三维坐标系下的圆、直线和平面拟合九磅十五便士的博客-CSDN博客_三维坐标系中圆的方程
    geometry - Tangents to a circle in 3D - Mathematics Stack Exchange

    2D空间计算:

    把点平移到圆心,以圆心为原点计算,最后再根据圆心进行偏移量偏移。

            // this approach is more geometrical and less algebraic than approach 1,
            // and far more stable. thanks to Mike Plotz for suggesting this direction.
            // https://answers.unity.com/questions/1617078/finding-a-tangent-vector-from-a-given-point-and-ci.html
            public static bool CircleTangents_2(Vector2 center, float r, Vector2 point, 
                ref Vector2 tanPosA, ref Vector2 tanPosB)
            {
                point -= center;    // point = point - center :point = c->p 向量
                                    // 也可以理解为,以center为圆心建立坐标系。
    
                float P = point.magnitude;
    
                // if p is inside the circle, there ain't no tangents.
                if (P <= r)
                {
                    return false;
                }
    
                float a = r * r / P;    // r * sin(theta)
                float q = r * (float)System.Math.Sqrt((P * P) - (r * r)) / P;// r * cos(theta)
    
                Vector2 pN = point / P; // 单位向量
                Vector2 pNP = new Vector2(-pN.y, pN.x); // 垂直于上向量的单位向量
                                                        //Dot点乘:-xy + xy = 0
                Vector2 va = pN * a;    // 圆上交点
    
                tanPosA = va + pNP * q;
                tanPosB = va - pNP * q;
    
                tanPosA += center;
                tanPosB += center;
    
                return true;
            }
    

    3D空间计算:

    获得圆心所在平面的,法线朝向。获得xz平面的法线向量。然后把所有已知向量,
    根据这两个法线向量进行旋转和位移转换。然后根据xz上的值进行2d计算,计算后,
    再旋转和位移转换回去。

    using SGF.Utility;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class SpaceCicleTest : MonoBehaviour
    {
        // Start is called before the first frame update
        void Start()
        {
    
        }
    
        // Update is called once per frame
        void Update()
        {
            Vector3 camPos = transform.position;
            Vector3 centerPos = center.position;
    
            // 绘制竖直方向两条切线
            // 投影到 normal = y 平面上
    
            // 原始切线
            Vector3 normalDir = Vector3.Cross(centerPos - camPos, Vector3.up).normalized;
            Quaternion rotOffset = Quaternion.FromToRotation(normalDir, Vector3.up);
            
            Vector3 camChangedPos = rotOffset * camPos;
            Vector3 centerChangedPos = rotOffset * centerPos;
    
            Debug.LogError(camChangedPos.y + "_" + centerChangedPos.y);
    
            Vector2 tanA = Vector2.zero, tanB = Vector2.zero;
            SGF.Utility.MathUtility.CircleTangents_2(new Vector2(centerChangedPos.x, centerChangedPos.z), circleRadius, new Vector2(camChangedPos.x, camChangedPos.z), ref tanA, ref tanB);
    
    
            Vector3 tana = new Vector3(tanA.x, centerChangedPos.y, tanA.y);
            Vector3 tanb = new Vector3(tanB.x, centerChangedPos.y, tanB.y);
    
            tana = Quaternion.Inverse(rotOffset) * tana;
            tanb = Quaternion.Inverse(rotOffset) * tanb;
    
            Debug.DrawLine(camPos, tana, Color.red);
            Debug.DrawLine(camPos, tanb, Color.red);
        }
    
    
        public Transform center;
        public float circleRadius = 0.8f;
        private void OnDrawGizmos()
        {
            if (center)
            {
                Gizmos.color = new Color(0.3f, 0.1f, 0.25f, 0.2f);
                Gizmos.DrawSphere(center.position, circleRadius);
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:2021-12-28【Math】空间圆切线计算

          本文链接:https://www.haomeiwen.com/subject/locpqrtx.html