Task: Xiaolin Wu's line algorithm




Go: package raster

import "math"

func ipart(x float64) float64 {
    return math.Floor(x)
}

func round(x float64) float64 {
    return ipart(x + .5)
}

func fpart(x float64) float64 {
    return x - ipart(x)
}

func rfpart(x float64) float64 {
    return 1 - fpart(x)
}


func (g *Grmap) AaLine(x1, y1, x2, y2 float64) {
    
    dx := x2 - x1
    dy := y2 - y1
    ax := dx
    if ax < 0 {
        ax = -ax
    }
    ay := dy
    if ay < 0 {
        ay = -ay
    }
    
    var plot func(int, int, float64)
    if ax < ay {
        x1, y1 = y1, x1
        x2, y2 = y2, x2
        dx, dy = dy, dx
        plot = func(x, y int, c float64) {
            g.SetPx(y, x, uint16(c*math.MaxUint16))
        }
    } else {
        plot = func(x, y int, c float64) {
            g.SetPx(x, y, uint16(c*math.MaxUint16))
        }
    }
    if x2 < x1 {
        x1, x2 = x2, x1
        y1, y2 = y2, y1
    }
    gradient := dy / dx

    
    xend := round(x1)
    yend := y1 + gradient*(xend-x1)
    xgap := rfpart(x1 + .5)
    xpxl1 := int(xend) 
    ypxl1 := int(ipart(yend))
    plot(xpxl1, ypxl1, rfpart(yend)*xgap)
    plot(xpxl1, ypxl1+1, fpart(yend)*xgap)
    intery := yend + gradient 

    
    xend = round(x2)
    yend = y2 + gradient*(xend-x2)
    xgap = fpart(x2 + 0.5)
    xpxl2 := int(xend) 
    ypxl2 := int(ipart(yend))
    plot(xpxl2, ypxl2, rfpart(yend)*xgap)
    plot(xpxl2, ypxl2+1, fpart(yend)*xgap)

    
    for x := xpxl1 + 1; x <= xpxl2-1; x++ {
        plot(x, int(ipart(intery)), rfpart(intery))
        plot(x, int(ipart(intery))+1, fpart(intery))
        intery = intery + gradient
    }
}


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;

        
        double xend = round(x0);
        double yend = y0 + gradient * (xend - x0);
        double xgap = rfpart(x0 + 0.5);
        double xpxl1 = xend; 
        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);
        }

        
        double intery = yend + gradient;

        
        xend = round(x1);
        yend = y1 + gradient * (xend - x1);
        xgap = fpart(x1 + 0.5);
        double xpxl2 = xend; 
        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);
        }

        
        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);
        });
    }
}