programming-examples/java/Data_Structures/Delaunay.java
2019-11-15 12:59:38 +01:00

109 lines
3.3 KiB
Java

import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.List;
public class Delaunay extends JFrame {
public static Triangle[] triangulateDelaunay(long[] x, long[] y) {
int n = x.length;
long[] z = new long[n];
for (int i = 0; i < n; i++)
z[i] = x[i] * x[i] + y[i] * y[i];
List<Triangle> res = new ArrayList<>();
for (int i = 0; i < n - 2; i++) {
for (int j = i + 1; j < n; j++) {
m1: for (int k = i + 1; k < n; k++) {
if (j == k)
continue;
long nx = (y[j] - y[i]) * (z[k] - z[i]) - (y[k] - y[i]) * (z[j] - z[i]);
long ny = (x[k] - x[i]) * (z[j] - z[i]) - (x[j] - x[i]) * (z[k] - z[i]);
long nz = (x[j] - x[i]) * (y[k] - y[i]) - (x[k] - x[i]) * (y[j] - y[i]);
if (nz >= 0)
continue;
for (int m = 0; m < n; m++) {
long dot = (x[m] - x[i]) * nx + (y[m] - y[i]) * ny + (z[m] - z[i]) * nz;
if (dot > 0)
continue m1;
}
// to deal with 4 points on a circle
int[] s1 = { i, j, k, i };
for (Triangle t : res) {
int[] s2 = { t.a, t.b, t.c, t.a };
for (int u = 0; u < 3; u++)
for (int v = 0; v < 3; v++)
if (isCrossIntersect(x[s1[u]], y[s1[u]], x[s1[u + 1]], y[s1[u + 1]], x[s2[v]],
y[s2[v]], x[s2[v + 1]], y[s2[v + 1]]))
continue m1;
}
res.add(new Triangle(i, j, k));
}
}
}
return res.toArray(new Triangle[0]);
}
static class Triangle {
int a, b, c;
public Triangle(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
static boolean isCrossIntersect(long x1, long y1, long x2, long y2, long x3, long y3, long x4, long y4) {
long z1 = (x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1);
long z2 = (x4 - x1) * (y2 - y1) - (y4 - y1) * (x2 - x1);
if (z1 < 0 && z2 < 0 || z1 > 0 && z2 > 0 || z1 == 0 || z2 == 0)
return false;
long z3 = (x1 - x3) * (y4 - y3) - (y1 - y3) * (x4 - x3);
long z4 = (x2 - x3) * (y4 - y3) - (y2 - y3) * (x4 - x3);
if (z3 < 0 && z4 < 0 || z3 > 0 && z4 > 0 || z3 == 0 || z4 == 0)
return false;
return true;
}
public Delaunay() {
// 4 points on a circle
// final long[] x = { 0, 0, 100, 100 };
// final long[] y = { 0, 100, 100, 0 };
int n = 100;
final long[] x = new long[n];
final long[] y = new long[n];
Random rnd = new Random();
for (int i = 0; i < n; i++) {
x[i] = rnd.nextInt(500) + 1;
y[i] = rnd.nextInt(500) + 1;
}
final Triangle[] ts = triangulateDelaunay(x, y);
JPanel panel = new JPanel() {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = ((Graphics2D) g);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(3));
g.setColor(Color.BLUE);
for (Triangle t : ts) {
g.drawLine((int) x[t.a], (int) y[t.a], (int) x[t.b], (int) y[t.b]);
g.drawLine((int) x[t.a], (int) y[t.a], (int) x[t.c], (int) y[t.c]);
g.drawLine((int) x[t.c], (int) y[t.c], (int) x[t.b], (int) y[t.b]);
}
g.setColor(Color.RED);
for (int i = 0; i < x.length; i++) {
g.drawOval((int) x[i] - 1, (int) y[i] - 1, 3, 3);
}
}
};
setContentPane(panel);
}
public static void main(String[] args) {
JFrame frame = new Delaunay();
frame.setSize(new Dimension(800, 600));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}