| 
 Lisp »Tips 'n Tricks 
»Funzioni ricorsive in AutoLISP
 »1
 | 2
 | 3
 | 4
 | 5
 | 6
 | 7 a
 , b
 , c
 , d
 , e
 >II
 >III
 >IV
 >V
 >VI
 >VII Frattali di Julia e Mandelbrot Per rappresentare i frattali lo schermo 2D del computer deve aprirsi come una finestra sul piano complesso. Julia L'insieme di Julia di z²+c (con z e c numeri complessi) è la regione di confine tra l'insieme di punti che fuggono all'infinito e l'insieme di punti attratti da un ciclo, cioè ogni punto del piano complesso con orbita che non fugge all'infinito né è attratta da un ciclo appartiene all'insieme di Julia di z²+c. L'algoritmo da implementare in autolisp per disegnare l'insieme di Julia di z²+c è il seguente: 
   Input: c1 e c2 (numeri reali di c=c1+ic2 parametro complesso di z²+c)
   Input: seleziona una griglia quadrata di punti MxN.
   Per ogni punto z di MxN calcola 20 iterazioni dell'orbita di z controllando se il punto cade fuori dal cerchio di raggio 2.
   Output: se tutti i 20 punti iterati dell'orbita cadono all'interno del cerchio di raggio 2 disegna il punto p(M,N).
 Il lisp disegna in nero l'insieme di punti contenuti nel quadrato |x|,|y| <= 2 la cui orbita non esce, prima di 20 iterazioni, dal cerchio con centro nell'origine e raggio 2. Inoltre |c|<=2. JL1.LSP | 
;
; JL1 (C)2004 by Claudio Piccini
; 3 Aprile 2004
; www.cg-cad.com
; Disegna il frattale di Julia
;
(defun julia ( itera / 
               N x0 y0 x y i z
 )
 (if (>= itera 0)
  (progn
   (setq x0 (+ -2 (/ itera K))) ;*
   (setq N 0)
   (while (<= N itera2)
    (setq y0 (- 2 (/ N K)))
    (setq x x0)
    (setq y y0)
    (setq i 0)
    (while
     (progn
      (setq i (1+ i))
      (setq x1 
       (+ (- (* x x)(* y y)) cx)
      )
      (setq y1 
       (+ (* 2 x y) cy)
      )
      (setq x x1)
      (setq y y1)
      (setq z (+ (* x x)(* y y)))
      (if (> z 4)  nil T) 
      (if (< i 20) T nil)
     )
    )
    (if (< z 4)
     (progn
      (command "_point" (list itera N))
      (command "_point" (list (- spec itera) (- spec N))) ;*
     )
    )
    (setq N (1+ N))
   )
   (julia (- itera 1))
  )
 )
)
(defun c:jl1 ( /  snapp cx cy itera itera2 K spec)
 (setvar "cmdecho" 0)
 (setq snapp (getvar "osmode"))
 (command "_osnap" "_non")
 (initget 1) ;non nil 
 (setq cx (getreal "\nparte reale di c: "))
 (initget 1) ;non nil 
 (setq cy (getreal "\nparte immag. di c: "))
 (initget (+ 1 2 4)) ;non nil, non 0, non negativo
 (setq itera (getint "\nlato della griglia: "))
 (setq spec itera)
 (setq itera2 (/ itera 2))
 (setq K (/ itera 4.0))
 (julia itera)
 (setvar "osmode" snapp)
 (command "_redraw")
 (setvar "cmdecho" 1)
 (princ)
)
;eof
 | 
 Test del LISP Command: jl1
parte reale di c: 0
 parte immag. di c: 0
 lato della griglia: 100
   Insieme di Julia di z²
 
 
 Command: jl1
parte reale di c: 0.360284
 parte immag. di c: 0.100376
 lato della griglia: 300
   Insieme di Julia di z²+0.360284+0.100376i
 
 
 Command: jl1
