/// <summary> /// 最短射线包围盒路径 /// </summary> /// <param name="line">线段</param> /// <param name="offset">偏移值</param> /// <param name="rbi">包围盒信息</param> /// <returns>true,表示线段与aabb有相交,并返回最短包围路径</returns> public override RBIResultType RayboundingNearestPath(LineSegment2D line, double offset, ref RayboundingInfo rbi) { if (rbi == null) { rbi = new RayboundingInfo(); } List <Double3> lineArray = new List <Double3>(); Double2 intersectionPoint = Double2.zero; Double2 pos1 = Double2.zero; for (int i = 0; i < this.pointArr.Length; i++) { if (line.GetIntersectPoint(GetEdge(i), ref intersectionPoint, ref pos1) == true) { lineArray.Add(new Double3(intersectionPoint.x, intersectionPoint.y, i)); } } int count = lineArray.Count; if (count == 0) { return(RBIResultType.Fail); } else if (count % 2 == 1) { lineArray.Sort((x, y) => MathUtil.GetCompareDis(new Double2(x.x, x.y), line.startPoint).CompareTo(MathUtil.GetCompareDis(new Double2(y.x, y.y), line.startPoint))); if (CheckIn(line.startPoint) == true) { rbi.SetNear(line, offset, new Double2(lineArray[0].x, lineArray[0].y)); return(RBIResultType.UnCrossstartPointIn); } else { rbi.SetNear(line, offset, new Double2(lineArray[count - 1].x, lineArray[count - 1].y)); return(RBIResultType.UnCrossendPointIn); } } else { // 先按距离进行排序。 lineArray.Sort((x, y) => MathUtil.GetCompareDis(new Double2(x.x, x.y), line.startPoint).CompareTo(MathUtil.GetCompareDis(new Double2(y.x, y.y), line.startPoint))); // bool isCross = true; bool isPathDir = CheckPathDir(lineArray[0], lineArray[lineArray.Count - 1], ref isCross); if (isCross == false) { rbi.SetNear(line, offset, new Double2(lineArray[0].x, lineArray[0].y)); return(RBIResultType.UnCross); } List <Double2> temppaths = new List <Double2>(); RayboundingNearestPath(lineArray[0], lineArray[lineArray.Count - 1], offset, isPathDir, ref temppaths); if (rbi.listpath == null) { rbi.listpath = temppaths; } else { rbi.listpath.AddRange(temppaths); } // 排斥需要扣除的点。 for (int i = 1; i < lineArray.Count - 1; i += 2) { if (CheckisSubChild((int)lineArray[0].z, (int)lineArray[lineArray.Count - 1].z, isPathDir, (int)lineArray[i].z, (int)lineArray[i + 1].z) == false) { continue; } List <Double2> listTemp = new List <Double2>(); RayboundingNearestPath(lineArray[i], lineArray[i + 1], offset, isPathDir, ref listTemp); if (listTemp.Count > 0) { foreach (Double2 pos in listTemp) { rbi.listpath.Remove(pos); } } } // if (rbi.listpath != null && rbi.listpath.Count > 0) { rbi.CalcHelpData(line, offset, new Double2(lineArray[0].x, lineArray[0].y), new Double2(lineArray[lineArray.Count - 1].x, lineArray[lineArray.Count - 1].y)); return(RBIResultType.Succ); } return(RBIResultType.Fail); } }
/// <summary> /// 最短射线包围盒路径 /// </summary> /// <param name="line">线段</param> /// <param name="offset">偏移值</param> /// <param name="rbi">包围盒信息</param> /// <returns>true,表示线段与aabb有相交,并返回最短包围路径</returns> public override RBIResultType RayboundingNearestPath(LineSegment2D line, double offset, ref RayboundingInfo rbi) { if (rbi == null) { rbi = new RayboundingInfo(); } int index = 0; Double3[] lineArray = new Double3[2]; Double2 intersectionPoint = Double2.zero; Double2 pos1 = Double2.zero; if (line.GetIntersectPoint(GetEdge(0), ref intersectionPoint, ref pos1) == true) { lineArray[index] = new Double3(intersectionPoint.x, intersectionPoint.y, 1); index++; } if (line.GetIntersectPoint(GetEdge(2), ref intersectionPoint, ref pos1) == true) { lineArray[index] = new Double3(intersectionPoint.x, intersectionPoint.y, 3); index++; } if (index < 2) { if (line.GetIntersectPoint(GetEdge(3), ref intersectionPoint, ref pos1) == true) { lineArray[index] = new Double3(intersectionPoint.x, intersectionPoint.y, 4); index++; } } if (index < 2) { if (line.GetIntersectPoint(GetEdge(1), ref intersectionPoint, ref pos1) == true) { lineArray[index] = new Double3(intersectionPoint.x, intersectionPoint.y, 2); index++; } } if (index == 2) { double v1 = (new Double2(lineArray[0].x, lineArray[0].y) - line.startPoint).sqrMagnitude; double v2 = (new Double2(lineArray[1].x, lineArray[1].y) - line.startPoint).sqrMagnitude; Double2 s; Double2 e; if (v1 < v2) { s = new Double2(lineArray[0].x, lineArray[0].y); e = new Double2(lineArray[1].x, lineArray[1].y); RayboundingNearestPath(new Double3(s.x, s.y, lineArray[0].z), new Double3(e.x, e.y, lineArray[1].z), offset, ref rbi.listpath); } else { e = new Double2(lineArray[0].x, lineArray[0].y); s = new Double2(lineArray[1].x, lineArray[1].y); RayboundingNearestPath(new Double3(s.x, s.y, lineArray[1].z), new Double3(e.x, e.y, lineArray[0].z), offset, ref rbi.listpath); } if (rbi.listpath != null && rbi.listpath.Count > 0) { rbi.CalcHelpData(line, offset, s, e); return(RBIResultType.Succ); } return(RBIResultType.Fail); } else { return(RBIResultType.Fail); } }
/// <summary> /// 最短射线包围盒路径 /// </summary> /// <param name="line">线段</param> /// <param name="offset">偏移值</param> /// <param name="rbi">包围盒信息</param> /// <returns>true,表示线段与aabb有相交,并返回最短包围路径</returns> public override RBIResultType RayboundingNearestPath(LineSegment2D line, double offset, ref RayboundingInfo rbi) { if (rbi == null) { rbi = new RayboundingInfo(); } Double2 diff = this.circleCenter - line.startPoint; if (diff == Double2.zero) { return(RBIResultType.Fail); } // Double2 projectoint = line.ProjectPoint(this.circleCenter); diff = this.circleCenter - projectoint; // 跟直线相交奥 double dis = diff.sqrMagnitude - this.radius * this.radius; if (dis >= 0) { return(RBIResultType.Fail); } dis = -dis; // 在同侧不行。 Double2 diff1 = line.startPoint - projectoint; Double2 diff2 = line.endPoint - projectoint; if (Double2.Dot(diff1, diff2) >= 0) { return(RBIResultType.Fail); } // if (diff1.sqrMagnitude < dis || diff2.sqrMagnitude < dis) { return(RBIResultType.Fail); } dis = System.Math.Sqrt(dis) + offset; Double2 p1 = projectoint - line.normalizedDir * dis; Double2 p2 = projectoint + line.normalizedDir * dis; double bigRadius = this.radius + offset; double angle = SignedAngleInCircle(p1 - this.circleCenter, p2 - this.circleCenter, bigRadius); int count = (int)(System.Math.Abs(angle / 0.25f)); double diffangle = angle / count; List <Double2> listpath = new List <Double2>(); Double2 startVector = (p1 - this.circleCenter).normalized * bigRadius; for (int i = 1; i <= count - 1; i++) { Double2 rorateVector = Double2.Rotate(startVector, -diffangle * i); listpath.Add(rorateVector + this.circleCenter); } rbi.listpath = listpath; if (rbi.listpath != null && rbi.listpath.Count > 0) { rbi.CalcHelpData(line, offset, p1, p2); return(RBIResultType.Succ); } return(RBIResultType.Fail); }