110 lines
3.1 KiB
Java
110 lines
3.1 KiB
Java
import java.awt.*;
|
|
import static java.lang.Math.*;
|
|
import javax.swing.*;
|
|
|
|
public class XiaolinWu extends JPanel {
|
|
|
|
public XiaolinWu() {
|
|
Dimension dim = new Dimension(640, 640);
|
|
setPreferredSize(dim);
|
|
setBackground(Color.white);
|
|
}
|
|
|
|
void plot(Graphics2D g, double x, double y, double c) {
|
|
g.setColor(new Color(0f, 0f, 0f, (float)c));
|
|
g.fillOval((int) x, (int) y, 2, 2);
|
|
}
|
|
|
|
int ipart(double x) {
|
|
return (int) x;
|
|
}
|
|
|
|
double fpart(double x) {
|
|
return x - floor(x);
|
|
}
|
|
|
|
double rfpart(double x) {
|
|
return 1.0 - fpart(x);
|
|
}
|
|
|
|
void drawLine(Graphics2D g, double x0, double y0, double x1, double y1) {
|
|
|
|
boolean steep = abs(y1 - y0) > abs(x1 - x0);
|
|
if (steep)
|
|
drawLine(g, y0, x0, y1, x1);
|
|
|
|
if (x0 > x1)
|
|
drawLine(g, x1, y1, x0, y0);
|
|
|
|
double dx = x1 - x0;
|
|
double dy = y1 - y0;
|
|
double gradient = dy / dx;
|
|
|
|
// handle first endpoint
|
|
double xend = round(x0);
|
|
double yend = y0 + gradient * (xend - x0);
|
|
double xgap = rfpart(x0 + 0.5);
|
|
double xpxl1 = xend; // this will be used in the main loop
|
|
double ypxl1 = ipart(yend);
|
|
|
|
if (steep) {
|
|
plot(g, ypxl1, xpxl1, rfpart(yend) * xgap);
|
|
plot(g, ypxl1 + 1, xpxl1, fpart(yend) * xgap);
|
|
} else {
|
|
plot(g, xpxl1, ypxl1, rfpart(yend) * xgap);
|
|
plot(g, xpxl1, ypxl1 + 1, fpart(yend) * xgap);
|
|
}
|
|
|
|
// first y-intersection for the main loop
|
|
double intery = yend + gradient;
|
|
|
|
// handle second endpoint
|
|
xend = round(x1);
|
|
yend = y1 + gradient * (xend - x1);
|
|
xgap = fpart(x1 + 0.5);
|
|
double xpxl2 = xend; // this will be used in the main loop
|
|
double ypxl2 = ipart(yend);
|
|
|
|
if (steep) {
|
|
plot(g, ypxl2, xpxl2, rfpart(yend) * xgap);
|
|
plot(g, ypxl2 + 1, xpxl2, fpart(yend) * xgap);
|
|
} else {
|
|
plot(g, xpxl2, ypxl2, rfpart(yend) * xgap);
|
|
plot(g, xpxl2, ypxl2 + 1, fpart(yend) * xgap);
|
|
}
|
|
|
|
// main loop
|
|
for (double x = xpxl1 + 1; x <= xpxl2 - 1; x++) {
|
|
if (steep) {
|
|
plot(g, ipart(intery), x, rfpart(intery));
|
|
plot(g, ipart(intery) + 1, x, fpart(intery));
|
|
} else {
|
|
plot(g, x, ipart(intery), rfpart(intery));
|
|
plot(g, x, ipart(intery) + 1, fpart(intery));
|
|
}
|
|
intery = intery + gradient;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void paintComponent(Graphics gg) {
|
|
super.paintComponent(gg);
|
|
Graphics2D g = (Graphics2D) gg;
|
|
|
|
drawLine(g, 550, 170, 50, 435);
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
SwingUtilities.invokeLater(() -> {
|
|
JFrame f = new JFrame();
|
|
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
f.setTitle("Xiaolin Wu's line algorithm");
|
|
f.setResizable(false);
|
|
f.add(new XiaolinWu(), BorderLayout.CENTER);
|
|
f.pack();
|
|
f.setLocationRelativeTo(null);
|
|
f.setVisible(true);
|
|
});
|
|
}
|
|
}
|