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.

ExampleMetricLine.java

 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   }