Newer
Older
EPQ-3D-renderer / src / Line.java
import java.awt.*;
import java.awt.image.BufferedImage;

// handles line and line drawing
public class Line {
    public Point2D point1;
    public Point2D point2;

    // initializer variables
    boolean is_initialised =  false;
    private Point2D realPoint1; private Point2D realPoint2;
    private int dx;
    private int dy; private int sDy;
    private char iterator;
    private Point2D xy;
    int[] returnVal = new int[]{0,0};
    // drawing progress variables
    private int iteratorVal;
    private int D;
    public Line(Point2D _point1, Point2D _point2){
        point1 = _point1;
        point2 = _point2;
    }

    /**
     * Draws onto a given image
     * @param img the image to draw onto
     */
    public void draw(BufferedImage img){

        if (!is_initialised){initialise();}
        if (iterator == 'x'){
            for (int i = 0; i <= dx; i++){
                nextPix();
                try {
                    img.setRGB(returnVal[0], returnVal[1], Color.HSBtoRGB(1, 1, 1));
                }
                catch (ArrayIndexOutOfBoundsException ref){
                    System.out.println(returnVal[0] + " " + returnVal[1]);
                }
            }
        } else {
            for (int i = 0; i <= dy; i++){
                nextPix();
                try {
                    img.setRGB(returnVal[0], returnVal[1], Color.HSBtoRGB(.5f, 1, 1));
                }
                catch (ArrayIndexOutOfBoundsException ref){
                    System.out.println(returnVal[0] + " " + returnVal[1]);
                }
            }
        }
        /*
         debug - draws the start and end of each line in white and green
         img.setRGB(realPoint1.intX(), realPoint1.intY(), Color.blue.getRGB());
         img.setRGB(realPoint2.intX(), realPoint2.intY(), Color.green.getRGB());
        */

        is_initialised = false;
    }

    /**
     * Performs the initial calculations required to draw the line
     * Is automatically called whenever nextpix() or draw() are called when initialise() has not run.
     */
    public void initialise(){
        if (point2.x > point1.x) {
            realPoint1 = point1;
            realPoint2 = point2;
        } else {  // if dx is less than zero, swap the points around
            realPoint1 = point2;
            realPoint2 = point1;
        }
        dx = realPoint2.intX() - realPoint1.intX(); // round all points to the nearest integer

        dy = realPoint2.intY() - realPoint1.intY(); // the line algorithm only works with integer arithmetic
        sDy = (int) Math.signum(dy); dy = Math.abs(dy);

        xy = new Point2D(realPoint1.intX(),realPoint1.intY());  // starting point

        // check if dy is greater than or less than dx
        if (dy < dx){
            iterator = 'x';
            D = (2*dy) - dx;
        }else{
            iterator='y';
            D = (2*dx) - dy;
        }

        iteratorVal = 0;
        is_initialised = true;
    }

    /**
     * @return the x and y coordinate of the next pixel in the line.
     */
    public int[] nextPix(){
        if(!is_initialised){initialise();}
        //OPTIMIZATION - avoid casting. have a different point class that uses integers instead of float
        returnVal[0] = xy.intX();
        returnVal[1] = xy.intY();
        if (iterator=='x' && iteratorVal < dx && iteratorVal != -1){
            if (D > 0) {
                D += 2 * (dy - dx);
                xy.y += sDy;
            } else {
                D += 2*dy;
            }
            xy.x += 1; // the line is always drawn left to right
        } else if(iterator =='y' && iteratorVal < dy && iteratorVal != -1) {
            if (D > 0) {
                D += 2 * (dx-dy);
                xy.x += 1; // the line is always drawn left to right
            } else {
                D += 2*dx;
            }
            xy.y += sDy;

        }
        else if(iteratorVal != -1) {
            iteratorVal = -1;
            returnVal[0] = realPoint2.intX();
            returnVal[1] = realPoint2.intY();
            return returnVal;
        }
        else {
            is_initialised = false;
            return null;
        }
        iteratorVal += 1;
        return returnVal;
    }
    }