Thursday, February 11, 2016

L-Systems in AutoLISP


One of the beautiful things about AutoCAD is the AutoLISP language which comes with it.  Experienced LISP programmers are likely to be familiar with the power of this early artificial intelligence language.  It is particularly well suited to CAD applications.  One of my favorite types of computer generated image is the L-System.  These systems follow some basic rules and rely on recursive subroutine calls to generate complexity.  Recursion is when a computer subroutine has the ability to call itself.  Only a few of the early programming languages had this capability which is one reason that LISP was so powerful for its time.

The other thing that I find amazing is the amount of complexity that can be generated from relatively simple code.  Following is the code used to generate this image.  You may need to fix the line wraps.  The radians to degrees and degrees to radians routines I got from the internet.

; converts radians to degrees
(defun RtD (r) (* 180.0 (/ r pi)))
; converts degrees to radians
(defun DtR (d) (* pi (/ d 180.0)))

(defun ls1 (x y alpha delta n) ; Sample Call: (ls1 0.0 0.0 90.0 25.0 7)
  
  ; x, y are the starting coordinates for the drawing
  ; Alpha is the starting angle, 90 means straight up
  ; Delta is the angle of each branch from the starting angle
  ; N is the number of iterations, it also controls the length of each branch
  
  (cond ((> n 1)                    ; Check to see if n is small down to 1 yet
    (setq x2 (+ x (* (cos (DtR alpha)) n))) ; Set up X2 and Y2 coordinates
    (setq y2 (+ y (* (sin (DtR alpha)) n))) ; X2 = X + N * cos(alpha)
    (setq p1 (list x y 0.0))                ; Create points 1 and 2
    (setq p2 (list x2 y2 0.0))
    (command "pline" p1 p2 "")              ; Draw a line from X,Y to X2,Y2
    (ls1 x2 y2 (+ alpha delta) delta (1- n)); Call the subroutine again
                                     ; Add alpha and delta, n-1
    (ls1 (+ x (* (cos (DtR alpha)) n)) (+ y (* (sin (DtR alpha)) n)) (- alpha delta) delta (1- n)) ; Call again
    )
    (T) ; This is required to end the cond, it is always true
  )
)

This is pretty simple code with hidden complexity.  I think the X2 and Y2 are globals because they seemed to change values when I put them in as parameters to the subroutine.  Save this code to your macro library and load it using "Load Application."  You may need to allow AutoCAD to run macros.  Turn OSNAP off by hitting F3.  To get the image below run it with the sample run call:

(ls1 0.0 0.0 90.0 25.0 7)




You can try varying the delta angle, alpha, or starting position.  Be careful not to make n too large too quickly or your system may lock up or crash.  It took quite a while to generate the image on my computer when n was only 16.  Here are some more images with various values of delta and n.