Java program to generate Voronoi Diagrams of specified settings, even in high resolutions – tested for 64K with increased Java VM  heap size – -Xmx8g option.

Voronoi 1000X500 distance order 2.0 100 points
Voronoi 1000X500 distance order 2.0 100 points.

Main.java

// 2018 TheFlyingKeyboard and released under MIT License
// theflyingkeyboard.net
public class Main {
    public static void main(String[] args) {
        Voronoi voronoi = new Voronoi(15360, 8640, 2, 100, true);

        voronoi.generate();
    }
}

Point2D.java

// 2018 TheFlyingKeyboard and released under MIT License
// theflyingkeyboard.net
public class Point2D {
    private int x;
    private int y;

    public Point2D(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

Point3D.java

// 2018 TheFlyingKeyboard and released under MIT License
// theflyingkeyboard.net
public class Point3D {
    private int x;
    private int y;
    private int z;

    public Point3D(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getZ() {
        return z;
    }
}

Voronoi.java

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.File;
import java.util.concurrent.ThreadLocalRandom;

// 2018 TheFlyingKeyboard and released under MIT License
// theflyingkeyboard.net
public class Voronoi {
    private final int width;
    private final int height;
    private final double distanceOrder;
    private final int numberOfPoints;
    private final Point2D[] points;
    private final Point3D[] colors;
    private final int pointSize = 5;
    private final boolean drawPoints;
    private BufferedImage bufferedImage;

    public Voronoi(int width, int height, double distanceOrder, int numberOfPoints, boolean drawPoints) {
        this.width = width;
        this.height = height;
        this.distanceOrder = distanceOrder;
        this.numberOfPoints = numberOfPoints;
        this.drawPoints = drawPoints;

        points = new Point2D[numberOfPoints];
        colors = new Point3D[numberOfPoints];
        bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        for (int i = 0; i < numberOfPoints; ++i) {
            points[i] = new Point2D(ThreadLocalRandom.current().nextInt(width), ThreadLocalRandom.current().nextInt(height));
            colors[i] = new Point3D(ThreadLocalRandom.current().nextInt(255), ThreadLocalRandom.current().nextInt(255), ThreadLocalRandom.current().nextInt(255));
        }
    }

    public void generate() {
        generateVoronoi();

        try {
            ImageIO.write(bufferedImage, "png", new File("Voronoi " + width + "X" + height + " " + " distance order " + distanceOrder + " " + numberOfPoints + " points.png"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void generateVoronoi() {
        //int counter = 0;
        int index;

        int[] imagePixelData = ((DataBufferInt) bufferedImage.getRaster().getDataBuffer()).getData();

        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; ++x) {
                //System.out.println((counter / (double) (height * width)) * 100 + "%");

                index = findClosestPoint(new Point2D(x, y));
                imagePixelData[y * width + x] = (colors[index].getX() << 16) | (colors[index].getY() << 8) | colors[index].getZ();

                //++counter;
            }
        }

        if (drawPoints) {
            drawPoints();
        }
    }

    private void drawPoints() {
        for (int i = 0; i < numberOfPoints; ++i) {
            for (int y = -pointSize; y <= pointSize; ++y) {
                for (int x = -pointSize; x <= pointSize; ++x) {
                    if (x * x + y * y <= pointSize * pointSize && x + points[i].getX() >= 0 &&
                            x + points[i].getX() < width && y + points[i].getY() >= 0 && y + points[i].getY() < height) {
                        bufferedImage.setRGB(x + points[i].getX(), y + points[i].getY(), 0);
                    }
                }
            }
        }
    }

    private int findClosestPoint(Point2D point) {
        int index = 0;
        double minDistance = distance(point, points[index]);
        double currentDistance;

        for (int i = 1; i < numberOfPoints; ++i) {
            currentDistance = distance(point, points[i]);

            if (currentDistance < minDistance) {
                minDistance = currentDistance;
                index = i;
            }
        }

        return index;
    }

    private double distance(Point2D pointA, Point2D pointB) {
        if (distanceOrder == 1.0d) {
            return Math.abs(pointA.getX() - pointB.getX()) + Math.abs(pointA.getY() - pointB.getY());
        }

        if (distanceOrder == 2.0d) {
            return Math.sqrt((pointA.getX() - pointB.getX()) * (pointA.getX() - pointB.getX())
                    + (pointA.getY() - pointB.getY()) * (pointA.getY() - pointB.getY()));
        }

        return Math.pow(Math.pow(Math.abs(pointA.getX() - pointB.getX()), distanceOrder) +
                Math.pow(Math.abs(pointA.getY() - pointB.getY()), distanceOrder), (1.0d / distanceOrder));
    }
}
Java Voronoi Diagram
Tagged on:                 

Leave a Reply

Your email address will not be published. Required fields are marked *

By continuing to use the site, you agree to the use of cookies. You can read more about it the Cookies&Privacy Policy Section Above. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this. You can read more about it the Cookies&Privacy Policy Section.

Close