2

I'm running into the problem that my rounded corners method returns non-uniform corners.
Method:

GraphicsPath GetRoundedPath(Rectangle r, int radius, bool topRight = true, bool topLeft = true, bool bottomLeft = true, bool bottomRight = true)
{
    GraphicsPath path = new GraphicsPath();

    if (topLeft)
        path.AddArc(r.X, r.Y, radius, radius, 180, 90);
    else path.AddLine(r.X, r.Y, r.Right, r.Y);

    if (topRight)
        path.AddArc(r.Right - radius, r.Y, radius, radius, 270, 90);
    else path.AddLine(r.Right, r.Y, r.Right, r.Height);

    if (bottomRight)
        path.AddArc(r.Right - radius, r.Bottom - radius, radius, radius, 0, 90);
    else path.AddLine(r.Right, r.Bottom, r.Right, r.Height);

    if (bottomLeft)
        path.AddArc(r.X, r.Bottom - radius, radius, radius, 90, 90);
    else path.AddLine(r.X, r.Bottom, r.X, r.Y);

    return path;
}

When invoke:

Panel p = new Panel();
p.BackColor = Color.Red;
p.Size = new Size(200, 200);
Controls.Add(p);
p.Region = new Region(GetRoundedPath(new Rectangle(p.ClientRectangle, 30, true, true, true, true));
p.Location = new Point(200, 200);

Return:
enter image description here
It is noticeable that the upper left corner is drawn normally, the upper right and lower left are crooked, and the lower left is even crooked.

After, I noticed that exactly one pixel was not visible on the right and bottom, then I opened the Paint(program) and painted it myself and got even corners:
enter image description here

What I tried:
Passed less Rectangle to GetRoundedPath
GetRoundedPath(new Rectangle(p.ClientRectangle.X, p.ClientRectangle.Y, p.ClientRectangle.Width - 1, p.ClientRectangle.Height - 1), 30, true, true, true, true)
The control just became a pixel smaller in width and height.
Don't to change Control.Region, to use Graphics.FillPath instead

p.Paint += (s, e) =>
{
    e.Graphics.FillPath(Brushes.Red, GetRoundedPath(p.ClientRectangle, 30, true, true, true, true));
};

Nothing has changed, I also tried to use it in conjunction with the first
Increase radius for individual corners

int oppositeRadius = (int)Math.Round(radius * 1.5)
...

The corners became stretched and looked more like slanted lines

UPD: I found similar post - Strange GraphicsPath.AddArc() behaviour but it work only with Region and all corners, when I have problem with GraphicsPath

Yotic
  • 136
  • 1
  • 8

1 Answers1

0

It looks like off by 1 pixel for center of arc error. Maybe try something like:

GraphicsPath GetRoundedPath(Rectangle r, int radius, bool topRight = true, bool topLeft = true, bool bottomLeft = true, bool bottomRight = true)
{
    GraphicsPath path = new GraphicsPath();

    if (topLeft)
        path.AddArc(r.X, r.Y, radius, radius, 180, 90);
    else path.AddLine(r.X, r.Y, r.Right, r.Y);

    if (topRight)
        path.AddArc(r.Right - radius - 1, r.Y, radius, radius, 270, 90);
    else path.AddLine(r.Right, r.Y, r.Right, r.Height);

    if (bottomRight)
        path.AddArc(r.Right - radius - 1, r.Bottom - radius - 1, radius, radius, 0, 90);
    else path.AddLine(r.Right, r.Bottom, r.Right, r.Height);

    if (bottomLeft)
        path.AddArc(r.X, r.Bottom - radius - 1, radius, radius, 90, 90);
    else path.AddLine(r.X, r.Bottom, r.X, r.Y);

    return path;
}
Nikolay
  • 3,658
  • 1
  • 24
  • 25
  • The corners are still crooked, the figure has only decreased by 1 pixel. Comparison - https://imgur.com/a/iBIAEsk – Yotic Jan 12 '23 at 02:53
  • I was reading docs for addArc method you use (https://learn.microsoft.com/en-us/windows/win32/api/gdipluspath/nf-gdipluspath-graphicspath-addarc(int_int_int_int_real_real) and noticed, that in this signature your radius param is not a radius, but full width or height of arc. So maybe radius/2 – Nikolay Jan 12 '23 at 06:26