parte reale di c: -1
 parte immag. di c: 0
 lato della griglia: 300
   Insieme di Julia di z²-1
 
 
 Command: jl1
parte reale di c: -0.1
 parte immag. di c: 0.8
 lato della griglia: 400
   Insieme di Julia di z²-0.1+0.8i
 
 
 Command: jl1
parte reale di c: -1.25
 parte immag. di c: 0
 lato della griglia: 400
   Insieme di Julia di z²-1.25
 
 
 Analisi del LISP (*) Con l'istruzione (setq itera2 (/ itera 2)) divido il lato della griglia per 2 e uso la variabile per il ciclo (while (<= N itera2) sfruttando la simmetria del sistema dinamico: dopo una iterazione le orbite di z e -z sono le stesse, quindi se l'orbita di z tende all'infinito lo stesso accade per -z.
z=(command "_point" (list itera N)) quindi
 -z=(command "_point" (list (- spec itera) (- spec N)))
 
 (*) Dalle formule di trasformazione :
 M=num_pixel*(x-l)/(r-l)
 N=num_pixel*(r-y)/(r-l)
 e con (|x|,|y| <= 2), scrivo:
 (setq K (/ itera 4.0)) ad es. con itera=M=400, K=100.0
 
 M=400*(x+2)/4
 N=400*(2-y)/4
 
 itera=K*(x+2)
 N=K*(2-y)
 
 (setq x0 (+ -2 (/ itera K)))
 (setq y0 (- 2 (/ N K)))
 JL2.LSP JL2 disegna le orbite in fuga all'infinito, con colori diversi secondo il variare dei tempi di fuga delle orbite.
La regione interna al confine di Julia è colorata in blu: è l'insieme dei punti non caotici, ciclici.
 | 
;
; JL2 (C)2004 by Claudio Piccini
; 3 Aprile 2004
; www.cg-cad.com
; Disegna il frattale di Julia
; e i tempi di fuga verso l'infinito
;
(defun julia ( itera / 
               N x0 y0 x y i z
 )
 (if (>= itera 0)
  (progn
   (setq x0 (+ -2 (/ itera K)))
   (setq N 0)
   (while (<= N itera2)
    (setq y0 (- 2 (/ N K)))
    (setq x x0)
    (setq y y0)
    (setq i 0)
    (while (< i 20)
     (setq x1 (+ (- (* x x)(* y y)) cx))
     (setq y1 (+ (* 2 x y) cy))
     (setq x x1)
     (setq y y1)
     (setq z (+ (* x x)(* y y)))
     (if (> z 4)
      (progn
       (cond
        ((< i  1)(command "_color" "_red"))
        ((< i  2)(command "_color" "_yellow"))
        ((< i  4)(command "_color" "_green"))
        ((< i 20)(command "_color" "_cyan"))
       )
       (setq i 20)
      )
     )
     (setq i (1+ i))
    )
    (if (< z 4)(command "_color" "_blue"))
    (command "_point" (list itera N))
    (command "_point" (list (- spec itera) (- spec N)))
    (setq N (1+ N))
   )
   (julia (- itera 1))
  )
 )
)
(defun c:jl2 ( /  snapp cx cy itera itera2 K spec)
 (setvar "cmdecho" 0)
 (setq snapp (getvar "osmode"))
 (command "_osnap" "_non")
 (initget 1) ;non nil 
 (setq cx (getreal "\nparte reale di c: "))
 (initget 1) ;non nil 
 (setq cy (getreal "\nparte immag. di c: "))
 (initget (+ 1 2 4)) ;non nil, non 0, non negativo
 (setq itera (getint "\nlato della griglia: "))
 (setq spec itera)
 (setq itera2 (/ itera 2))
 (setq K (/ itera 4.0))
 (julia itera)
 (setvar "osmode" snapp)
 (command "_color" "_bylayer")
 (command "_redraw")
 (setvar "cmdecho" 1)
 (princ)
)
;eof
 | 
 Test del LISP Command: jl2
