Home

Introduction to Drawing

 

GDI+ Tools: The Pen

 

Introduction

The most basic tool used in drawing is the pen. The GDI+ library provides a pen through the Pen class.

 

Creating a Pen

To obtain a pen, you can declare a variable of type Pen using one of the constructors of its class.

Characteristics of a Pen

 

The Color of a Pen

The primary piece of information you must specify about a pen is its color. To do this, you can use the following constructor: 

new : 
    color:Color -> Pen

Here is an example:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form(MaximizeBox = true, Text = "Exercise")

let exercisePaint(e : PaintEventArgs) =
    let clr : Color = Color.Violet
    let pnBorder : Pen = new Pen(clr)

exercise.Paint.Add exercisePaint
do Application.Run exercise

Instead of first declaring a Color variable, you can directly define the color in the constructor. Here is an example:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form(MaximizeBox = true, Text = "Exercise")

let exercisePaint(e : PaintEventArgs) =
    let pnBorder : Pen = new Pen(Color.Red)

exercise.Paint.Add exercisePaint
do Application.Run exercise

If you just want to create a regular pen whose only known characteristic would be its color, the System.Drawing namespace provides the Pens class. The primary, and in fact only, role of the Pens class is to define a simple pen and only specify its color. To make this possible, the Pens class is equipped with only static properties that each represents the name of a color. The names are those of common colors (such as Red, Green, Blue, Yellow, Violet, etc), the colors used on web pages (such as LightBlue or DarkGreen, etc), the colors defined in Microsoft Windows (such as ActiveBorder, AppWorkspace, or ButtonFace, etc), and many others. When accessing a Pens property, it produces a Pen object. This means that you can access a pen to initialize a Pen variable. Here is an example:

 let pnBorder : Pen = Pens.Red

If you have already created a pen, to change its color, you can assign the desired color name or color value to the Pen.Color property.

The Width of a Pen

The simplest pen is meant to draw a tinny line. Here is an example of a line drawn with a simple pen:

Line

Such a simple pen is said to have a width of 1 pixel. To give you the ability to support or modify the width of a pen, the Pen class is equipped with a Width property.

When creating a pen, to specify is width, you can use the following constructor:

new : 
        color:Color * 
        width:float32 -> Pen

While the first argument represents the color as we saw in the previous section, the second argument specifies the width, which must be a floating-point value. Here is an example:

let pnBorder : Pen = new Pen(Color.Tomato, 5.00F)

If you have already defined a pen and you want to change its width, the Pen class provides the Width property. Using this property, to modify the width of a pen, assign a floating-point number to its Width property. Here is an example:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form(MaximizeBox = true, Text = "Exercise")

let exercisePaint(e : PaintEventArgs) =
    let pnBorder : Pen = new Pen(Color.Brown)
    
    // Do something, if necessary
    pnBorder.Width <- 3.00F
    // Do something, if necessary
    
exercise.Paint.Add exercisePaint
do Application.Run exercise

In the same way, you can change, increase, or decrease the width of a pen as often as you want. Here are examples:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form(MaximizeBox = true)

let exercisePaint(e : PaintEventArgs) =
    let pnBorder : Pen = new Pen(Color.Brown);
    
    // Do something, if necessary
    pnBorder.Width <- 3.00F
    // Do something, if necessary
    pnBorder.Width <- 6.00F
    // Do something, if necessary
    pnBorder.Width <- 12.00F
    // Do something, if necessary
    pnBorder.Width <- 26.00F
    // Do something, if necessary
    pnBorder.Width <- 44.00F
    // Do something, if necessary

exercise.Paint.Add exercisePaint
do Application.Run exercise

We may get the following result:

If a pen has already been defined and you want to know its width, get the value of its Width property.

The Start Cap of a Pen

If you use a pen with a small width, such as 1 pixel, you may not notice how a line drawn with it starts but with a significantly wide pen, you would notice that it starts with a flat shape. An alternative is to have round, square, or triangle start. This is referred to as the start cap.

