thedarklord47 - 1 year ago 68

Java Question

So I am trying to draw an arc and put a circle around its round endpoint, but I am having issues due to rounding to the nearest pixel. This is visible in some but not all cases.

Is there a way to draw circles using floating points and anti-aliasing to eliminate this rounding error?

You can run this code to see the problem. I have drawn arcs of 0 length (appearing as large dots) instead of full arcs for clarity.

`import java.awt.*;`

import javax.swing.*;

public class Example extends JFrame {

private int CENTER = 200;

private static int WINDOW = 400;

private int LEFT = 50;

private int TOP = 50;

private int DIM = 300;

private int DIAMETER = 26;

public Example () {

super();

}

public void paint (Graphics g) {

Graphics2D g2 = (Graphics2D) g;

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

g2.setStroke(new BasicStroke(16, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER));

g2.setColor(new Color(0, 0, 255));

g2.drawArc(LEFT, TOP, DIM, DIM, 0, 0);

g2.drawArc(LEFT, TOP, DIM, DIM, 32, 0);

g2.drawArc(LEFT, TOP, DIM, DIM, 115, 0);

g2.drawArc(LEFT, TOP, DIM, DIM, 200, 0);

g2.drawArc(LEFT, TOP, DIM, DIM, 331, 0);

this.drawCircle(g2, 0);

this.drawCircle(g2, 32);

this.drawCircle(g2, 115);

this.drawCircle(g2, 200);

this.drawCircle(g2, 331);

g2.setStroke(new BasicStroke(1));

g2.setColor(new Color(0, 0, 0));

g2.drawLine(0, CENTER, DIM * 2, CENTER);

g2.drawLine(CENTER, 0, CENTER, DIM * 2);

}

private void drawCircle(Graphics2D g, int angle) {

g.setStroke(new BasicStroke(3));

g.setColor(new Color(0, 0, 255));

g.drawOval(

Math.round(CENTER + (float)(Math.cos(Math.toRadians(angle)) * (DIM/2)) - DIAMETER/2),

Math.round(CENTER - (float)(Math.sin(Math.toRadians(angle)) * (DIM/2)) - DIAMETER/2),

DIAMETER,

DIAMETER

);

}

public static void main (String args[]) {

Example e = new Example();

e.setSize(WINDOW, WINDOW);

e.setVisible(true);

e.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}

Answer Source

Thank you trashgod for pointing out the use of Ellipse2D. For others, the only code modifications required for float precision Ovals/Circles is below:

```
import java.awt.*;
...
g2.drawOval(x, y, width, height);
```

becomes

```
import java.awt.*;
import java.awt.geom.Ellipse2D;
...
g2.draw(new Ellipse2D.Float(x, y, width, height));
```

Also, add these to make them pretty:

```
g2.setRenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHints(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
```