Search code examples
racketpenmiter

Why does my Racket pen draw extra pixels where two lines join despite using 'butt and 'miter?


I'm making two squares as seen in the following image.One red and one blue square

The yellow circle is not part of the image, but it shows some pixels that I'm expecting to not be there. I have no experience with computer graphics, but from what I've read in the documentation, these pixels should not be there. Do I have unrealistic expectations or am I doing something wrong to get these 'overflow' pixels as shown by the yellow circle in my above drawing?

Here is the code that generates the boxes.

     #lang racket/gui

(define dc (new svg-dc%  
                [width 64]
                [height 64]
                [output "boxes.svg"]
                [exists 'replace]))
(send dc start-doc "boxes.svg")
(send dc start-page)

        (define old-brush (send dc get-brush))
        (define old-pen (send dc get-pen))
        (send dc set-brush 
          (new brush% [style 'solid]
                      [color "White"]))
        (send dc set-pen 
          (new pen% [width 0]
                    [color "Black"]
                    [cap 'butt]
                    [join 'miter]))
        (send dc set-pen old-pen)
        (send dc set-brush old-brush)   

        (send dc set-pen
          (new pen% [width 0]
                    [color "Black"]
                    [cap 'butt]
                    [join 'miter]))
        (send dc set-brush 
          (new brush% [style 'solid]
                      [color "Red"]))
        (define path (new dc-path%))
        (send path move-to 0 0)
        (send path line-to 10 0)
        (send path line-to 10 10)
        (send path line-to 0 10)
        (send path close)
        (send dc draw-path path 0 0)
        (send dc set-pen old-pen)
        (send dc set-brush old-brush)

        (send dc set-pen 
          (new pen% [width 0]
                    [color "Black"]
                    [cap 'butt]
                    [join 'miter]))
        (send dc set-brush
          (new brush% [style 'solid]
                      [color "Blue"]))
        (define path2 (new dc-path%))
        (send path2 move-to 0 0)
        (send path2 line-to 10 0)
        (send path2 line-to 10 10)
        (send path2 line-to 0 10)
        (send path2 close)
        (send dc draw-path path2 10 0)
        (send dc set-pen old-pen)
        (send dc set-brush old-brush)

(send dc end-page)
(send dc end-doc)

Solution

  • This is just a comment, but I needed some more space.

    Things to look out for:

    anti aliasing  - turn it of
    smoothing      - is the mode unsmoothed or aligned?
    

    Let's say the first pixel has opposite corners (0,0) and (1,1). Without aligment, you can choose a square pen of size and make a dot at (0.5,0.5) in order not to draw outside the pixel.

    If things are aligned, you need to adjust accordingly.

    See set-smoothing.

    https://docs.racket-lang.org/draw/dc___.html#%28meth._%28%28%28lib._racket%2Fdraw..rkt%29._dc~3c~25~3e%29._set-smoothing%29%29

    UPDATE

    As far as I can tell, adding the line:

    (send dc set-smoothing 'aligned)
    

    at the beginning will fix the problem.