Home

GDI+ Shapes: Curves

 

Introduction to Curves

A curve is a line that joins two or more points. If only two points are involved, the line would join them but the line is not straight. If there are three points A, B, and C, the line would start on the first point A, cross the second point B, and stop at the last point C. If more than three points are involved, the line would start on the first, cross the second, cross the third and each line before stopping on the last. The points of a curve don't have to be aligned. In fact, the whole idea of drawing a curve is to have a non-straight line that joins different non-aligned points. This can be illustrated with the following three curves labeled C1, C2, and C3:

The first curve, C1, includes only two points. The second, C2 includes three points. The third, C3, includes four points.

The section between two points is called a segment. This also means that a curve can be distinguished by the number of segments it has. If a curve is made of only two points, this means that it has only one segment from the first to the second, which is the last, point. If a curve includes three points, it has two segments. The first segment spans from the first point to the second point and the second segment spans from the second point to the third point. Based on this, the number of segments of a curve is equal to the number of its points - 1.

A curve can be drawn in GDI+ using the Graphics.DrawCurve() method. When drawing a curve, you must specify how many points would be involved. This means that you can first declare an array of Point or PointF values. Because it is left up to you to decide on this issue, the Graphics class provides the following syntaxes of the DrawCurve() method:

Public Sub DrawCurve(pen As Pen, points As Point())
Public Sub DrawCurve(pen As Pen, points As PointF())

This version of the method takes an array of Point or PointF values as arguments. The number of members of the array depends on you. Here is an example that uses four points to draw a curve with three segments:

Imports System.Drawing
Imports System.Windows.Forms

Module Exercise

    Public Class Starter
        Inherits Form

        Dim components As System.ComponentModel.Container

        Public Sub New()
            InitializeComponent()
        End Sub

        Public Sub InitializeComponent()

        End Sub

        Private Sub FormPaint(ByVal sender As Object, _
                              ByVal e As PaintEventArgs) _
                              Handles MyBase.Paint

            Dim penCurrent As Pen = New Pen(Color.Blue)
            Dim pt As Point() = {New Point(40, 42), _
                                 New Point(188, 246), _
                                 New Point(484, 192), _
                                 New Point(350, 48)}

            e.Graphics.DrawCurve(penCurrent, pt)

        End Sub
    End Class

    Function Main() As Integer

        Dim frmStart As Starter = New Starter

        Application.Run(frmStart)

        Return 0
    End Function

End Module

This would produce:

Curve

As you can see, when the curve is drawn, a bent line crosses the intermediary points between the first and the last. To make the lines non-straight, the compiler uses a value called tension used to bend the line. If you want, you can specify the bending factor that should be applied. To do this, you would use the following version of the DrawCurve() method:

Public Sub DrawCurve(pen As Pen, points As Point(), tension As Single)
Public Sub DrawCurve(pen As Pen, points As PointF(), tension As Single)

The amount of bending to apply is passed as the tension argument. It can be passed as a decimal value >= 0.00. If this value is passed as 0.00, the lines would be drawn straight. Here is an example:

Private Sub FormPaint(ByVal sender As Object, _
                              ByVal e As PaintEventArgs) _
                              Handles MyBase.Paint

            Dim penCurrent As Pen = New Pen(Color.Blue)
            Dim pt As Point() = {New Point(40, 42), _
                   New Point(188, 246), _
                                  New Point(484, 192), _
                   New Point(350, 48)}

            e.Graphics.DrawCurve(penCurrent, pt, 0.0F)

End Sub

Curve

This means that, if you want a real curve, either you don't pass the tension argument and use the first version of the method or you pass the tension argument as a value higher than 0.00. Here is an example:

Private Sub FormPaint(ByVal sender As Object, _
                              ByVal e As PaintEventArgs) _
                              Handles MyBase.Paint

            Dim penCurrent As Pen = New Pen(Color.Blue)
            Dim pt As Point() = {New Point(40, 42), _
                   New Point(188, 246), _
                                  New Point(484, 192), _
                   New Point(350, 48)}

            e.Graphics.DrawCurve(penCurrent, pt, 2.15F)

