图形碰撞检测 圆与矩形

先建立我们需要的数据模型:

1. 向量:

  1 /**
  2      * 向量类,默认使用正交基
  3      */
  4     public class SHVector
  5     {
  6         public var x:Number;
  7         public var y:Number;
  8         public var z:Number;
  9
 10         /**
 11          * 构造函数
 12          */
 13         public function SHVector(x:Number, y:Number, z:Number = 0)
 14         {
 15             this.x = x;
 16             this.y = y;
 17             this.z = z;
 18         }
 19
 20         /**
 21          * 向量的模
 22          */
 23         public function model():Number
 24         {
 25             return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
 26         }
 27
 28         /**
 29          * 加法
 30          */
 31         public function add(vector:SHVector):SHVector
 32         {
 33             return new SHVector(
 34                 this.x + vector.x,
 35                 this.y + vector.y,
 36                 this.z + vector.z
 37             );
 38         }
 39
 40         /**
 41          * 减法
 42          */
 43         public function sub(vector:SHVector, reverse:Boolean = false):SHVector
 44         {
 45             if (!reverse) {
 46                 return new SHVector(
 47                     this.x - vector.x,
 48                     this.y - vector.y,
 49                     this.z - vector.z
 50                 );
 51             }
 52             else {
 53                 return new SHVector(
 54                     vector.x - this.x,
 55                     vector.y - this.y,
 56                     vector.z - this.z
 57                 );
 58             }
 59         }
 60
 61         /**
 62          * 点乘(内积)
 63          */
 64         public function dot(vector:SHVector):Number
 65         {
 66             return this.x * vector.x + this.y * vector.y + this.z * vector.z;
 67         }
 68
 69         /**
 70          * 叉乘(外积)
 71          */
 72         public function cross(vector:SHVector):SHVector
 73         {
 74             var resultVector:SHVector = new SHVector(
 75                 this.y * vector.z - this.z * vector.y,
 76                 this.z * vector.x - this.x * vector.z,
 77                 this.x * vector.y - this.y * vector.x
 78             );
 79
 80             return resultVector;
 81         }
 82
 83         /**
 84          * 求两条向量的夹角,以弧度为单位
 85          */
 86         public function angle(vector:SHVector):Number
 87         {
 88             if (this.model() == 0 ||
 89                 vector.model() == 0)
 90                 return 0;
 91
 92             return Math.acos(this.dot(vector) / (this.model() * vector.model()));
 93         }
 94
 95         /**
 96          * 对象信息
 97          */
 98         public function toString():String
 99         {
100             return "x:" + this.x + "," +
101                    "y:" + this.y + "," +
102                    "z:" + this.z + "," +
103                    "model:" + this.model();
104         }

2. 圆:

 1 /**
 2      * 圆形类
 3      */
 4     public class SHCircle extends RigidityObject
 5     {
 6         public var r:Number;
 7
 8         public var vector:SHVector;
 9
10         /**
11          * 构造函数
12          */
13         public function SHCircle(x:Number, y:Number, r:Number)
14         {
15             super();
16
17             this.x = x;
18             this.y = y;
19             this.r = r;
20
21             this.vector = new SHVector(x, y);
22
23             this.leftBorder = this.x - this.r;
24             this.rightBorder = this.x + this.r;
25             this.topBorder = this.y - this.r;
26             this.bottomBorder = this.y + this.r;
27
28             this.draw();
29         }
30
31         /**
32          * 更新
33          */
34         override public function update():void
35         {
36             this.x += this.speedX;
37             this.y += this.speedY;
38
39             this.vector.x = this.x;
40             this.vector.y = this.y;
41
42             this.leftBorder = this.x - this.r;
43             this.rightBorder = this.x + this.r;
44             this.topBorder = this.y - this.r;
45             this.bottomBorder = this.y + this.r;
46         }
47
48         /**
49          * 绘制
50          */
51         override protected function draw():void
52         {
53             this.graphics.clear();
54             this.graphics.lineStyle(1, 0x000000);
55             this.graphics.drawCircle(this.x, this.y, this.r);
56         }
57     }

3. 矩形:

 1 /**
 2      * 矩形类
 3      */
 4     public class SHRect extends RigidityObject
 5     {
 6         public var vx1:Number;
 7         public var vy1:Number;
 8         public var vx2:Number;
 9         public var vy2:Number;
10         public var vx3:Number;
11         public var vy3:Number;
12         public var vx4:Number;
13         public var vy4:Number;
14
15         public var vector1:SHVector;
16         public var vector2:SHVector;
17         public var vector3:SHVector;
18         public var vector4:SHVector;
19
20         /**
21          * 构造函数
22          */
23         public function SHRect(vx1:Number, vy1:Number, vx2:Number, vy2:Number, vx3:Number, vy3:Number, vx4:Number, vy4:Number)
24         {
25             super();
26
27             this.vx1 = vx1;
28             this.vy1 = vy1;
29             this.vx2 = vx2;
30             this.vy2 = vy2;
31             this.vx3 = vx3;
32             this.vy3 = vy3;
33             this.vx4 = vx4;
34             this.vy4 = vy4;
35
36             this.vector1 = new SHVector(vx1, vy1);
37             this.vector2 = new SHVector(vx2, vy2);
38             this.vector3 = new SHVector(vx3, vy3);
39             this.vector4 = new SHVector(vx4, vy4);
40
41             this.leftBorder = this.x + vx1;
42             this.rightBorder = this.x + vx2;
43             this.topBorder = this.y + vy1;
44             this.bottomBorder = this.y + vy3;
45
46             this.draw();
47         }
48
49         /**
50          * 更新
51          */
52         override public function update():void
53         {
54             this.x += this.speedX;
55             this.y += this.speedY;
56
57             this.vector1.x = this.x + this.vx1;
58             this.vector1.y = this.y + this.vy1;
59             this.vector2.x = this.x + this.vx2;
60             this.vector2.y = this.y + this.vy2;
61             this.vector3.x = this.x + this.vx3;
62             this.vector3.y = this.y + this.vy3;
63             this.vector4.x = this.x + this.vx4;
64             this.vector4.y = this.y + this.vy4;
65
66             this.leftBorder = this.x + this.vx1;
67             this.rightBorder = this.x + this.vx2;
68             this.topBorder = this.y + this.vy1;
69             this.bottomBorder = this.y + this.vy3;
70         }
71
72         /**
73          * 绘制
74          */
75         override protected function draw():void
76         {
77             this.graphics.clear();
78             this.graphics.lineStyle(1, 0x000000);
79             this.graphics.moveTo(this.vx1, this.vy1);
80             this.graphics.lineTo(this.vx2, this.vy2);
81             this.graphics.lineTo(this.vx3, this.vy3);
82             this.graphics.lineTo(this.vx4, this.vy4);
83             this.graphics.lineTo(this.vx1, this.vy1);
84         }
85     }

 

  为了更清楚的说明矩形和圆的是否相交的情况,先绘制一张图形:

  从图中可以看出圆和矩形位置的三种情况:

  1. 完全不相交:圆形的位置在左上角的两条灰色直线左方,这种情况的判断方式可以通过计算圆心到两条红色直线的距离来得到,图中的黑色箭头实线就代表距离d1和d2,假如我们知道矩形的长是w,宽是h,圆的半径r:

  那么只要满足d1 > r + w / 2 或者 d2 > r + h / 2,圆和矩形就必然不会相交。我们通常会首先使用这个条件进行判断,得出是否肯定不相交的结论。如果这个判断失败,那么圆和矩形有可能相交但也可能不相交(从图中可以清楚看出),我们就需要进行接下来两种情况的判断。

  注:两条红色直线是穿过矩形中心,并分别与矩形的长宽边平行的直线,我们知道矩形中心坐标,和两边的中点坐标就可以得出这两条直线的方程。因为我们知道了矩形4个顶点的坐标,很容易就可以求的矩形中心点和矩形边中点的坐标;

  2. 圆与矩形的边相交:在通过了情况1的验证后,只要满足d1 <= w / 2 或者 d2 <= h / 2,就表明了圆和矩形的某条边一定相交了;

  3. 圆与矩形的顶点相交:如果情况2判断失败,就只剩下和顶点相交的情况了,这个判断很简单,只需要计算圆心到4个顶点的距离是否小于半径r即可;

具体实现:

 1 /**
 2          * 求出点到某条直线的距离
 3          */
 4         static public function computeDistanceBetweenPointAndLine(x:Number, y:Number, x1:Number, y1:Number, x2:Number, y2:Number):Number
 5         {
 6             var a:Number = y2 - y1;
 7             var b:Number = x1 - x2;
 8             var c:Number = x2 * y1 - x1 * y2;
 9
10             return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b);
11         }
12         /**
13          * 检测圆和矩形的相交
14          */
15         static public function detectCircleAndRectCollision(circle:SHCircle, rect:SHRect):Boolean
16         {
17             var ABLength:Number = (rect.vector2.sub(rect.vector1)).model(); // 求AB边的长度
18             var DALength:Number = (rect.vector1.sub(rect.vector4)).model(); // 求AD边的长度
19             var halfABLength:Number = ABLength / 2;
20             var halfDALength:Number = DALength / 2;
21
22             var vectorAB:SHVector = rect.vector2.sub(rect.vector1);
23             var vectorAC:SHVector = rect.vector3.sub(rect.vector1);
24             var vectorAD:SHVector = rect.vector4.sub(rect.vector1);
25
26             // 矩形中心坐标
27             var rectCenterX:Number = rect.x + vectorAC.x / 2;
28             var rectCenterY:Number = rect.y + vectorAC.y / 2;
29             // AB边的中点坐标
30             var ABCenterX:Number = rect.x + vectorAB.x / 2;
31             var ABCenterY:Number = rect.y + vectorAB.y / 2;
32             // AD边的中点坐标
33             var ADCenterX:Number = rect.x + vectorAD.x / 2;
34             var ADCenterY:Number = rect.y + vectorAD.y / 2;
35
36             // 圆心到两条直线的距离
37             var d1:Number = CollisionDetectionUtil.computeDistanceBetweenPointAndLine(circle.x, circle.y, rectCenterX, rectCenterY, ADCenterX, ADCenterY);
38             if (d1 > (halfDALength + circle.r))
39                 return false;
40             var d2:Number = CollisionDetectionUtil.computeDistanceBetweenPointAndLine(circle.x, circle.y, rectCenterX, rectCenterY, ABCenterX, ABCenterY);
41             if (d2 > (halfABLength + circle.r))
42                 return false;
43
44             trace(d1, halfDALength);
45             trace(d2, halfABLength);
46
47             // 与矩形某条边相交
48             if ((d1 <= halfDALength) ||
49                 (d2 <= halfABLength))
50                 return true;
51
52             trace(circle.vector.sub(rect.vector1).model());
53             trace(circle.vector.sub(rect.vector2).model());
54             trace(circle.vector.sub(rect.vector3).model());
55             trace(circle.vector.sub(rect.vector4).model());
56
57             // 与矩形顶点相交
58             if (circle.vector.sub(rect.vector1).model() <= circle.r ||
59                 circle.vector.sub(rect.vector2).model() <= circle.r ||
60                 circle.vector.sub(rect.vector3).model() <= circle.r ||
61                 circle.vector.sub(rect.vector4).model() <= circle.r)
62                 return true;
63
64             return false;
65         }

  

