-
简介
- 这是自己计算机图形老师布置的一个简单的上机作业,叫我们把自己名字里的字扣出空心区域,然后进行填充
- 大致看了一下,好像没有这方面的文章,所以我来写一篇,给那些有类似题目的提供一下我的思路
- 主要使用的是 OpenGL,中点画线法 和 种子填充法
具体思路
- 首先先把所有的点给确定下来,因为中点画线法只能够画两点之间的线条
- 确定点坐标的过程很繁琐,你需要一个点一个点的确定
- 然后区域围成之后就可以使用种子填充了
- 在使用种子填充的时候注意一下对边界的判断
- 我的办法是在画点的时候就把该点置为 1,表示该点被使用过了
MyCode
#include <GL/glut.h>
#include<math.h>
#include<iostream>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
class Point {
public:
Point(int _x, int _y) {
x = _x;
y = _y;
}
int x, y;
};
double x00, y00, x11, y11;
int flag[2021][2021] = {0};
void Flood (int a, int b) {
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, -1, 0, 1 };
stack<Point> q;
q.push(Point(a, b));
flag[a + 1000][b + 1000] = 1;
while (q.size()) {
auto t = q.top();
q.pop();
for (int i = 0; i < 4; i++) {
int n = t.x + dx[i];
int m = t.y + dy[i];
cout << m << n << endl;
if (n < -1000 || n > 1000 || m < -1000 || m >= 1000) continue;
if (flag[n + 1000][m + 1000]) continue;
flag[n + 1000][m + 1000] = 1;
glBegin(GL_POINTS);
glColor3f(1, 0, 0);
glVertex2f((double)n / 1000, (double)m / 1000);
glEnd();
q.push(Point(n, m));
glFlush();
}
}
}
void MidPoint() {
vector<Point> line;
line.push_back(Point(100, 500));
line.push_back(Point(150, 500));
line.push_back(Point(0, 100));
line.push_back(Point(100, 500));
line.push_back(Point(0, 100));
line.push_back(Point(50, 100));
line.push_back(Point(130, 420));
line.push_back(Point(150, 500));
line.push_back(Point(50, 100));
line.push_back(Point(100, 300));
line.push_back(Point(130, 420));
line.push_back(Point(240, 420));
line.push_back(Point(100, 300));
line.push_back(Point(240, 300));
line.push_back(Point(240, 420));
line.push_back(Point(240, 300));
line.push_back(Point(100, 200));
line.push_back(Point(100, 250));
line.push_back(Point(100, 150));
line.push_back(Point(100, 100));
line.push_back(Point(100, 250));
line.push_back(Point(240, 250));
line.push_back(Point(240, 250));
line.push_back(Point(240, 200));
line.push_back(Point(100, 200));
line.push_back(Point(140, 200));
line.push_back(Point(200, 200));
line.push_back(Point(240, 200));
line.push_back(Point(140, 200));
line.push_back(Point(140, 150));
line.push_back(Point(100, 150));
line.push_back(Point(140, 150));
line.push_back(Point(200, 200));
line.push_back(Point(200, 150));
line.push_back(Point(200, 150));
line.push_back(Point(240, 150));
line.push_back(Point(240, 150));
line.push_back(Point(240, 100));
line.push_back(Point(100, 100));
line.push_back(Point(140, 100));
line.push_back(Point(200, 100));
line.push_back(Point(240, 100));
line.push_back(Point(140, 100));
line.push_back(Point(140, -100));
line.push_back(Point(200, 100));
line.push_back(Point(200, -10));
line.push_back(Point(200, -10));
line.push_back(Point(240, 10));
line.push_back(Point(140, -100));
line.push_back(Point(300, -20));
line.push_back(Point(240, 10));
line.push_back(Point(300, -20));
line.push_back(Point(400, 500));
line.push_back(Point(450, 500));
line.push_back(Point(300, 250));
line.push_back(Point(400, 500));
line.push_back(Point(300, 250));
line.push_back(Point(350, 250));
line.push_back(Point(350, 250));
line.push_back(Point(370, 300));
line.push_back(Point(430, 450));
line.push_back(Point(450, 500));
line.push_back(Point(430, 450));
line.push_back(Point(700, 450));
line.push_back(Point(390, 350));
line.push_back(Point(410, 400));
line.push_back(Point(410, 400));
line.push_back(Point(600, 350));
line.push_back(Point(560, 250));
line.push_back(Point(600, 350));
line.push_back(Point(390, 350));
line.push_back(Point(560, 250));
line.push_back(Point(370, 300));
line.push_back(Point(520, 150));
line.push_back(Point(400, 100));
line.push_back(Point(520, 150));
line.push_back(Point(400, 100));
line.push_back(Point(500, -50));
line.push_back(Point(500, -50));
line.push_back(Point(580, 150));
line.push_back(Point(620, 250));
line.push_back(Point(700, 450));
line.push_back(Point(580, 150));
line.push_back(Point(580, -100));
line.push_back(Point(620, 250));
line.push_back(Point(770, 250));
line.push_back(Point(770, 250));
line.push_back(Point(770, -100));
line.push_back(Point(580, -100));
line.push_back(Point(770, -100));
line.push_back(Point(620, 200));
line.push_back(Point(740, 200));
line.push_back(Point(740, 200));
line.push_back(Point(740, -50));
line.push_back(Point(620, -50));
line.push_back(Point(740, -50));
line.push_back(Point(620, -50));
line.push_back(Point(620, 200));
for (int i = 0; i < line.size() - 1; i += 2) {
x00 = line[i].x;
y00 = line[i].y;
x11 = line[i + 1].x;
y11 = line[i + 1].y;
double A = y00 - y11;
double B = x11 - x00;
double k = -1 * (A / B);
double x, y,t;
double d;
if (x11 < x00) {
t = x11;
x11 = x00;
x00 = t;
t = y11;
y11 = y00;
y00 = t;
}
if (k >= 0 && k <= 1) {
d = (2 * A + B);
x = x00;
y = y00;
while (x != x11) {
glBegin(GL_POINTS);
glColor3f(0, 1, 1);
glVertex2f(x / 1000, y / 1000);
flag[(int)(x + 1000)][(int)(y + 1000)] = 1;
glEnd();
if (d <= 0) {
x += 1;
y += 1;
d += (2 * (A + B));
}
else {
x++;
d += (2 * A);
}
glFlush();
}
}
if (k > 1) {
d = (A + 2 * B);
x = x00;
y = y00;
while (y != y11) {
glBegin(GL_POINTS);
glColor3f(0, 1, 1);
glVertex2f(x / 1000, y / 1000);
flag[(int)(x + 1000)][(int)(y + 1000)] = 1;
glEnd();
if (d < 0) {
y += 1;
d += (2 * B);
}
else {
y += 1;
x += 1;
d += (2 * (A + B));
}
glFlush();
}
}
if (k >= -1 && k < 0) {
d = (2 * A - B);
x = x00;
y = y00;
while (x != x11) {
glBegin(GL_POINTS);
glColor3f(0, 1, 1);
glVertex2f(x / 1000, y / 1000);
flag[(int)(x + 1000)][(int)(y + 1000)] = 1;
glEnd();
if (d < 0) {
x += 1;
d += (2 * A);
}
else {
x += 1;
y -= 1;
d += (2 * (A - B));
}
glFlush();
}
}
if (k < -1) {
d = (int)(A - 2 * B);
x = x00;
y = y00;
while (y != y11) {
glBegin(GL_POINTS);
glColor3f(0, 1, 1);
glVertex2f(x / 1000, y / 1000);
flag[(int)(x + 1000)][(int)(y + 1000)] = 1;
glEnd();
if (d < 0) {
y -= 1;
x += 1;
d += (2 * (A - B));
}
else {
y -= 1;
d -= (2 * B);
}
glFlush();
}
}
}
Flood(25, 102);
Flood(141, 90);
Flood(521, 151);
}
void display() {
MidPoint();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(200, 200);
glutInitWindowSize(500, 500);
glutCreateWindow("对名字进行填充");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
运行结果
注意事项
- 在
glVertex2f(x / 1000, y / 1000);
里 x
和 y
不能是 int
类型的 - 在种子算法的填充中,使用
queue
和 stack
都是可以的,但是queue
的填充过程更好看一点