[cl-gd-devel] with-transformation off-by-one bug?

Michael J. Forster mike at sharedlogic.ca
Tue Sep 11 16:13:24 UTC 2007


Hi Edi,

I'm using CL-GD with both LispWorks 5.0 on OS X and CMUCL 19b on
FreeBSD to plot some graphs, and I'm very grateful for your work
here.  CL-GD is slick to use and more than fast enough for
generating sparklines on an interactive web-based dashboard.

I'm using WITH-TRANSFORMATION to simplify the graph plotting, and
it's not behaving the way I would expect.  As I read it in the
documentation, this...

(with-transformation (:x1 0
                       :width width
                       :y1 0
                       :height height)
   ...)


... should transform the coordinate system from this...

0,0 -----> width - 1
|
|
|
V
height - 1


... to this...

height - 1
^
|
|
|
0,0 -----> width - 1


Instead, I get this...

height
^
|
|
|
0,1 -----> width - 1


The y-axis transformation isn't consistent with that of the x-axis.
What's even more confusing, is that if the x-axis transformation
does work then the following should only complain about y1, y2, and
height, and not about x1, x2, and width, but that's not the case:

(let ((height 100)
       (width 100))
   (with-transformation (:x1 0
                         :x2 (1- width)
                         :width width
                         :y1 0
                         :y2 (1- height)
                         :height height)
     ...))


Indeed, when I checked the macroexpansion, I see...

(UNLESS #:X154021 (SETQ #:X154021 (- #:X254022 #:WIDTH54023)))
(UNLESS #:X254022 (SETQ #:X254022 (+ #:X154021 #:WIDTH54023)))
(UNLESS #:WIDTH54023 (SETQ #:WIDTH54023 (- #:X254022 #:X154021)))
(UNLESS #:Y154024 (SETQ #:Y154024 (- #:Y254025 #:HEIGHT54026)))
(UNLESS #:Y254025 (SETQ #:Y254025 (+ #:Y154024 #:HEIGHT54026)))
(UNLESS #:HEIGHT54026 (SETQ #:HEIGHT54026 (- #:Y254025 #:Y154024)))


Again, I would have thought, instead, that...

width = (x2 - x1) + 1
height = (y2 - y1) + 1


So, the y-axis transformation isn't what I expected, but the
macroexpansion suggests that the x-axis transformation should be
off by one as well, yet it isn't.

Am I nuts?

Below is the snippet I was running to grok WITH-TRANSFORMATION.
I can mail you the images I got, if you like.

Thanks in advance,

Mike


(let* ((height 100)
        (width 100)
        (origin+1 (list 1 1))
        (x-axis+1 (list 10 1 20 1 30 1 40 1 50 1 60 1 70 1 80 1 90 1  
width 1))
        (y-axis+1 (list 1 10 1 20 1 30 1 40 1 50 1 60 1 70 1 80 1 90  
1 height))
        (x-axis-end+1 (list (1- width) 1))
        (y-axis-end+1 (list 1 (1- height))))
   (cl-gd:with-image* (width height)
     (allocate-color 255 255 255)
     (let ((black (allocate-color 0 0 0))
           (red (allocate-color 255 0 0))
           (green (allocate-color 0 255 0))
           (blue (allocate-color 0 0 255))
           (yellow (allocate-color 255 255 0)))
       (draw-rectangle* 0
                        (1- height) ; or 0 and ...
                        (1- width)
                        0           ; (1- height), doesn't matter
                        :color yellow)
       (draw-rectangle* 0
                        height ; or 0 and ...
                        width
                        0      ; ... height, doesn't matter
                        :color black)
       (set-pixels origin+1 :color red)
       (set-pixels x-axis+1 :color green)
       (set-pixels x-axis-end+1 :color blue)
       (set-pixels y-axis+1 :color green)
       (set-pixels y-axis-end+1 :color blue))
     (write-image-to-file "/tmp/test1.png"
                          :if-exists :supersede))
   (cl-gd:with-image* (width height)
     (allocate-color 255 255 255)
     (let ((black (allocate-color 0 0 0))
           (red (allocate-color 255 0 0))
           (green (allocate-color 0 255 0))
           (blue (allocate-color 0 0 255))
           (yellow (allocate-color 255 255 0)))
       (with-transformation (:x1 0
                             ;;:x2 99
                             :width width
                             :y1 0
                             ;;:y2 99
                             :height height
                             )
         (draw-rectangle* 0
                          (1- height) ; or 0 and ...
                          (1- width)
                          0           ; (1- height), doesn't matter
                          :color yellow)
         (draw-rectangle* 0
                          height ; or 0 and ...
                          width
                          0      ; ... height, doesn't matter
                          :color black)
         (set-pixels origin+1 :color red)
         (set-pixels x-axis+1 :color green)
         (set-pixels x-axis-end+1 :color blue)
         (set-pixels y-axis+1 :color green)
         (set-pixels y-axis-end+1 :color blue))
       (write-image-to-file "/tmp/test2.png"
                            :if-exists :supersede))))




--
Michael J. Forster <mike at sharedlogic.ca>




More information about the Cl-gd-devel mailing list