Newer
Older
EPQ-3D-renderer / src / main / java / uk / org / floop / epq3d / Line2d.java
@cory cory on 2 Feb 2023 4 KB Fix #17
package uk.org.floop.epq3d;

import java.awt.*;
import java.awt.image.BufferedImage;

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

    public boolean isDrawn;

    // 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};
    private double gradient; // z gradient of the line in terms of X

    // drawing progress variables
    private int iteratorVal;
    private int D;
    public Line2d(Point2D _point1, Point2D _point2, boolean _isDrawn){
        point1 = _point1;
        point2 = _point2;
        isDrawn = _isDrawn;
    }
    /**
     * 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();
                if(returnVal[0] >= 0 && returnVal[0] < img.getWidth() && returnVal[1] >= 0 && returnVal[1] < img.getHeight()) { // check if drawing in bounds
                    img.setRGB(returnVal[0], returnVal[1], Color.HSBtoRGB(1, 1, 1));
                }
            }
        } else {
            for (int i = 0; i <= dy; i++){
                nextPix();
                if(returnVal[0] >= 0 && returnVal[0] < img.getWidth() && returnVal[1] >= 0 && returnVal[1] < img.getHeight()) { // check if drawing in bounds
                    img.setRGB(returnVal[0], returnVal[1], Color.HSBtoRGB(.5f, 1, 1));
                }
            }
        }
        is_initialised = false;
        /*
         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());
        */
    }

    /**
     * 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(){
        // initialise brensenham algorithm
        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.x - realPoint1.x;
        dy = realPoint2.y - realPoint1.y;
        sDy = (int) Math.signum(dy); dy = Math.abs(dy);

        xy = new Point2D(realPoint1.x,realPoint1.y);  // 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;

        // init other variables
        // dz / dx
        gradient = (realPoint2.z-realPoint1.z) /
                (realPoint2.x - realPoint1.x);
        is_initialised = true;
    }

    /**
     * @return the x and y coordinate of the next pixel in the line.
     */
    public int[] nextPix(){
        if(!is_initialised){initialise();}
        returnVal[0] = xy.x;
        returnVal[1] = xy.y;
        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.x;
            returnVal[1] = realPoint2.y;
            return returnVal;
        }
        else {
            is_initialised = false;
            throw new RuntimeException("Accessed too many line pixels");
        }
        iteratorVal += 1;
        return returnVal;
    }
    public double getZVal(int x){
        return realPoint1.z + (gradient * (double)(x - realPoint1.x));
    }
    }