In questo esercizio a partire dalla primitiva della sfera cartesiana, cioè costruita con paralleli equidistanti, vogliamo costruire, in prima approssimazione, un fusto dorico. Le misure le ho ricavate da L.Malerba, Forme e spazio, vol.1, Bologna, 1961, pag.33, Selinunte, Tempio “C”.
Diametro imo scapo di=1.7
Diametro sommo scapo ds=1
Altezza fusto h=6.5
Dal disegno risulta evidente che in basso la tangente alla curva di rastrematura è verticale. Come curva per il profilo utilizziamo una parabola con concavità verso il basso:
y=e-a*x^2 (massimo in x=0 con y=e, radici in +/-sqr(e/a) )
Deve risultare h= sqr(e/a), da cui a=e/h^2, dove e è l’entasis: e=(di-ds)/2
Dato che utilizzeremo una primitiva della sfera che ordina le quote dal polo N (=0) al polo S (=2*r), trasliamo la curva verso x+ del valore h:
y= e(1- (x-h)^2/ h^2)+di/2 (1)
Verifichiamo in 2D se la curva è corretta:
di= 1.7
ds=1
h=6.5
n= !resol, numero intero, fine parametri
e=(di-ds)/2
For j=0 to n !n+1 vertici di suddivisione, n segmenti
Put h/n*j, e*(1- (h/n*j-h)^2/ h^2)+ds/2 !sostituito nella (1) x con h/n*j
Next j
POLY2 nsp/2, 1, get (nsp)
Line2 0,0, h,0 !asse colonna
Line2 h,0, h,di/2 !imo
Line2 0,0, 0,ds/2 !sommo
A questo punto costruiamo la sezione, che prevede 18 scanalature, con proporzioni .5/2.4 tra profondità e larghezza.
Un parallelo di raggio r(j) della sfera si scrive:
x=r(j)*cos(u)
y= r(j)*sin(u)
con u= 180/m*i , i variabile da 0 a 2*m-1 (o da 1 a 2*m)
Tradotto in linea 2D (sezione imo scapo):
m= !resol
r=di/2
for i=0 to 2*m-1
put r*cos(180/m*i ), r*sin(180/m*i )
next i
POLY2 nsp/2, 1+4, get (nsp)
Da notare che utilizziamo risoluzioni diverse per il profilo e per il diametro, questo perché la sezione è molto più complessa e richiede una definizione alta.
Per costruire le scanalature utilizziamo la funzione y=-abs(sin(x)) con periodo 180 e oscillazione tra 0 e -1.
Poiché per i=2*m dobbiamo avere 18 minimi, dovremo scrivere:
y=-abs(sin(90/m*i*18))
Anche in questo caso si rivela l’utilità del calcolatore, per verificare se la formula è corretta, altrimenti si effettuano i dovuti aggiustamenti.
Il perimetro della circonferenza di raggio r è circa 6*r (sarebbe 2*pi*r), quindi la larghezza della singola scanalatura è: Ls=6*r/18=r/3, poiché la profondità ha proporzioni .5/2.4 l’ampiezza della funzione sinus è:
.5*r/7.2=r/14.4
y=- r/14.4*abs(sin(90/m*i*18))
questa funzione andrà sommata a quella che definisce il parallelo.
In conclusione la sezione deve avere questa forma:
p=18 !numero scanalature
for i=0 to 2*m-1
put r*(1-1/14.4*abs(sin(90/m*i*p)))*cos(180/m*i ), r*(1-1/14.4*abs(sin(90/m*i*p)))*sin(180/m*i )
next i
POLY2 nsp/2, 1+4, get (nsp) !curva chiusa: aggiungere valore 4
Ora si tratta di applicare le variazioni alla sfera.
Procedo da uno script che avevo realizzato per l’ellissoide, che prevede risoluzioni diverse per meridiani ed equatore. Poi lo adatterò al nostro caso:
m= !numero paralleli-1
n= !numero meridiani
r1= !semiasse x
r2= !semiasse y
r3= !semiasse z
zcs= !quota centro ellissoide/sfera
l=2*r3/m
t=360/n
base
Vert 0, 0, zcs+r3
for j=1 to m-1
for i=0 to n-1
x=l*j
y=1/r3*sqr(r3^2-(x-r3)^2)
Vert r1*cos(t*i)*y,r2*sin(t*i)*y,zcs+r3-x !n*(m-1) vertici+1=n*(m-1)+1
next i
next j
Vert 0,0,zcs-r3 !
Per capire come sono ordinati i vertici occorre considerare i valori che assumono per j=0 e per j=m.
Nel nostro caso sono scritti con un ordine che va dall’alto al basso e sono espressi in coordinate cilindriche e non polari (per cui i paralleli sono equidistanti).
Per utilizzare questo script come sfera da deformare occorre unificare i raggi,
al posto di y=sqr(r^2-(x-r)^2) si utilizzerà allora qualsiasi funzione y=y(x,i):
l=2*r/m
t=360/n
Vert 0, 0, zcs+r !Polo N
for j=1 to m-1
for i=0 to n-1
x=l*j
y=sqr(r^2-(x-r)^2)
Vert cos(t*i)*y, sin(t*i)*y, zcs+r-x
next i
next j
Vert 0,0,zcs-r !Polo s
Inoltre, per evitare che si generino due piramidi ai poli, occorre ancora cambiare lo script dell’ellissoide, eliminando i poli con i relativi EDGES e sostituendo i PGON triangolari con due nuovi PGON di n lati piatti, che formeranno le basi inferiore e superiore. In pratica si cambia la primitiva dell’ellissoide in una primitiva di cilindroide, delimitato da due superfici piane orizzontali.
Per farlo occorre intervenire prima sul loop dei vertici, ampliando l’intervallo di definizione da:
j compreso in [1,m-1] a j compreso in [0,m]
Questa operazione genera però nuovi vertici, pertanto, avendo aumentato di 2 il valore m,
occorre scrivere in coda alla definizione dei vertici: m=m+2,
oppure occorrerà, manualmente, sostituire tutti vecchi valori di m con m+2 a partire dalla definizione degli EDGES fino ai PGON.
A questo punto si eliminano i due vertici relativi ai poli. Poiché però il polo N era stato conteggiato negli indici degli EDGES, occorre diminuire tutti gli indici di 1. Vanno poi eliminatati gli EDGES che si collegavano ai poli. Infine vanno cancellati i PGON triangolari sostituendoli con PGON di n lati, che girano l’uno in senso antiorario (corrisponde al parallelo più in alto) e l’altro in senso orario.
Sotto riportiamo l’intero script dell’ellissoide e lo script del cilindroide da esso ricavato:
!inizio script ellissoide, parametri: m, n, r1, r2, r3, zcs
l=2*r3/m
t=360/n
BASE
Vert 0,0,zcs+r3 !Polo Nord
for j=1 to m-1
for i=0 to n-1
x=l*j
y=1/r3*sqr(r3^2-(x-r3)^2)
Vert r1*cos(t*i)*y,r2*sin(t*i)*y,zcs+r3-x !n*(m-1) vertici+1=n*(m-1)+1
next i
next j
Vert 0,0,zcs-r3 ! Polo Sud
for j=0 to m-2 !m-1 paralleli: n*(m-1) edges totali: da 1 a n*(m-1) edges
for i=1 to n-1
EDGE 1+n*j+i,1+n*j+i+1, -1, -1, s
next i
EDGE 1+n*j+n,1+n*j+1, -1, -1, s ! edge finale: n si ricollega a 1
next j
for j=0 to m-3 !n meridiani: n*(m-2) edges totali: da n*(m-1)+1 a n*(m-1)+n*(m-2)
for i=1 to n
EDGE 1+i+n*j,1+n+i+n*j, -1, -1, s
next i
next j
for i=1 to n !2*n segmenti di meridiani ai poli
EDGE 1+i,1, -1, -1, s !n edges al polo nord: da n*(m-1)+n*(m-2)+1 a n*(m-1)+n*(m-2)+n
next i
for i=1 to n
EDGE 1+n*(m-2)+i,n*(m-1)+2, -1, -1, s !n edges al polo sud: da n*(m-1)+n*(m-2)+n+1 a n*(m-1)+n*(m-2)+2*n
next i
for i=1 to n-1
PGON 3, 0, -1, i,n*(m-2)+n*(m-1)+1+i,-(n*(m-2)+n*(m-1)+i) !calotta nord
next i
PGON 3, 0, -1, n,n*(m-2)+n*(m-1)+1,-(n*(m-2)+n*(m-1)+n) !chiusura calotta nord
for i=1 to n-1
PGON 3, 0, -1, -(n*(m-2)+i),(n*(m-2)+n*m+i),-(n*(m-2)+n*m+1+i) !calotta sud
next i
PGON 3, 0, -1, -n*(m-1),(n*(m-1)+n*m),-(n*(m-2)+n*m+1) !chiusura calotta sud
for j=0 to m-3
for i=1 to n-1
PGON 4, 0, -1, -i-j*n,n*(m-1)+i+j*n ,n+i+j*n,-(n*(m-1)+1+i+j*n)
next i
PGON 4, 0, -1, -n-j*n,n*(m-1)+n+j*n ,n+n+j*n,-(n*(m-1)+1+j*n)
next j
body -1
end
!inizio script cilindroide, parametri: m, n, r1, r2, r3, zcs, dr (definisce le dimensioni delle basi)
l=2*r3/m
t=360/n
base
for j=0 to m !(3)
for i=0 to n-1
x=l*j
y=1/r3*sqr(r3^2-(x-r3)^2)+dr
Vert r1*cos(t*i)*y,r2*sin(t*i)*y,zcs+r3-x !n*(m-1) vertici+1=n*(m-1)+1
next i
next j
for i=1 to n-1 !gli edges con s=0 sono contorno basi
EDGE i,1+i, -1, -1, 0
next i
EDGE n,1, -1, -1, 0
for j=1 to m-1
for i=1 to n-1
EDGE n*j+i,1+n*j+i, -1, -1, s
next i
EDGE n*j+n,1+n*j, -1, -1, s
next j
for i=1 to n-1
EDGE n*m+i,1+n*m+i, -1, -1, 0
next i
EDGE n*m+n,1+n*m, -1, -1, 0 !m+1 paralleli: n*(m+1) edges totali: da 1 a n*(m+1) edges
for j=0 to m-1
for i=1 to n
EDGE i+n*j,n+i+n*j, -1, -1, s
next i
next j !n meridiani: n*m edges totali: da n*(m+1)+1 a n*(m+1)+n*m
for j=0 to m-1
for i=1 to n-1
PGON 4, 0, -1, -i-j*n,n*(m+1)+i+j*n ,n+i+j*n,-(n*(m+1)+1+i+j*n)
next i
PGON 4, 0, -1, -n-j*n,n*(m+1)+n+j*n ,n+n+j*n,-(n*(m+1)+1+j*n)
next j
for i=1 to n
put i
next i
PGON nsp, 0, -1, get(nsp) !top
for i=1 to n
put -(n*(m+1)+1-i)
next i
PGON nsp, 0, -1, get(nsp) !bottom
body -1
end
Un altro problema è che la sezione orizzontale nel cilindroide è formata da n vertici, mentre la sezione 2D era formata da 2*m vertici, per cui occorre cambiare la funzione
(1-1/14.4*abs(sin(90/m*i*p))) con (1-1/14.4*abs(sin(180/n*i*p)))
Per avere l’equazione del fusto dorico basta inserire la funzione
y=- r/14.4*abs(sin(90/m*i*18))
al posto di quella che definisce l’ellisse, oltre ad aggiungere in sezione la curva abs(sin),
moltiplicando per (1-1/14.4*abs(sin(90/m*i*p)))
La risoluzione n dei paralleli dovrebbe essere un multiplo di 18.
Lo script dei vertici, da inserire in (3) nel cilindroide, sarà il seguente:
for j=1 to m-1
for i=0 to n-1
x=l*j
y= e*(1- (h/n*j-h)^2/ h^2)+ds/2
Vert cos(t*i)*y*(1-1/14.4*abs(sin(180/m*i*p))),
sin(t*i)*y*(1-1/14.4*abs(sin(180/m*i*p))),
zcs+r-x !n*(m-1) vertici+1=n*(m-1)+1
next i
next j
Esiste comunque una forma denominata SWEEP che permette di ottenere un risultato analogo, ma occorre sempre definire le due funzioni del profilo e della sezione. In più c’è un altro rompicapo: poiché le sezioni seguono una variazione lineare ( si ingrandiscono o si rimpiccioliscono secondo un fattore costante), occorre calcolare una funzione che cambi le distanze successive della direttrice in modo non lineare, per ottenere un profilo curvo.
SWEEP n, m , alfa, scala , j1 + 2*j2 + 4*j3 + 16*j5 + 32*j6 + 64*j7,
u1, v1, s1, ... un, vn, sn, !nodi della sezione 2D
x1, y1, z1, ... xm, ym, zm !punti del profilo 3D
alfa definisce l’angolo in cui ruota la curva da una sezione all’altra,
la scala aumenta o riduce la sezione da un punto del profilo al successivo.
I seguenti valori determinano la visibilità o il rendering
j1 superficie inferiore; j2 sup. superiore; j3 sup. laterale; j5 spigoli inferiori; j6 spigoli superiori: j7 superficie segmentata (altrimenti liscia)
Valori di stato dei nodi si:
0: segmenti uscenti dal nodo visibili ( 1: invisibili)
Risulta evidente che se si vuole passare da una misura iniziale della sezione L1 ad una finale Lm,
il fattore scala deve valere: scala=(Lm/L1)^(1/(m-1))
Infatti nell’ultimo punto m del profilo il valore iniziale L1 sarà stato moltiplicato del fattore scala per m-1 volte.
Detta h l’altezza totale della sweep (supponendo una direttrice retta e verticale),
per ottenere il profilo curvo occorre passare dalla funzione lineare y=(L1-Lm)- (L1-Lm)/h*x a una funzione
y=f(x), tale che y(0)=L1-Lm e y(h)=0, ovvero entrambe si devono toccare lungo gli assi.
Determinato un punto di ascissa x0, l’ordinata corrispondente sulla retta risulta:
y0=L1-Lm-( L1-Lm)/h*x0
Il punto x0 dovrà essere traslato fino a quella posizione sull’asse x dove la curva assume il valore y0,
che si trova risolvendo rispetto x l’equazione:
f(x)=y0 ovvero f(x)= L1-Lm-( L1-Lm)/h*x0
Se si conosce la funzione inversa della f(x), che indichiamo con invf, risulterà:
x=invf( L1-Lm-( L1-Lm)/h*y0 )
Nel caso del coseno la funzione inversa è l’arcoseno.
In particolare y=A*cos(B*x ) ha come inversa: x=1/B*acs(y/A)
Vogliamo ora costruire una superficie rastremata secondo la funzione:
y=(L1-Lm)*cos(90/h*x )
che ha come inversa:
x= h/90 *acs(y /(L1-Lm)) (5)
m=6 !m=numero sezioni, m-1=numero parti cilindroidi
L1=.85
Lm=.5
h=6.5
for i=1 to m
y=(i-1)/(m-1)
put 0,0,h/90*acs( 1-y )
next i
sc=(Lm/L1)^(1/(m-1))
SWEEP 2, m , 0, sc , 1 + 2 + 4 + 16 + 32 ,
0, 0 ,901, L1,360,4001, !nodi della sezione 2D: 0,0,901 fissa il centro della crf: L1,360,4001
get (nsp) !punti del profilo 3D=asse verticale, con addensamenti in alto
Per ottenere le scanalature occorre cambiare la forma della sezione:
m=6 !m=numero sezioni, m-1=numero parti cilindroidi
n=18*2 !risoluzione sezione
p=18 !numero scanalature
L1=.85
Lm=.5
h=6.5
for i=0 to 2*n-1
put L1*(1-1/14.4*abs(sin(90/n*i*p)))*cos(180/n*i ), L1*(1-1/14.4*abs(sin(90/n*i*p)))*sin(180/n*i ),0
next i
for i=1 to m
y=(i-1)/(m-1)
put 0,0,h/90*acs( 1-y )
next i
sc=(Lm/L1)^(1/(m-1))
SWEEP 2*n, m , 0, sc , 1 + 2 + 4 + 16 + 32 + 64,
get (nsp)