C#判断一个球体和矩形最短距离

2 篇文章 0 订阅

主要判断球体和矩形边沿最短举例,
申明类:

/// <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; 
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

火狐鞥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值