使用比例绘制和缩放矩形 [英] Drawing and scaling rectangle using a ratio

查看:92
本文介绍了使用比例绘制和缩放矩形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序,可以用鼠标在四个方向中的任何一个上绘制一个矩形.

I have a program where I can, with the mouse, draw a rectangle in any of four directions.

在PictureBox上使用这些矩形来裁剪图像的一部分.

These rectangles are used on a pictureBox to crop parts of an image.

必须在保持给定尺寸比例(例如320 x 200)的同时绘制这些矩形.

These rectangles must be drawn while maintaining the ratio of a given dimension for example 320 x 200.

我希望此工具的行为与Photoshop中的裁切工具非常相似,或者与此处的裁切示例类似: https://imageresize.org/

I want this tool to behave pretty much exactly like the crop tool in Photoshop, or like in the crop example found here: https://imageresize.org/

我的大多数元素都能正常工作,我只是在努力进行一些几何计算.

I have most elements working correctly I'm just struggling on a few geometric calculations.

请参阅我的代码中的右下"示例.效果很好,基本上我只想将此确切公式应用于其他方向.

See the "Bottom right" example in my code. This works perfectly and basically I just want to apply this exact formula to the other directions.

我几个小时以来一直在进行不同的计算,但似乎无法解决.

I have been playing with different calculations for hours and I just can't seem to work it out.

这是工作代码:

 Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
    'Draw rectangle keeping aspect ratio
    If e.Button = Windows.Forms.MouseButtons.Left Then
        If e.X > startPos.X And e.Y > startPos.Y Then
            'Bottom right
            mRect = New Rectangle(mRect.Left, mRect.Top, e.X - mRect.Left, e.Y - mRect.Top)
            mRect.Size = New Size(mRect.Width, mRect.Width / Ratio.Text)
            If e.Y < mRect.Bottom Then
                mRect = Rectangle.FromLTRB(startPos.X, startPos.Y, e.X, e.Y)
                mRect.Size = New Size(mRect.Height * Ratio.Text, mRect.Height)
            End If
            Me.Invalidate()
        ElseIf e.X < startPos.X And e.Y > startPos.Y Then
            'Bottom left
            mRect = New Rectangle(e.X, startPos.Y, startPos.X - e.X, e.Y - startPos.Y)
            mRect.Size = New Size(mRect.Width, mRect.Width / Ratio.Text)
            Me.Invalidate()
        ElseIf e.X > startPos.X And e.Y < startPos.Y Then
            'Top right
            mRect = New Rectangle(startPos.X, e.Y, e.X - startPos.X, startPos.Y - e.Y)
            mRect.Size = New Size(mRect.Height * 1.6, mRect.Height)
            Me.Invalidate()
        ElseIf e.X < startPos.X And e.Y < startPos.Y Then
            'Top left
            mRect = New Rectangle(e.X, e.Y, startPos.X - e.X, startPos.Y - e.Y)
            mRect.Size = New Size(mRect.Width, mRect.Width / Ratio.Text)
            Me.Invalidate()
        End If
    End If
End Sub

任何帮助将不胜感激.谢谢!

Any help would be hugely appreciated. Thanks!

下面是当前的工作方式,您可以在西北地区绘图时看到时髦.对于所有象限,我需要获得与东南相同的行为(或代码的右下角).

Below is how things currently work, you can see things go funky when drawing in the north west region. I need to get the same behavior as the south east (or bottom right per the code) for all quadrants.

推荐答案

当将Rectangle应用于Rectangle维度时,我提出了一种略有不同的方法来计算光标的当前位置.

I propose a slightly different method to calculate the current position of the cursor, when a Ratio is applied to the Rectangle dimensions.

您当然需要使用Control的MouseDown事件保存Rectangle的开始位置,然后使用MouseMove事件来跟踪Mouse的运动.

You need of course to save the starting position of the Rectangle, using the MouseDown event of a Control, then track the Mouse movements, using the MouseMove event.

