我正在开始一个飞镖计分程序(在我的飞镖室使用自己),并希望用户能够点击飞镖板图片的不同区域来注册投掷的飞镖。
此程序可调整大小,因此当用户更改程序窗口大小时,飞镖板的图片可以改变它的大小。
我使用多边形列表(pointF-arrays)来映射每个区域并运行一些计算以查看鼠标单击是否在多边形区域内,但是如何在调整图片框大小时正确缩放这些多边形?我的多边形是硬编码的,用于以特定尺寸映射图片的飞镖区域。
编辑:在Olivier Jacot-Descombes的精彩答案之后,我使用GetScaledPoint函数修复了缩放,该函数将鼠标指针x和y值转换为与原始图片大小相匹配的值,很容易检查原始多边形中的命中。如果有人有兴趣,我已经在下面的代码中编辑了解决方案。在这个例子中,Picture1是一个飞镖板的图片(像这个http://quizmasters.biz/Pub%20Genius/Darts/Gfx/Dartboard_05.jpg),设置为sizemode = stretch和docking = fill。
Public Class DartBoard
Dim Double20 = New PointF() {New PointF(263, 78), New PointF(275, 76), New PointF(284, 76), New PointF(293, 75), New PointF(306, 75), New PointF(319, 75), New PointF(332, 76), New PointF(330, 89), New PointF(320, 88), New PointF(309, 87), New PointF(300, 87), New PointF(289, 88), New PointF(277, 89), New PointF(267, 91), New PointF(264, 78)}
Dim Triple20 = New PointF() {New PointF(279, 154), New PointF(285, 154), New PointF(293, 154), New PointF(301, 152), New PointF(306, 152), New PointF(312, 152), New PointF(314, 151), New PointF(322, 152), New PointF(320, 167), New PointF(312, 165), New PointF(304, 164), New PointF(297, 165), New PointF(289, 166), New PointF(281, 166), New PointF(277, 154), New PointF(283, 153), New PointF(291, 153), New PointF(299, 152), New PointF(308, 152), New PointF(314, 153), New PointF(322, 153)}
Private startwidth As Integer = 0
Private startheight As Integer = 0
Public Structure DartBoardAreaStruct
Public Points As Integer
Public Area() As PointF
End Structure
Dim DartBoardAreas As New List(Of DartBoardAreaStruct)
Private Sub DartBoard_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
DartBoardAreas.Add(New DartBoardAreaStruct With {.Area = Double20, .Points = 40})
DartBoardAreas.Add(New DartBoardAreaStruct With {.Area = Triple20, .Points = 60})
startwidth = PictureBox1.Width
startheight = PictureBox1.Height
End Sub
Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
Dim scaledpos As PointF = GetScaledPoint(e.Location)
For Each DartBoardArea In DartBoardAreas
If Me.PolyGonHitTest(DartBoardArea.Area, scaledpos) Then
MsgBox(DartBoardArea.Points)
End If
Next
End Sub
Public Function PolyGonHitTest(ByVal polygonPoints() As PointF, ByVal mousePos As PointF) As Boolean
Dim path As New System.Drawing.Drawing2D.GraphicsPath
path.AddLines(polygonPoints)
Dim region As New Region(path)
If region.IsVisible(mousePos) Then Return True
Return False
End Function
Function GetScaledPoint(ByVal s As Point) As PointF
Dim xfactor As Double = 0
Dim yfactor As Double = 0
Dim OriginalSize As Size = New Size(startwidth, startheight)
Dim NewSize As Size = New Size(PictureBox1.Width, PictureBox1.Height)
If NewSize.Width < OriginalSize.Width Then
xfactor = OriginalSize.Width / NewSize.Width
Else
xfactor = NewSize.Width / OriginalSize.Width
End If
If NewSize.Height < OriginalSize.Height Then
yfactor = OriginalSize.Height / NewSize.Height
Else
yfactor = NewSize.Height / OriginalSize.Height
End If
Return New PointF(s.X / xfactor, s.Y / yfactor)
End Function
End Class
答案 0 :(得分:1)
简单快速的解决方案是保持多边形不变,但要缩放鼠标坐标。例如,您可以在0.0f和1.0f之间使用多边形坐标,并缩放鼠标坐标,如:
xScaled As Single = e.X/DartBoardArea.Width
yScaled As Single = e.Y/DartBoardArea.Height
scaledPos As PointF = new PointF(xScaled, yScaled)