【續集】 C語言圖形和函式影象的繪製【其他部分 第二章】
第二章【續集】 圖形和函式影象的繪製
圓形和拋物線的繪製
繪製函式影象的第二種方法
同一座標系下繪製多個函式影象(交叉影象)
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、調整輸出行寬比(因螢幕的行寬比不是一比一,因此不進行調整會導致輸出為橢圓)
按照以上步驟編寫程式碼如下:
C++ Code By DuanXu-yzc
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 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語言初學者經常遇到的問題,實際上大多數簡單的圖形並不需要使用複雜的控制結構,所見即所得的方法更加簡潔,不過對於複雜的圖形或者函式影象,使用控制結構會更好。在使用控制結構輸出圖形時,要把握一個原則:只能逐行輸出,因此,在輸出一行時必須把這一行中所有需要輸出的字元全部輸出,所以,找到每行中各個位置需要輸出的字元(或者說,各字元在每行中的位置)尤為關鍵!我們有兩種方法來確定位置,其中第二種方法更通用簡潔。在輸出圖形時,特別是函式影象,要充分利用對稱、平移關係簡化程式,另外,要注意調節螢幕的行寬比和適當的影象放大,防止影象失真。
宣告
2、在未經博主斷絮允許的情況下,任何個人和機構都不得以任何理由出版此文章,否則必將追究法律責任!