概述
内容:画一个空心汉字和一个圆
设计一个画任意直线和圆的算法,可选所学的任一图形扫描转换算法(中点或bresenham算法),不能使用任何画线/画圆的API;
使用画线算法实现空心汉字的绘制,汉字必须为4划以上;
使用你设计的画圆算法绘制这个空心字的外接圆;
设计一种填充算法实现汉字的填充;
1.中点画圆法
生成八分之一圆,其他部分可以通过一系列的简单反射变换得到。
(1)已知圆心在原点的圆上的一点的(x,y),函数circlePlotPoint()
根据对称性得到8个对称点,分别为(y,x),(y,-x),(x,-y),(-x,-y),(-y,-x),(-y,x),(-x,y);
(2)函数circleMidpoint()
如果此时点的位置为(X1,Y1),那么下一个点位置只可能是(X1+1,Y1)或者(X1+1,Y1-1),根据判别式d:
d<0,应取(X1+1,Y1)为下一个点,d=d+2*x+3;
d>=0应取(X1+1,Y1-1)为下一个点,d=d+(x-y)+5;
2.中点画线法
(1)强制起点在终点左侧,如果不是的话,则交换两点;
(2)函数MidPoint()
分为四种情况,斜率0=<k<=1、斜率1<k、斜率-1 =<k<0和斜率k<-1时,根据每种情况下的判别式d,判断下一个点的位置;
(3) 函数setPoint()
每画一个点,就将其对应的flag置为1,说明此点已填充,则边界上所有的点的flag都已经置为1,为填充时判断边界做了准备。
3.种子填充法
函数Flood()
(1)先将种子像素压入栈;
(2)如果栈不为空,栈顶像素出栈;
(3)按左上右下的顺序搜索与出栈像素相邻的4个像素,若像素的flag值是1,说明该像素已填充,结束本次循环;若像素的flag值是0,说明该像素未填充,将该像素入栈。
#include <gl/glut.h>
#include <math.h>
#include <windows.h>
#include <iostream>
#include <vector>
#include <stack>
#include <stdlib.h>
using namespace std;
int xc, yc, r;
int flag[2000][2000] = { 0 };
int winwidth = 500, winheight = 500;//窗口长宽
//声明一个类
class screenPt
{
public:
screenPt()
{
x = y = 0;
}
void setCoords(GLint xCoordValue, GLint yCoordValue) {
x = xCoordValue;
y = yCoordValue;
}
GLint x, y;
};
void init() {
glClearColor(0, 0, 0, 0);//设置绘制窗口颜色为黑色
glClear(GL_COLOR_BUFFER_BIT);//清除窗口显示内容
/*设置为投影类型模式和其他观察参数*/
glPointSize(1.0f);
glColor3f(1.0, 0.0, 0.0);//设置颜色为红
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//左上角坐标为(0,0),长宽为500
gluOrtho2D(0, winwidth, winheight, 0);
}
//画点
void setPixel(GLint xCoord, GLint yCoord) {
glBegin(GL_POINTS);
glVertex2i(xCoord, yCoord);
glEnd();
}
//八个对称点
void circlePlotPoints(GLint xc, GLint yc, screenPt circpt) {
setPixel(xc + circpt.x, yc + circpt.y);
setPixel(xc - circpt.x, yc + circpt.y);
setPixel(xc + circpt.x, yc - circpt.y);
setPixel(xc - circpt.x, yc - circpt.y);
setPixel(xc + circpt.y, yc + circpt.x);
setPixel(xc - circpt.y, yc + circpt.x);
setPixel(xc + circpt.y, yc - circpt.x);
setPixel(xc - circpt.y, yc - circpt.x);
}
/*中心画圆法*/
void circleMidpoint(GLint xc, GLint yc, GLint radius) {
glClear(GL_COLOR_BUFFER_BIT);//清除窗口显示内容
screenPt circpt;//创建一个对象
GLint p = 1 - radius;
circpt.setCoords(0, radius);
//显示圆弧上的八个点
circlePlotPoints(xc, yc, circpt);
while (circpt.x < circpt.y) {
circpt.x++;
if (p < 0) {
p += 2 * circpt.x + 3;
}
else {
circpt.y--;
p += 2 * (circpt.x - circpt.y) + 5;
}
//显示圆弧上的八个点
circlePlotPoints(xc, yc, circpt);
}
}
class Point {
public:
Point();
Point(GLint _x, GLint _y) {
x = _x;
y = _y;
}
GLint x, y;
};
// 种子填充
void Flood(int a, int b) {
// (x - 1, y); //left
// (x, y - 1); //up
// (x + 1, y); //right
// (x, y + 1); //down
int dx[4] = { -1, 0, 1,0 };
int dy[4] = { 0, -1, 0,1 };
stack<Point> q;
q.push(Point(a, b));
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 (flag[n][m])
continue;
flag[n][m] = 1;
glBegin(GL_POINTS);
glColor3f(255, 255, 0);
glVertex2f(n ,m );
glEnd();
q.push(Point(n, m));
glFlush();
}
}
}
//画线之间的点
void setPoint(GLint x,GLint y) {
glBegin(GL_POINTS);
glColor3f(249, 216, 118);//
glVertex2f(x, y);//指定顶点的值
flag[(int)(x )][(int)(y )] = 1;
glEnd();
}
void MidPoint() {
//将点的信息放到line中保存
vector<Point> line;
//第一部分连接点 4
line.push_back(Point(240, 150));
line.push_back(Point(255, 150));
line.push_back(Point(255, 150));
line.push_back(Point(265, 165));
line.push_back(Point(250, 165));
line.push_back(Point(265, 165));
line.push_back(Point(240, 150));
line.push_back(Point(250, 165));
第2部分连接点 22
line.push_back(Point(200, 185));
line.push_back(Point(215, 185));
line.push_back(Point(200, 185));
line.push_back(Point(200, 220));
line.push_back(Point(200, 220));
line.push_back(Point(215, 220));
line.push_back(Point(215, 210));
line.push_back(Point(215, 220));
line.push_back(Point(215, 185));
line.push_back(Point(215, 190));
line.push_back(Point(215, 190));
line.push_back(Point(305, 190));
line.push_back(Point(305, 185));
line.push_back(Point(305, 190));
line.push_back(Point(305, 185));
line.push_back(Point(325, 185));
line.push_back(Point(325, 185));
line.push_back(Point(325, 220));
line.push_back(Point(310, 220));
line.push_back(Point(325, 220));
line.push_back(Point(310, 210));
line.push_back(Point(310, 220));
line.push_back(Point(215, 210));
line.push_back(Point(310, 210));
第3部分连接点 36
line.push_back(Point(180,240));
line.push_back(Point(240, 240));
line.push_back(Point(180, 240));
line.push_back(Point(180, 250));
line.push_back(Point(240, 240));
line.push_back(Point(250, 225));
line.push_back(Point(250, 225));
line.push_back(Point(270, 225));
line.push_back(Point(260, 240));
line.push_back(Point(270, 225));
line.push_back(Point(260, 240));
line.push_back(Point(345, 240));
line.push_back(Point(180, 250));
line.push_back(Point(235, 250));
line.push_back(Point(250, 250));
line.push_back(Point(290, 250));
line.push_back(Point(210, 290));
line.push_back(Point(235,250));
line.push_back(Point(210, 290));
line.push_back(Point(230, 300));
line.push_back(Point(190, 340));
line.push_back(Point(230, 300));
line.push_back(Point(190, 340));
line.push_back(Point(195, 350));
line.push_back(Point(195, 350));
line.push_back(Point(245, 310));
line.push_back(Point(245, 310));
line.push_back(Point(320, 340));
line.push_back(Point(320, 340));
line.push_back(Point(325, 330));
line.push_back(Point(265, 300));
line.push_back(Point(325, 330));
line.push_back(Point(265, 300));
line.push_back(Point(310, 250));
line.push_back(Point(310, 250));
line.push_back(Point(345, 250));
line.push_back(Point(345, 240));
line.push_back(Point(345, 250));
第四部分连接点 4
line.push_back(Point(235, 285));
line.push_back(Point(250, 250));
line.push_back(Point(235, 285));
line.push_back(Point(250, 290));
line.push_back(Point(250, 290));
line.push_back(Point(290, 250));
//中点画线法
for (int i = 0; i < line.size() - 1; i += 2) {
double x0, y0, x1, y1;
x0 = line[i].x;
y0 = line[i].y;
x1 = line[i + 1].x;
y1 = line[i + 1].y;
double A = y0 - y1;
double B = x1 - x0;
double k = -1 * (A / B);
double t;
double d;
//强制起点在终点左侧,如果不是的话,则交换两点;
if (x1 < x0) {
t = x1;
x1 = x0;
x0 = t;
t = y1;
y1 = y0;
y0 = t;
}
//斜率0=<k<=1
if (k >= 0 && k <= 1) {
d = (2 * A + B);
while (x0 != x1) {
setPoint(x0, y0);
if (d <= 0) {
x0 += 1;
y0 += 1;
d += (2 * (A + B));
}
else {
x0++;
d += (2 * A);
}
//glFlush();
}
}
//斜率大于1
if (k > 1) {
d = (A + 2 * B);
while (y0 != y1) {
setPoint(x0, y0);
if (d < 0) {
y0 += 1;
d += (2 * B);
}
else {
y0 += 1;
x0 += 1;
d += (2 * (A + B));
}
//glFlush();
}
}
//斜率大于等于-1 小于0时
if (k >= -1 && k < 0) {
d = (2 * A - B);
while (x0 != x1) {
setPoint(x0, y0);
if (d < 0) {
x0 += 1;
d += (2 * A);
}
else {
x0 += 1;
y0 -= 1;
d += (2 * (A - B));
}
//glFlush();
}
}
//斜率小于-1时
if (k < -1) {
d = (int)(A - 2 * B);
while (y0 != y1) {
setPoint(x0, y0);
if (d < 0) {
y0 -= 1;
x0 += 1;
d += (2 * (A - B));
}
else {
y0 -= 1;
d -= (2 * B);
}
//glFlush();
}
}
}
//调用种子填充
setPixel(210, 200);
Flood(210,200);
setPixel(245, 155);
Flood(245, 155);
setPixel(181, 241);
Flood(181, 241);
}
void display() {
circleMidpoint(250, 250, 120);
MidPoint();
//glFlush();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);//初始化
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);//设置绘制模式
glutInitWindowPosition(400, 150); //设置窗口的位置
glutInitWindowSize(winwidth, winheight);
glutCreateWindow("绘制并填充”安“"); //创建窗口并赋予title
init();
glutDisplayFunc(display);
glutMainLoop();
}
结果:
最后
以上就是傻傻睫毛膏为你收集整理的【OpenGL C++】画一个空心汉字和一个圆,并填充汉字(中点画线法,中点画圆法,种子填充法)的全部内容,希望文章能够帮你解决【OpenGL C++】画一个空心汉字和一个圆,并填充汉字(中点画线法,中点画圆法,种子填充法)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复