我坚持在Visual Basic中绘制贝塞尔曲线

时间:2018-11-26 08:50:35

标签: vb.net

https://i.snag.gy/iQUyxz.jpg

我正在VS 2017中处理Windows应用程序窗体。要求是通过使用三个输入数字(如(56、150、400))绘制贝塞尔曲线。

我真的很困惑如何绘制它。

Private Sub DrawCurve_Click(sender As Object, e As EventArgs) Handles DrawCurve.Click
    Try
        'Declared myColor earlier
        Dim color = myColor
        Dim myPen As Pen = New Pen(myColor, 8)
        Dim myGraphics As Graphics = Me.CreateGraphics
        Dim pt1 As Point = New Point(CInt(curvePT1.Text),CInt(curvePT1.Text))
        Dim pt2 As Point = New Point(CInt(curvePT2.Text),CInt(curvePT2.Text))
        Dim pt3 As Point = New Point(CInt(curvePT2.Text),CInt(curvePT2.Text))
        Dim curvedPoints As Point() = {pt1, pt2, pt3}
        'Draw Bezier Curve
        CreateGraphics().Clear(Form.ActiveForm.BackColor)
        myGraphics.DrawBezier(myPen, curvedPoints)
    Catch
        MsgBox("Please enter numerical value!")
    End Try
End Sub

2 个答案:

答案 0 :(得分:0)

通过三个点绘制样条曲线与绘制三次贝塞尔曲线不会产生相同的结果。样条曲线趋向于具有更陡峭的弯曲(想像一下晾衣架)。

实际上,.Net框架确实包含二次Beziers:WPF中的QuadraticBezierSegment。有了合适的引用,在System.Drawing上下文中创建一个函数来使用它并不难。

但是使用普通算法绘制二次Bezier曲线甚至更容易。首先选择要绘制的点数-5个点可能就足够了,如果想要更平滑的结果,则更多。这是一个函数(加上2个支持函数),在给定3个控制点和要绘制的点数的情况下,该函数返回代表二次Bezier的PointF列表:

        Public Function QuadraticBezier(controlPoint1 As PointF, controlPoint2 As PointF, 
controlPoint3 As PointF, numberOfPoints As Integer) As PointF()

          Dim lst As New List(Of PointF)
          For t As Double = 0 To 1 Step 1 / (numberOfPoints - 1)
             lst.Add(QuadBezierPoint(controlPoint1, controlPoint2, controlPoint3, t))
          Next
          Return lst.ToArray

       End Function

       Private Function QuadBezierPoint(p1 As PointF, p2 As PointF, p3 As PointF, t As Double) 
As PointF

          Dim q1 As PointF = LinearInterpolate(p1, p2, t)
          Dim q2 As PointF = LinearInterpolate(p2, p3, t)
          Return LinearInterpolate(q1, q2, t)

       End Function

       Private Function LinearInterpolate(p1 As PointF, p2 As PointF, t As Double) 
As PointF

          Dim x As Double = p1.X + (p2.X - p1.X) * t
          Dim y As Double = p1.Y + (p2.Y - p1.Y) * t
          Return New PointF(CSng(x), CSng(y))

       End Function

一旦有了点,就可以根据需要绘制曲线,例如使用Graphics.DrawCurve或作为直线。即使只获得5分,看起来也仅比获得3分更像一个Bezier。

答案 1 :(得分:0)

事后思考。原始问题最简单的答案就是复制可用的点之一。例如p2,如下所示:

    Dim curvedPoints As Point() = {pt1, pt2, pt2, pt3}
    '.... 
    'Draw Bezier Curve
    myGraphics.DrawBezier(myPen, curvedPoints)

结果将与二次贝塞尔曲线不同,因为加倍的点在曲线上更难“拉”。但这仍然是贝塞尔曲线。

BB