(好不容易排好版,结果复制上来就又乱了)
“在数学上,理想的直线是没有宽度的,它是由无数个点构成的集合”。在计算机图形
学中,绘制线宽为一个像素的直线有三种常用算法:数值微分法(DDA)、中点画线法和 Bresenham 算法。这里,我是用 Java
中的 Applet 来实现中点画线算法。
设画直线过程中当前像素点为(𝑥𝑝,𝑦𝑝),下一个像素点有两个选择点𝑃1(𝑥𝑝 +1,
𝑦𝑝)或 𝑃2(𝑥𝑝+1 , 𝑦𝑝+1)。取中点
M=(𝑥𝑝+1 , 𝑦𝑝+0.5),Q 为理想直线与𝑥𝑝 +1 的交点。当 M 在 Q 的上 方时,取下点𝑃2;当 M 在 Q
点的下方时,取上点𝑃1。
直线的方程为F = (x,y) = ax + by + c = 0 ,a = 𝑦0 − 𝑦1,b
= 𝑥1 − 𝑥0,c = 𝑥0𝑦1 − 𝑥1𝑦0 ,想要判断 M 在 Q
点的上方还是下方
(I)斜率小于 1
时:
需要构造判别式 d = F(M) = F(𝑥𝑝 + 1,𝑦𝑝 + 0.5) = 𝑎(𝑥𝑝 + 1) + 𝑏(𝑦𝑝 +
0.5) + c.
设从点(𝑥0,𝑦0)开始画线,d 的初值𝑑0 = F(𝑥0 + 1,𝑦0 + 0.5) = F(𝑥0,𝑦0) + 𝑎 +
0.5𝑏,因为 F(𝑥0,𝑦0) = 0,所以𝑑0 = 𝑎 + 0.5𝑏.
(1) 当d ≥ 0时,取正右方像素𝑃1(𝑥𝑝 +1,
𝑦𝑝)。判断下一个像素的位置时,应计算 𝑑1 = 𝐹(𝑥𝑝 + 2,𝑦𝑝 + 0.5) = 𝑎(𝑥𝑝 + 2) + 𝑏(𝑦𝑝 +
0.5) + c = d + a,增量为 a;
(2) 当d < 0时,取右上方像素𝑃2(𝑥𝑝 +1, 𝑦𝑝 + 1)。判断下一个像素的位置时,应计算 𝑑2 =
𝐹(𝑥𝑝 + 2,𝑦𝑝 + 1.5) = 𝑎(𝑥𝑝 + 2) + 𝑏(𝑦𝑝 + 1.5) + c = d + a + b,增量为
a+b;
(II)斜率大于 1
时:
需要构造判别式 d = F(M) = F(𝑥𝑝 + 0.5,𝑦𝑝 + 1) = 𝑎(𝑥𝑝 + 0.5) + 𝑏(𝑦𝑝 +
1) + c.
设从点(𝑥0,𝑦0)开始画线,d 的初值𝑑0 = F(𝑥0 + 0.5,𝑦0 + 1) = F(𝑥0,𝑦0) + 0.5𝑎
+ 𝑏,因为 F(𝑥0,𝑦0) = 0,所以𝑑0 = 0.5𝑎 + 𝑏.
(1) 当d < 0时,取正上方像素𝑃1(𝑥𝑝 , 𝑦𝑝 + 1)。判断下一个像素的位置时,应计算 𝑑1 = 𝐹(𝑥𝑝
+ 0.5,𝑦𝑝 + 2) = 𝑎(𝑥𝑝 + 0.5) + 𝑏(𝑦𝑝 + 2) + c = d + b,增量为 b;
(2) 当d ≥ 0时,取右上方像素𝑃2(𝑥𝑝 +1, 𝑦𝑝 +
1)。判断下一个像素的位置时,应计算 𝑑2 = 𝐹(𝑥𝑝 + 1.5,𝑦𝑝 + 2) = 𝑎(𝑥𝑝 + 1.5) + 𝑏(𝑦𝑝 +
2) + c = d + a + b,增量为 a+b;
import
java.applet.Applet;
import
java.awt.Color;
import
java.awt.Graphics;
import
java.util.Scanner;
public
class MidPoint extends Applet {
int a[] = new int[4];
public void init() {
setSize(300, 300);
Scanner sc = new Scanner(System.in);
System.out.println("input two point");
for (int i = 0; i < 4; i++) {
a[i] = sc.nextInt();
}
}
public void paint(Graphics g) {
g.setColor(Color.pink);
for (int i = 10; i <= 210; i += 10) {
g.drawLine(i, 10, i, 210);//
竖线
g.drawLine(10, i, 210, i);//
横线
}
g.setColor(Color.BLACK);
g.drawLine(10, 210, 220, 210);// x坐标
g.drawLine(10, 0, 10, 210);// y坐标
int x0 = a[0];
int y0 = a[1];
int x1 = a[2];
int y1 = a[3];
int a, b, d1, d2, d, x, y;
a = y0 - y1;
b = x1 - x0;
if (Math.abs(a / b) <= 1) {//
斜率绝对值小于1
d = 2 * a + b;
d1 = 2 * a;
d2 = 2 * (a + b);
} else {//
大于1
d = a + 2 * b;
d1 = 2 * b;
d2 = 2 * (a + b);
}
x = x0;
y = y0;
g.drawOval(x * 10 - 2 + 10, 210 - y * 10 - 2, 4, 4);//
起始点
if (Math.abs(a / b) <= 1) {//
斜率小于1
while (x < x1) {
if (d < 0) {
x++;
y++;
d += d2;
} else {
x++;
d += d1;
}
g.drawOval(x * 10 - 2 + 10, 210 - y * 10 - 2, 4, 4);//
描点
}
} else {//
斜率大于1
while (y < y1) {
if (d > 0) {
x++;
y++;
d += d2;
} else {
y++;
d += d1;
}
g.drawOval(x * 10 - 2 + 10, 210 - y * 10 - 2, 4, 4);//
描点
}
}
g.drawLine(x0 * 10 + 10, 210 - y0 * 10, x * 10 + 10, 210 - y *
10);//
画直线
}
}