时间: 2024-11-08 17:21:29

图形碰撞检测 圆与矩形的相关文章

iOS:quartz2D绘图(画一些简单的图形,如直线、三角形、圆、矩形、文字等)

前一篇几乎已经详细介绍了Quartz2D的所有知识,这一篇以及后面就不废话了,主要是用具体的实例来演示绘图效果. 这里我们先来绘制一些简单的图形(如直线.三角形.圆.矩形.文字.图像),它有两种方式可以绘制,一种是通过上下文绘制,另一种是通过路径绘制.下面对绘制三角形做了一个两种方式绘制的演示. 绘制基本的图形,需要在操作的视图类中重写- (void)drawRect:(CGRect)rect方法,并在在该方法中绘制图形.绘制图像既可以重写该方法绘制,也可以不用重写该方法,它有封装好的方法.这里

圆与矩形碰撞检测

圆与矩形的碰撞检测,假设矩形中心点v0, 上边中心点v1, 右边中心点v2, 圆心v, 圆半径r, 矩形半宽w1, 矩形半高h1,.v0为矩形的坐标系原点,(v0,v2)为矩形坐标系x轴,(v0,v1)为矩形坐标系y轴,圆心到矩形y轴距离为w2, 圆心到矩形x轴距离为h2,如图所示: 根据图示可以很容易的写出圆与矩形的碰撞检测算法: 圆与矩形碰撞检测

MFC 直线 虚线 折线 圆 椭圆 矩形 弧形

****Dlg.h头文件添加: //为工程添加画笔.点变量数组 public: CPen m_pen[5]; CPoint m_point[5]; public: void DrawLine(CDC *pDC); void DrawPolyline(CDC *pDC); void DrawPolygon(CDC *pDC); void DrawRect(CDC *pDC); void DrawRoundRect(CDC *pDC); void DrawEllipse(CDC *pDC); voi

判断圆和矩形是否相交(非面积相交)

月赛题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=1165 题解. 问题很简单,给你一个矩形和一个圆,问你是否他们相交.注意,这里的相交不是面积相交.也就是说,圆在矩形内(且不相切)是不相交的.或者矩形在圆内(且矩形的四个点不在圆上)也是不相交的. 那么,我们怎么来判断呢? 中间轮廓线是矩形的边,各向外和内距离为圆半径r划线(当然,四个角的肯定不太标准). 如果圆心在红色区域的话,肯定是会与圆相交了... 当然,如果我们根本画不出来这

ArcGIS Engine 开发(二)线、圆、矩形、面、文本编辑功能

ArcGIS Engine 开发(二)线.圆.矩形.面.文本编辑功能,这些都是实现课上的源代码,自己调试好了,直接可以放到vs2010下跑,希望能对大家有所帮助 好了,先来看效果 二.下面是调试好的代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using Syste

