GDI+: Curve-Based Shapes |
|
public: void DrawCurve(Pen *pen, Point points[]); public: void DrawCurve(Pen *pen, PointF points[]);
|
|
private: System::Void Form1_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e) { Pen *penCurrent = new Pen(Color::Blue); Point pt[] = { Point( 40, 42), Point(188, 246), Point(484, 192), Point(350, 48) }; e->Graphics->DrawCurve(penCurrent, pt); }
This would produce:
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: void DrawCurve(Pen *pen, Point points[], float tension); public: void DrawCurve(Pen *pen, PointF points[], float tension);
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: System::Void Form1_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e) { Pen *penCurrent = new Pen(Color::Blue); Point pt[] = { Point(40, 42), Point(188, 246), Point(484, 192), Point(350, 48) }; e->Graphics->DrawCurve(penCurrent, pt, 0.00F); } |
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: System::Void Form1_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e) { Pen *penCurrent = new Pen(Color::Blue); Point pt[] = { Point(40, 42), Point(188, 246), Point(484, 192), Point(350, 48) }; e->Graphics->DrawCurve(penCurrent, pt, 2.15F); }
This would produce:
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: System::Void Form1_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e) { Pen *penCurrent = new Pen(Color::Blue); PointF pt[] = { PointF(20.00F, 322.00F), PointF(124, 24), PointF(214, 242), PointF(275, 28), PointF(380.00F, 322.00F) }; e->Graphics->DrawCurve(penCurrent, pt); }
This would produce:
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: void DrawCurve(Pen *pen, PointF[] points, int offset, int numberOfSegments); 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: System::Void Form1_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e) { Pen *penCurrent = new Pen(Color::Blue); PointF pt[] = { PointF(20.00F, 322.00F), PointF(124, 24), PointF(214, 242), PointF(275, 28), PointF(380.00F, 322.00F) }; e->Graphics->DrawCurve(penCurrent, pt, 1, 2); }
This would produce:
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: |
private: System::Void Form1_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e) { Pen *penCurrent = new Pen(Color::Blue); PointF pt[] = { PointF(20.00F, 322.00F), PointF(124, 24), PointF(214, 242), PointF(275, 28), PointF(380.00F, 322.00F) }; e->Graphics->DrawCurve(penCurrent, pt, 0, 4, 0); }
This would produce:
Or you can pass the tension with any positive value of your choice. Here is an example:
private: System::Void Form1_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e) { Pen *penCurrent = new Pen(Color::Blue); PointF pt[] = { PointF(20.00F, 322.00F), PointF(124, 24), PointF(214, 242), PointF(275, 28), PointF(380.00F, 322.00F) }; e->Graphics->DrawCurve(penCurrent, pt, 1, 3, 1.750F); }
This would produce:
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: 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: To draw a bézier curve, the Graphics class provides the DrawBezier() method that is overloaded in three versions whose syntaxes are: public: void DrawBezier(Pen *pen, Point pt1, Point pt2, Point pt3, Point pt4); public: void DrawBezier(Pen *pen, PointF pt1, PointF pt2, PointF pt3, PointF pt4); public: void DrawBezier(Pen *pen, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4); 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: |
private: System::Void Form1_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e) { Pen *penCurrent = new Pen(Color::Blue); Point pt1 = Point(20, 12), pt2 = Point(88, 246), pt3 = Point(364, 192), pt4 = Point(250, 48); e->Graphics->DrawBezier(penCurrent, pt1, pt2, pt3, pt4); }
This would produce:
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: public: void DrawBeziers(Pen *pen, Point points[]); public: void DrawBeziers(Pen *pen, PointF points[]); 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: |
private: System::Void Form1_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e) { Pen *penCurrent = new Pen(Color::Blue); Point pt[] = { Point(20, 12), Point(88, 246), Point(364, 192), Point(250, 48) }; e->Graphics->DrawBeziers(penCurrent, pt); }
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: |
private: System::Void Form1_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e) { Pen *penCurrent = new Pen(Color::Blue); Point pt[] = { Point( 10, 5), Point(340, 60), Point(320, 148), Point(150, 120), Point(24, 220), Point(250, 150), Point(304, 240) }; e->Graphics->DrawBeziers(penCurrent, pt); }
This would produce:
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: public: void DrawClosedCurve(Pen *pen, Point points[]); public: void DrawClosedCurve(Pen *pen, PointF points[]); 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: |
private: System::Void Form1_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e) { Pen *penCurrent = new Pen(Color::Blue); Point pt[] = { Point(40, 42), Point(188, 246), Point(484, 192), Point(350, 48) }; e->Graphics->DrawClosedCurve(penCurrent, pt); }
This would produce: 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: To draw this type of shape using the ClosedCurve() method, you can use one of the following versions of the method: public: void DrawClosedCurve(Pen *pen, Point points[], float tension, FillMode fillmode); public: void DrawClosedCurve(Pen *pen, PointF points[], float tension, FillMode fillmode); 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: |
private: System::Void Form1_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e) { using namespace System::Drawing::Drawing2D; Pen *penCurrent = new Pen(Color::Red); Point pt[] = { Point(40, 42), Point(188, 246), Point(484, 192), Point(350, 48) }; e->Graphics->DrawClosedCurve(penCurrent, pt, 0.75F, FillMode::Winding); }
This would produce:
|
||
Home | Copyright © 2004-2010 FunctionX, Inc. | |
|