(好不容易排好版,结果复制上来就又乱了)    

“在数学上,理想的直线是没有宽度的,它是由无数个点构成的集合”。在计算机图形 学中,绘制线宽为一个像素的直线有三种常用算法:数值微分法(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; 



控制台输入起始点和终止点坐标,applet程序呈现绘图

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);// 画直线

        }

}