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); }
public static float GetHoverDis(Vector3 lp1, Vector3 lp2, Vector3 modelP) { var _lp1 = new Vector3(lp1.x, 0, lp1.z); var _lp2 = new Vector3(lp2.x, 0, lp2.z); var _modelP = new Vector3(modelP.x, 0, modelP.z); var _area = Geometric.GetArea(_lp1, _lp2, _modelP); //三角形面积 var _lLength = Vector3.Distance(_lp1, _lp2); //lp1,lp2长度 var dis = 2 * _area / _lLength; //modelP到lp1,lp2的距离 return(dis); }
public static bool AlmostOnLine(Vector3 lineP1, Vector3 lineP2, float width, Vector3 toCheck) { Vector3 _lineDir = (lineP2 - lineP1).normalized; lineP1 += _lineDir * 99; lineP2 -= _lineDir * 99; Quaternion q = QuaternionUtility.Euler(0, 90, 0); Vector3 _rightDir = (q * _lineDir).normalized; Vector3 lp1Right = lineP1 + _rightDir * 0.5f * width - _lineDir * 0.5f * width; Vector3 lp1Left = lineP1 - _rightDir * 0.5f * width - _lineDir * 0.5f * width; Vector3 lp2Right = lineP2 + _rightDir * 0.5f * width + _lineDir * 0.5f * width; Vector3 lp2Left = lineP2 - _rightDir * 0.5f * width + _lineDir * 0.5f * width; return(Geometric.IsPointInArea(new[] { lp1Right, lp2Right, lp2Left, lp1Left }, toCheck)); }
public static bool IsPointAlmostOnSegment(Vector3 lineP1, Vector3 lineP2, float width, Vector3 toCheck) { Vector3 _lineDir = (lineP2 - lineP1).normalized; Quaternion q = QuaternionUtility.Euler(0, 90, 0); Vector3 _rightDir = (q * _lineDir).normalized; Vector3 diff = _rightDir * width - _lineDir * width; Vector3 lp1Right = lineP1 + diff; Vector3 lp1Left = lineP1 - diff; Vector3 lp2Right = lineP2 + diff; Vector3 lp2Left = lineP2 - diff; var res = Geometric.IsPointInArea(new[] { lp1Right, lp2Right, lp2Left, lp1Left }, toCheck); 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)); }
public static Vector3 GetHoverPointOfLine(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 * 99; Vector3 __E = modelP + mDir * 99; //临时的两个线点 //if (!Geometric.Meet(__S, __E, lp1, lp2))//不相交 //{ // return default(Vector3); //} //到这里还能执行的话是相交且接近, 就要计算点 Vector3 res = Geometric.GetCrossPointOfLine(__E, __S, lp1, lp2); if ((Mathf.Abs(res.x - modelP.x) < 0.01f)) { res.x = modelP.x; } if ((Mathf.Abs(res.z - modelP.z) < 0.01f)) { res.z = modelP.z; } return(res); }
public static bool IsTwoLinePointPartCover(Vector3 a, Vector3 b, Vector3 c, Vector3 d, float offset = 0.03f) { return(Geometric.IsPointAlmostOnSegment(a, b, offset, c) || Geometric.IsPointAlmostOnSegment(a, b, offset, d) || Geometric.IsPointAlmostOnSegment(c, d, offset, a) || Geometric.IsPointAlmostOnSegment(c, d, offset, b)); }
public static bool Meet_crossWay(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4) { Vector3 crossP = GetCrossPointOfLine(p1, p2, p3, p4); return(Geometric.IsPointOnSegment(p1, p2, crossP) && Geometric.IsPointOnSegment(p3, p4, crossP)); }