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 67 forks source link

MAKE-LINE behaving oddly with small values of stroke weight #103

Closed iamFIREcracker closed 8 months ago

iamFIREcracker commented 8 months ago

The following sketch is setup to do 2 things:

  1. Change the coordinate system to place (0, 0) in the center of the window and range from -1 to 1 in both coordinates
  2. Plot 0.3*sin(7x)
(defsketch make-line-bug ((title "MAKE-LINE bug")
                          (width 600)
                          (height 400)
                          (ratio (/ width height)))
  (scale (/ width 2 ratio) (/ height 2))
  (translate ratio 1)
  (background +black+)
  (let ((points (loop for x from (- ratio) upto ratio by (/ 1 1000)
                      collect (cons x (* (sin (* 7 x)) 0.3)))))
    (with-pen (make-pen :stroke +red+ :weight (/ 1 height))
      (loop for (x1 . y1) in points for (x2 . y2) in (cdr points) do
            (line x1 y1 x2 y2)))))

If you run it, you should be presented the following which hardly resemble what one might expect when trying to plot sin(x):

Screenshot 2023-11-05 at 9 41 33 PM

After a little bit of fiddling with skecth's source, I realized MAKE-LINE was using FLOOR to figure out the triangle strip to draw, and when I replaced FLOOR with / things immediately started to look better:

diff --git a/src/shapes.lisp b/src/shapes.lisp
index 19d786e..415191d 100644
--- a/src/shapes.lisp
+++ b/src/shapes.lisp
@@ -18,9 +18,9 @@
          (w (/ (or (pen-weight (env-pen *env*)) 1) 2))
          (dx (* 2 (sin a) w))
          (dy (* 2 (cos a) w))
-         (dx+ (floor dx 2))
+         (dx+ (/ dx 2))
          (dx- (- dx dx+))
-         (dy+ (floor dy 2))
+         (dy+ (/ dy 2))
          (dy- (- dy dy+)))
     (lambda ()
       (draw-shape
Screenshot 2023-11-05 at 9 50 30 PM

I am sure there is a reason why FLOOR was chosen instead of /, but it clearly does not work as expected when PEN-WEIGHT returns avalue smaller than 1 (1/400 in this example).

Gleefre commented 8 months ago

It indeed seems like an exact division would suit better here.

Another example:

(defsketch make-line-bug ()
  (translate 100 100)
  (scale 10)
  (with-pen (make-pen :weight 3 :stroke +black+ :fill +white+)
    (destructuring-bind (x y x* y*) (list 1 2 1 9)
      (line x y x* y*)
      (circle x y 1/10)
      (circle x* y* 1/10))))

The result: image (You can see that the line is not properly centered)

After applying the fix: image

vydd commented 8 months ago

Thank you both!