GDI+: Curved Shapes

原文 http://www.functionx.com/vcsharp2003/gdi/curves.htm


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. 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 void DrawCurve(Pen pen, Point[] points);
public void DrawCurve(Pen pen, PointF[] points);

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:

private void Form1_DoubleClick(object sender, System.EventArgs e)
{
	Graphics graph = this.CreateGraphics();
	Pen penCurrent = new Pen(Color.Blue);
	Point[] pt     = { new Point(40,  42), new Point(188, 246),
                                          new Point(484, 192), new Point(350,  48) };

	graph.DrawCurve(penCurrent, pt);
}

This would produce:


As you can see, when the curve is draw, 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 version 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 void Form1_DoubleClick(object sender, System.EventArgs e)
{
	Graphics graph = this.CreateGraphics();
	Pen penCurrent = new Pen(Color.Blue);
	Point[] pt     = { new Point(40,  42), new Point(188, 246),
		   new Point(484, 192), new Point(350,  48) };

	graph.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 void Form1_DoubleClick(object sender, System.EventArgs e)
{
	Graphics graph = this.CreateGraphics();
	Pen penCurrent = new Pen(Color.Blue);
	Point[] pt     = { new Point(40,  42), new Point(188, 246),
		   new Point(484, 192), new Point(350,  48) };

	graph.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 void Form1_DoubleClick(object sender, System.EventArgs e)
{
	Graphics graph = this.CreateGraphics();
	Pen penCurrent = new Pen(Color.Blue);
	PointF[] pt     = {   new PointF(20F,  322F), new PointF(124, 24),
		              new PointF(214, 242), new PointF(275,  28),
                        	              new PointF(380F,  322F) };

	graph.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 void Form1_DoubleClick(object sender, System.EventArgs e)
{
	Graphics graph = this.CreateGraphics();
	Pen penCurrent = new Pen(Color.Blue);
	PointF[] pt     = {   new PointF(20F,  322F), new PointF(124, 24),
		              new PointF(214, 242), new PointF(275,  28),
		              new PointF(380F,  322F) };

		              graph.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 void Form1_DoubleClick(object sender, System.EventArgs e)
{
	Graphics graph = this.CreateGraphics();
	Pen penCurrent = new Pen(Color.Blue);
	PointF[] pt     = {   new PointF(20F,  322F), new PointF(124, 24),
			  new PointF(214, 242), new PointF(275,  28),
			  new PointF(380F,  322F) };

	graph.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 void Form1_DoubleClick(object sender, System.EventArgs e)
{
	Graphics graph = this.CreateGraphics();
	Pen penCurrent = new Pen(Color.Blue);
	PointF[] pt     = {   new PointF(20F,  322F), new PointF(124, 24),
		              new PointF(214, 242), new PointF(275,  28),
		              new PointF(380F,  322F) };

	graph.DrawCurve(penCurrent, pt, 1, 3, 1.750F);
}

This would produce:


 


A B閦ier Curve

 

A b閦ier 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閦ier curve could have been drawn using the following four points:


To draw a b閦ier 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閦ier line, you can use either four Point or PointF values or the coordinates of the four points. Here is an example:

private void button1_Click(object sender, System.EventArgs e)
{
	Graphics graph = this.CreateGraphics();
	Pen penCurrent = new Pen(Color.Blue);
	Point pt1 = new Point(20,  12),
	         pt2 = new Point(88, 246),
	         pt3 = new Point(364, 192),
	         pt4 = new Point(250,  48);
	graph.DrawBezier(penCurrent, pt1, pt2, pt3, pt4);
}

This would produce:



A Series of B閦ier Curves

 

The Graphics.DrawBezier() method is used to draw one b閦ier curve. If you want to draw many b閦ier 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閦ier curve can be drawn as follows and produce the same result:

private void button1_Click(object sender, System.EventArgs e)
{
	Graphics graph = this.CreateGraphics();
	Pen penCurrent = new Pen(Color.Blue);
	Point[] pt = { new Point(20,  12), new Point(88, 246),
		      new Point(364, 192), new Point(250,  48) };
	graph.DrawBeziers(penCurrent, pt);
}

The advantage of using DrawBeziers() is that it allows you to draw a b閦ier curve using 7Point or PointF values. Here is an example:

private void button1_Click(object sender, System.EventArgs e)
{
	Graphics graph = this.CreateGraphics();
	Pen penCurrent = new Pen(Color.Blue);
	Point[] pt = { 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) };
	graph.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 theGraphics.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 fourPoint or four PointF values. When executed, each of these methods gets together 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 void Form1_DoubleClick(object sender, System.EventArgs e)
{
	Graphics graph  = this.CreateGraphics();
	Pen penCurrent = new Pen(Color.Red);
	Point[] pt           = { new Point(40,  42), new Point(188, 246),
		                new Point(484, 192), new Point(350,  48) };

	graph.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.Drawing2Dnamespace. The FillMode enumerator has two members: Alternate and Winding. Here is an example:

private void Form1_DoubleClick(object sender, System.EventArgs e)
{
	Graphics graph = this.CreateGraphics();
	Pen penCurrent = new Pen(Color.Red);
	Point[] pt     = { new Point(40,  42), new Point(188, 246),
		       new Point(484, 192), new Point(350,  48) };

	graph.DrawClosedCurve(penCurrent, pt, 0.75F, FillMode.Winding);
}

This would produce:


 

 

时间: 2024-08-02 02:21:58

GDI+: Curved Shapes的相关文章

GDI+ Tutorial for Beginners

原文 GDI+ Tutorial for Beginners GDI+ is next evolution of GDI. Using GDI objects in earlier versions of Visual Studio was a pain. In Visual Studio .NET, Microsoft has taken care of most of the GDI problems and have made it easy to use. GDI+ resides in

gdi+-GDI+中一个窗体的CDC* pDC实例化两个Graphics对象问题

问题描述 GDI+中一个窗体的CDC* pDC实例化两个Graphics对象问题 代码如下:void CMyCtrl::Draw(CDC* pDC CRect rc){ Pen pen(Color(255 255 255 255)(float)1.5); SolidBrush solidbrush(Color(255 213 213 213)); pen.SetDashStyle((DashStyle)DashStyleSolid); Graphics Test(pDC->m_hDC); Tes

c++- 我用VS2010的GDI+写了双缓冲为什么还是画面抖动?

问题描述 我用VS2010的GDI+写了双缓冲为什么还是画面抖动? public: Graphics *gg; Graphics g=dc.GetSafeHdc(); gg->DrawImage(bk,0,0); gg->DrawImage(zj,x,y,0+frame*100,0,100,120,UnitPixel); g.DrawImage(&bb,0,0); 解决方案 Graphics g=dc.GetSafeHdc();此处的dc是兼容dc吗?若不是,建议使用兼容dc. 解决方

gdi+-vs2012调试时出现异常

问题描述 vs2012调试时出现异常 win8 x64 下安装了vs2012 补丁到update 3,一直正常使用,昨天觉得系统有点慢,就还原了下原来的做得ghost备份.vs2012变成了update 1. 悲剧发生了,所有的winform源代码都出现了问题:可以编译生成程序,但是不能调试,一启动调试,就出现"未正确初始化 GDI+ (内部 GDI+ 错误).",是在窗体InitializeComponent时提示的错误. 将vs2012补丁更新到update 3,仍然显示同样的错误

C# 数据库系统中使用GDI+绘制柱状图

在C#+SQL Server数据库做系统中,通常需要对数据库中的数据进行绘制图形报表方便经理查看,虽然有很多实用的水晶报表控件和图表控件实现该功能,但我还是想讲讲如何使用GDI绘制简单的柱状图.(推荐大家不要手画,尽量使用已有控件函数绘制) 一.前言 我们在使用C#+SQL Server做的简单应用系统是一个手机销售的系统,所以它有不同手机品牌和不同年份销售手机的利润和数量的柱状图,方便公司经理查看那个月和那种品牌手机销售更好,方便进货增加企业利润.其中它点击"输入年份",查看&quo

Fireworks MX2004之Shapes工具组应用实例一 变形花朵

应用实例 在FWMX2004之Shapes初探系列的教程中,曾经给大家演示了用工具箱Shapes工具组的Star(星形)工具制作的一个变形的花朵效果,不知道大家是否还记得,这里我们再次制作了一种变形花朵效果,如下图所示: 如果大家对Star工具已经钻研的比较透彻的话,应该对实现这样的效果不陌生,因为我们在FWMX2004中来实现这种效果可以说是轻而易举的,不信的话,请跟我来吧! 1.打开FWMX2004,新建文件,大小.背景色随意. 2.选取工具箱的Shapes形状组的Star绘制工具,在编辑区

FWMX2004 之 Shapes 初体验(二)

大家好,欢迎大家回来继续和我一起早早体验FWMX2004之Shapes带给我们的全新体验! 在上一节,我们一起详细的研究了工具箱上的Shapes工具组的使用方法,操作技巧,本节我们就来看看Shapes浮动面板带给我们的新奇感受吧! 首先我们再次来看看Shapes浮动面板都有哪些新东西: 可以看到,Shapes面板里面目前共有9个形状组:Clock(钟表).Cog(齿轮).Cube(立方体).Cylinder(圆柱体).Frame(像框).Perspective(透视图).Tabs(制表符).Ta

Fireworks MX2004 之Shapes初体验

估计最近让大家高兴的一个消息无外于是MM公司刚刚推出的"三剑客"MX2004试用版了!想必大家都已经开始试用了吧!这里我们不谈别的,只管来看FWMX2004,呵呵,FWMX2004到底还是真的带给了我们一些让我们心动的东西:更新的软件界面:虚线描边的加入:增强的模糊滤镜--添加了动态模糊.径向模糊等滤镜:完美的双字节支持--对于汉语的支持非常棒了:更加亲和的材质填充展现:增强的位图颜色替换.处理工具:当然还有我们今天要重点谈到的Shapes--好多漂亮的Shapes等我们来使用啊!那么

Fireworks MX2004之Shapes工具组应用实例 -- 变形花朵

应用实例 在FWMX2004之Shapes初探系列的教程中,曾经给大家演示了用工具箱Shapes工具组的Star(星形)工具制作的一个变形的花朵效果,不知道大家是否还记得,这里我们再次制作了一种变形花朵效果,如下图所示: 如果大家对Star工具已经钻研的比较透彻的话,应该对实现这样的效果不陌生,因为我们在FWMX2004中来实现这种效果可以说是轻而易举的,不信的话,请跟我来吧! 1.打开FWMX2004,新建文件,大小.背景色随意. 2.选取工具箱的Shapes形状组的Star绘制工具,在编辑区