import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class HypercubePlot extends JPanel {
private static final int NUM_DIMENSIONS = 8;
private static final int WINDOW_SIZE = 800;
private static final double ANGLE = Math.PI / 4;
private double[][] vertices;
private int[][] edges;
private double[][] projectedVertices3D;
private double[][] projectedVertices45678;
private String[] labels;
public HypercubePlot() {
generateHypercubeVertices(NUM_DIMENSIONS);
generateHypercubeEdges(NUM_DIMENSIONS);
rotateVertices3D();
projectVertices45678();
labels = new String[vertices.length];
for (int i = 0; i < vertices.length; i++) {
StringBuilder labelBuilder = new StringBuilder();
for (double v : vertices[i]) {
labelBuilder.append((int) v);
}
labels[i] = labelBuilder.toString();
}
setPreferredSize(new Dimension(WINDOW_SIZE, WINDOW_SIZE));
}
private void generateHypercubeVertices(int dimensions) {
int numVertices = (int) Math.pow(2, dimensions);
vertices = new double[numVertices][dimensions];
for (int i = 0; i < numVertices; i++) {
for (int j = 0; j < dimensions; j++) {
vertices[i][j] = i / (int) Math.pow(2, j) % 2 == 0 ? -1 : 1;
}
}
}
private void generateHypercubeEdges(int dimensions) {
int numVertices = (int) Math.pow(2, dimensions);
int maxNumEdges = dimensions * (numVertices - 1) / 2;
edges = new int[maxNumEdges][2];
int edgeIndex = 0;
for (int i = 0; i < numVertices; i++) {
for (int j = i + 1; j < numVertices; j++) {
int diffCount = 0;
for (int k = 0; k < dimensions; k++) {
if (vertices[i][k] != vertices[j][k]) {
diffCount++;
}
}
if (diffCount == 1) {
edges[edgeIndex][0] = i;
edges[edgeIndex][1] = j;
edgeIndex++;
}
}
}
}
private void rotateVertices3D() {
projectedVertices3D = new double[vertices.length][3];
double[][] rotationMatrix3D = {
{Math.cos(ANGLE), 0, -Math.sin(ANGLE)},
{0, Math.cos(ANGLE), 0},
{Math.sin(ANGLE), 0, Math.cos(ANGLE)}
};
for (int i = 0; i < vertices.length; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < NUM_DIMENSIONS; k++) {
projectedVertices3D[i][j] += vertices[i][k] * rotationMatrix3D[k][j];
}
}
}
}
private void projectVertices45678() {
projectedVertices45678 = new double[projectedVertices3D.length][5];
double[][] rotationMatrix45678 = {
{1, 0, 0},
{0, Math.cos(ANGLE), -Math.sin(ANGLE)},
{0, Math.sin(ANGLE), Math.cos(ANGLE)}
};
for (int i = 0; i < projectedVertices3D.length; i++) {
for (int j = 0; j < 5; j++) {
for (int k = 0; k < 3; k++) {
projectedVertices45678[i][j] += projectedVertices3D[i][k] * rotationMatrix45678[k][j];
}
}
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int offsetX = getWidth() / 2;
int offsetY = getHeight() / 2;
// Plot the 3D hypercube edges
for (int[] edge : edges) {
int x1 = (int) projectedVertices3D[edge[0]][0] + offsetX;
int y1 = (int) projectedVertices3D[edge[0]][1] + offsetY;
int x2 = (int) projectedVertices3D[edge[1]][0] + offsetX;
int y2 = (int) projectedVertices3D[edge[1]][1] + offsetY;
g2d.setColor(Color.BLACK);
g2d.drawLine(x1, y1, x2, y2);
}
// Plot projected vertices with labels
for (int i = 0; i < projectedVertices3D.length; i++) {
int x = (int) projectedVertices3D[i][0] + offsetX;
int y = (int) projectedVertices3D[i][1] + offsetY;
g2d.setColor(Color.RED);
g2d.fillOval(x - 5, y - 5, 10, 10);
g2d.setColor(Color.BLACK);
g2d.drawString(labels[i], x, y);
}
// Create illusion lines connecting projected vertices in 3D space
for (int i = 0; i < projectedVertices3D.length; i++) {
for (int j = i + 1; j < projectedVertices3D.length; j++) {
int x1 = (int) projectedVertices3D[i][0] + offsetX;
int y1 = (int) projectedVertices3D[i][1] + offsetY;
int x2 = (int) projectedVertices3D[j][0] + offsetX;
int y2 = (int) projectedVertices3D[j][1] + offsetY;
g2d.setColor(Color.GRAY);
g2d.drawLine(x1, y1, x2, y2);
}
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Hypercube Plot");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
HypercubePlot hypercubePlot = new HypercubePlot();
frame.getContentPane().add(hypercubePlot);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}