public static Vector3 GetHoverPoint(Vector3 lp1, Vector3 lp2, Vector3 modelP, float attachR) { var _area = Geometric.GetArea(lp1, lp2, modelP); //三角形面积 var _lLength = Vector3.Distance(lp1, lp2); //lp1,lp2长度 var dis = _lLength < 1e-3 ? attachR + 1 : 2 * _area / _lLength; //modelP到lp1,lp2的距离 if (dis > attachR) //太远 { return(default(Vector3)); } Vector3 lDir = lp1 - lp2; //直线方向 Vector3 mDir = QuaternionUtility.Euler(0, 90, 0) * lDir; //xz平面上垂直直线方向 Vector3 __S = modelP - mDir * 999; Vector3 __E = modelP + mDir * 999; //临时的两个线点 if (!Geometric.Meet(__S, __E, lp1, lp2)) //不相交 { return(default(Vector3)); } //到这里还能执行的话是相交且接近, 就要计算点 Vector3 res = Geometric.GetCorssPointOfSegment(__E, __S, lp1, lp2); return(res); }
/// <summary> /// 使用向量叉乘来计算任意多边形面积 /// </summary> /// <param name="points">顺序描述的点集</param> /// <returns>面积</returns> public static float GetArea(params Vector3[] points) { //去重 List <Vector3> toCalcualte = new List <Vector3>(points); for (int i = 0; i < toCalcualte.Count; i++) { for (int j = 0; j < toCalcualte.Count; j++) { if (j != i && toCalcualte[i] == toCalcualte[j]) { toCalcualte.RemoveAt(j); j--; } } } int n = toCalcualte.Count; for (int i = 0; i < n; i++) { if (Geometric.Meet(toCalcualte[i], toCalcualte[(i + 1) % n], toCalcualte[(i + 2) % n], toCalcualte[(i + 3) % n])) { var temp = toCalcualte[(i + 2) % n]; toCalcualte[(i + 2) % n] = toCalcualte[(i + 1) % n]; toCalcualte[(i + 1) % n] = temp; } } points = toCalcualte.ToArray(); float area = 0f; Vector3 ANXI = toCalcualte[0] + Vector3.one * 100;//要尽量远来补平舍入误差 for (int i = 0; i < points.Length; i++) { area += cross(ANXI, points[i], points[(i + 1) % points.Length]); } area /= 2f; return(Mathf.Abs(area)); }