Skip to content

[rshapes] Fix DrawPolyLinesEx()#6004

Open
MatthewRoush wants to merge 1 commit into
raysan5:masterfrom
MatthewRoush:master
Open

[rshapes] Fix DrawPolyLinesEx()#6004
MatthewRoush wants to merge 1 commit into
raysan5:masterfrom
MatthewRoush:master

Conversation

@MatthewRoush

Copy link
Copy Markdown
Contributor

If innerRadius is less than 0, it causes the outline to overlap itself and even grow outside of the polygon's bounds when thick is greater than radius. Clamping innerRadius to 0 fixes these problems.

If `innerRadius` is less than 0, it causes the outline to overlap itself and even grow outside of the polygon's bounds when `thick` is greater than `radius`. Clamping `innerRadius` to 0 fixes these problems.
@Gooh456

Gooh456 commented Jul 22, 2026

Copy link
Copy Markdown

The thick <= 0.0f early-return and the fmaxf(0.0f, ...) clamp on innerRadius both look correct for the degenerate cases this is targeting.

Separately (pre-existing, not introduced by this PR, but it's on the exact line you're already touching): innerRadius = radius - (thick*cosf(DEG2RAD*exteriorAngle/2.0f)) looks like it has a double degrees→radians conversion. exteriorAngle is computed two lines up as 360.0f/(float)sides*DEG2RAD — i.e. it's already in radians, same as angleStep in DrawPoly/DrawPolyLines, which is used directly in cosf()/sinf() with no extra DEG2RAD multiplication. Here it gets multiplied by DEG2RAD a second time before going into cosf().

Checked this numerically (compiled the same formula in a standalone C program) for sides 3 through 20:

sides= 3 buggy=0.99983 correct=0.50000
sides= 4 buggy=0.99991 correct=0.70711
sides= 5 buggy=0.99994 correct=0.80902
sides= 6 buggy=0.99996 correct=0.86603
sides= 8 buggy=0.99998 correct=0.92388
sides=12 buggy=0.99999 correct=0.96593
sides=20 buggy=1.00000 correct=0.98769

cosf(DEG2RAD*exteriorAngle/2.0f) stays pinned to ~1.0 across the whole range regardless of sides, while dropping the extra DEG2RAD* gives the value that actually varies with the polygon's exterior angle like the rest of the function does. Since the whole point of that cosine term is presumably to compensate for the miter angle at each vertex, the current formula effectively ignores sides when scaling innerRadius — for low side counts (triangle, square) the drawn outline would end up noticeably different from what the corrected formula gives. Since you're already modifying this line for the thick<=0/clamp fix, might be worth dropping the extra DEG2RAD* here too (or, if it's intentional for some reason I'm not seeing, a comment would help future readers).

@MatthewRoush

Copy link
Copy Markdown
Contributor Author

Yeah, that also looked weird to me as well. I think you would want to use the apothem for good results, because ideally the line thickness is measured from the edges and not the vertices.

This produces good visual results with the test program at the bottom.

float apothem = radius*cosf(DEG2RAD*180.0f/(float)sides);
float innerRadius = fmaxf(0.0f, radius - thick*(radius/apothem));

I don't know how mathematically correct this formula is, but it seems to work out nicely.

Test program

#include "raylib.h"

int main(void) {
    InitWindow(800, 450, "Test");
    SetTargetFPS(60);

    int thick = 2;

    while (!WindowShouldClose()) {
        if (IsKeyPressed(KEY_UP))   thick = thick + 1;
        if (IsKeyPressed(KEY_DOWN)) thick = thick - 1;
        thick = (thick < 1) ? 1 : (thick > 60) ? 60 : thick;

        BeginDrawing();
        ClearBackground(DARKGRAY);

        DrawText(TextFormat("thick = %d", thick), 10, 300, 20, GREEN);

        // These should match (except for maybe some floating point rounding)
        DrawRectangle(10, 10, 40, 40, LIGHTGRAY);
        DrawRectangleLinesEx((Rectangle){10, 10, 40, 40}, (float)thick, BLUE);

        DrawPoly((Vector2){30.0f, 80.0f}, 4, 28.284f, 45.0f, LIGHTGRAY);
        DrawPolyLinesEx((Vector2){30.0f, 80.0f}, 4, 28.284f, 45.0f, (float)thick, BLUE);

        // These should match (except for maybe some floating point rounding)
        DrawCircle(80, 30, 20.0f, LIGHTGRAY);
        DrawCircleLinesEx((Vector2){80.0f, 30.0f}, 20.0f, (float)thick, BLUE);

        DrawPoly((Vector2){80.0f, 80.0f}, 36, 20.0f, 0.0f, LIGHTGRAY);
        DrawPolyLinesEx((Vector2){80.0f, 80.0f}, 36, 20.0f, 0.0f, (float)thick, BLUE);

        // Some other shapes
        DrawPoly((Vector2){190.0f, 70.0f}, 3, 60.0f, 0.0f, LIGHTGRAY);
        DrawPolyLinesEx((Vector2){190.0f, 70.0f}, 3, 60.0f, 0.0f, (float)thick, BLUE);

        DrawPoly((Vector2){330.0f, 70.0f}, 4, 60.0f, 0.0f, LIGHTGRAY);
        DrawPolyLinesEx((Vector2){330.0f, 70.0f}, 4, 60.0f, 0.0f, (float)thick, BLUE);

        DrawPoly((Vector2){470.0f, 70.0f}, 5, 60.0f, 0.0f, LIGHTGRAY);
        DrawPolyLinesEx((Vector2){470.0f, 70.0f}, 5, 60.0f, 0.0f, (float)thick, BLUE);

        DrawPoly((Vector2){610.0f, 70.0f}, 6, 60.0f, 0.0f, LIGHTGRAY);
        DrawPolyLinesEx((Vector2){610.0f, 70.0f}, 6, 60.0f, 0.0f, (float)thick, BLUE);

        DrawPoly((Vector2){190.0f, 210.0f}, 7, 60.0f, 0.0f, LIGHTGRAY);
        DrawPolyLinesEx((Vector2){190.0f, 210.0f}, 7, 60.0f, 0.0f, (float)thick, BLUE);

        DrawPoly((Vector2){330.0f, 210.0f}, 8, 60.0f, 0.0f, LIGHTGRAY);
        DrawPolyLinesEx((Vector2){330.0f, 210.0f}, 8, 60.0f, 0.0f, (float)thick, BLUE);

        DrawPoly((Vector2){470.0f, 210.0f}, 9, 60.0f, 0.0f, LIGHTGRAY);
        DrawPolyLinesEx((Vector2){470.0f, 210.0f}, 9, 60.0f, 0.0f, (float)thick, BLUE);

        DrawPoly((Vector2){610.0f, 210.0f}, 10, 60.0f, 0.0f, LIGHTGRAY);
        DrawPolyLinesEx((Vector2){610.0f, 210.0f}, 10, 60.0f, 0.0f, (float)thick, BLUE);

        EndDrawing();
    }

    CloseWindow();
    return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants