計算機輔助與圖形學作業(一)——畫直線,畫橢圓,實現軸對稱

如需轉載本文,請註明出處。

前段時間有個圖形學的課程作業,花了點時間做了出來,今天在這裏分享一下供後來者學習、借鑑(其實就是粘貼複製,大家懂的,嘿嘿)。

首先,聲明一下所用的環境爲:VS2015+EasyX圖形庫。因爲要實現繪圖,最好有專門的庫,MFC也可以實現繪圖,不過太麻煩。其中EasyX圖形庫官網地址爲:https://easyx.cn,直接點擊下載,然後傻瓜式安裝即可。而且EasyX圖形庫調用的接口也很簡單。

接下來該說一下實現的需求了:

  1. 實現繪製直線的功能
  2. 實現繪製橢圓的功能
  3. 實現對稱的功能

然後先上結果給大家看一下,畢竟這個纔有說服力。

其中,黃色的爲橢圓,紅色的爲對稱軸直線,綠色的兩條直線,一條爲原始圖形,使用繪圖算法畫的,另一條爲對稱得到的圖形。爲了看起來更美觀,設置了一個座標系。

接下來上源碼:

/*
	使用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;
}

源碼鏈接:https://github.com/xsgaaaa/Computer-Graphics-Homeworks

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章