第二章【续集】 图形和函数图像的绘制
前面我们详细介绍了C语言绘制常见图形和正弦余弦图像的方法,此篇文章为上一篇(http://blog.csdn.net/duanxu_yzc/article/details/12745757,强烈建议:先看上一篇再看续集!!!)的继续,主要有以下内容:
圆形和抛物线的绘制
绘制函数图像的第二种方法
同一坐标系下绘制多个函数图像(交叉图像)
4、圆形和抛物线的绘制
有了前面绘制三角函数图像的基础,圆形和抛物线的绘制应该非常简单,我们以圆形为例说明:
a、观察需要绘制的图像
每行需要输出两个点,而且图像左右轴对称
b、使用的函数:(x-10)2+(y-10)2=102
c、输出21行,行坐标间距为1
d、左半圆的列号:10-sqrt(100-(r-10)*(r-10))
右半圆的列号:10+sqrt(100-(r-10)*(r-10))
e、调整输出行宽比(因屏幕的行宽比不是一比一,因此不进行调整会导致输出为椭圆)
按照以上步骤编写代码如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
/* * 绘制圆形(圆心坐标(10,10),半径为10) */ #include <stdio.h> #include <math.h> int main ( void ) { int rows; int r; int c; float adjust; rows = 20; adjust = 2. 3; // 屏幕行宽比(输出屏幕行间距和列间距不同,用adjust作为调整) for ( r= 20; r>= 0; r-- ) { // 左半圆 for ( c= 0; c<adjust*( 10-sqrt( 100-(r- 10)*(r- 10))); c++ ) printf ( " " ); printf ( "*" ); // 右半圆 for ( ; c<adjust*( 10+sqrt( 100-(r- 10)*(r- 10))); c++ ) printf ( " " ); printf ( "*" ); printf ( "\n" ); } return 0; } |
得到的图像:
抛物线的绘制与圆形极为相似,直接上代码和结果:
/* * 绘制抛物线 */ #include <stdio.h> #include <math.h> int main ( void ) { int rows; int r; int c; double adjust = 2.3; rows = 20; for ( r=rows; r>=0; r-- ) { for ( c=0; c<adjust*(10-sqrt(5*r)); c++ ) printf ( " " ); printf ( "*" ); for ( ; c<adjust*(10+sqrt(5*r)); c++ ) printf ( " " ); printf ( "*" ); printf ( "\n" ); } return 0; }
5、绘制函数图像的第二种方法
到目前为止,我们使用的方法都是逐行输出,然后通过反函数找到每行需要输出星号的位置,最后通过输出相应个数的空格,确定星号的位置,输出星号。现在介绍另外一种方法,其实与已知的方法很相似,区别在于不需要先输出空格来确定星号的位置,而是逐个判断每行中的各列需要输出的字符是空格还是星号,以圆形为例,每行中,只有列号(调整比例后的)为adjust*(10-sqrt(5*r)和adjust*(10+sqrt(5*r)的位置需要输出星号,其余位置均输出空格。按照这个方法我们重新编写程序如下:
/* * 绘制圆形(圆心坐标(10,10),半径为10)的另一种方法 */ #include <stdio.h> #include <math.h> int main ( void ) { int rows; int r; int c; int left; int right; float adjust = 2.3; rows = 20; for ( r=rows; r>=0; r-- ) { left = adjust*(10-sqrt(100-(r-10)*(r-10))); // 左半圆的列号(将浮点转化为整型) right = adjust*(10+sqrt(100-(r-10)*(r-10))); // 右半圆的列号(将浮点转化为整型) for ( c=0; c<=adjust*20; c++ ) { if ( c == left || c == right ) printf ( "*" ); else printf ( " " ); } printf ( "\n" ); } return 0; }得到图像:
(这个图像与前一种方法绘制的图像有一处明显不同,为什么?请读者思考。)
6、同一坐标系下绘制多个函数图像(交叉图像)
我们来观察一下直线和圆在同一坐标系下相交的图形:
同样,这个图像也需要逐行输出,如果按照第一种绘制方法,就需要确定每行中星号的位置,我们发现,图像上半部分的星号依次出现在:左半圆、右半圆、直线,中间部分是:左半圆、直线、右半圆,下半部分是:直线、左半圆、右半圆,这使得我们需要在程序中需要针对不同的行段采取不同的输出顺序,如果图像更复杂的话,这同情况会变得更糟糕。我们再看看第二种绘制方法,这种方法只需要知道哪些地方需要输出星号,并不需要明确的顺序,因此更适合这种交叉图像输出的情况,下面是绘制直线和圆的代码和结果:
/* * 同一坐标系下绘制圆形和直线 */ #include <stdio.h> #include <math.h> int main ( void ) { int rows = 20; int r; int c; int round_l; int round_r; int line; float adjust = 2.3; for ( r=rows; r>=0; r-- ) { round_l = adjust*(10-sqrt(100-(r-10)*(r-10))); round_r = adjust*(10+sqrt(100-(r-10)*(r-10))); line = adjust*r; for ( c=0; c<=adjust*20; c++ ) if ( ( c == round_l && c == line ) || ( c == round_r && c == line ) ) printf ( "+" ); // 交叉的点标记'+' else if ( c == round_l || c == round_r ) printf ( "*" ); // 圆形边界标记'*' else if ( c == line ) printf ( "+" ); // 直线标记'+' else printf ( " " ); // 其它位置标记空格 printf ( "\n" ); } return 0; }
使用同样的方法绘制余弦和正弦的交叉图像如下:
/* * 同一坐标系中绘制余弦和正弦图像 */ #include <stdio.h> #include <math.h> #define PI 3.14 int main ( void ) { int rows = 20; float r; int c; int sin_1; int sin_2; int sin_3; int sin_4; int cos_1; int cos_2; float adjust = 10; for ( r=1; r>0; r-=0.1 ) { sin_1 = adjust * asin(r); sin_2 = adjust * (PI-asin(r)); cos_1 = adjust * acos(r); cos_2 = adjust * (2*PI-acos(r)); for ( c=0; c<=adjust*2*PI; c++ ) if ( ( c == sin_1 && c == cos_1 ) || ( c == sin_2 && c == cos_1 ) || ( c == sin_1 && c == cos_2 ) || ( c == sin_2 && c == cos_2 ) ) printf ( "+" ); else if ( c == sin_1 || c == sin_2 ) printf ( "*" ); else if ( c == cos_1 || c == cos_2 ) printf ( "+" ); else printf ( " " ); printf ( "\n" ); } for ( r=0; r>=-1; r-=0.1 ) { sin_3 = adjust * (PI-asin(r)); sin_4 = adjust * (2*PI+asin(r)); cos_1 = adjust * acos(r); cos_2 = adjust * (2*PI-acos(r)); for ( c=0; c<=adjust*2*PI; c++ ) if ( ( c == sin_3 && c == cos_1 ) || ( c == sin_4 && c == cos_1 ) || ( c == sin_3 && c == cos_2 ) || ( c == sin_4 && c == cos_2 ) ) printf ( "+" ); else if ( c == sin_3 || c == sin_4 ) printf ( "*" ); else if ( c == cos_1 || c == cos_2 ) printf ( "+" ); else printf ( " " ); printf ( "\n" ); } return 0; }
本章总结
图形输出是C语言初学者经常遇到的问题,实际上大多数简单的图形并不需要使用复杂的控制结构,所见即所得的方法更加简洁,不过对于复杂的图形或者函数图像,使用控制结构会更好。在使用控制结构输出图形时,要把握一个原则:只能逐行输出,因此,在输出一行时必须把这一行中所有需要输出的字符全部输出,所以,找到每行中各个位置需要输出的字符(或者说,各字符在每行中的位置)尤为关键!我们有两种方法来确定位置,其中第二种方法更通用简洁。在输出图形时,特别是函数图像,要充分利用对称、平移关系简化程序,另外,要注意调节屏幕的行宽比和适当的图像放大,防止图像失真。
声明
1、此博文版权归断絮所有,如需转载请注明出处http://blog.csdn.net/duanxu_yzc/article/details/12970225,谢谢。
2、在未经博主断絮允许的情况下,任何个人和机构都不得以任何理由出版此文章,否则必将追究法律责任!