cg-Cad

Lisp »Tips 'n Tricks »Lisp & Array »1 »2 »3 »4 »5 »6 »7 »8 »9 »10

Bézier definisce la curva P(u) in funzione della posizione di n+1 punti di controllo p.
P(u)=ni=0piBi,n(u)
Bi,n(u) è detta blending function
Bi,n(u)=C(n,i)ui(1-u)n-i
C(n,i) è il coefficiente binomiale
C(n,i)=n!/(i!(n-1)!)
Le Bi,n(u) costituiscono la chiave del comportamento delle curve di Bézier.
Le funzioni di miscelamento blending function possiedono determinate proprietà ed in particolare le seguenti:
1. Le Bi,n(u) devono interpolare (non approssimare) il primo e l'ultimo punto di controllo (p0, pn) cioè la curva inizia in p0 e termina in pn
2. Le Bi,n(u) devono essere simmetriche rispetto a u e a (1-u) cioè invertendo la sequenza dei punti di controllo si ottiene la stessa curva (un esempio di democrazia).

BEZ4 disegna e salva su file TXT le Curve di Bézier.
Legge dal file DATI.TXT le coordinate x,y,z dei punti di controllo (vedi tutorial n.58).

BEZ4

;|
   BEZ4.LSP (26 Giugno 2005)
   Copyright (C) 2005 Claudio Piccini.
   All rights reserved
   www.cg-cad.com

   Legge dal file DATI.TXT le coordinate x,y,z dei punti di controllo
   Struttura del file DATI.TXT:
   '(
   (x y z)
   ...
   (x y z)
   )
   Salva su file TXT le coordinate x,y,z dei punti della Curva di Bezier
   
   Implementa in AutoLISP l'algoritmo 21.8
   in 'Principi di CG', Newman, Sproull (McGraw-Hill)
|;

(defun xyzArray ( NR NC nome / i j L X e str ) 
 (setq str (strcat "\nInizializzazione Matrice" nome " Punti di Controllo di Bezier"))
 (princ str)
 (setq i 0)
 (while (< i NR)
  (setq j 0)
  (while (< j NC)
   (if (= j 2)
    (setq e 0.0) ; Z=0
    (progn
     (setq str (strcat "\nInserire elemento " nome "[" (itoa i) "],[" (itoa j) "]: ")) 
     (initget 1)
     (setq e (getreal str))
    )
   )
   (setq L (append L (list e)))
   (setq j (1+ j))
  )
  (setq X (append X (list L)))
  (setq L nil)
  (setq i (1+ i))
 )
 (setq X X)
)

(defun xyzList ( NR nome / i L X p1 str ) 
 (setq str (strcat "\nInizializzazione Matrice" nome " Punti di Controllo di Bezier"))
 (princ str)
 (setq i 1)
 (repeat NR
  (setq str (strcat "\nSeleziona " (itoa i) " Punto di Controllo..."))
  (setq p1 (getpoint str))
  (setq L (append L (list (car p1)(cadr p1)(caddr p1))))
  (setq X (append X (list L)))
  (setq L nil)
  (setq i (1+ i))
 )
 (setq X X)
)

(defun xyzFile ( / nDir nf 
                   NR NC lista 
                   str i j e 
                   punto X 
 )
 (setq nDir (getvar "dwgprefix"))
 (setq nf (strcat nDir "dati.txt"))
 (setq lista (load nf))
 (setq NR (length lista))
 (setq str (strcat "\nnumero righe file DATI.TXT=" (itoa NR)))
 (princ str)
 (setq NC (length (car lista)))
 (setq str (strcat "\nnumero colonne file DATI.TXT=" (itoa NC)))
 (princ str)
 (setq i 0)
 (while (< i NR)
  (setq j 0)
  (while (< j NC)
   (setq e (nth j (nth i lista)))
   (setq punto (append punto (list e)))
   (setq j (1+ j))
  )
  (setq X (append X (list punto))) 
  (setq punto nil)
  (setq i (1+ i))
 )
 (setq X X)
)

(defun disPuntiControllo ( NR NC lista / i j x y z )
 (setq i 0)
 (while (< i NR)
  (setq j 0)
  (while (< j NC)
   (setq x (nth j (nth i lista)))
   (setq y (nth (+ j 1) (nth i lista)))
   (setq z (nth (+ j 2) (nth i lista)))
   (command "_point" (list x y z))
   (setq j (1+ j))
  )
  (setq i (1+ i))
 )
)

(defun disCurva ( lista / NR nDir nf f1 i xyz str )
 (setq nDir (getvar "dwgprefix"))
 (setq nf (getstring 50 "\nNome del file di output (es. curva.txt): "))
 (if (/= nf "")
  (progn
   (setq nf (strcat nDir nf))
   (setq f1 (open nf "w"))
   (setq NR (length lista))
   (setq i 0)
   (while (< i NR)
    (setq xyz (nth i lista))
    (command "_point" xyz)
    (setq str 
     (strcat "\nP[" (itoa i) "]=" 
      (rtos (car xyz) 2 6)
      " "
      (rtos (cadr xyz) 2 6)
      " 0"
     )
    )
    (princ str f1)
    (setq i (1+ i))
   )
   (close f1)
  )
 )
)

(defun Cb ( N i / j a )
 (setq a 1)
 (setq j (+ i 1))
 (while (<= j N)
  (setq a (* a j))
  (setq j (1+ j))
 )
 (setq j 1)
 (while (<= j (- N i))
  (setq a (/ (* 1.0 a) j))
  (setq j (1+ j))
 )
 (setq a a)
)