To support the starting shape of a line, the Pen class is equipped with a property named StartCap. The Pen.StartCap property is of based on the LineCap enumeration whose members are: AnchorMask, ArrowAnchor, Custom, DiamondAnchor, Flat, NoAnchor, Round, RoundAnchor, Square, SquareAnchor, and Triangle. To specify the start cap, assign the desired LineCap member to the StartCap property of the pen. Here are examples:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form(MaximizeBox = true)

let exercisePaint(e : PaintEventArgs) =
    let pnBorder : Pen = new Pen(Color.Brown);
        
    pnBorder.Width <- 12.00F;
    pnBorder.StartCap <- System.Drawing.Drawing2D.LineCap.AnchorMask
    // Do something, if necessary
    pnBorder.StartCap <- System.Drawing.Drawing2D.LineCap.ArrowAnchor
    // Do something, if necessary
    pnBorder.StartCap <- System.Drawing.Drawing2D.LineCap.DiamondAnchor
    // Do something, if necessary
    pnBorder.StartCap <- System.Drawing.Drawing2D.LineCap.Flat
    // Do something, if necessary
    pnBorder.StartCap <- System.Drawing.Drawing2D.LineCap.NoAnchor
    // Do something, if necessary
    pnBorder.StartCap <- System.Drawing.Drawing2D.LineCap.Round
    // Do something, if necessary
    pnBorder.StartCap <- System.Drawing.Drawing2D.LineCap.RoundAnchor
    // Do something, if necessary
    pnBorder.StartCap <- System.Drawing.Drawing2D.LineCap.Square
    // Do something, if necessary
    pnBorder.StartCap <- System.Drawing.Drawing2D.LineCap.SquareAnchor
    // Do something, if necessary
    pnBorder.StartCap <- System.Drawing.Drawing2D.LineCap.Triangle
    // Do something, if necessary

exercise.Paint.Add exercisePaint
do Application.Run exercise

These may produce the following results:

If none of the available members of the LineCap enumeration suits you, you can define a custom cap using the CustomStartCap class.

The End Cap of a Pen

You can also control the end cap of a line. To support this, the Pen class is equipped with a property named EndCap that also is based on the LineCap enumeration with the same value. Using a combination of the start and end caps, you can control how a line starts and how it ends. If none of the available members of the LineCap enumeration suits you, you can define a custom cap using the CustomEndCap class.

Regular Shapes

 

Rectangles and Squares

A rectangle is a geometric figure made of four sides that compose four right angles. To draw a rectangle, you can either specify the Rectangle value that encloses it, or you can define its location and its dimensions. To draw a rectangle that is enclosed in a Rectangle value, you can use the following version of the Graphics.DrawRectangle() method:

member DrawRectangle :
        pen:Pen *
        rect:Rectangle -> unit

Remember that such a rectangle object can be illustrated as follows:

After defining a Rectangle variable, you can pass it to the method. Here is an example:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Red)
    let Rect : Rectangle = new Rectangle(20, 20, 248, 162)

    e.Graphics.DrawRectangle(penCurrent, Rect)

exercise.Paint.Add exercisePaint
do Application.Run exercise

Remember that you can also define a Pen and/or a Rectangle objects in the parentheses of the method:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    e.Graphics.DrawRectangle(new Pen(Color.Red), new Rectangle(20, 20, 248, 162))

exercise.Paint.Add exercisePaint
do Application.Run exercise

This would produce:

A Rectangle Drawn From a Rectangle Value

It is (very) important to remember that the third argument of the Rectangle represents its width (and not its right) value and the fourth argument represents its height (and not its bottom) value. This is a confusing fact for those who have programmed in GDI: GDI+ defines a Rectangle differently than GDI. In fact, to determine the location and dimensions of a rectangle to draw, the Graphics class provides the following versions of the DrawRectangle() method:

member DrawRectangle :
        pen:Pen *
        x:int *
        y:int *
        width:int *
        height:int -> unit

