基于曲线的图形
一、曲线
曲线是连接两点或多点的线条,如果仅仅涉及两个点,线条将把它们连接在一起,但这个线条不是直的。如果有三个点A、B、C,这条线将从A点开始,穿过B点,结束于C点。如果多于三个点,这条线将起始与第一个点,依次穿过中间的若干点,结束于最后的点。曲线中的点不必排成一条直线,实际上,绘制曲线的整体思想是用非直的线条连接不在一条直线上的点,下图的C 1、C2、C3可以说明这一点:
 图十六、曲线示意图 | 曲线C1包括两个点,曲线C2包括3个点,曲线C3包括4个点。
两点间的部分称为线段。这也意味着曲线可以由包含的线段的个数来进行区分。如果一个曲线仅仅由两个点构成,这意味着它只有一个线段,连接着第一、第二个点,如果一个曲线包括三个点,它有两个线段,第一个线段跨越第一、第二个点,第二个线段跨越第二、第三个点。综上所述,曲线的线段数等于点数减去一。
GDI+中使用Graphics::DrawCurve()方法画曲线,在画一个曲线时,必须说明所涉及到的点数,这意味着首先要声明一个Point 或PointF数组,正是考虑到这一点,Graphics类定义的DrawCurve()的方法如下:
public: void DrawCurve(Pen *pen, Point points[]); public: void DrawCurve(Pen *pen, PointF points[]); | 这个版本的方法使用了Point 或 PointF值作为参数,数组的成员数由你规定,这里有一个例子使用四个点来绘制一个含有三个线段的曲线:
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); } | 它的效果图如下所示:
 图十七、曲线效果图 | 正如你所见到的,当画一个曲线时,一个弯曲的线条穿越起始点和终点之间的中间点,为了使线条是非直的,编译器使用一个称为张力的值来弯曲线条,这个张力值可以通过定义弯曲系数的形式来修改,为了这么做,使用下列版本的DrawCurve()方法:
public: void DrawCurve(Pen *pen, Point points[], float tension); public: void DrawCurve(Pen *pen, PointF points[], float tension); | 弯曲程度由张力参数决定,它可以是大于等于0.00的十进制数,如果该值等于0.00,将画一个直线。下面是一个例子:
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); } |
 图十八、代码运行效果图 | 这意味着,如果想画一个真正的曲线,或者是不传递张力参数,使用这个方法的第一个版本,或者是传递的张力的参数值大于0.00。这里有个例子:
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); } | 这将产生如下效果:
 图十九、代码运行效果图 | DrawCurve()方法的两个版本准许在开始的第一个点绘制曲线,下面的例子使用了5个点,产生了4个线段:
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); } | 效果如图所示:
 图二十、代码运行效果图 | 如果需要的话,可以随意在任意一个点开始曲线,为了支持这一点,Graphics类提供了以下版本的DrawCurve()方法:
| public: void DrawCurve(Pen *pen, PointF[] points, int offset, int numberOfSegments); | offset参数用来规定在开始绘制之前跳需要跃过的点数,首先需要决定的就是offset参数必须设置为0或者更高的数,如果将这个参数设置为0,曲线将从第一个点开始绘制。如果这个参数设置为1,第一个点将不包含在曲线之内。这意味着曲线从第二个点开始绘制,以此类推。如果设置为2,第一和第二个点都不在曲线内,曲线从第三个点开始。
通过offset参数规定曲线的起点后,然后就需要设定曲线的段数,这个段数必须要小于可用的段数,它等于所有段落数减去offset值。下面是一个例子:
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); } | 效果图如下:
 图二十一、代码运行效果图 | 再一次,编译器在绘制曲线时需要申请张力,如果愿意使用一个直线段或使用一个不同于默认值的张力的话,可以使用下列版本的Graphics::DrawCurve()方法:
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); | 这次,你可以传递0值给张力,以此来得到直线,代码如下:
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); } | 效果如图:
 图二十二、代码运行效果图 | 也可以向张力参数传递任何正值,这有个例子:
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); } | 效果如图:
 图二十三、代码运行效果图 |
|
|