主要判断球体和矩形边沿最短举例,
申明类:
/// <summary>
/// 球的信息
/// </summary>
public class Ball
{
private int radius = 5; //球半径
private Point addr = new Point(0, 0);
private Point dir = new Point(0, 0);
private Point speed = new Point(0, 0);
/// <summary>
/// 球的半径
/// </summary>
public int Radius
{
get { return radius; }
set { radius = value; }
}
/// <summary>
/// 位置
/// </summary>
public Point Addr
{
get { return addr; }
set { addr = value; }
}
/// <summary>
/// 运行方向
/// </summary>
public Point Dir
{
get { return dir; }
set { dir = value; }
}
/// <summary>
/// 速度
/// </summary>
public Point Speed
{
get { return speed; }
set { speed = value; }
}
}
/// <summary>
///矩形的信息
/// </summary>
public class Rect
{
private int width = 0;
private int height = 0;
private int sta = 0;
private Point addr = new Point(0,0);
/// <summary>
/// 宽
/// </summary>
public int Width
{
get { return width; }
set { width = value; }
}
/// <summary>
/// 高
/// </summary>
public int Height
{
get { return height; }
set { height = value; }
}
/// <summary>
/// 状态 0不存在 1 需要敲击一次才能消除 2 需要敲击2次才能小区 99:不能消除
/// </summary>
public int Stat
{
get { return sta; }
set { sta = value; }
}
/// <summary>
/// 地址
/// </summary>
public Point Addr
{
get { return addr; }
set { addr = value; }
}
}
计算距离
/// <summary>
/// 获取距离最近的点
/// </summary>
/// <param name="addr"></param>
private double check_leng( Rect p, Ball b)
{
double leng= Math.Sqrt(Math.Pow(p.Addr.X - b.Addr.X, 2) + Math.Pow(p.Addr.Y - b.Addr.Y, 2));
double max_len = Math.Sqrt(Math.Pow(p.Width/2, 2) + Math.Pow(p.Height/2, 2)) + b.Radius;
double min_len = Math.Min(Math.Min(p.Height/2, p.Width/2), b.Radius);
double min_x = -1;
double min_y = -1;
double min_1 = -1;
double min_2 = -1;
double min_3 = -1;
double min_4 = -1;
if (leng < min_len) //小于最小距离,两物体相交 或位于内部
{
//逻辑上不允许出现此种情况
return -1;
}
else
{
//根据中心坐标位置确定需要判断的边界(有可能交互的边界)
if ((b.Addr.X >= p.Addr.X - p.Width / 2 + b.Radius) && (b.Addr.X <= p.Addr.X + p.Width / 2 - b.Radius)) //位于Y轴方向区域类
{
if (b.Addr.Y <= p.Addr.Y - p.Height / 2 - b.Radius) //圆心位于矩形的下边沿
{
min_y = Math.Abs(b.Addr.Y + b.Radius - (p.Addr.Y - p.Height / 2));
}
else if (b.Addr.Y >= p.Addr.Y + p.Height / 2 + b.Radius) //圆心位于的上边沿
{
min_y = Math.Abs(b.Addr.Y - b.Radius - (p.Addr.Y + p.Height / 2));
}
else //圆心位于矩形内
{
min_y = -1;
}
return min_y;
}
else if ((b.Addr.Y >= p.Addr.Y - p.Height / 2 + b.Radius) && (b.Addr.Y <= p.Addr.Y + p.Height / 2 - b.Radius))//位于矩形X轴方向区域类
{
if (b.Addr.X <= p.Addr.X - p.Width / 2 - b.Radius) //圆心位于矩形的左边沿
{
min_x = Math.Abs(b.Addr.X + b.Radius - (p.Addr.X - p.Width / 2));
}
else if (b.Addr.X >= p.Addr.X + p.Width / 2 + b.Radius) //圆心位于矩形的右边沿
{
min_x = Math.Abs(b.Addr.X - b.Radius - (p.Addr.X + p.Width / 2));
}
else //圆心位于矩形内
{
min_x = -1;
}
return min_x;
}
else if ((b.Addr.X <= p.Addr.X - p.Width / 2 + b.Radius) && (b.Addr.Y <= p.Addr.Y - p.Height / 2 + b.Radius)) //第四象域
{
for (int rad_t = 270; rad_t <= 360; rad_t++)
{
double x = b.Addr.X + b.Radius * Math.Cos(Math.PI * rad_t / 180);
double y = b.Addr.Y - b.Radius * Math.Sin(Math.PI * rad_t / 180); //算出球边沿的坐标
double m = p.Addr.X - p.Width / 2;
double n = p.Addr.Y - p.Height / 2;
double mint_t = Math.Sqrt(Math.Pow(m - x, 2) + Math.Pow(n - y, 2));
if (b.Addr.X > m)
{
mint_t = Math.Min(mint_t, Math.Abs(y - n));
}
else if (b.Addr.Y > n)
{
mint_t = Math.Min(mint_t, Math.Abs(x - m));
}
if (min_4 != -1)
{
if ((x > p.Addr.X - p.Width / 2) && (y > p.Addr.Y - p.Height / 2))
{
min_4 = -1;
break;
}
else
{
if (mint_t < min_4)
{
min_4 = mint_t;
}
}
}
else
{
if ((x > p.Addr.X - p.Width / 2) && (y > p.Addr.Y - p.Height / 2))
{
min_4 = -1;
break;
}
else
{
min_4 = mint_t;
}
}
}
return min_4;
}
else if ((b.Addr.X > p.Addr.X + p.Width / 2 - b.Radius) && (b.Addr.Y <= p.Addr.Y - p.Height / 2+b.Radius)) //第三象域
{
for (int rad_t = 180; rad_t <= 270; rad_t++)
{
double x = b.Addr.X + b.Radius * Math.Cos(Math.PI * rad_t / 180);
double y = b.Addr.Y - b.Radius * Math.Sin(Math.PI * rad_t / 180); //算出球边沿的坐标
double m = p.Addr.X + p.Width / 2;
double n = p.Addr.Y - p.Height / 2;
double mint_t = Math.Sqrt(Math.Pow(m - x, 2) + Math.Pow(n - y, 2));
if (b.Addr.X < m)
{
mint_t = Math.Min(mint_t, Math.Abs(y - n));
}
else if (b.Addr.Y > n)
{
mint_t = Math.Min(mint_t, Math.Abs(x - m));
}
//double mint_t = Math.Sqrt(Math.Pow(p.Addr.X + p.Width / 2 - x, 2) + Math.Pow(p.Addr.Y - p.Height / 2 - y, 2));
if (min_3 != -1)
{
if ((x < p.Addr.X + p.Width / 2) && (y > p.Addr.Y - p.Height / 2))
{
min_3 = -1;
break;
}
else
if (mint_t < min_3)
{
min_3 = mint_t;
}
}
else
{
if ((x < p.Addr.X + p.Width / 2) && (y > p.Addr.Y - p.Height / 2))
{
min_3 = -1;
break;
}
else
{
}
min_3 = mint_t;
}
}
return min_3;
}
else if ((b.Addr.X > p.Addr.X + p.Width / 2 - b.Radius) && (b.Addr.Y > p.Addr.Y + p.Height / 2 - b.Radius))//第二象域
{
for (int rad_t = 90; rad_t <= 180; rad_t++)
{
double x = b.Addr.X + b.Radius * Math.Cos(Math.PI * rad_t / 180);
double y = b.Addr.Y - b.Radius * Math.Sin(Math.PI * rad_t / 180); //算出球边沿的坐标
double m = p.Addr.X + p.Width / 2;
double n = p.Addr.Y + p.Height / 2;
double mint_t = Math.Sqrt(Math.Pow(m - x, 2) + Math.Pow(n - y, 2));
if (b.Addr.X < m)
{
mint_t = Math.Min(mint_t, Math.Abs(y - n));
}
else if (b.Addr.Y < n)
{
mint_t = Math.Min(mint_t, Math.Abs(x - m));
}
if (min_2 != -1)
{
if ((x < p.Addr.X + p.Width / 2) && (y < p.Addr.Y + p.Height / 2))
{
min_2 = -1;
break;
}
else
{
if (mint_t < min_2)
{
min_2 = mint_t;
}
}
}
else
{
if ((x < p.Addr.X + p.Width / 2) && (y < p.Addr.Y + p.Height / 2))
{
min_2 = -1;
break;
}
else
{
min_2 = mint_t;
}
}
}
return min_2;
}
else if ((b.Addr.X <= p.Addr.X - p.Width / 2 + b.Radius) && (b.Addr.Y > p.Addr.Y + p.Height / 2 - b.Radius)) //第一象域
{
for (int rad_t = 0; rad_t <= 90; rad_t++)
{
double x = b.Addr.X + b.Radius * Math.Cos(Math.PI * rad_t / 180);
double y = b.Addr.Y - b.Radius * Math.Sin(Math.PI * rad_t / 180); //算出球边沿的坐标
double m = p.Addr.X - p.Width / 2;
double n = p.Addr.Y + p.Height / 2;
double mint_t = Math.Sqrt(Math.Pow(m - x, 2) + Math.Pow(n - y, 2));
if (b.Addr.X > m)
{
mint_t = Math.Min(mint_t, Math.Abs(y - n));
}
else if (b.Addr.Y < n)
{
mint_t = Math.Min(mint_t, Math.Abs(x - m));
}
if (min_1 != -1)
{
if ((x > p.Addr.X - p.Width / 2) && (y < p.Addr.Y + p.Height / 2))
{
min_1 = -1;
break;
}
else
{
if (mint_t < min_1)
{
min_1 = mint_t;
}
}
}
else
{
if ((x >p.Addr.X - p.Width / 2) && (y < p.Addr.Y + p.Height / 2))
{
min_1 = -1;
break;
}
else
{
min_1 = mint_t;
}
}
}
return min_1;
}
return -98;
}
}