理论部分
中点直线算法是通过在像素中确定与理想直线最靠近的像素来进行扫描转换的。

在上图中,假设直线的斜率0≤m≤10\le m \le 10≤m≤1。假设当前最近的像素已经确认为P(xk,yk)P(x_k, y_k)P(xk,yk),由于xxx位最大的位移方向,因此直线在xxx方向上每次增加一个像素单位,而在yyy方向上是否增加一个像素单位,即PPP点的下一个点是选P1(xk+1,yk)P_1(x_{k+1},y_k)P1(xk+1,yk)还是P2(xk+1,yk+1)P_2(x_{k+1},y_k+1)P2(xk+1,yk+1),取决于两个备选像素哪一个离理想像素最近
设M(xk+1,yk+0.5)M(x_k+1, y_k+0.5)M(xk+1,yk+0.5)位P1P2P_1P_2P1P2的中点,QQQ是理想直线与直线x=xk+1x=x_k+1x=xk+1的交点。在图中可以看出,P2P_2P2离理想像素QQQ更近,所以应该选择P2P_2P2作为下一个像素。
像素选择的方法:理想像素QQQ在中点MMM上方,则选取P2P_2P2,否则选取P1P_1P1。如果Q=MQ=MQ=M,规定选取P1P_1P1
假设直线的起点为(x1,y1)(x_1,y_1)(x1,y1),终点为(x2,y2)(x_2,y_2)(x2,y2),则直线方程为:F(x,y)=ax+by+c=0F(x,y)=ax+by+c=0F(x,y)=ax+by+c=0
其中,a=y1−y2a=y_1-y_2a=y1−y2,b=x2−x1b=x_2-x_1b=x2−x1,c=x1y2−x2y1c=x_1y_2-x_2y_1c=x1y2−x2y1
如果点(x,y)(x,y)(x,y)在直线上,则F(x,y)=0F(x,y)=0F(x,y)=0
如果点(x,y)(x,y)(x,y)在直线的上方,则F(x,y)>0F(x,y)>0F(x,y)>0
如果点(x,y)(x,y)(x,y)在直线的下方,则F(x,y)<0F(x,y)<0F(x,y)<0
因此要判断中点MMM在理想点QQQ上方还是下方,只需要奖M(xk+1,yk+0.5)M(x_k+1,y_k+0.5)M(xk+1,yk+0.5)代入方程,得
d=F(xk+1,yk+0.5)=a(xk+1)+b(yk+0.5)+cd=F(x_k+1,y_k+0.5)=a(x_k+1)+b(y_k+0.5)+cd=F(xk+1,yk+0.5)=a(xk+1)+b(yk+0.5)+c
当d≥0d\ge 0d≥0时,取P1P_1P1像素后,此时下一个候选像素的判别式为:
d1=F(xk+2,yk+0.5)=a(xk+2)+b(yk+0.5)+c=d+ad_1=F(x_k+2,y_k+0.5)=a(x_k+2)+b(y_k+0.5)+c=d+ad1=F(xk+2,yk+0.5)=a(xk+2)+b(yk+0.5)+c=d+a
当d<0d \lt 0d<0时,取P2P_2P2像素后,此时下一个候选像素的判别式为:
d2=F(xk+2,yk+1.5)=a(xk+2)+b(yk+1.5)+c=d+(a+b)d_2=F(x_k+2,y_k+1.5)=a(x_k+2)+b(y_k+1.5)+c=d+(a+b)d2=F(xk+2,yk+1.5)=a(xk+2)+b(yk+1.5)+c=d+(a+b)
ddd的初始值d0d_0d0,d0=F(x1+1,y1+0.5)=a(x1+1)+b(yk+0.5)+c=F(x1,y1)+a+0.5bd_0=F(x_1+1,y_1+0.5)=a(x_1+1)+b(y_k+0.5)+c=F(x_1,y_1)+a+0.5bd0=F(x1+1,y1+0.5)=a(x1+1)+b(yk+0.5)+c=F(x1,y1)+a+0.5b,其中F(x1,y1)F(x_1,y_1)F(x1,y1)是起点,必然在直线上,所以d0=a+0.5bd_0=a+0.5bd0=a+0.5b
OpenGL代码
#pragma once
#include "Object.h"
class MLA : public Object
{
public:
MLA(glm::vec2 startPoint, glm::vec2 endPoint);
MLA(float x1, float y1, float x2, float y2);
~MLA();
void Draw(Shader* shader);
void Draw(Shader* shader, Texture2D tex);
private:
glm::vec2 startPoint;
glm::vec2 endPoint;
void CalculatePoints();
};
#include "MLA.h"
MLA::MLA(glm::vec2 startPoint, glm::vec2 endPoint)
: Object(), startPoint(startPoint), endPoint(endPoint)
{
CalculatePoints();
SetData();
}
MLA::MLA(float x1, float y1, float x2, float y2)
: Object(), startPoint(x1, y1), endPoint(x2, y2)
{
CalculatePoints();
SetData();
}
MLA::~MLA()
{
}
void MLA::Draw(Shader* shader)
{
glBindVertexArray(VAO);
glDrawArrays(GL_POINTS, 0, vertices.size());
glBindVertexArray(0);
}
void MLA::Draw(Shader* shader, Texture2D tex)
{
}
void MLA::CalculatePoints()
{
float a = endPoint.x - startPoint.x;
float b = endPoint.y - startPoint.y;
float d = (2 * a + b) * 0.01f;
float d1 = 2 * a * 0.01f;
float d2 = 2 * (a + b) * 0.01f;
float x = startPoint.x;
float y = startPoint.y;
while (x < endPoint.x)
{
if (d < 0)
{
x += 0.01f;
y += 0.01f;
d += d2;
}
else
{
x += 0.01f;
d += d1;
}
vertices.push_back(Vertex(x, y, 0.0f));
}
}
3286

被折叠的 条评论
为什么被折叠?