member DrawRectangle :
        pen:Pen *
        x:float32 *
        y:float32 *
        width:float32 *
        height:float32 -> unit

This time, the rectangle is represented by its location with a point at (x, y) and its dimensions with the width and height argument. This can be illustrated in a Windows coordinate system as follows:

Rectangle

Based on this, the earlier rectangle can also be drawn with the following:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    e.Graphics.DrawRectangle(new Pen(Color.Red), 20, 20, 248, 162)

exercise.Paint.Add exercisePaint
do Application.Run exercise

A square is a rectangle whose four sides are equal.

A Series of Rectangles

The DrawRectangle() method is used to draw one rectangle. If you plan to draw many rectangles, you can proceed in one step by using the Graphics.DrawRectangles() method. It comes in two versions whose syntaxes are:

member DrawRectangles : 
        pen:Pen * 
        rects:Rectangle[] -> unit

member DrawRectangles : 
        pen:Pen * 
        rects:RectangleF[] -> unit

This method requires an array of Rectangle or RectangleF values. When executed, it draws individual rectangles using each member of the array as its own rectangle. Here is an example:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Red);
    let Rect : Rectangle array = [| new Rectangle(20,  20, 120, 20);
                                    new Rectangle(20,  50, 120, 30);
                                    new Rectangle(20,  90, 120, 40);
                                    new Rectangle(20, 140, 120, 60) |]

    e.Graphics.DrawRectangles(penCurrent, Rect)

exercise.Paint.Add exercisePaint
do Application.Run exercise

This would produce:

Rectangles

Ellipses and Circles

An ellipse is a closed continuous line whose points are positioned so that two points exactly opposite each other have the exact same distant from a central point. It can be illustrated as follows:

Ellipse

Because an ellipse can fit in a rectangle, in GDI+ programming, an ellipse is defined with regards to a rectangle it would fit in. To draw an ellipse, you can use the Graphics.DrawEllipse() method that comes in four versions whose syntaxes are:

member DrawEllipse : 
        pen:Pen * 
        rect:Rectangle -> unit

member DrawEllipse : 
        pen:Pen * 
        rect:RectangleF -> unit

member DrawEllipse : 
        pen:Pen * 
        x:int * 
        y:int * 
        width:int * 
        height:int -> unit

member DrawEllipse : 
        pen:Pen * 
        x:float32 * 
        y:float32 * 
        width:float32 * 
        height:float32 -> unit

The arguments of this method play the same roll as those of the Graphics.DrawRectangle() method:

Ellipse 2

Here is an example:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Red)

    e.Graphics.DrawEllipse(penCurrent, new Rectangle(20, 20, 226, 144))

exercise.Paint.Add exercisePaint
do Application.Run exercise

Ellipse

Lines

 

Introduction

A line is a junction of two points. This means that a line has a beginning and an end:

Line Definition

The beginning and the end are two distinct points. Based on this, a line is represented either with two Point values or by four numbers representing its values on the Cartesian axes. To draw a line, the Graphics class is equipped with the following overloaded DrawLine() method: 

member DrawLine : 
        pen:Pen * 
        pt1:Point * 
        pt2:Point -> unit

member DrawLine : 
        pen:Pen * 
        pt1:PointF * 
        pt2:PointF -> unit

member DrawLine : 
        pen:Pen * 
        x1:int * 
        y1:int * 
        x2:int * 
        y2:int -> unit

member DrawLine : 
        pen:Pen * 
        x1:float32 * 
        y1:float32 * 
        x2:float32 * 
        y2:float32 -> unit

If the line is represented with natural numbers, its origin can be specified as a Point pt1 and its end would be represented with a Point pt2. If the line is drawn using floating numbers, you can start it at one PointF pt1 and end it at another PointF pt2. Otherwise, you can specify the starting point with coordinates (x1, y1) and the end would be represented with coordinates (x2, y2). The same type of line can be drawn using decimal values from coordinates (x1, y1) to coordinates (x2, y2).

Here is an example that draws three lines:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let mutable penCurrent : Pen = new Pen(Color.Red)
    e.Graphics.DrawLine(penCurrent, 20, 20, 205, 20)

    penCurrent <- new Pen(Color.Green, 3.50F)
    e.Graphics.DrawLine(penCurrent, 40, 40, 225, 40)

    penCurrent <- new Pen(Color.Blue, 7.25F)
    e.Graphics.DrawLine(penCurrent, 30, 60, 215, 60)

exercise.Paint.Add exercisePaint
do Application.Run exercise

Line

A Series of Lines

The above DrawLine() method is used to draw one line. If you intend to draw a group of lines at once, you can use the Graphics.DrawLines() method. It is overloaded with two versions as follows:

member DrawLines : 
        pen:Pen * 
        points:Point[] -> unit

member DrawLines : 
        pen:Pen * 
        points:PointF[] -> unit

To use this method, you should first define an array of either Point for natural numbers that represent Cartesian coordinates or PointF for floating numbers. Here is an example:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let Coordinates : Point array = [| new Point( 20,  10)
                                       new Point(205,  20)
                                       new Point( 40,  40)
                                       new Point(225,  60)
                                       new Point( 30,  80)
                                       new Point(215, 100) |]

    let penCurrent : Pen = new Pen(Color.Red)
    e.Graphics.DrawLines(penCurrent, Coordinates)

exercise.Paint.Add exercisePaint
do Application.Run exercise

This would produce:

Drawing Lines

Polygons

A polygon is a series of connected lines with the whole shape being closed. In other words, a polygon is defined a group of lines so that, except for the first line of the group, the starting point of each line is the same as the end point of the previous line and the end point of the last line is connected to the start point of the first line.

To draw a polygon, you can use the Graphics.Polygon() method. It is overloaded with two versions as follows:

member DrawPolygon : 
        pen:Pen * 
        points:Point[] -> unit

member DrawPolygon : 
        pen:Pen * 
        points:PointF[] -> unit

To use this method, you can first declare a Point or PointF array and pass it as the second argument to the method. Here is an example:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let Pt : Point array = [| new Point( 20,  50)
                              new Point(180,  50)
                              new Point(180,  20)
                              new Point(230,  70)
                              new Point(180, 120)
                              new Point(180,  90)
                              new Point( 20,  90) |]

    let penCurrent : Pen = new Pen(Color.Red)
    e.Graphics.DrawPolygon(penCurrent, Pt)

exercise.Paint.Add exercisePaint
do Application.Run exercise

This would produce:

Polygon

     
 

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:

member DrawCurve : 
        pen:Pen * 
        points:Point[] -> unit

member DrawCurve : 
        pen:Pen * 
        points:PointF[] -> unit

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:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    let pts : Point array = [| new Point( 40,  42)
                               new Point(188, 246)
                               new Point(484, 192)
                               new Point(350,  48) |]

    e.Graphics.DrawCurve(penCurrent, pts)

exercise.Paint.Add exercisePaint
do Application.Run exercise

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:

member DrawCurve : 
        pen:Pen * 
        points:Point[] * 
        tension:float32 -> unit

member DrawCurve : 
        pen:Pen * 
        points:PointF[] * 
        tension:float32 -> unit

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:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    let pts : Point array = [| new Point(40,  42)
                               new Point(188, 246)
                               new Point(484, 192)
                               new Point(350,  48) |]

    e.Graphics.DrawCurve(penCurrent, pts, 0.00F)

exercise.Paint.Add exercisePaint
do Application.Run exercise

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:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    let pts : Point array = [| new Point(40,  42)
                               new Point(188, 246)
                               new Point(484, 192)
                               new Point(350,  48) |]

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

