Simple JavaFX program to generate Voronoi Diagrams of specified settings.

Voronoi diagram generated in JavaFX with 25 random placed points.
Voronoi diagram generated using JavaFX with 25 random placed points using Euclidean distance (distance order of 2).

Main.java

import javafx.application.Application;

// 2018 TheFlyingKeyboard and released under MIT License
// theflyingkeyboard.net
public class Main  {
    public static void main(String[] args) {
        Application.launch(Voronoi.class, args);
    }
}

Voronoi.java

import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

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

// 2018 TheFlyingKeyboard and released under MIT License
// theflyingkeyboard.net
public class Voronoi extends Application {
    private final int width = 1000;
    private final int height = 500;
    private final double distanceOrder = 2.0d;
    private final int numberOfPoints = 25;
    private final Point2D[] points = new Point2D[numberOfPoints];
    private final Color[] colors = new Color[numberOfPoints];
    private final int pointSize = 10;
    private Canvas canvas;

    @Override
    public void init() {
        for (int i = 0; i < numberOfPoints; ++i) {
            points[i] = new Point2D(ThreadLocalRandom.current().nextInt(width), ThreadLocalRandom.current().nextInt(height));
            colors[i] = Color.rgb(ThreadLocalRandom.current().nextInt(255), ThreadLocalRandom.current().nextInt(255), ThreadLocalRandom.current().nextInt(255));
        }
    }

    @Override
    public void start(Stage stage) {
        canvas = new Canvas(width, height);
        generateVoronoi();

        Pane root = new Pane();
        root.getChildren().add(canvas);
        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.setTitle("Voronoi Diagram");
        stage.show();

        File file = new File("Voronoi " + width + "X" + height + " " + numberOfPoints + " points.png");
        WritableImage writableImage = new WritableImage(width, height);
        canvas.snapshot(null, writableImage);
        RenderedImage renderedImage = SwingFXUtils.fromFXImage(writableImage, null);
        try {
            ImageIO.write(renderedImage, "png", file);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void generateVoronoi() {
        PixelWriter pixelWriter = canvas.getGraphicsContext2D().getPixelWriter();

        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; ++x) {
                pixelWriter.setColor(x, y, colors[findClosestPoint(new Point2D(x, y))]);
            }
        }

        GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
        graphicsContext.setFill(Color.BLACK);

        for (int i = 0; i < numberOfPoints; ++i) {
            graphicsContext.fillOval(points[i].getX(), points[i].getY(), pointSize, pointSize);
        }
    }

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

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

 



JavaFX 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