1

Suppose that I have the given array:

int[] array = {
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0
    };

Would there be a way to draw graphics into that array? For example assume that we have a way to access the data in this array by an x and y coordinate could we make a method that would put a line through this array dependant on 2 coordinates. The code would look something like this:

public void drawLine(int x1, int y1, int x2, int y2) {
    ...     
}

And would transfer something like this:

int[] array = {
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0
    };

Into this:

int[] array = {
        1, 0, 0, 0, 0,
        0, 1, 0, 0, 0,
        0, 0, 1, 0, 0,
        0, 0, 0, 1, 0,
        0, 0, 0, 0, 1
    };

You would have to be able to pass in any set of coordinates and have a calculated line placed through the array. How would I implement this?

Calling drawLine(1,0,3,4) would create something like:

int[] array = {
    0, 1, 0, 0, 0,
    0, 0, 1, 0, 0,
    0, 0, 1, 0, 0,
    0, 0, 0, 1, 0,
    0, 0, 0, 1, 0
};

Also if your up to it is there a way I could specify any number of points and have them all connected and then filled in? (No I don't want to use any libraries).

Llewv
  • 123
  • 14
  • 1
    [Bresenham's line algorithm](https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm) is useful for drawling lines. – MikeCAT Jun 09 '16 at 13:21
  • how would an input of `drawiLine(1,0,2,4)` look like? Atleast for me there is no universal solution, since it´s not clear how the result `any set of coordinates` could look like. – SomeJavaGuy Jun 09 '16 at 13:22
  • 1
    An `y` coordinate makes no sense in a one-dimensional array. – Arnaud Jun 09 '16 at 13:22
  • 1
    You would have to establish somewhere in your code the width/height of your grid to be able to draw lines, since you are using a plain 1D array. – khelwood Jun 09 '16 at 13:23
  • @Berger I think he means 2d arrays. – theVoid Jun 09 '16 at 13:26
  • The width and height are both 5 as in the visual representation. However it is important that they could be anything. – Llewv Jun 09 '16 at 13:27
  • your array is the image - so any drawing you can do on the image you can do on the array - that you present it as a magical new problem is your magic dust – gpasch Jun 09 '16 at 14:48

1 Answers1

2

Very cheaty way to do it (without implementing the drawing logic yourself) would be to use BufferedImage with the dimensions of your array and draw on that. After drawing the line you want you would iterate over the pixels of the BufferedImage and check which pixels are painted.

private static void drawToArray(int[][] array2d, int x1, int y1, int x2, int y2) {
    int width = array2d[0].length; // width is columns and columns are second
    int height = array2d.length; // height is rows and rows are first

    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = image.createGraphics();
    g2d.setBackground(Color.WHITE);
    g2d.fillRect(0, 0, width, height);  // paint background white
    g2d.setColor(Color.BLACK);
    BasicStroke bs = new BasicStroke(1); // set black brush to size 1 (1 pixel)
    g2d.setStroke(bs);

    g2d.drawLine(x1, y1, x2, y2); // paint line on image

    // fill array with values, check entire image
    for (int row = 0; row < height; row++) {
        for (int column = 0; column < width; column++) {
            int clr = image.getRGB(row,column); // get color of pixel at position
            if (clr == Color.WHITE.getRGB()) { // white is -1
                array2d[row][column] = 0;
            } else {
                array2d[row][column] = 1;
            }
        }
    }
    g2d.dispose();
    // returning array is not necesery I am editing the array2d variable passed in
}

Usage

int[][] arr = new int[5][5];
drawToArray(arr, 0, 0, 2, 5);

This example assumes that your array is two dimensional and that each row is of same length. If you want to use one dimensional array, you will have to define its width and height yourself. Also instead of

array2d[row][column] = 0;

you would have

array1d[row*width + column] = 0;

Edit 1: edited my answer to be more general

Edit 2: Considering performance

I doubt that I can improve the drawLine method so only place for improvement is conversion to 2d array. It is possible to get the array of pixels represented as integer values from Image and convert that to 2d array. I updated the draw ToArray method and left commented out lines there as explanation.

private static void drawToArray(int[][] array2d, int x1, int y1, int x2, int y2) {
    int width = array2d[0].length; // width is columns and columns are second
    int height = array2d.length; // height is rows and rows are first

    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = image.createGraphics();   // default color of image is 0 no need to paint background, just draw with color diferent than 0
    //g2d.setColor(Color.WHITE);               // default brush color is different than 0, expicitly setting is unnecesery
    //BasicStroke bs = new BasicStroke(1);
    //g2d.setStroke(bs);                       // default is 1 pixel expicitly setting is unnecesery

    g2d.drawLine(x1, y1, x2, y2); // paint line on image

    int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
    for (int i = 0, row = 0, col = 0; i < pixels.length; i++) {
        array2d[row][col] = pixels[i] == 0 ? 0 : 1; // no performance difference vs if/else just readability
        //array2d[row][col] = pixels[i]; // if you write it like this you will be "painting" with '-1's instead of '1's and save one if/else
        col++;
        // if is more readable here no performance difference vs ternary
        if (col == width) {
            col = 0;
            row++;
        }
    }
    g2d.dispose();
}

Only other place where to improve performance is to not convert it to 2d array at all and access the values like I mentioned before. But if you want to "paint" with number 1 instead of default -1 you will have to loop trough the array of pixels anyway to replace the -1s with 1s.

MatheM
  • 801
  • 7
  • 17
  • I have to run code like that many times a second what is the performance like? – Llewv Jun 10 '16 at 00:19
  • @Llewv My example is using Graphics to draw a line. I doubt that I can get more efficient with custom code. Only performance hit I can do something about is the conversion to int array. getRGB() is probably slow. For fast conversion to int array check out this [question](http://stackoverflow.com/questions/6524196/java-get-pixel-array-from-image). – MatheM Jun 10 '16 at 06:56