【计算机图形学/Unity游戏开发】判断圆与矩形是否相交(SC-102-L06课后习题 2)

视频链接:【银鸟工作室课程】SC-102 Unity游戏开发 I 第六课:程序化物理

SC-102 第六课:程序化物理 课后习题 2

题目:编写一个判断圆与矩形是否相交的函数。


首先将问题拆解简化为:圆与矩形的四条边是否相交。显然,若至少存在一条与圆相交的边,则该矩形也相交。特别地,若四条边都不相交,此时有可能是矩形完全包含圆,需要特别判断。

接下来,从理论上分析如何判断圆与线段是否相交(默认已知:线段端点和圆心坐标、圆半径)。

  1. 线段所在直线与圆心的距离大于半径。【相离】
    在这里插入图片描述

    两点式直线方程: x − x 1 x 1 − x 2 = y − y 1 y 1 − y 2 \frac{x-x_1}{x_1-x_2}=\frac{y-y_1}{y_1-y_2} x1x2xx1=y1y2yy1,转换为一般直线方程( y = k x + b y=kx+b y=kx+b):
    Y a b = y 1 − y 2 x 1 − x 2 x + x 1 y 2 − x 2 y 1 x 1 − x 2 Y_{ab}=\frac{y_1-y_2}{x_1-x_2}x+\frac{x_1y_2-x_2y_1}{x_1-x_2} Yab=x1x2y1y2x+x1x2x1y2x2y1
    根据点到直线的距离公式:
    d = ∣ k x 0 − y 0 + b ∣ k 2 + 1 d=\frac{\left|kx_0-y_0+b\right|}{\sqrt{k^2+1}} d=k2+1 kx0y0+b
    判断出距离 d d d 大于半径 r r r,说明该线段一定在圆的外部

    注意:当 A B AB AB 与 y 轴平行时(即上图所示),此时方程应为 x = x 1 x=x_1 x=x1,而距离则是 ∣ x 1 − x 0 ∣ |x_1-x_0| x1x0,需要在此特判

  2. 线段所在直线与圆心的距离小于半径。【不确定】
    2.1 线段存在至少一个端点与圆心距离小于半径。【相交】
    在这里插入图片描述

    通过两点距离公式: d = ( x 1 − x 0 ) 2 + ( y 1 − y 0 ) 2 d=\sqrt{(x_1-x_0)^2+(y_1-y_0)^2} d=(x1x0)2+(y1y0)2 分别计算 A A A B B B 与圆心 C C C 的距离,再与半径比较,判断出存在一个小于的,则该线段与圆相交(或被圆完全包含)

    2.2 线段两个端点都在圆外。【不确定】
    2.2.1 两个端点都在以“圆心到线段的垂线”为分割线的同一侧。【相离】
    在这里插入图片描述

    根据端点所在直线的斜率 k a b k_{ab} kab,得到垂线的斜率 k c d = − 1 k a b k_{cd}=-\frac{1}{k_{ab}} kcd=kab1,于是垂线方向上的向量可为: C D → = ( 1 , k c d ) \overrightarrow{CD}=(1,k_{cd}) CD =(1,kcd),然后将其分别与 C B → \overrightarrow{CB} CB C A → \overrightarrow{CA} CA 叉乘,若叉乘结果的 z 轴分量同号,则说明两个端点在同一侧,则线段与圆相离。

    注意:当 A B AB AB 垂直时其斜率未定义(可理解为无穷大),此时直接将 C D CD CD 的斜率赋值为 0 即可;当 A B AB AB 水平时其斜率为 0,应该规避“除以 0”,此时 C D → \overrightarrow{CD} CD 的方向即为 y 轴方向,因此直接将其赋值为 ( 0 , 1 ) (0,1) (0,1),故需要在此特判。

    此外,值得注意的是, C D → \overrightarrow{CD} CD 的方向即可以是沿垂线正方向指向 A B AB AB 所在的直线,也可以沿垂线反方向背指直线。因为我们关心的是两个结果是否异号,而正反方向并不会影响这一特性,它们在逻辑上都一致地将空间按垂线分为两部分。

    叉乘可用于判断向量间的左右关系,例如:在判断点是否在三角形内部时可利用该特性

    2.2.2 两个端点在以“圆心到线段的垂线”为分割线的两侧。【相交】
    在这里插入图片描述

    若叉乘结果的 z 轴分量异号,则说明两个端点在两侧,则线段与圆相交。

计算完四条边与圆的关系后,若四条边均与圆相离(更准确来说,应都是第 1 种情况的相离),需要特判矩形是否“完全包含”圆:

此时判断圆心是否在矩形内即可,方法应该有很多,这里我使用一种比较偷懒的方法,就是按矩形的对角线将其分割为两个三角形,再判断圆心是否在其中的一个三角形内部(复用了习题 1 的方法)。

在这里插入图片描述
Unity 程序实现脚本文件包链接:https://github.com/Hocchi01/SilverjayCoursesExercises/blob/main/SC-102-6/SC-102-6-2.unitypackage

最终效果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值