(defun BBlend ( i N u / j v )
 (setq v (Cb N i))
 (setq j 1)
 (while (<= j i)
  (setq v (* v u))
  (setq j (1+ j))
 )
 (setq j 1)
 (while (<= j (- N i))
  (setq v (* v (- 1 u)))
  (setq j (1+ j))
 )
 (setq v v)
)

(defun Bezier ( xx yy zz u N P / i b e pnt L)
 (setq xx 0 yy 0 zz 0)
 (setq i 0)
 (while (<= i N)
  (setq b (BBlend i N u))
  (setq e (nth 0 (nth i P)))
  (setq xx (+ xx (* e b)))
  (setq e (nth 1 (nth i P)))
  (setq yy (+ yy (* e b)))
  (setq e (nth 2 (nth i P)))
  (setq zz (+ zz (* e b)))
  (setq i (1+ i))
 )
 (setq x xx)
 (setq y yy)
 (setq z zz)
 (setq L (append L (list x y z)))
)

(defun c:bez4 ( / snapp
                  N P NR NC
                  i rsp x y z p1
                  steps A L
 )
 (setvar "cmdecho" 0)
 (setq snapp (getvar "osmode"))
 (command "_osnap" "_non")
 (setq x 0 y 0 z 0)
 (while
  (progn
   (initget (+ 2 4)) ; N>0  
   (setq N (getint "\nGrado del polinomio <3..7> [3]: "))
   (if (= N nil)
    (progn
     (setq N 3)
     nil
    )
    T
   )
   (if (and (>= N 3)(<= N 7)) nil T)
  )
 )
 (setq NR (+ N 1) NC 3)
 (initget (+ 2 4)) ; steps>0
 (setq steps (getint "\nNumero punti della curva [100]: "))
 (if (= steps nil)(setq steps 100))
 (initget "t T d D f F")
 (setq rsp (getkword "\nInput punti controllo tastiera,disegno,file? <t,d,f> [d]: "))
 (cond 
  ((or (= rsp "t")(= rsp "T"))
   (setq P (xyzArray NR NC " P")) ; Input Punti di Controllo (tastiera)
   (disPuntiControllo NR NC P)    ; Disegna i Punti di Controllo
  )
  ((or (= rsp "d")(= rsp "D")(= rsp nil))
   (setq P (xyzList NR " P"))     ; Input Punti di Controllo (disegno)
   (disPuntiControllo NR NC P)    ; Disegna i Punti di Controllo
  )
  ((or (= rsp "f")(= rsp "F"))
   (setq P (xyzFile))          ; Input Punti di Controllo (file DATI.TXT)
   (disPuntiControllo NR NC P) ; Disegna i Punti di Controllo
  )
 )
 ;|
      Salva in A la Curva di Bezier
 |;
 (setq i 0)
 (while (< i steps)
  (setq L (Bezier x y z (/ i (* steps 1.0)) N P))
  (setq A (append A (list L)))
  (setq i (1+ i))
 )
 ;|
      Disegna e salva in TXT la Curva di Bezier
 |;
 (disCurva A)
 (setvar "osmode" snapp)
 (command "_redraw")
 (setvar "cmdecho" 1)
 (princ)
)
;;;eof

Test del Lisp

file DATI.TXT:
'(
(0 0 0)
(0 1 0)
(1 1 0)
(1 2 0)
)

Command: bez4
Grado del polinomio <3..7> [3]: Invio
Numero punti della curva [100]: Invio
Input punti controllo tastiera,disegno,file? <t,d,f> [d]: f
numero righe file DATI.TXT=4
numero colonne file DATI.TXT=3
Nome del file di output (es. curva.txt): curva.txt

BEZ4.LSP

file DATI.TXT:
'(
(1 2 0 "era l'ultimo")
(1 1 0 "era il penultimo")
(0 1 0 "era il secondo")
(0 0 0 "era il primo")
)

Command: bez4
Grado del polinomio <3..7> [3]: Invio
Numero punti della curva [100]: Invio
Input punti controllo tastiera,disegno,file? <t,d,f> [d]: f
numero righe file DATI.TXT=4
numero colonne file DATI.TXT=4
Nome del file di output (es. curva.txt): curva.txt

BEZ4.LSP

Output file .TXT:
P[0]=1 2 0
P[1]=0.999702 1.970298 0
P[2]=0.998816 1.941184 0
P[3]=0.997354 1.912646 0
...
P[96]=0.004672 0.115328 0
P[97]=0.002646 0.087354 0
P[98]=0.001184 0.058816 0
P[99]=0.000298 0.029702 0

Il lisp evidenzia una caratteristica della Curva: è possibile far passare la curva molto vicino ad un vertice X definendo un punto multiplo nel vertice X.
Esempio file DATI.TXT:
'(
(1 2 0 "")
(1 1 0 "")
(0 1 0 "punto multiplo 1")
(0 1 0 "punto multiplo 2")
(0 1 0 "punto multiplo 3")
(0 1 0 "punto multiplo 4")
(0 1 0 "punto multiplo 5")
(0 0 0 "")
)

BEZ4.LSP

Per approfondire:
W.M. Newman, R.F. Sproull, Principi di Computer Graphics - 1987, McGraw-Hill
M.E. Mortenson, Modelli geometrici in Computer Graphics - 1989, McGraw-Hill

Lisp »Tips 'n Tricks

Ultimo Aggiornamento_Last Update: 26 Giugno 2005