如何缩放映射到调整大小图片的多边形

时间:2011-09-29 10:54:36

标签: vb.net scaling hittest point-in-polygon

我正在开始一个飞镖计分程序(在我的飞镖室使用自己),并希望用户能够点击飞镖板图片的不同区域来注册投掷的飞镖。

此程序可调整大小,因此当用户更改程序窗口大小时,飞镖板的图片可以改变它的大小。

我使用多边形列表(pointF-arrays)来映射每个区域并运行一些计算以查看鼠标单击是否在多边形区域内,但是如何在调整图片框大小时正确缩放这些多边形?我的多边形是硬编码的,用于以特定尺寸映射图片的飞镖区域。

enter image description here

编辑:在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

1 个答案:

答案 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)