要绘制正余弦曲线,有以下关键几步:
-
参数化表示:
-
通过将角度 x 作为自变量,可以得到 y 的值,即 y=sin(x)或 y=cos(x)。
-
将 x 的范围设置为 [−π,π] 即可以完整表示一个正弦或余弦波的周期。
-
-
坐标变换:
-
在计算机图形中绘制曲线实现可视化,需要将数学坐标转换为图形坐标。这通常涉及缩放和位移操作。例如,乘以一个缩放因子(如 50)以放大波形,并将坐标平移到可见区域。
-
-
逐点绘制:
-
在绘制过程中,可以通过循环遍历角度值,并使用三角函数计算相应的 y 值,随后通过图形API(以OpenGL为例),定义顶点(即每个点的 x 和 y 值)并使用绘制命令(
GL_LINE_STRIP表示折线绘制
;GL_POINTS表示点绘制
)来显示这些点。
-
代码实现如下:
#include <windows.h>
#include <gl/glut.h>
#include <math.h>
#define PI 3.1415926
static GLsizei iMode = 1;
int winWidth = 500, winHeight = 500;
void init(void) {
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // 设置清屏颜色为白色
}
// 窗口大小调整函数
void Reshape(int w, int h) {
winWidth = w;
winHeight = h;
glViewport(0, 0, w, h); // 设置视口为整个窗口
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-250.0, 250.0, -250.0, 250.0); // 根据需要设置二维坐标范围
}
// 绘制正弦曲线的函数
void DrawSineWave(bool isStrip) {
if (isStrip) {
glBegin(GL_LINE_STRIP); // 使用折线连接点
} else {
glBegin(GL_POINTS); // 仅绘制点
}
glColor3f(1.0, 0.0, 0.0); // 设置颜色为红色
for (float x = -PI; x < PI; x += PI / 90) { // 从 -π 到 π 计算正弦值
float y = sin(x); // 由于sin函数,需要将角度转化为弧度,步长根据需要进行调整(越小越平滑,这里选用PI/90)
glVertex2f(50 * x, 50 * y); // 根据 x 计算 y,并进行一定程度的缩放
}
glEnd();
}
// 绘制余弦曲线的函数(同上)
void DrawCosineWave(bool isStrip) {
if (isStrip) {
glBegin(GL_LINE_STRIP);
} else {
glBegin(GL_POINTS);
}
glColor3f(1.0, 0.0, 0.0);
for (float x = -PI; x < PI; x += PI / 90) {
float y = cos(x);
glVertex2f(50 * x, 50 * y);
}
glEnd();
}
// 绘制函数
void Display(void) {
glClear(GL_COLOR_BUFFER_BIT); // 清空颜色缓存
// 绘制坐标轴
glColor3f(0.0, 0.0, 1.0); // 设置颜色为蓝色
glBegin(GL_LINES);
glVertex2f(-250.0, 0);
glVertex2f(250.0, 0);
glVertex2f(0, -250.0);
glVertex2f(0, 250.0);
glEnd();
// 根据当前模式绘制正弦或余弦曲线
switch (iMode) {
case 1: DrawSineWave(false); break; // 点绘制正弦曲线
case 2: DrawSineWave(true); break; // 折线绘制正弦曲线
case 3: DrawCosineWave(false); break; // 点绘制余弦曲线
case 4: DrawCosineWave(true); break; // 折线绘制余弦曲线
}
glutSwapBuffers(); // 交换前后缓存
}
// 菜单处理函数
void ProcessMenu(int value) {
iMode = value; // 更新当前模式
glutPostRedisplay(); // 请求重新绘制
}
// 主函数
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Sine/Cosine Curve");
// 创建菜单
int menu = glutCreateMenu(ProcessMenu);
glutAddMenuEntry("Point to draw sine curve", 1);
glutAddMenuEntry("Line to draw sine curve", 2);
glutAddMenuEntry("Point to draw cosine curve", 3);
glutAddMenuEntry("Line to draw cosine curve", 4);
init();
glutReshapeFunc(Reshape);
glutDisplayFunc(Display);
glutAttachMenu(GLUT_RIGHT_BUTTON); // 右键菜单调出菜单
glutMainLoop();
return 0;
}
代码效果图:
看上去点绘制和折线绘制的视觉差异不是特别明显,我们以正弦曲线为例再放大看看: