Centered dot not centered?!

The code below renders rectangular checkboxes: Dots centered in frames. I think the code should produce a symmetrical result (prefectly centered dot; equal distance between frame and dot on all sides) but it doesn’t:

example

This happens under Windows with Processing 3/Java 8 (it seems ok on my Android device, which has higher pixel density). Is this my mistake or an issue of Processing?

// distance between frame and dot (on all sides of dot), here 1/5 of font height

int dot_spacing = Font_H / 5;  

// calculate position and width of dot (height == width)

int dot_x = X_Checkbox + dot_spacing;
int dot_w = H_Checkbox - dot_spacing - dot_spacing;

// checkbox frame

stroke(...);
noFill();
rect  (X_Checkbox, y, H_Checkbox, H_Checkbox);

// checkbox dot

noStroke();
fill    (Palette_ARGB[Palette][Legend_PenFG]);
rect    (dot_x, y + dot_spacing, dot_w, dot_w);

Numbers would help a bit, but i’ll just make them up.
Lets say the fontH is 10, x_Checkbox = 10, H_Checkbox = 10 and y = 10:

dot_x = 10 + 2 = 12;
dot_w = 10 - 2 - 2 = 6;
then :
rect(10, 10, 10, 10);
rect(12, 12, 6, 6);
which results in the dot being 2 dist from the left and top, but 4 from right and bottom.

Just remove one from the 2 - dot_spacings s and it should be fine.

Please provide a runnable sketch.
It is impossible for us to know why your checkmarks and checkboxes are not lining up when we don’t know the value of a single variable.

But if you use rectMode(CENTER), they should be lining up perfectly.

They don’t line up because the math wasn’t right :sweat_smile:

rect(10, 10, 10, 10) … rect(12, 12, 6, 6) … which results in the dot being 2 dist from the left and top, but 4 from right and bottom

I don’t get the explanation. The values seem correct to me. The frame is 10x10 and the dot is 6x6. That means there should be 2 pixels on all sides of the dot (including the outer frame), hence 2 pixel offset to coordinates of outer frame (10 + 2)?!

if you use rectMode(CENTER),

I use the default mode, CORNER (there is more stuff in my app to render near those boxes).

Please provide a runnable sketch

Okay…

void setup() {  }

void
draw()
{
    int dot_spacing = 2;   // distance between frame and dot (on all sides of dot)
    int X_Checkbox  = 10;
    int Y_Checkbox  = 10;
    int H_Checkbox  = 10;  // width = height
    
    // calculate position and width of dot (height == width)
    
    int dot_x = X_Checkbox + dot_spacing;
    int dot_w = H_Checkbox - dot_spacing - dot_spacing;
    
    // checkbox frame
    
    stroke(0);
    noFill();
    rect  (X_Checkbox, Y_Checkbox, H_Checkbox, H_Checkbox);
    
    // checkbox dot
    
    noStroke();
    fill    (0);
    rect    (dot_x, Y_Checkbox + dot_spacing, dot_w, dot_w);
}

Yeah, you’re right… I just don’t seem to get used to rect taking x,y,w,h, but think its formX, fromY, toX, toY… sorry :sweat_smile:

Well, to solve your problem, just add +1 to dot_w.
The code is right and it executes right. The problem lies in how the pixels are displayed from left to right.

You either need to stroke both rectangles or stroke neither. The stroke changes the size of the rectangle.

Try the following:

    strokeWeight(5);
    stroke(0);
    noFill();
    rect  (X_Checkbox, Y_Checkbox, H_Checkbox, H_Checkbox);
        
    fill(255);
    noStroke();
    rect  (X_Checkbox, Y_Checkbox, H_Checkbox, H_Checkbox);

You’ll see that the 2nd rectangle does not completely cover the 1st rectangle, even though they are the same size.

So in your code, it will work correctly if you comment out the noStroke(); line.

1 Like

Or if you need stroke you’ll have to add the stroke size to dot_x. Note that stroke(0) still is one pixel in size. So you’ll have to add strokeWeight + 1 to dot_x to get the right size.

will work correctly if you comment out the noStroke(); line.

This centers the dot. Unfortunately the dot gets a weird 3D effect if noStroke() is omitted (and if rendering with alpha is used). Enlarged example:

example

void setup() {}

void
draw()
{
    int dot_spacing = 3;   // distance between frame and dot (on all sides of dot)
    int X_Checkbox  = 10;
    int Y_Checkbox  = 16;
    int H_Checkbox  = 16;  // width = height

    background(255);
    
    // calculate position and width of dot (height == width)
    
    int dot_x = X_Checkbox + dot_spacing;
    int dot_w = H_Checkbox - dot_spacing - dot_spacing;
    
    strokeWeight(1.1);
    
    // checkbox frame
    
    stroke(0, 64);
    noFill();
    rect  (X_Checkbox, Y_Checkbox, H_Checkbox, H_Checkbox);
    
    // render dot
   
    stroke(0, 64);
    fill  (0, 64);
    rect  (dot_x, Y_Checkbox + dot_spacing, dot_w, dot_w);
}

I thought I could fix this with a fully transparent stroke for the dot’s rect but then the dot is off-center again.

you’ll have to add the stroke size to

If I fiddle with the coordinates and widths until it’s right under Windows, it’s wrong under Android. Under Android, my original code leads to a perfect result. I guess I’ll have to use platform-specific kludges.

I guess I am more concerned that it operates differently under Android versus Windows, even though both are Java. I wonder then about p5js and python as well. This is undoubtedly due to differences in the underlying graphics packages the implementations use. I would recommend filing a bug report.

If a grey rectangle is rendered on a white background, some edges stay sharp but some get smoothed - they do not get rendered equally (as one would expect?):
smoothing
With this kind of asymmetry in the filled rect() (but not in the frame), it seems impossible to achieve pixel-perfect alignment. I’ll try to use an image for the checkbox and scale it to the desired size.