到目前为止,我所知道的关于矢量投影的一切都来自互联网,所以我有点困惑。首先,我假设当我们将多边形的顶点投影到轴上时,我们得到标量投影而不是矢量投影。其公式为(A.B)/ | A |,现在在this tutorial中,它们只是使用点积投影到轴上。这是因为矢量和轴是垂直的还是什么?尽管如此,我还是想在C#中编写一个粗略的版本,但它似乎没有返回正确的结果
Rectangle r1 = new Rectangle(300, 200, 50, 50);
Rectangle r2 = new Rectangle(340, 240, 50, 50);
bool areColliding(Rectangle r1, Rectangle r2)
{
/* Using clockwise labelling
*
* B*
* . .
* . .
* A * C*
* . .
* . .
* D*
*
*/
//Calculate vectors and normals of Rectangle 1
Point r1A = r1.Location;
Point r1B = new Point(r1.Location.X + r1.Width, r1.Location.Y);
Point r1C = new Point(r1.Location.X, r1.Location.Y + r1.Height);
Point r1D = new Point(r1.Location.X + r1.Width, r1.Location.Y + r1.Height);
Vector2 r1AB = new Vector2(r1B.X - r1A.X, r1B.Y - r1A.Y);
Vector2 r1BC = new Vector2(r1C.X - r1B.X, r1C.Y - r1B.Y);
Vector2 r1CD = new Vector2(r1D.X - r1C.X, r1D.Y - r1C.Y);
Vector2 r1DA = new Vector2(r1A.X - r1D.X, r1A.Y - r1D.Y);
Vector2 r1AB_Normal = getNormal(r1AB);
Vector2 r1BC_Normal = getNormal(r1BC);
Vector2 r1CD_Normal = getNormal(r1CD);
Vector2 r1DA_Normal = getNormal(r1DA);
Point[] r1Points = {r1A, r1B, r1C, r1D};
Vector2[] Axes1 = { r1AB_Normal, r1BC_Normal, r1CD_Normal, r1DA_Normal };
//Calculate vectors and normals of Rectangle 2
Point r2A = r2.Location;
Point r2B = new Point(r2.Location.X + r2.Width, r2.Location.Y);
Point r2C = new Point(r2.Location.X, r2.Location.Y + r2.Height);
Point r2D = new Point(r2.Location.X + r2.Width, r2.Location.Y + r2.Height);
Vector2 r2AB = new Vector2(r2B.X - r2A.X, r2B.Y - r2A.Y);
Vector2 r2BC = new Vector2(r2C.X - r2B.X, r2C.Y - r2B.Y);
Vector2 r2CD = new Vector2(r2D.X - r2C.X, r2D.Y - r2C.Y);
Vector2 r2DA = new Vector2(r2A.X - r2D.X, r2A.Y - r2D.Y);
Vector2 r2AB_Normal = getNormal(r2AB);
Vector2 r2BC_Normal = getNormal(r2BC);
Vector2 r2CD_Normal = getNormal(r2CD);
Vector2 r2DA_Normal = getNormal(r2DA);
Point[] r2Points = { r2A, r2B, r2C, r2D };
Vector2[] Axes2 = { r2AB_Normal, r2BC_Normal, r2CD_Normal, r2DA_Normal };
//Start projecting each vertex on to each axis
for (int i = 0; i < Axes1.Length; i++)
{
float r1Min = Vector2.Dot(Axes1[i], new Vector2(r1Points[0].X, r1Points[0].Y));
float r1Max = float.NaN;
for (int p = 1; p < r1Points.Length; p++)
{
float dot = Vector2.Dot(Axes1[i], new Vector2(r1Points[p].X, r1Points[p].Y));
if (dot < r1Min)
{
r1Min = dot;
}
}
float r2Min = Vector2.Dot(Axes1[i], new Vector2(r1Points[0].X, r1Points[0].Y));
float r2Max = float.NaN;
for (int p = 1; p < r2Points.Length; p++)
{
float dot = Vector2.Dot(Axes1[i], new Vector2(r1Points[p].X, r1Points[p].Y));
if (dot < r2Min)
{
r2Min = dot;
}
}
if (r1Min < r2Max)
{
return true;
}
}
for (int i = 0; i < Axes2.Length; i++)
{
float r1Min = Vector2.Dot(Axes1[i], new Vector2(r1Points[0].X, r1Points[0].Y));
float r1Max = float.NaN;
for (int p = 1; p < r1Points.Length; p++)
{
float dot = Vector2.Dot(Axes1[i], new Vector2(r1Points[p].X, r1Points[p].Y));
if (dot < r1Min)
{
r1Min = dot;
}
}
float r2Min = Vector2.Dot(Axes1[i], new Vector2(r1Points[0].X, r1Points[0].Y));
float r2Max = float.NaN;
for (int p = 1; p < r2Points.Length; p++)
{
float dot = Vector2.Dot(Axes1[i], new Vector2(r1Points[p].X, r1Points[p].Y));
if (dot < r2Min)
{
r2Min = dot;
}
}
if (r1Min < r2Max)
{
return true;
}
}
return false;
}
Vector2 getNormal(Vector2 v)
{
return new Vector2(-v.Y, v.X);
}