Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New draw.aaline width algorithm #3191

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

mzivic7
Copy link
Contributor

@mzivic7 mzivic7 commented Oct 23, 2024

This PR adds completely new implementation for draw.aaline width. Previous implementation (#3140) uses Bresenham's algorithm, and because of that, line cant be drawn at float coordinates (they are converted to ints instead).
New implementation uses modified Xiaolin Wu's algorithm that allows drawing at float coordinates, and is faster.

Old width implementation is removed for pgce 2.5.2 in #3192

aaline

How it works

Original draw_aaline code is used, heavily modified:

  • 2 antialiased pixels (2 are drawn for each point) are moved, leaving gap between, the size of width
  • that gap is filled either with horizontal or vertical lines, depending on steepines
  • Same thing is done to both endpoints
  • Clipping is also modified to support width
  • Using drawhorzlineclipbounding and new drawvertlineclipbounding to handle special cases when drawing lines outside surface.
Sample code
import pygame
pygame.init()
screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
    screen.fill("black")
    pygame.draw.aaline(screen, "white", (120, 100), (220, 160), 16)
    pygame.draw.aaline(screen, "white", (180, 170), (100, 260), 16)
    pygame.draw.aaline(screen, "white", (70.7, 240.2), (150.2, 150.6), 7)
    pygame.display.flip()
    clock.tick(60)
pygame.quit()

@mzivic7 mzivic7 requested a review from a team as a code owner October 23, 2024 11:35
Remove unused variables
@mzivic7 mzivic7 mentioned this pull request Oct 23, 2024
19 tasks
@yunline yunline added draw pygame.draw bugfix PR that fixes bug labels Oct 24, 2024
@bilhox bilhox added this to the 2.5.3 milestone Oct 30, 2024
Copy link
Member

@MyreMylar MyreMylar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output looks good to my old eyes, all the draw_test tests still pass on CI and locally.

I also did a bit of line drawing performance testing from some old tests for draw.line() I had lying about which shows that this new implementation is about twice as fast as the old implementation for draw.aaline():

Testing output:

New Draw AA Line:

Test 1:

100003 function calls in 0.960 seconds
100003 function calls in 0.954 seconds
100003 function calls in 0.958 seconds  

Test 2:

Draw Line - short, inside surface                   - 250003 function calls in 2.396 seconds
Draw Line - long, inside surface                    - 250003 function calls in 16.341 seconds
Draw Line - short, edges outside surface            - 250003 function calls in 0.625 seconds
Draw Line - long, edges a long way outside surface  - 250003 function calls in 14.244 seconds


Old Draw AA Line:

Test 1:

100003 function calls in 2.348 seconds
100003 function calls in 2.350 seconds
100003 function calls in 2.347 seconds

Test 2:

Draw Line - short, inside surface                  - 250003 function calls in 4.675 seconds
Draw Line - long, inside surface                   - 250003 function calls in 26.600 seconds
Draw Line - short, edges outside surface           - 250003 function calls in 0.801 seconds
Draw Line - long, edges a long way outside surface - 250003 function calls in 23.880 seconds


Regular, non-AA line:

Test 1:
100003 function calls in 0.520 seconds
100003 function calls in 0.523 seconds
100003 function calls in 0.523 seconds

Test 2:
Draw Line - short, inside surface                  - 250003 function calls in 1.083 seconds
Draw Line - long, inside surface                   - 250003 function calls in 6.175 seconds
Draw Line - short, edges outside surface           - 250003 function calls in 0.504 seconds
Draw Line - long, edges a long way outside surface - 250003 function calls in 6.011 seconds

Approved 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugfix PR that fixes bug draw pygame.draw
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants