vydd / sketch

A Common Lisp framework for the creation of electronic art, visual design, game prototyping, game making, computer graphics, exploration of human-computer interaction, and more.
MIT License
1.39k stars 66 forks source link

Add new join methods for when polyline angles are too sharp. #168

Open Kevinpgalligan opened 2 months ago

Kevinpgalligan commented 2 months ago

Attempting to fix the polyline bug, see: https://github.com/vydd/sketch/issues/53

Visual artifacts were appearing for polylines with sharp corners. This is a known problem when using the miter method of joining 2 lines. The join points are calculated by extending the left and right sides of the lines until they intersect. If there's a small angle between the lines, however, the intersection points go to infinity and beyond (they're almost parallel), creating visual artifacts.

The solution implemented here is to switch to a different join method when there's a small angle between the lines. I arbitrarily chose a cutoff of 20 degrees to switch from meter join to bevel join. I find that the transition from miter to bevel is too jarring if the cutoff angle is smaller than that, but I'm open to changing it. I also added a cutoff of 2 degrees to switch from the bevel method to a "simple" join, because bevel also gets buggy when the lines are parallel-ish.

In the future, we could make the cutoff angles configurable. It would also be possible to allow the user the choose the join they want, and add more joins like rounded.

Will share some of the experimenting I've done to confirm the fix.

Kevinpgalligan commented 2 months ago

Testing.

(defsketch polytest
            ((width 520)
             (height 110))
          (with-pen (make-pen :stroke +white+ :weight 2)
            (loop for i from 0
                  for gap in '(0 5 10 25 50)
                  do (polyline (+ 10 (* i 100)) 10
                               (+ 10 (* i 100) (/ gap 2)) 100
                               (+ 10 (* i 100) gap) 10))))

Miter join is used on the right, bevel is used to the left of that, and the "simple" join is used (at least) on the far left.

polyline-debug

Here's what it was like before. Note that for small enough angles, the line width isn't consistent and the edge is so pointy that it goes off the screen.

old-polyline-debug