exercise.Paint.Add exercisePaint
do Application.Run exercise

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:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    let pts : PointF array = [| new PointF( 20.00F, 322.00F)
                                new PointF(124.00F,  24.00F)
                                new PointF(214.00F, 242.00F)
                                new PointF(275.00F,  28.00F)
                                new PointF(380.00F, 322.00F) |]

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

exercise.Paint.Add exercisePaint
do Application.Run exercise

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:

member DrawCurve : 
        pen:Pen * 
        points:PointF[] * 
        offset:int * 
        numberOfSegments:int -> unit

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:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    let pts : PointF array = [| new PointF( 20.00F, 322.00F)
                                new PointF(124.00F,  24.00F)
                                new PointF(214.00F, 242.00F)
                                new PointF(275.00F,  28.00F)
                                new PointF(380.00F,  322.00F) |]

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

exercise.Paint.Add exercisePaint
do Application.Run exercise

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 void DrawCurve(Pen pen, 
		   Point[] points, 
		   int offset, 
		   int numberOfSegments, 
		   float tension);
public void DrawCurve(Pen pen, 
		   PointF[] points, 
		   int offset, 
		   int numberOfSegments, 
		   float tension);

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

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    let pts : PointF array = [| new PointF( 20.00F, 322.00F)
                                new PointF(124.00F, 24.00F)
                                new PointF(214.00F, 242.00F)
                                new PointF(275.00F, 28.00F)
                                new PointF(380.00F, 322.00F) |]

    e.Graphics.DrawCurve(penCurrent, pts, 0, 4, 0.00F)

exercise.Paint.Add exercisePaint
do Application.Run exercise

This would produce:

Curve

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

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    let pts : PointF array = [| new PointF(20.00F, 322.00F)
                                new PointF(124.00F, 24.00F)
                                new PointF(214.00F, 242.00F)
                                new PointF(275.00F, 28.00F)
                                new PointF(380.00F, 322.00F) |]

    e.Graphics.DrawCurve(penCurrent, pts, 1, 3, 1.750F)

exercise.Paint.Add exercisePaint
do Application.Run exercise

This would produce:

Curve

A Bézier Curve

A bézier curve is a continuous line that is drawn using four points that are not necessarily aligned. It can be illustrated as follows:

Bezier

To draw this line (with four points), the compiler would draw a curve from the first point to the fourth point. Then it would bend the curve by bringing each middle (half-center) side close to the second and the third points respectively, without touching those second and third points. For example, the above bézier curve could have been drawn using the following four points:

Bezier Illustration

To draw a bézier curve, the Graphics class provides the DrawBezier() method that is overloaded in three versions whose syntaxes are:

member DrawBezier : 
        pen:Pen * 
        pt1:Point * 
        pt2:Point * 
        pt3:Point * 
        pt4:Point -> unit

member DrawBezier : 
        pen:Pen * 
        pt1:PointF * 
        pt2:PointF * 
        pt3:PointF * 
        pt4:PointF -> unit

member DrawBezier : 
        pen:Pen * 
        x1:float32 * 
        y1:float32 * 
        x2:float32 * 
        y2:float32 * 
        x3:float32 * 
        y3:float32 * 
        x4:float32 * 
        y4:float32 -> unit

Based on this, to draw a bézier line, you can use either four Point or PointF values or the coordinates of the four points. Here is an example:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    let pt1 : Point = new Point( 20,  12)
    let pt2 : Point = new Point( 88, 246)
    let pt3 : Point = new Point(364, 192)
    let pt4 : Point = new Point(250,  48)

    e.Graphics.DrawBezier(penCurrent, pt1, pt2, pt3, pt4)

exercise.Paint.Add exercisePaint
do Application.Run exercise

This would produce:

Bezier Curve

A Series of Bézier Curves

The Graphics.DrawBezier() method is used to draw one bézier curve. If you want to draw many bézier curves, you can call the Graphics.DrawBeziers() method that is overloaded in two versions as follows:

member DrawBeziers : 
        pen:Pen * 
        points:Point[] -> unit

member DrawBeziers : 
        pen:Pen * 
        points:PointF[] -> unit

The DrawBeziers() method requires an array of Point of PointF values. When working with only four coordinates, the DrawBeziers() method works exactly like DrawBezier(), the different is that, while DrawBezier() expects four Point or four PointF values, DrawBeziers() expects an array of Point or PointF values. Using, DrawBeziers(), the above bézier curve can be drawn as follows and produce the same result:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    let pts : Point array = [| new Point(20,  12)
                               new Point(88, 246)
                               new Point(364, 192)
                               new Point(250,  48) |]

    e.Graphics.DrawBeziers(penCurrent, pts)

exercise.Paint.Add exercisePaint
do Application.Run exercise

This would produce:

Curve

A characteristic of using DrawBeziers() is that it allows you to draw a bézier curve using 7 Point or PointF values. Here is an example:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    let pts : Point array = [| new Point( 10,   5)
                               new Point(340,  60)
                               new Point(320, 148)
                               new Point(150, 120)
                               new Point( 24, 220)
                               new Point(250, 150)
                               new Point(304, 240) |]

    e.Graphics.DrawBeziers(penCurrent, pts)

exercise.Paint.Add exercisePaint
do Application.Run exercise

This would produce:

Beziers

 

A Closed Curve

If you use either the DrawLines(), the DrawBezier() or the DrawBeziers() methods, you would get a continuous line or a series of lines that has a beginning and an end. Alternatively, GDI+ allows you to draw a series of lines but join the end of the last line to the beginning of the first line to have a closed shape. To draw this figure, you can call the Graphics.DrawClosedCurve() method that is overloaded in four versions. Two of them have the following syntaxes:

member DrawClosedCurve : 
        pen:Pen * 
        points:Point[] -> unit

member DrawClosedCurve : 
        pen:Pen * 
        points:PointF[] -> unit

These two versions are the easiest to use. They allow you to provide an array of four Point or four PointF values. When executed, each of these methods draws a curve that passes through each coordinate and closes the curve by joining the end point to the first unless both points are the same. Here is an example:

open System
open System.Drawing
open System.Windows.Forms

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    let pts : Point array = [| new Point( 40,  42)
                               new Point(188, 246)
                               new Point(484, 192)
                               new Point(350,  48) |]

    e.Graphics.DrawClosedCurve(penCurrent, pts)

exercise.Paint.Add exercisePaint
do Application.Run exercise

This would produce:

Closed Curve

The first two versions are used to draw the lines but curve them in order to make the shape appear smooth. If you want, you can draw the lines straight from one point to the next without curving them. Using this scenario, the above shape would appear as follows:

Closed Shape With Straight Lines

To draw this type of shape using the DrawClosedCurve() method, you can use one of the following versions of the method:

member DrawClosedCurve : 
        pen:Pen * 
        points:Point[] * 
        tension:float32 * 
        fillmode:FillMode -> unit

member DrawClosedCurve : 
        pen:Pen * 
        points:PointF[] * 
        tension:float32 * 
        fillmode:FillMode -> unit

These versions allow you to specify the tension and the fill mode. The tension factor allow you to specify how much curve would be applied. If this value is passed as 0.00, the points would be joined with straight lines. Otherwise, you can apply a tension using an appropriate decimal value.

The fillmode factor determines how the interior of the curve would be filled. It is controlled through the FillMode enumerator that is defined in the System.Drawing.Drawing2D namespace. The FillMode enumerator has two members: Alternate and Winding. Here is an example:

open System
open System.Drawing
open System.Windows.Forms
open System.Drawing.Drawing2D

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    let pts : Point array = [| new Point( 40,  42)
                               new Point(188, 246)
                               new Point(484, 192)
                               new Point(350,  48) |]

    e.Graphics.DrawClosedCurve(penCurrent, pts, 0.75F, FillMode.Winding)

exercise.Paint.Add exercisePaint
do Application.Run exercise

This would produce:

Closed Curve

