在空间三维坐标系下的圆、直线和平面拟合九磅十五便士的博客-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);
}
}
}
网友评论