如需轉載本文,請註明出處。
前段時間有個圖形學的課程作業,花了點時間做了出來,今天在這裏分享一下供後來者學習、借鑑(其實就是粘貼複製,大家懂的,嘿嘿)。
首先,聲明一下所用的環境爲:VS2015+EasyX圖形庫。因爲要實現繪圖,最好有專門的庫,MFC也可以實現繪圖,不過太麻煩。其中EasyX圖形庫官網地址爲:https://easyx.cn,直接點擊下載,然後傻瓜式安裝即可。而且EasyX圖形庫調用的接口也很簡單。
接下來該說一下實現的需求了:
- 實現繪製直線的功能
- 實現繪製橢圓的功能
- 實現對稱的功能
然後先上結果給大家看一下,畢竟這個纔有說服力。
其中,黃色的爲橢圓,紅色的爲對稱軸直線,綠色的兩條直線,一條爲原始圖形,使用繪圖算法畫的,另一條爲對稱得到的圖形。爲了看起來更美觀,設置了一個座標系。
接下來上源碼:
/*
使用EasyX圖形庫來構造繪圖環境
實現中點畫線、bresenham畫線、橢圓的畫法、對稱的畫法
默認座標原點在左上方
這裏新設置一個座標系,原點在屏幕中心
*/
#include <iostream>
#include <graphics.h>
#include<conio.h>
using namespace std;
void coordinatetransform(int &x, int &y) //座標系轉換,將新座標系轉換到原始座標系
{
x = x + 640;
y = 480 - y;
}
//對點進行對稱變換
void wholecolor(int xc, int yc, int x, int y, int color)
{
putpixel(xc + x, yc + y, color);
putpixel(xc + x, yc - y, color);
putpixel(xc - x, yc + y, color);
putpixel(xc - x, yc - y, color);
}
//畫橢圓的算法
void DrawEllipse(int xc, int yc, int a, int b, int color)
{
coordinatetransform(xc, yc);
int x = 0, y = b;
int aa = a*a, bb = b*b;
int d = (int)(bb + aa*(-b + 0.25) + 0.5); //初始值
wholecolor(xc, yc, x, y, color);
while (bb*x < aa*y) //四分之一圓的上半部分
{
if (d < 0) {
d += bb*(2 * x + 3);
x++;
}
else{
d += bb*(2 * x + 3) + aa*(-2 * y + 2); y--; x++;
}
wholecolor(xc, yc, x, y, color);
}
d = (int)(bb*(x + 0.5)*(x + 0.5) + aa*(y - 1)*(y - 1) - aa*bb + 0.5);
while (y > 0) { //四分之一圓的下半部分
if (d > 0) {
d += aa*(-2 * y + 3);
y--;
}
else {
d += bb*(2 * x + 2) + aa*(-2 * y + 3);
x++; y--;
}
wholecolor(xc, yc, x, y, color);
}
}
//中點畫線法
void Midline(int x1, int y1, int x2, int y2, int color)
{
coordinatetransform(x1, y1);
coordinatetransform(x2, y2);
int x = x1, y = y1;
int a = y1 - y2, b = x2 - x1;
int cx = (b >= 0 ? 1 : (b = -b, -1));
int cy = (a <= 0 ? 1 : (a = -a, -1));
putpixel(x, y, color);
int d, d1, d2;
if (-a <= b) // 斜率絕對值 <= 1
{
d = 2 * a + b;
d1 = 2 * a;
d2 = 2 * (a + b);
while (x != x2)
{
if (d < 0)
y += cy, d += d2;
else
d += d1;
x += cx;
putpixel(x, y, color);
}
}
else // 斜率絕對值 > 1
{
d = 2 * b + a;
d1 = 2 * b;
d2 = 2 * (a + b);
while (y != y2)
{
if (d < 0)
d += d1;
else
x += cx, d += d2;
y += cy;
putpixel(x, y, color);
}
}
}
//Bresenham畫線算法
void Bresenham(int x1, int y1, int x2, int y2,int color)
{
coordinatetransform(x1, y1);
coordinatetransform(x2, y2);
int x, y, dx, dy, p1, i;
dx = x2 - x1;
dy = y2 - y1;
if (abs(dx) > abs(dy)) //斜率絕對值在(0,1),步進方向爲x軸
{
if (x1 < x2) //默認畫點從左往右畫
{
x = x1;
y = y1;
}
else
{
x = x2;
y = y2;
}
putpixel(x, y, color);
p1 = 2 * abs(dy) - abs(dx); //計算初始pi的值
for (i = min(x1, x2); i < max(x1, x2); i++)
{
x = x + 1;
if (p1 >= 0)
{
if (dx*dy >= 0)
y = y + 1;
else
y = y - 1; //若Pi>=0,y(i+1)=y(i)±1
p1 = p1 + 2 * (abs(dy) - abs(dx)); //更新pi
}
else
{
y = y; //若Pi<0,y(i+1)=y(i)
p1 = p1 + 2 * abs(dy); //更新pi
}
putpixel(x, y, color);
}
}
else
{
if (y1 < y2)
{ //步進方向爲y軸,默認畫點從下往上畫
x = x1;
y = y1;
}
else
{
x = x2;
y = y2;
}
putpixel(x, y, color);
p1 = 2 * abs(dx) - abs(dy);
for (i = min(y1, y2); i < max(y1, y2); i++)
{
y = y + 1;
if (p1 >= 0)
{
if (dx*dy >= 0) //判斷x方向是增加還是減少,很關鍵
x = x + 1;
else
x = x - 1;
p1 = p1 + 2 * (abs(dx) - abs(dy));
}
else
{
x = x;
p1 = p1 + 2 * abs(dx);
}
putpixel(x, y, color);
}
}
}
/*
此函數用於求對稱點
(x1,y1),(x2,y2) 確定對稱軸
(px,py) 爲待求的對稱點
(* symmetricX,* symmetricY) 爲(px,py)關於直線的對稱點
*/
void SymmetricPoint(int x1, int y1, int x2, int y2, int px, int py, int* symmetricX, int* symmetricY)
{
float A = (y1 - y2);
float B = (x2 - x1);
float C = x1*y2 - x2*y1;
float D = (A*px + B*py + C) / (A*A + B*B);
int x = int(double(px) - 2.0*A*D);
int y = int(double(py) - 2.0*B*D);
*symmetricX = x;
*symmetricY = y;
}
void init() //初始化圖形界面
{
initgraph(1280, 960); //初始化繪圖界面
line(0, 480, 1280, 480); //畫一條水平直線充當X軸
line(1270, 470, 1280, 480);
line(1270, 490, 1280, 480);
line(640, 0, 640, 960); //畫一條垂直直線充當Y軸
line(630, 10, 640, 0);
line(650, 10, 640, 0);
ellipse(650, 490, 660, 505); //畫個橢圓充當座標原點
}
int main()
{
init();
int xa, ya, xb, yb;
Midline(-100, -200, 300, 300,RED); //中點畫線法畫線,作爲對稱軸
Bresenham(30,70,-200,200,GREEN); //Bresenham畫線法畫線,作爲對稱直線
SymmetricPoint(-100, -200, 300, 300, 30, 70, &xa, &ya);
SymmetricPoint(-100, -200, 300, 300, -200, 200, &xb, &yb);
Bresenham(xa, ya,xb, yb, GREEN); //Bresenham畫線法畫線,作爲對稱後得到的直線
DrawEllipse(200, 200, 160, 100, YELLOW); //畫橢圓 中心(200,200) 長軸160 短軸100
system("pause");
closegraph(); //關閉圖形
return 0;
}