Remember that the higher the tension, the sharper the corners. If you want the shape to show straight lines, pass a tension of 0.00F.

Pies

A pie is a fraction of an ellipse delimited by a starting angle and an angle that constitutes the desired portion to make up a pie. It can be illustrated as follows:

Pie Illustration

To draw a pie, you can use the Graphics.DrawPie() method that comes in various versions as follows:

member DrawPie :
        pen:Pen *
        rect:Rectangle *
        startAngle:float32 *
        sweepAngle:float32 -> unit

member DrawPie :
        pen:Pen *
        rect:RectangleF *
        startAngle:float32 *
        sweepAngle:float32 -> unit

member DrawPie :
        pen:Pen *
        x:int *
        y:int *
        width:int *
        height:int *
        startAngle:int *
        sweepAngle:int -> unit

member DrawPie : 
        pen:Pen *
        x:float32 *
        y:float32 *
        width:float32 *
        height:float32 *
        startAngle:float32 *
        sweepAngle:float32 -> unit

A pie is based on an ellipse (like an arc). The ellipse would fit in a rectangle passed as the rect argument. The rectangle can also be specified by its location (x, y) and its dimensions (width and height).

Inside of the parent rectangle in which an ellipse would be drawn, you set a starting angle. This angle is measured from 0 up counted clockwise (like the numbers of an analog clock). This means that an angle of 90 represents 6 o'clock and not 12 o'clock. This starting angle is passed as the startAngle argument.

After specifying the starting angle, you must specify the amount of angle covered by the pie. This also is measured clockwise. This value is passed as the sweepAngle argument.

Here is an example:

open System
open System.Drawing
open System.Windows.Forms
open System.Drawing.Drawing2D

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    e.Graphics.DrawPie(penCurrent, 20, 20, 200, 100, 45, 255)

exercise.Paint.Add exercisePaint
do Application.Run exercise

This would produce:

Pie

Arcs

An arc is a portion or segment of an ellipse, meaning an arc is a non-complete ellipse. While a pie is a closed shape, an arc is not: it uses only a portion of the line that defines an ellipse. Because an arc must confirm to the shape of an ellipse, it is defined as it fits in a rectangle and can be illustrated as follows:

Arc

To support arcs, the Graphics class is equipped with the DrawArc() method that is provided in four versions whose syntaxes are:

member DrawArc : 
        pen:Pen * 
        rect:Rectangle * 
        startAngle:float32 * 
        sweepAngle:float32 -> unit

member DrawArc : 
        pen:Pen * 
        rect:RectangleF * 
        startAngle:float32 * 
        sweepAngle:float32 -> unit

member DrawArc : 
        pen:Pen * 
        x:int * 
        y:int * 
        width:int * 
        height:int * 
        startAngle:int * 
        sweepAngle:int -> unit

member DrawArc : 
        pen:Pen * 
        x:float32 * 
        y:float32 * 
        width:float32 * 
        height:float32 * 
        startAngle:float32 * 
        sweepAngle:float32 -> unit

The ellipse that would contain the arc must be drawn in a Rectangle or a RectangleF rect. You can also define that ellipse by the coordinates of its inscribed rectangle x, y, and its dimensions width, height.  Besides the borders of the rectangle in which the arc would fit, an arc must specify its starting angle, startAngle, measured clockwise from the x-axis its starting point. An arc must also determine its sweep angle measured clockwise from the startAngle parameter to the end of the arc. These two value follow the same definitions we reviewed for the Graphics.Pie() method.

Here is an example:

open System
open System.Drawing
open System.Windows.Forms
open System.Drawing.Drawing2D

let exercise = new Form()

let exercisePaint(e : PaintEventArgs) =
    let penCurrent : Pen = new Pen(Color.Blue)
    e.Graphics.DrawArc(penCurrent, 20, 20, 200, 150, 225, 200)

exercise.Paint.Add exercisePaint
do Application.Run exercise

Arc

   
   
 

Home Copyright © 2015, FunctionX Home