Rupert Madden-Abbott
Rupert Madden-Abbott

Reputation: 13278

Why is a Pixmap circle off by 1?

I'm trying to draw a circle using Pixmap. To make the problem clearer, I'm filling the entire Pixmap area in white, then drawing the circle in a different color. Here is the code that I feel should work.

I'm setting the width/height of the Pixmap to twice the size of the radius of the circle.

Then I'm drawing a circle in the middle of the Pixmap at (radius, radius).

public static Texture circle(int radius, Color color) {
  Pixmap pixmap = new Pixmap(radius * 2, radius * 2, Pixmap.Format.RGBA4444);
  pixmap.setColor(Color.WHITE);
  pixmap.fill();
  pixmap.setColor(color);
  pixmap.fillCircle(radius, radius, radius);
  Texture texture = new Texture(pixmap);
  pixmap.dispose();
}

Unfortunately, the Pixmap cuts off the circle on the right and bottom sides. For example:

enter image description here

If I increase the size of the Pixmap by 1 in both the width and height, then it looks fine:

enter image description here

I can just arbitrarily add an extra pixel but I'd like to understand why this is necessary. Why does setting the radius of the circle to X result in a diameter that is actually X + 1?

Upvotes: 3

Views: 91

Answers (2)

CryptoFool
CryptoFool

Reputation: 23089

To get the result you want, the location of the circle's center would have to fall between two pixels, so that there are a similar number of whole pixels on either side of that location. My guess is that the Pixmap code defines a pixel's location to mean the center of a pixel. So the point (radius, radius) is closer to the right edge than the left, and (radius-1, radius-1) is closer to the left edge than the right. With this definition of location, the center of your circle should be at location (radius-.5, radius-.5).

If you have to put the center of the circle in the middle of a pixel, then it makes sense that you'd use the location (radius, radius) for the circle and that you'd need the width and height of the Pixmap to be (2*radius + 1, 2*radius+1). This way, there are the same number of pixels, radius+.5 pixels, on either side of the center of the circle. You might at that point want to draw a circle of radius radius + .5 if the library will take that.

Upvotes: 2

bornander
bornander

Reputation: 1148

Because it draws a circle centered on a pixel, not between pixels.

So the actual radius of the circle drawn is one more than passed in, a circle with radius 1 is drawn as (numbers are coordinates in this example):

 012
0 X
1XCX
2 X

This technically has a radius of 1.5, but now it's centered on a pixel (C). I am guessing this is to allow you to place it accurately, as if it actually had a radius of 2, you wouldn't be able to place the center on a pixel.

Upvotes: 1

Related Questions