模塊5 曲線和曲面
一 實(shí)驗(yàn)?zāi)康?/strong>
- 編寫曲線和曲面的算法
二 實(shí)驗(yàn)內(nèi)容
1:繪制Bezier曲線,并采用自行設(shè)計(jì)輸入和交互修改數(shù)據(jù)點(diǎn)的方式。
實(shí)驗(yàn)結(jié)果如下圖所示:
第一步:輸入特征多邊形的頂點(diǎn)個(gè)數(shù),并按照順序輸入頂點(diǎn)的坐標(biāo)。
第二步:點(diǎn)擊左鍵生成bezier曲線(白色部分)和多邊形頂點(diǎn)(綠色部分)。
?
第三步:點(diǎn)擊右鍵修改頂點(diǎn),首先輸入需要修改的頂點(diǎn)在數(shù)組中的坐標(biāo)(即順序個(gè)數(shù)-1),此處以(100,100)為例,將其修改為(100,300)。
第四步:通過敲擊回車鍵,可觀察修改后的bezier曲線和頂點(diǎn)。
?
第五步:如果需要繼續(xù)修改頂點(diǎn)坐標(biāo),用戶可以繼續(xù)點(diǎn)擊右鍵,重復(fù)上述操作。此處不再贅述。如果需要退出圖像繪制界面,用戶可以通過敲擊esc鍵,即可退出本實(shí)驗(yàn)界面。
2:繪制Bezier曲面,雙三次類型。
實(shí)驗(yàn)結(jié)果如下圖所示:
2.1:繪制Bezier曲面,并采用自行設(shè)計(jì)輸入和交互修改數(shù)據(jù)點(diǎn)的方式,改進(jìn)。
實(shí)驗(yàn)結(jié)果如下圖所示:
修改數(shù)據(jù)點(diǎn):
?
新貝塞爾曲面:
三 程序說明
最終的實(shí)驗(yàn)代碼如下表所示:
1題 |
// // 程序名稱:Bezier曲線 // 功??? 能:繪制Bezier曲線,并采用自行設(shè)計(jì)輸入和交互修改數(shù)據(jù)點(diǎn)的方式。 // 編譯環(huán)境:VS2019,EasyX_20220116 // 最后修改:2022-4-28 #include <graphics.h> #include <conio.h> #include <iostream> #include <math.h> using namespace std; //特征多邊形的特征 int n; int px[100], py[100]; //初始化特征多邊形 void initialize() { ??? cout << "please input the number of your points (no more than 100)" << endl; ??? cin >> n; ??? cout << "please input each coordinate of your points in order" << endl; ??? for (int i = 0; i < n; i++) { ???????? cin >> px[i] >> py[i]; ??? } ??? cout << "successfully set" << endl; }文章來源地址http://www.zghlxwxcb.cn/news/detail-456478.html //遞歸 int Factorial(int nn) { ??? if (nn == 0 || nn == 1) return 1; ??? else return nn * Factorial(nn - 1); } //繪制bezier曲線 void Bezier() { ??? int nn = n - 1; ??? //line(px[0], py[0], px[1], py[1]); ??? double i = 0, n1, n2; ??? n1 = Factorial(nn); ??? moveto(px[0], py[0]); ??? POINT point; ??? //在[0,1]內(nèi)循環(huán) ??? for (; i <= 1; i += 0.01) { ???????? point.x = 0; ???????? point.y = 0; ???????? for (int j = 0; j <= nn; j++) { ???????????? n2 = (n1 / (Factorial(j) * Factorial(nn - j))) * pow(i, j) * pow(1 - i, nn - j); ???????????? point.x += n2 * px[j]; ???????????? point.y += n2 * py[j]; ???????? } ???????? lineto(point.x, point.y); ??? } ??? lineto(px[n - 1], py[n - 1]); ??? //描繪用戶定義的點(diǎn) ??? for (int ii = 0; ii < n; ii++) { ???????? setfillcolor(GREEN); ???????? fillcircle(px[ii], py[ii], 3); ??? } } //主函數(shù) int main() { ??? //初始化 ??? initialize(); ??? initgraph(640, 480); ??? ExMessage m; ??? //繪制圖像 ??? while (1) { ???????? m = getmessage(EX_MOUSE | EX_KEY); ???????? switch (m.message) { ???????????? //右鍵修改坐標(biāo)信息 ???????? ??? case WM_RBUTTONDOWN: ????????????????? closegraph(); ????????????????? int arr, newx, newy; ????????????????? //輸入數(shù)組中的坐標(biāo),進(jìn)行修改 ????????????????? cout << "which point do you want to change? please input its array number" << endl; ????????????????? while (1) { ????????????????????? cin >> arr; ????????????????????? if (arr >= n) { ????????????????????????? cout << "input error, try again" << endl; ????????????????????? } ????????????????????? else { ????????????????????????? break; ????????????????????? } ????????????????? } ????????????????? cout << "please input the reset coordinate" << endl; ????????????????? cin >> newx >> newy; ????????????????? px[arr] = newx; ????????????????? py[arr] = newy; ????????????????? cout << "successfully reset, please wait a second to see a new graph" << endl; ????????????????? initgraph(640, 480); ???????????? //左鍵繪制 ???????????? case WM_LBUTTONDOWN: ????????????????? Bezier(); ???????????? //退出圖形化界面 ???????????? case WM_KEYDOWN: ????????????????? if (m.vkcode == VK_ESCAPE) { ????????????????????? return 0; ????????????????? } ???????? } ??? } ??? _getch(); ??? closegraph(); ??? return 0;文章來源:http://www.zghlxwxcb.cn/news/detail-456478.html } |
2題 |
// // 程序名稱:Bezier曲面 // 功??? 能:繪制Bezier曲面,雙三次類型。 // 編譯環(huán)境:VS2019,EasyX_20220116 // 最后修改:2022-5-9 #include <graphics.h> #include <conio.h> #include <iostream> #include <cmath> using namespace std; #define pi 3.1415926 #define MAX 20 //三維點(diǎn)類 class Point3D { public: ??? double x, y, z; ??? Point3D(int x = 0, int y = 0, int z = 0) { ???????? this->x = x; ???????? this->y = y; ???????? this->z = z; ??? }; ??? void operator=(Point3D& a) { ???????? x = a.x; ???????? y = a.y; ???????? z = a.z; ??? }; ??? Point3D operator*(double a) { ???????? return Point3D(a * x, a * y, a * z); ??? }; ??? Point3D operator+(Point3D a) { ???????? return Point3D(x + a.x, y + a.y, z + a.z); ??? }; ??? void operator+=(Point3D a) { ???????? x += a.x; ???????? y += a.y; ???????? z += a.z; ??? }; }; //求階乘 long int Factorial(int n) { ??? int i, sum = 1; ??? if (n == 0) { ???????? return 1; ??? } ??? for (i = 2; i <= n; i++) { ???????? sum *= i; ??? } ??? return sum; } //Bernstein函數(shù) double Bernstein(int i, int n, double t) { ??? return (double)Factorial(n) / Factorial(i) / Factorial(n - i) * pow(t, i) * pow(1 - t, n - i); } //Bezier曲面求解 void BezierCurve(Point3D p[][MAX], int n, int m, int nd, int md, double sita, double fai) { ??? double hu = 1.0 / nd; ??? double hv = 1.0 / md; ??? double u = 0, v = 0; ??? int i, j, k, l; ??? sita = sita * pi / 180; ??? fai = fai * pi / 180; ??? int** pB = new int* [nd + 1]; ??? for (i = 0; i <= nd; i++) { ???????? pB[i] = new int[2 * md + 2]; ??? } ??? Point3D ptemp(0, 0, 0); ??? for (i = 0; i <= nd; i++, u += hu) { ???????? v = 0; ???????? for (j = 0; j <= 2 * md + 1; j += 2, v += hv) { ???????????? ptemp.x = 0; ???????????? ptemp.y = 0; ???????????? ptemp.z = 0; ???????????? for (k = 0; k <= n; k++) { ????????????????? for (l = 0; l <= m; l++) { ????????????????????? ptemp += p[k][l] * Bernstein(k, n, u) * Bernstein(l, m, v); ????????????????? } ???????????? } ???????????? pB[i][j] = ptemp.x * cos(sita) - ptemp.y * sin(sita) + 500; ???????????? pB[i][j + 1] = -ptemp.x * sin(sita) * sin(fai) - ptemp.y * cos(sita) * sin(fai) + ptemp.z * cos(fai) + 400; ???????? } ???????? drawpoly(md + 1, pB[i]); ??? } ??? for (i = 0; i < nd + 1; i++) { ???????? delete[]pB[i]; ??? } ??? delete[]pB; } //畫控制多邊形 void drawControlPoly_3D(Point3D p[][MAX], int n, int m, double sita, double fai, int color) { ??? int** p2d = new int* [n + 1]; ??? int i, j; ??? setcolor(color); ??? sita = sita * pi / 180; ??? fai = fai * pi / 180; ??? for (i = 0; i < n + 1; i++) { ???????? p2d[i] = new int[2 * m + 4]; ??? } ??? char str[80]; ??? //3D->2D ??? for (i = 0; i <= n; i++) { ???????? for (j = 0; j <= m; j++) { ???????????? p2d[i][2 * j] = p[i][j].x * cos(sita) - p[i][j].y * sin(sita) + 500; ???????????? p2d[i][2 * j + 1] = -p[i][j].x * sin(sita) * sin(fai) - p[i][j].y * cos(sita) * sin(fai) + p[i][j].z * cos(fai) + 400; ???????? } ???????? p2d[i][2 * j] = p2d[i][0]; ???????? p2d[i][2 * j + 1] = p2d[i][1]; ???????? drawpoly(m + 2, p2d[i]); ??? } ??? for (j = 0; j <= 2 * m + 1; j += 2) { ???????? moveto(p2d[0][j], p2d[0][j + 1]); ???????? for (i = 1; i <= n; i++) { ???????????? lineto(p2d[i][j], p2d[i][j + 1]); ???????? } ??? } ??? for (i = 0; i < n + 1; i++) { ???????? delete[]p2d[i]; ??? } ??? delete[]p2d; } //雙幾次曲面 void BezierCurve_Shuang(Point3D p[][MAX], int pn, int pm, int nd, int md, double sita, double fai, int shuangjici) { ??? int i, j, k, l; ??? Point3D point[MAX][MAX]; ??? for (i = 0; i < pn - shuangjici; i += shuangjici) { ???????? for (j = 0; j < pm - shuangjici; j += shuangjici) { ???????????? for (k = 0; k <= shuangjici; k++) { ????????????????? for (l = 0; l <= shuangjici; l++) { ????????????????????? point[k][l] = p[i + k][j + l]; ????????????????? } ???????????? } ???????????? BezierCurve(point, shuangjici, shuangjici, nd, md, sita, fai); ???????? } ??? } } //主函數(shù) int main() { ??? int n; ??? double fai, sita; ??? //固定角度了。 ??? sita = 20; ??? fai = 160; ??? n = 3; ??? //頂點(diǎn)集合 ??? Point3D p[][MAX] = { ???????? {Point3D(0,0,0),Point3D(150,150,150),Point3D(250,150,150),Point3D(400,0,0)}, ??? ??? {Point3D(50,200,0),Point3D(150,250,150),Point3D(250,250,150),Point3D(450,200,0)}, ??? ??? {Point3D(20,400,0),Point3D(150,350,150),Point3D(250,350,150),Point3D(420,400,0)}, ??? ??? {Point3D(0,600,0),Point3D(150,550,150),Point3D(250,550,150),Point3D(400,600,0)} ??? }; ??? /* ??? cout << "please input sita and fai" << endl; ??? cin >> sita >> fai; ??? cout << "please input your n" << endl; ??? cin >> n; ??? */ ??? //初始化界面 ??? initgraph(1000, 700); ??? setcolor(RED); ??? //Bezier曲面 ??? BezierCurve_Shuang(p, 4, 4, 100, 100, sita, fai, n); ??? //畫控制多邊形 ??? drawControlPoly_3D(p, 3, 3, sita, fai, GREEN); ??? _getch(); ??? closegraph(); ??? return 0; } |
2題改進(jìn)版本 |
// // 程序名稱:Bezier曲面 // 功??? 能:繪制Bezier曲面,并采用自行設(shè)計(jì)輸入和交互修改數(shù)據(jù)點(diǎn)的方式。 // 編譯環(huán)境:VS2019,EasyX_20220116 // 最后修改:2022-5-13 #include <iostream> #include <graphics.h> #include <conio.h> #include <math.h> using namespace std; #define PI 3.1415926 //定義 N * N 的控制點(diǎn)數(shù)組 const int N = 8; float controlPoints[N][N][3] ={ ??? { {-150, -150, 100}, {-100, -150, 0}, {-50, -150, 0}, {0, -150, 50}, {50, -150, 0}, {100, -150, 0}, {150, -150, -100}, {200, -150, 0} }, ??? { {-150, -100, 0}, {-100, -100, 50}, {-50, -100, -100}, {0, -100, 0}, {50, -100, 0}, {100, -100, 100}, {150, -100, 0}, {200, -100, -50} }, ??? { {-150, -50, 0}, {-100, -50, 0}, {-50, -50, 50}, {0, -50, 0}, {50, -50, 0}, {100, -50, 0}, {150, -50, -50}, {200, -50, 0} }, ??? { {-150, 0, -50}, {-100, 0, -100}, {-50, 0, 0}, {0, 0, 150}, {50, 0, 0}, {100, 0, -100}, {150, 0, -50}, {200, 0, -50} }, ??? { {-150, 50, 0}, {-100, 50, 0}, {-50, 50, -100}, {0, 50, 0}, {50, 50, 50}, {100, 50, 0}, {150, 50, 0}, {200, 50, 50} }, ??? { {-150, 100, 50}, {-100, 100, 0}, {-50, 100, 0}, {0, 100, -50}, {50, 100, -50}, {100, 100, 50}, {150, 100, 0}, {200, 100, 0} }, ??? { {-150, 150, 0}, {-100, 150, 100}, {-50, 150, -100}, {0, 150, 0}, {50, 150, 0}, {100, 150, 0}, {150, 150, -150}, {200, 150, 50} }, ??? { {-150, 200, 0}, {-100, 200, 0}, {-50, 200, 50}, {0, 200, -50}, {50, 200, 0}, {100, 200, -100}, {150, 200, 0}, {200, 200, 50} } }; //計(jì)算貝塞爾基函數(shù)的C值 int C(int n, int k) { ??? if (k > n) { ??????? return 0; ??? } ??? int c = 1; ??? for (int i = 0; i < k; i++) { ??????? c *= (n - i); ??????? c /= (i + 1); ??? } ??? return c; } //勾勒函數(shù) void display(float x, float y, float z) { ??? putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400), int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300), RED); ??? putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400) + 1, int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300), RED); ??? putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400) - 1, int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300), RED); ??? putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400), int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300) + 1, RED); ??? putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400), int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300) - 1, RED); ??? putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400) + 1, int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300) + 1, RED); ??? putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400) + 1, int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300) - 1, RED); ??? putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400) - 1, int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300) + 1, RED); ??? putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400) - 1, int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300) - 1, RED); } //Bezier曲面繪制 void Bezier() { ??? //繪制控制點(diǎn) ??? for (int i = 0; i < N - 1; i++) { ??????? for (int j = 0; j < N - 1; j++) { ??????????? fillcircle(int(0.7071 * controlPoints[i][j][0] - 0.7071 * controlPoints[i][j][1] + 0.5f + 400), int(-0.4082 * controlPoints[i][j][0] - 0.4082 * controlPoints[i][j][1] + 0.8165 * controlPoints[i][j][2] + 0.5f + 300), 3); ??????? } ??? } ??? // 繪制貝塞爾曲面 ??? const int nPoints = 50;? // 每行/列計(jì)算的點(diǎn)數(shù) ??? float uStep = 1.0f / nPoints; ??? float vStep = 1.0f / nPoints; ??? for (float u = 0; u < 1; u += uStep) { ??????? for (float v = 0; v < 1; v += vStep) { ??????????? float x = 0, y = 0, z = 0; ??????????? for (int i = 0; i < N; i++) { ??????????????? for (int j = 0; j < N; j++) { ??????????????????? // 計(jì)算貝塞爾基函數(shù)的值 ??????????????????? float basisU = powf(1 - u, N - 1 - i) * powf(u, i) * float(C(N - 1, i)); ??????????????????? float basisV = powf(1 - v, N - 1 - j) * powf(v, j) * float(C(N - 1, j)); ??????????????????? float basis = basisU * basisV; ??????????????????? // 使用貝塞爾基函數(shù)的值和控制點(diǎn)計(jì)算曲面上的點(diǎn) ??????????????????? x += basis * controlPoints[i][j][0]; ??????????????????? y += basis * controlPoints[i][j][1]; ??????????????????? z += basis * controlPoints[i][j][2]; ??????????????? } ??????????? } ??????????? // 將曲面上的點(diǎn)連接起來 ??????????? display(x, y, z); ??????? } ??? } } //主函數(shù) int main(){ ??? initgraph(800, 600); ??? Bezier(); ??? ExMessage m; ??? while (1) { ??????? m = getmessage(EX_MOUSE | EX_KEY); ??????? switch (m.message) { ??????? case WM_RBUTTONDOWN: ??????????? //右鍵修改坐標(biāo)信息 ??????????? closegraph(); ??????????? int row, column, newx, newy, newz; ??????????? //輸入數(shù)組中的坐標(biāo),進(jìn)行修改 ??????????? cout << "which point do you want to change? please input its row & column array number" << endl; ??????????? while (1) { ??????????????? cin >> row; ??????????????? cin >> column; ??????????????? if (row >= N) { ??????????????????? cout << "row number input error, try again" << endl; ??????????????? } ??????????????? else if (column >= N) { ??????????????????? cout << "column number input error, try again" << endl; ??????????????? } ??????????????? else { ??????????????????? break; ??????????????? } ??????????? } ??????????? cout << "please input the reset coordinate" << endl; ??????????? cin >> newx >> newy >> newz; ??????? ????controlPoints[row][column][0] = newx; ??????????? controlPoints[row][column][1] = newy; ??????????? controlPoints[row][column][2] = newz; ??????????? cout << "successfully reset, please wait a second to see a new graph" << endl; ??????????? initgraph(800, 600); ??????? case WM_LBUTTONDOWN: ??????????? //左鍵繪制 ??????????? Bezier(); ??????? case WM_KEYDOWN: ??????????? //退出圖形化界面 ??????????? if (m.vkcode == VK_ESCAPE) { ??????????????? return 0; ??????????? } ??????? } ??? } ??? ??? _getch(); ??? closegraph(); ??? return 0; } |
到了這里,關(guān)于【計(jì)算機(jī)圖形學(xué)】曲線和曲面的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!