照常计算光标的当前位置(在偏移"为负数时交换当前的光标位置"和起始位置").

The current position of the Cursor is calculated as usual (swapping the current Cursor Location the and Starting Position when the Offsets are negative).

唯一的区别是矩形的高度,而整体尺寸受比率"约束.
在这种情况下, Rectangle.Location.Y Rectangle.Width / Ratio 度量确定.如果 Cursor.Location.Y 位于起始位置(Cursor.Location.Y <= StartingPosition.Y)上方,则此位置可见.就像您发布的代码一样.

The only difference is the Height of the Rectangle, when the overall size is subject to a Ratio constraint.
In this case, the Rectangle.Location.Y is determined by the Rectangle.Width / Ratio measure. This becomes visible if the Cursor.Location.Y is above the starting location (Cursor.Location.Y <= StartingPosition.Y). Just like in the code you posted.

对于该示例,我正在使用一个自定义的Rectangle类,该类包含绘制形状所需的所有信息,无论是否在其尺寸上应用了特定的Ratio.

For the example, I'm using a custom Rectangle class that holds all the informations need to draw a shape, with or without a specific Ratio applied to its dimensions.

请注意, Ratio 被硬编码为1.6:仅用于 测试,当然可以将其设置为其他任何内容.

Note that the Ratio is hardcoded to 1.6: it's just to for testing, of course it can be set to anything else.

结果的可视示例:

Private DrawingRects As List(Of DrawingRectangle) = New List(Of DrawingRectangle)()


Private Sub PicureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PicureBox1.MouseDown

    If e.Button = MouseButtons.Left Then
        DrawingRects.Add(New DrawingRectangle() With {
            .DrawingcColor = Color.LightGreen,
            .Location = e.Location,
            .Owner = CType(sender, Control),
            .Ratio = 1.6,
            .Size = Size.Empty,
            .StartPosition = e.Location
        })
    End If
End Sub

Private Sub PicureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PicureBox1.MouseMove

    If e.Button = MouseButtons.Left Then
        Dim rect As DrawingRectangle = DrawingRects.Last()
        If e.X < rect.StartPosition.X Then rect.Location = New Point(e.X, rect.Location.Y)
        If e.Y < rect.StartPosition.Y Then rect.Location = New Point(rect.Location.X, e.Y)

        Dim currentWidth As Integer = Math.Abs(rect.StartPosition.X - e.X)

        If rect.Ratio = 1.0F Then
            rect.Size = New Size(currentWidth, Math.Abs(rect.StartPosition.Y - e.Y))
        Else
            If rect.StartPosition.Y <= rect.Location.Y Then
                rect.Size = New Size(currentWidth, CType(Math.Abs(rect.StartPosition.X - e.X) / rect.Ratio, Integer))
            Else
                Dim currentHeight As Integer = CType(currentWidth / rect.Ratio, Integer)
                rect.Location = New Point(rect.Location.X, rect.StartPosition.Y - currentHeight)
                rect.Size = New Size(currentWidth, currentHeight)
            End If
        End If
        DrawingRects(DrawingRects.Count - 1) = rect

        DirectCast(sender, Control).Invalidate()
    End If
End Sub

Private Sub PicureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PicureBox1.Paint

    Dim canvas As Control = DirectCast(sender, Control)

    If DrawingRects.Count > 0 Then
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
        For Each rect As DrawingRectangle In DrawingRects
            If canvas IsNot rect.Owner Then Continue For
            Using pen As New Pen(rect.DrawingcColor, rect.PenSize)
                e.Graphics.DrawRectangle(pen, New Rectangle(rect.Location, rect.Size))
            End Using
        Next
    End If
End Sub

DrawingRectangle 类:

The DrawingRectangle class:

注意:该类具有 Owner 属性,引用了当前的Control 绘制形状的位置:允许将 List(Of DrawingRectangle) 与 同时使用不同的控件.

Note: the class has an Owner property, referencing the current Control where the shape is drawn: this allows to use a List(Of DrawingRectangle) with different controls at the same time.

Public Class DrawingRectangle
    Private rectAspect As SizeF = SizeF.Empty
    Private rectRatio As Single = 0F

    Public Property Owner As Control
    Public Property Location As Point
    Public Property Size As Size
    Public Property StartPosition As Point
    Public Property DrawingcColor As Color
    Public Property PenSize As Single

    Public Property Aspect() As SizeF
        Get
            Return rectAspect
        End Get
        Set(ByVal value As SizeF)
            Me.rectAspect = value
            SetAspectRatio(value)
        End Set
    End Property

    Public Property Ratio As Single
        Get
            Return rectRatio
        End Get
        Set(ByVal value As Single)
            rectRatio = value
            SetAspectRatio(value)
        End Set
    End Property

    Private Sub SetAspectRatio(aspect As SizeF)
        Me.rectRatio = aspect.Width / aspect.Height
    End Sub
    Private Sub SetAspectRatio(ratio As Single)
        Me.rectAspect = New SizeF(100, 100 / ratio)
    End Sub
End Class

这篇关于使用比例绘制和缩放矩形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