// g++ Ellipse.cpp -o test libglfw3dll.a libopengl32.a
// .\test
#include <bits/stdc++.h>
#include <GL/gl.h>
#include "glfw3.h"
using namespace std;
class screenPt
{
private:
float x, y;
public:
// ScreenPt()
// {
// x = y = 0; // 默认在原点
// }
void setCoords(float xCoordValue, float yCoordValue)
{
x = xCoordValue;
y = yCoordValue;
}
float getx() const
{
return x;
}
float gety() const
{
return y;
}
void incrementx()
{
x++;
}
void decrementy()
{
y--;
}
};
void setPixel(float xCoord, float yCoord) // 自定义画点函数
{
glBegin(GL_POINTS);
glVertex2f((float)(xCoord)/1000, (float)(yCoord)/1000);
glEnd;
}
// inline int round(const float a)
// {
// return int(a+0.5);
// }
void ellipseMidpoint(float xc, float yc, float Rx, float Ry) // 将椭圆圆心、x轴截距和y轴截距传入,此处默认y轴截距更大
{
int Rx2 = Rx*Rx;
int Ry2 = Ry*Ry;
screenPt ellipsePt;
float p1 = (Ry2-Rx2*Ry+0.25*Rx2); // 初始化区域1
ellipsePt.setCoords(0, Ry);
void ellipsePlotPoints(float, float, screenPt);
ellipsePlotPoints(xc, yc, ellipsePt); // 画四个顶点
/***********************区域二**********************/
while (Ry2*ellipsePt.getx() <= Rx2*ellipsePt.gety())
{
ellipsePt.incrementx();
if(p1<0)
{
p1 += Ry2*(2*ellipsePt.getx()+1);
}
else
{
ellipsePt.decrementy();
p1 += Ry2*(2*ellipsePt.getx()+1)-2*Rx2*ellipsePt.gety();
}
ellipsePlotPoints(xc, yc, ellipsePt);
}
/**********************区域二***********************/
// Rx2 = Rx*Rx, Ry2 = Ry*Ry;
// cout<<"x="<<ellipsePt.getx()<<' '<<"y="<<ellipsePt.gety()<<Rx<<Ry<<endl;
float combx = (ellipsePt.getx()+0.5)*(ellipsePt.getx()+0.5);
float comby = (ellipsePt.gety()-1)*(ellipsePt.gety()-1);
// cout<<"combx="<<combx<<' '<<"comby="<<comby<<endl;
float p2 = (Ry2*combx+Rx2*comby-Rx2*Ry2)/1000; // 为什么需要手动除以1000?
// cout<<"initp2="<<p2<<endl;
while(ellipsePt.gety()>0)
{
// cout<<"p2="<<p2<<endl;
ellipsePt.decrementy();
if(p2>0)
{
// cout<<'*'<<endl;
// cout<<"1 "<<p2<<endl;
cout<<'&'<<Rx2*(1-2*ellipsePt.gety())<<endl;
p2 += Rx2*(1-2*ellipsePt.gety());
// cout<<"2 "<<p2<<endl;
}
else
{
// cout<<'*'<<endl;
ellipsePt.incrementx();
p2 += 2*Ry2*ellipsePt.getx()+Rx2*(1-2*ellipsePt.gety());
}
ellipsePlotPoints(xc, yc, ellipsePt);
}
}
void ellipsePlotPoints(float xc, float yc, screenPt ellipsePt)
{
setPixel(xc+ellipsePt.getx(), yc+ellipsePt.gety());
setPixel(xc+ellipsePt.getx(), yc-ellipsePt.gety());
setPixel(xc-ellipsePt.getx(), yc+ellipsePt.gety());
setPixel(xc-ellipsePt.getx(), yc-ellipsePt.gety());
}
/********************************************************************/
void processInput(GLFWwindow *window)
{
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
int main()
{
if (!glfwInit()) return -1;
GLFWwindow* window;
window = glfwCreateWindow(960, 960, "MidPointEllipse", NULL ,NULL); //创建窗口对象
if (!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
while (!glfwWindowShouldClose(window))
{
processInput(window);
ellipseMidpoint(0, 0, 800, 900);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
在原始代码的基础上,发现需要将p2的初始值调小1000倍。调试过程中发现在画区域二的时候p2始终无法小于0,因为
Δ
p
2
\Delta p_2
Δp2的数量级比p2小了1e3,需要1000+次后才可能进入p2<0的条件判断,而一共也没有这么多点。
仍然会出现连接处空洞的问题,即y趋近0的一段消失,尝试发现椭圆形状越接近圆连接处空洞越小。