parte reale di c: -1
 parte immag. di c: 0
 lato della griglia: 400
   Insieme di Julia di z²-1
 
 
 JL3.LSP Con JL3 il tempo per generare il disegno diminuisce perché il lisp non disegna la regione interna al confine di Julia. | 
;
; JL3 (C)2004 by Claudio Piccini
; 4 Aprile 2004
; www.cg-cad.com
; Disegna il frattale di Julia
; e i tempi di fuga verso l'infinito
;
(defun julia ( itera / 
               N x0 y0 x y i z
 )
 (if (>= itera 0)
  (progn
   (setq x0 (+ -2 (/ itera K)))
   (setq N 0)
   (while (<= N itera2)
    (setq y0 (- 2 (/ N K)))
    (setq x x0)
    (setq y y0)
    (setq i 0)
    (while (< i 20)
     (setq x1 (+ (- (* x x)(* y y)) cx))
     (setq y1 (+ (* 2 x y) cy))
     (setq x x1)
     (setq y y1)
     (setq z (+ (* x x)(* y y)))
     (if (> z 4)
      (progn
       (cond
        ((< i  1)(command "_color" "_red"))
        ((< i  4)(command "_color" "_yellow"))
        ((< i  8)(command "_color" "_green"))
        ((< i 10)(command "_color" "_cyan"))
        ((< i 20)(command "_color" "_blue"))
       )
       (setq i 20)
      )
     )
     (setq i (1+ i))
    )
    (if (> z 4)
     (progn
      (command "_point" (list itera N))
      (command "_point" 
       (list (- spec itera)(- spec N))
      )
     )
    )
    (setq N (1+ N))
   )
   (julia (- itera 1))
  )
 )
)
(defun c:jl3 ( /  snapp cx cy itera itera2 K spec)
 (setvar "cmdecho" 0)
 (setq snapp (getvar "osmode"))
 (command "_osnap" "_non")
 (initget 1) ;non nil 
 (setq cx (getreal "\nparte reale di c: "))
 (initget 1) ;non nil 
 (setq cy (getreal "\nparte immag. di c: "))
 (initget (+ 1 2 4)) ;non nil, non 0, non negativo
 (setq itera (getint "\nlato della griglia: "))
 (setq spec itera)
 (setq itera2 (/ itera 2))
 (setq K (/ itera 4.0))
 (julia itera)
 (setvar "osmode" snapp)
 (command "_color" "_bylayer")
 (command "_redraw")
 (setvar "cmdecho" 1)
 (princ)
)
;eof
 | 
 Mandelbrot Prima si è visto il ruolo giocato dall'orbita di 0 nella ricerca di cicli attrattori per f(x)=x²+c; in conseguenza di ciò tale orbita è chiamata orbita critica e 0 punto critico.
Nel piano complesso l'insieme dei valori di c per cui l'orbita critica di z²+c non tende all'infinito è detto insieme di Mandelbrot.
 Per disegnare l'insieme si deve calcolare l'orbita di 0 per n iterazioni e per ogni punto vedere se il modulo è maggiore di 2, cioè se l'orbita è al di fuori del cerchio di raggio 2 allora sfugge all'infinito e quindi non appartiene all'insieme.
 
 Ecco i passi dell'algoritmo:
 - Seleziona una griglia quadrata di punti MxN.
 - Leggi ogni punto della griglia come un valore di c.
 - Per ogni c calcola 30 iterazioni dell'orbita di 0 e vedi se sfugge all'infinito altrimenti disegna il punto.
 MANB.LSP | 
