Triangulation 2DΒΆ
Creates a Delaunay triangulation <https://en.wikipedia.org/wiki/Delaunay_triangulation> from a set of 2D points. Then displays the results using Swing.
1 public static void main( String[] args ) {
2
3 // Rectangular region points will be randomly put into
4 int width = 400, height = 300;
5
6 // border that points won't be place inside of
7 int border = 10;
8
9 // Randomly generate points
10 var random = new Random(0xF00D);
11 var points = new DogArray<>(Point2D_F64::new);
12 for (int i = 0; i < 50; i++) {
13 // Avoid generating points right on the image edge. This is for appearance only
14 double x = border + random.nextDouble()*(width - 2*border);
15 double y = border + random.nextDouble()*(height - 2*border);
16 points.grow().setTo(x, y);
17 }
18
19 // Compute the Delaunay triangulation
20 var delaunay = new DelaunayIncrementalWalk();
21
22 // Uncomment below to print debug info to stdout
23 // delaunay.setVerbose(System.out, null);
24
25 // To make it more generic a function interface is used for the points array. This avoids making you
26 // convert it into a specific array format
27 delaunay.process(( idx, p ) -> {
28 p.setTo(points.get(idx));
29 return true;
30 }, points.size);
31
32 // Convert internal results into a standard mesh data structure
33 Mesh2D_F64 mesh = delaunay.toMesh(null);
34
35 visualizeWithSwing(width, height, mesh);
36 }
37
38 /// Visualize results using Swing. Draws the triangles and points.
39 private static void visualizeWithSwing( int width, int height, Mesh2D_F64 mesh ) {
40 // Visualize results
41 var image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
42 Graphics2D g2 = image.createGraphics();
43
44 // Turn on antialiasing so that it looks less like graphics from the 1980s
45 g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
46 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
47
48 // White background
49 g2.setColor(Color.WHITE);
50 g2.fillRect(0, 0, width, height);
51
52 // Draw the triangles
53 g2.setStroke(new BasicStroke(2));
54 g2.setColor(Color.BLACK);
55 var line = new Line2D.Double();
56 var triangle = new Triangle2D_F64();
57 for (int triangleID = 0; triangleID < mesh.triangles.size; triangleID += 3) {
58 mesh.getTriangle(triangleID, triangle);
59
60 for (int i = 0, j = 2; i < 3; j = i, i++) {
61 Point2D_F64 a = triangle.get(j);
62 Point2D_F64 b = triangle.get(i);
63 line.setLine(a.x, a.y, b.x, b.y);
64 g2.draw(line);
65 }
66 }
67
68 // Draw the points
69 g2.setColor(Color.RED);
70 int r = 5;
71 var oval = new Ellipse2D.Double();
72 for (int pointID = 0; pointID < mesh.points.size(); pointID++) {
73 Point2D_F64 p = mesh.points.getTemp(pointID);
74 oval.setFrame(p.x - r, p.y - r, 2*r, 2*r);
75 g2.fill(oval);
76 }
77
78 var panel = new JPanel() {
79 @Override protected void paintComponent( Graphics g ) {
80 super.paintComponent(g);
81 g.drawImage(image, 0, 0, null);
82 }
83 };
84 panel.setPreferredSize(new Dimension(width + 10, height + 10));
85
86 var frame = new JFrame();
87 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
88 frame.add(panel);
89 frame.pack();
90 frame.setVisible(true);
91 }