End Sub

This would produce:

A curve with a tension value of 2.15

Both versions of the DrawCurve() method that we have used allow you to start the curve on the first point. Consider the following example that draws a curve of five points resulting in four segments:

Private Sub FormPaint(ByVal sender As Object, _
                              ByVal e As PaintEventArgs) _
                              Handles MyBase.Paint

            Dim penCurrent As Pen = New Pen(Color.Blue)
            Dim pt As PointF() = {New PointF(20.0F, 322.0F), _
           New PointF(124, 24), _
                       New PointF(214, 242), _
           New PointF(275, 28), _
                        New PointF(380.0F, 322.0)}

            e.Graphics.DrawCurve(penCurrent, pt)

End Sub

This would produce:

Curve

If you want, you can start the curve on any point instead of the first. To support this, the Graphics class provides the following version of the DrawCurve() method:

Public Sub DrawCurve(pen As Pen, points As PointF(), _
	             offset As Integer, numberOfSegments As Integer)

The offset argument allows you to specify how many points should be skipped before starting to draw. The first conclusion is that the value of the offset must be 0 or higher. If you pass this argument as 0, the curve would be drawn from the first point. If you pass this argument as 1, the first point would not be considered in the curve. This means that the drawing of the curve would start on the second point and so on. If you pass it as 2, the first and the second point would not be part of the curve, meaning that the curve would start on the third point. 

After the curve has started from the point you specify using the offset argument, you can then specify how many segments of the curve would be drawn. This number must be lower than the number of available segments, that is after subtracting the offset value from the total number of segments of the array. Here is an example:

Private Sub FormPaint(ByVal sender As Object, _
                              ByVal e As PaintEventArgs) _
                              Handles MyBase.Paint

            Dim penCurrent As Pen = New Pen(Color.Blue)
            Dim pt As PointF() = {	New PointF(20.0F, 322.0F), _
		              	New PointF(124, 24), _
                 		New PointF(214, 242), _
      			New PointF(275, 28), _
                        		New PointF(380.0F, 322.0F) }

            e.Graphics.DrawCurve(penCurrent, pt, 1, 2)

End Sub

This would produce:

A curve with an offset value and a limited number of segments

Once again, the compiler arranges to apply a tension when drawing the curve. If you would prefer to use straight lines or to apply a different tension than the default, you can use the following version of the Graphics.DrawCurve() method:

Public Sub DrawCurve(pen As Pen, points As Point(), offset As Integer, _
		    numberOfSegments As Integer, tension As Single)
Public Sub DrawCurve(pen As Pen, points As PointF(),offset As Integer, _
		    numberOfSegments As Integer, tension As Single)

This time, you can pass the value of the tension as 0 to get straight lines:

Private Sub FormPaint(ByVal sender As Object, _
                              ByVal e As PaintEventArgs) _
                              Handles MyBase.Paint

            Dim penCurrent As Pen = New Pen(Color.Blue)
            Dim pt As PointF() = {	New PointF(20.0F, 322.0), _
      			New PointF(124, 24), _
                    		New PointF(214, 242), _
      			New PointF(275, 28), _
                    		New PointF(380.0F, 322.0) }

            e.Graphics.DrawCurve(penCurrent, pt, 0, 4, 0)

End Sub

This would produce:

Curve

Or you can pass the tension with any positive value of your choice. Here is an example:

Private Sub FormPaint(ByVal sender As Object, _
                              ByVal e As PaintEventArgs) _
                              Handles MyBase.Paint

            Dim penCurrent As Pen = New Pen(Color.Blue)
            Dim pt As PointF() = {New PointF(20.0F, 322.0F), New PointF(124, 24), _
                               New PointF(214, 242), New PointF(275, 28), _
                                   New PointF(380.0F, 322.0F)}

            e.Graphics.DrawCurve(penCurrent, pt, 1, 3, 1.75F)

End Sub

This would produce:

Curve

 

 

Home Copyright © 2008-2016, FunctionX, Inc. Home