数学图形之圆柱面

(1)圆柱面 vertices = dimension1:72 dimension2:72 u = from 0 to (2*PI) dimension1 v = from (-5) to (5) dimension2 r = 5 x = r*cos(u) y = v z = r*sin(u) (2)任意角度圆柱面 vertices = dimension1:72 dimension2:72 u = from (-5) to (5) dimension2 v = from 0 to (2*PI)

Android Shape画圆,矩形

画圆环代码如下: 画圆环,外边的边界宽度大一点即可: <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="false" > <solid and

opencv画直线圆椭圆矩形

今天看到以前写的简单的小程序,突然想整理一下,希望对大家有用 #include <cv.h> #include <highgui.h> #pragma comment(lib, "cv.lib") #pragma comment(lib, "cxcore.lib") #pragma comment(lib, "highgui.lib") int main() { CvMat* srcMat1; CvMat* srcMat2

图形碰撞检测 点与三角形

点与三角形的碰撞检测有很多方法,基本思想都是使用向量,利用向量之间的关系得出一些数据,然后利用这些数据进行判断.为了完成目的,我们先要建立基本的数据模型(代码使用的语言是ActionScrpit): 1. 向量类: 1 /** 2 * 向量类,默认使用正交基 3 */ 4 public class SHVector 5 { 6 public var x:Number; 7 public var y:Number; 8 public var z:Number; 9 10 /** 11 * 构造函数