我正在尝试查看图像框是否与e图形线交互。 我当前的代码:
e.Graphics.DrawLine(SystemPens.ButtonShadow, a, b);
if (pictureBox1.Bounds.IntersectsWith(e.GraphicsLine.Bounds))
{
dead();
}
我不确定该怎么做。
答案 0 :(得分:2)
要测试矩形和直线的交点,您可以使用Wikipedia文章中的许多方法之一,也可以使用涉及GraphicsPaths
和Regions
的GDI +技巧..:
using System.Drawing.Drawing2D;
..
bool Intersects(Point a, Point b, Rectangle r)
{
if (Math.Min(a.X, b.X) > r.Right) return false; // *
if (Math.Max(a.X, b.X) < r.Left) return false; // *
if (Math.Min(a.Y, b.Y) > r.Bottom) return false; // *
if (Math.Max(a.Y, b.Y) < r.Top) return false; // *
if (r.Contains(a)) return true; // **
if (r.Contains(b)) return true; // **
using (GraphicsPath gp = new GraphicsPath())
using (Pen pen = new Pen(Color.Empty, 0.5f))
using (Region reg = new Region(r))
using (Graphics g = CreateGraphics())
{
gp.AddLine(a,b);
gp.Widen(pen); // we need to widen the line path just a little
reg.Intersect(gp);
if (reg.IsEmpty(g)) return false;
}
return true;
}
这是一个小的测试结果:
由于Region.IsEmpty
可能不是很快,所以我在通话前进行了一些琐碎的测试,以提高速度。有关区域see here的性能问题的讨论。从这一点上,我猜可以得出一个结论,即用一个简单的矩形进行测试实际上仍然会相当快。
对于真正快速的测试,您可能需要实现真正的限幅方法。 This looks nice ..
但是与该分析方法相比,该地区的GDI +技巧有一个很大的优势:我将处理可以放入GraphicsPath
的任何形状,包括圆形,椭圆形,多边形,各种组合以及复杂的形状跟踪路径。并且由于Region
支持所有设置操作,因此您的想象力是极限。
这使您可以测试飞船或怪物的复杂形状;还有一些其他技巧,您甚至可以测试旋转的形状。
请注意,如果您要测试复杂的形状,则需要:
GraphicsPath
gp.GetBounds()
)这里是相同的示例,只是用椭圆代替矩形:
答案 1 :(得分:2)
您在这里。原始代码在C中,我翻译为vb.net。该代码适用于直线和矩形。
'//min_clip_x is the distance of the left side of rect
'//min_clip_y is the distance of the upper side of rect
'//max_clip_x is the distance of the right side of rect
'//min_clip_y is the distance of the down side of rect
Private Function Clip_Line(ByVal x1 As Integer, ByVal y1 As Integer, ByVal x2 As Integer, ByVal y2 As Integer,
ByVal min_clip_x As Integer, ByVal max_clip_x As Integer, ByVal min_clip_y As Integer,
ByVal max_clip_y As Integer) As Boolean
Const CLIP_CODE_C As Integer = 0
Const CLIP_CODE_N As Integer = 8
Const CLIP_CODE_S As Integer = 4
Const CLIP_CODE_E As Integer = 2
Const CLIP_CODE_W As Integer = 1
Const CLIP_CODE_NE As Integer = 10
Const CLIP_CODE_SE As Integer = 6
Const CLIP_CODE_NW As Integer = 9
Const CLIP_CODE_SW As Integer = 5
Dim p1_code As Integer = 0
Dim p2_code As Integer = 0
Dim xc1, yc1, xc2, yc2 As Integer
xc1 = x1
yc1 = y1
xc2 = x2
yc2 = y2
'//determine codes for p1 And p2
If y1 < min_clip_y Then
p1_code = p1_code Or CLIP_CODE_N
Else
If y1 > max_clip_y Then
p1_code = p1_code Or CLIP_CODE_S
End If
End If
If (x1 < min_clip_x) Then
p1_code = p1_code Or CLIP_CODE_W
Else
If (x1 > max_clip_x) Then
p1_code = p1_code Or CLIP_CODE_E
End If
End If
If (y2 < min_clip_y) Then
p2_code = p2_code Or CLIP_CODE_N
Else
If (y2 > max_clip_y) Then
p2_code = p2_code Or CLIP_CODE_S
End If
End If
If (x2 < min_clip_x) Then
p2_code = p2_code Or CLIP_CODE_W
Else
If (x2 > max_clip_x) Then
p2_code = p2_code Or CLIP_CODE_E
End If
End If
'//try And trivially reject
If CBool(p1_code And p2_code) Then
Return False
End If
'//test for totally visible, if so leave points untouched
If (p1_code = 0 And p2_code = 0) Then
Return True
End If
'//determine end clip point for p1
Select Case p1_code
Case CLIP_CODE_C
Exit Select
Case CLIP_CODE_N
yc1 = min_clip_y
xc1 = CInt(x1 + 0.5 + (min_clip_y - y1) * (x2 - x1) / (y2 - y1))
Exit Select
Case CLIP_CODE_S
yc1 = max_clip_y
xc1 = CInt(x1 + 0.5 + (max_clip_y - y1) * (x2 - x1) / (y2 - y1))
Exit Select
Case CLIP_CODE_W
xc1 = min_clip_x
yc1 = CInt(y1 + 0.5 + (min_clip_x - x1) * (y2 - y1) / (x2 - x1))
Exit Select
Case CLIP_CODE_E
xc1 = max_clip_x
yc1 = CInt(y1 + 0.5 + (max_clip_x - x1) * (y2 - y1) / (x2 - x1))
Exit Select
Case CLIP_CODE_NE
'//north hline intersection
yc1 = min_clip_y
xc1 = CInt(x1 + 0.5 + (min_clip_y - y1) * (x2 - x1) / (y2 - y1))
'//test if intersection Is valid,
'//if so then done, else compute next
If (xc1 < min_clip_x) Or (xc1 > max_clip_x) Then
'//east vline intersection
xc1 = max_clip_x
yc1 = CInt(y1 + 0.5 + (max_clip_x - x1) * (y2 - y1) / (x2 - x1))
End If
Exit Select
Case CLIP_CODE_SE
'//south hline intersection
yc1 = max_clip_y
xc1 = CInt(x1 + 0.5 + (max_clip_y - y1) * (x2 - x1) / (y2 - y1))
'//test if intersection Is valid,
'//if so then done, else compute next
If (xc1 < min_clip_x) Or (xc1 > max_clip_x) Then
'//east vline intersection
xc1 = max_clip_x
yc1 = CInt(y1 + 0.5 + (max_clip_x - x1) * (y2 - y1) / (x2 - x1))
End If
Exit Select
Case CLIP_CODE_NW
'//north hline intersection
yc1 = min_clip_y
xc1 = CInt(x1 + 0.5 + (min_clip_y - y1) * (x2 - x1) / (y2 - y1))
'//test if intersection Is valid,
'//if so then done, else compute next
If (xc1 < min_clip_x) Or (xc1 > max_clip_x) Then
xc1 = min_clip_x
yc1 = CInt(y1 + 0.5 + (min_clip_x - x1) * (y2 - y1) / (x2 - x1))
End If
Exit Select
Case CLIP_CODE_SW
'//south hline intersection
yc1 = max_clip_y
xc1 = CInt(x1 + 0.5 + (max_clip_y - y1) * (x2 - x1) / (y2 - y1))
'//test if intersection Is valid,
'//if so then done, else compute next
If (xc1 < min_clip_x) Or (xc1 > max_clip_x) Then
xc1 = min_clip_x
yc1 = CInt(CDbl(y1) + 0.5 + CDbl(min_clip_x - x1) * CDbl(y2 - y1) / CDbl(x2 - x1))
End If
Exit Select
Case Else
Exit Select
End Select
'//determine end clip point for p2
Select Case p2_code
Case CLIP_CODE_C
Exit Select
Case CLIP_CODE_N
yc2 = min_clip_y
xc2 = CInt(x2 + (min_clip_y - y2) * (x1 - x2) / (y1 - y2))
Exit Select
Case CLIP_CODE_S
yc2 = max_clip_y
xc2 = CInt(x2 + (max_clip_y - y2) * (x1 - x2) / (y1 - y2))
Exit Select
Case CLIP_CODE_W
xc2 = min_clip_x
yc2 = CInt(y2 + (min_clip_x - x2) * (y1 - y2) / (x1 - x2))
Exit Select
Case CLIP_CODE_E
xc2 = max_clip_x
yc2 = CInt(y2 + (max_clip_x - x2) * (y1 - y2) / (x1 - x2))
Exit Select
Case CLIP_CODE_NE
'//north hline intersection
yc2 = min_clip_y
xc2 = CInt(x2 + 0.5 + (min_clip_y - y2) * (x1 - x2) / (y1 - y2))
'//test if intersection Is valid,
'//if so then done, else compute next
If (xc2 < min_clip_x) Or (xc2 > max_clip_x) Then
'//east vline intersection
xc2 = max_clip_x
yc2 = CInt(y2 + 0.5 + (max_clip_x - x2) * (y1 - y2) / (x1 - x2))
End If
Exit Select
Case CLIP_CODE_SE
'//south hline intersection
yc2 = max_clip_y
xc2 = CInt(x2 + 0.5 + (max_clip_y - y2) * (x1 - x2) / (y1 - y2))
'//test if intersection Is valid,
'//if so then done, else compute next
If (xc2 < min_clip_x) Or (xc2 > max_clip_x) Then
'//east vline intersection
xc2 = max_clip_x
yc2 = CInt(y2 + 0.5 + (max_clip_x - x2) * (y1 - y2) / (x1 - x2))
End If
Exit Select
Case CLIP_CODE_NW
'//north hline intersection
yc2 = min_clip_y
xc2 = CInt(x2 + 0.5 + (min_clip_y - y2) * (x1 - x2) / (y1 - y2))
'//test if intersection Is valid,
'//if so then done, else compute next
If (xc2 < min_clip_x) Or (xc2 > max_clip_x) Then
xc2 = min_clip_x
yc2 = CInt(y2 + 0.5 + (min_clip_x - x2) * (y1 - y2) / (x1 - x2))
End If
Exit Select
Case CLIP_CODE_SW
'//south hline intersection
yc2 = max_clip_y
xc2 = CInt(x2 + 0.5 + (max_clip_y - y2) * (x1 - x2) / (y1 - y2))
'//test if intersection Is valid,
'//if so then done, else compute next
If (xc2 < min_clip_x) Or (xc2 > max_clip_x) Then
xc2 = min_clip_x
yc2 = CInt(y2 + 0.5 + (min_clip_x - x2) * (y1 - y2) / (x1 - x2))
End If
Exit Select
Case Else
Exit Select
End Select
'//do bounds check
If (xc1 < min_clip_x) Or (xc1 > max_clip_x) Or (yc1 < min_clip_y) Or (yc1 > max_clip_y) Or
(xc2 < min_clip_x) Or (xc2 > max_clip_x) Or (yc2 < min_clip_y) Or (yc2 > max_clip_y) Then
Return False '//no collision
End If
Return True '//collision
End Function