3、x 与 P 的距离即为所求;
/// <summary>
/// 线段与点的最短距离。
/// </summary>
/// <param name="x0">线段起点</param>
/// <param name="u">线段向量</param>
/// <param name="x">求解点</param>
/// <returns></returns>
public static float SqrDistanceBetweenSegmentAndPoint(Vector2 x0, Vector2 u, Vector2 x)
{
float t = Vector2.Dot(x - x0, u) / u.sqrMagnitude;
return (x - (x0 + Mathf.Clamp01(t) * u)).sqrMagnitude;
}
为避免开方计算,结果使用距离的平方。
圆形与胶囊体
分离轴是线段上距离圆心最近的点P与圆心所在方向。
定义胶囊体:
/// <summary>
/// 胶囊体
/// </summary>
public struct CapsuleArea
{
public Vector2 X0;
public Vector2 U;
public float d;
}
相交判断:
/// <summary>
/// 判断胶囊体与圆形相交
/// </summary>
/// <param name="capsuleArea"></param>
/// <param name="circleArea"></param>
/// <returns></returns>
public static bool Capsule(CapsuleArea capsuleArea, CircleArea circleArea)
{
float sqrD = SegmentPointSqrDistance(capsuleArea.X0, capsuleArea.U, circleArea.o);
return sqrD < (circleArea.r + capsuleArea.d) * (circleArea.r + capsuleArea.d);
}
圆形与扇形
当扇形角度大于180度时,就不再是凸多边形了,不能适用于分离轴理论。我们可以找出相交时圆心的所有可能区域,并把区域划分成可以简单验证的几个区域,逐个试验。
这里共划分了2个区间
1、半径为两者半径和的扇形区间,角度方向同扇形。验证方法是;验证距离与夹角。
2、扇形边为轴,圆形半径为大小组成的胶囊体空间,由于扇形的对称性,我们可以通过把圆心映射到一侧,从而只需要计算1条边。
定义扇形:
/// <summary>
/// 扇形区间。
/// </summary>
public struct SectorArea
{
public Vector2 o;
public float r;
public Vector2 direction;
public float angle;
}
相交检测:
/// <summary>
/// 判断圆形与扇形相交。
/// </summary>
/// <param name="sectorArea"></param>
/// <param name="target"></param>
/// <returns></returns>
public static bool Sector(SectorArea sectorArea, CircleArea target)
{
Vector2 tempDistance = target.o - sectorArea.o;
float halfAngle = Mathf.Deg2Rad * sectorArea.angle / 2;
if (tempDistance.sqrMagnitude < (sectorArea.r + target.r) * (sectorArea.r + target.r))
{
if (Vector3.Angle(tempDistance, sectorArea.direction) < sectorArea.angle / 2)
{
return true;
}
else
{
Vector2 targetInSectorAxis = new Vector2(Vector2.Dot(tempDistance,
sectorArea.direction), Mathf.Abs(Vector2.Dot(tempDistance, new Vector2(-sectorArea.direction.y, sectorArea.direction.x))));
Vector2 directionInSectorAxis = sectorArea.r * new Vector2(Mathf.Cos(halfAngle), Mathf.Sin(halfAngle));
return SegmentPointSqrDistance(Vector2.zero, directionInSectorAxis, targetInSectorAxis) <= target.r * target.r;
}
}
return false;
}