;
; manb.lsp (C)2004 by Claudio Piccini
; 4 Aprile 2004
; www.cg-cad.com
; Disegna il frattale di Mandelbrot
;
(defun mandelbrot ( itera / N cx cy x y x1 y1 R i )
 (if (>= itera 0)
  (progn
   (setq N 0)
   (while (<= N itera2)
    (setq cx (+ -2 (/ itera K)))
    (setq cy (- 2 (/ N K)))
    (setq x cx)
    (setq y cy)
    (setq i 0)
    (while
     (progn
      (setq i (1+ i))
      (setq x1 (+ (- (* x x)(* y y)) cx))
      (setq y1 (+ (* 2 x y) cy))
      (setq R (+ (* x1 x1)(* y1 y1)))
      (setq x x1)
      (setq y y1)
      (if (> R 4)  nil T) 
      (if (< i 30) T nil)
     )
    )
    (if (< R 4)
     (progn
      (command "_point" (list itera N))
      (command "_point" (list itera (- spec N))
      )
     )
    )
    (setq N (1+ N))
   )
   (mandelbrot (- itera 1))
  )
 )
)
(defun c:manb ( /  snapp itera itera2 K spec)
 (setvar "cmdecho" 0)
 (setq snapp (getvar "osmode"))
 (command "_osnap" "_non")
 (initget (+ 1 2 4)) ;non nil, non 0, non negativo
 (setq itera (getint "\nlato della griglia: "))
 (setq spec itera)
 (setq itera2 (/ itera 2))
 (setq K (/ itera 4.0))
 (mandelbrot itera)
 (setvar "osmode" snapp)
 (command "_redraw")
 (setvar "cmdecho" 1)
 (princ)
)
;eof
 | 
 Test del LISP Command: manb
lato della griglia: 300
   Insieme di Mandelbrot
 
 
 L'insieme di M nella tipica forma a cuore con isole puntiformi attorno... MANB2.LSP MANB2 disegna solo le orbite in fuga all'infinito, con colori diversi secondo il variare dei tempi di fuga delle orbite. | 
;
; manb2.lsp (C)2004 by Claudio Piccini
; 4 Aprile 2004
; www.cg-cad.com
; Disegna il frattale di Mandelbrot
;
(defun mandelbrot ( itera / 
               N cx cy x y x1 y1 R i
 )
 (if (>= itera 0)
  (progn
   (setq N 0)
   (while (<= N itera2)
    (setq cx (+ -2 (/ itera K)))
    (setq cy (- 2 (/ N K)))
    (setq x cx)
    (setq y cy)
    (setq i 0)
    (while (< i 30)
     (setq x1 (+ (- (* x x)(* y y)) cx))
     (setq y1 (+ (* 2 x y) cy))
     (setq R (+ (* x1 x1)(* y1 y1)))
     (setq x x1)
     (setq y y1)
     (if (> R 4)
      (progn
       (cond
        ((< i  1)(command "_color" "_red"))
        ((< i  4)(command "_color" "_yellow"))
        ((< i  8)(command "_color" "_green"))
        ((< i 10)(command "_color" "_cyan"))
        ((< i 30)(command "_color" "_blue"))
       )
       (setq i 30)
      )
     )
     (setq i (1+ i))
    )
    (if (> R 4)
     (progn
      (command "_point" (list itera N))
      (command "_point" (list itera (- spec N))
      )
     )
    )
    (setq N (1+ N))
   )
   (mandelbrot (- itera 1))
  )
 )
)
(defun c:manb2 ( /  snapp itera itera2 K spec)
 (setvar "cmdecho" 0)
 (setq snapp (getvar "osmode"))
 (command "_osnap" "_non")
 (initget (+ 1 2 4)) ;non nil, non 0, non negativo
 (setq itera (getint "\nlato della griglia: "))
 (setq spec itera)
 (setq itera2 (/ itera 2))
 (setq K (/ itera 4.0))
 (mandelbrot itera)
 (setvar "osmode" snapp)
 (command "_color" "_bylayer")
 (command "_redraw")
 (setvar "cmdecho" 1)
 (princ)
)
;eof
 | 
 Test del LISP Command: manb2
lato della griglia: 400
 
 Il colore blu dichiara che le isole puntiformi sono in realtà connesse al cuore dell'insieme. Lisp »Tips 'n Tricks Ultimo Aggiornamento_Last Update: 5 Aprile 2004 |