Scripts: Difference between revisions
m (→Posizionamento) |
Renatorivo (talk | contribs) No edit summary |
||
Line 2: | Line 2: | ||
== Introduzione allo Scripting == |
== Introduzione allo Scripting == |
||
Per Scripting |
Per Scripting si intende l'uso dell'interprete Python interno di FreeCAD per generare oggetti. FreeCAD può essere usato come "ottimo" sostituto di OpenSCAD, perché possiede un vero e proprio interprete Python, con il pieno supporto per tutti i costrutti di un linguaggio di programmazione, quasi tutto quello che si può realizzare con l'interfaccia grafica è possibile realizzarlo anche attraverso un programma Python. |
||
Le informazioni sullo scripting sono però sparse nella documentazione di FreeCAD, non c'è una uniformità di "scritture" e alcune cose sono spiegate in maniera complicata per chi comincia. |
Le informazioni sullo scripting sono però sparse nella documentazione di FreeCAD, non c'è una uniformità di "scritture" e alcune cose sono spiegate in maniera complicata per chi comincia. |
||
Line 9: | Line 9: | ||
== Primo assaggio == |
== Primo assaggio == |
||
Purtroppo non esiste un modo per attivare l'editor di Python interno, però c'è un trucco, FreeCAD apre un file con estensione |
Purtroppo non esiste un modo per attivare l'editor di Python interno, però c'è un trucco, FreeCAD apre un file con estensione {{incode|.py}} nell'editor interno di Python, niente di più semplice che creare un file con il proprio editor di testo preferito, poi aprirlo con FreeCAD. |
||
Il modo più semplice è quello di battere queste poche righe: |
Il modo più semplice è quello di battere queste poche righe: |
||
Line 29: | Line 29: | ||
"""nome del file.py |
"""nome del file.py |
||
Dare un nome descrittivo di quello che fa lo script |
|||
""" |
""" |
||
Line 64: | Line 64: | ||
clear_doc() |
clear_doc() |
||
# EPS= tolerance to |
# EPS= tolerance to use to cut the parts |
||
EPS = 0.10 |
EPS = 0.10 |
||
EPS_C = EPS * -0.5 |
EPS_C = EPS * -0.5 |
||
Line 71: | Line 71: | ||
</nowiki> |
</nowiki> |
||
Alcuni trucchi sono incorporati in questo codice: |
Alcuni trucchi che sono incorporati in questo codice: |
||
* |
* {{incode|import FreeCAD}} Questo serve per importare FreeCAD all'interno dell'interprete Python, può sembrare superfluo, ma non lo è |
||
* |
* {{incode|from FreeCAD import Base, Vector}} Base e Vector sono molto usati, vi risparmiano molto testo da battere, e se non lo fate dovete scrivere ad esempio {{incode|FreeCAD.Vector}} ogni volta che usate un {{incode|Vector}} |
||
Line 81: | Line 81: | ||
{{Code|code= |
|||
<nowiki> |
|||
def cubo(nome, lung, larg, alt): |
def cubo(nome, lung, larg, alt): |
||
obj_b = DOC.addObject("Part::Box", nome) |
obj_b = DOC.addObject("Part::Box", nome) |
||
Line 96: | Line 96: | ||
setview() |
setview() |
||
}} |
|||
</nowiki> |
|||
Line 107: | Line 107: | ||
== Qualcosa in più == |
== Qualcosa in più == |
||
Niente di eccezionale, quanto ci si può aspettare da un cubo, la stessa cosa possiamo fare con un cilindro, |
Niente di eccezionale, quanto ci si può aspettare da un cubo, la stessa cosa possiamo fare con un cilindro, aggiungete queste linee dopo il metodo che crea il cubo e prima della riga '''obj = cubo(...''' |
||
{{Code|code= |
|||
<nowiki> |
|||
def base_cyl(nome, ang, rad, alt ): |
def base_cyl(nome, ang, rad, alt ): |
||
obj = DOC.addObject("Part::Cylinder", nome) |
obj = DOC.addObject("Part::Cylinder", nome) |
||
Line 120: | Line 120: | ||
return obj |
return obj |
||
}} |
|||
</nowiki> |
|||
Anche qui nulla di eccezionale, notiamo alcune nella costruzione del codice: |
Anche qui nulla di eccezionale, notiamo alcune cose nella costruzione del codice: |
||
* L'assenza dei riferimenti usuali in molta documentazione ad |
* L'assenza dei riferimenti usuali in molta documentazione ad {{incode|App.}}, è pienamente voluto, in futuro si potrà riusare il codice per accedere a FreeCAD dall'esterno di FreeCAD, e sarà necessario importare FreeCAD come un normale modulo Python, con alcune accortezze. La scelta è voluta anche nel solco degli standard di Python per cui è meglio sapere sempre da dove arrivano le cose, ovviamente App è poco significativo. |
||
* La definizione all'inizio di una "costante" DOC, per contenere |
* La definizione all'inizio di una "costante" DOC, per contenere {{incode|FreeCAD.activeDocument()}}, ovviamente il nome "costante" è solo considerando dal punto di vista semantico il nostro "documento attivo", da qui l'uso della convenzione del nome "TUTTO MAIUSCOLO" per le "costanti". |
||
* ogni metodo ritorna un |
* ogni metodo ritorna un geometria, questo diventerà importante fra poco. |
||
* la creazione della geometria non comporta la proprietà |
* la creazione della geometria non comporta la proprietà {{incode|Placement}}, se si utilizzano geometrie semplici per creare geometrie più complesse, la gestione della proprietà {{incode|Placement}} è una cosa delicata. |
||
Ora dobbiamo pur farci qualcosa con questi oggetti, |
Ora dobbiamo pur farci qualcosa con questi oggetti, quindi introduciamo le operazioni booleane. Un esempio di metodo che compie un'operazione di '''Unione''' è questo: |
||
{{Code|code= |
|||
<nowiki> |
|||
def fuse_obj(nome, obj_0, obj_1): |
def fuse_obj(nome, obj_0, obj_1): |
||
obj = DOC.addObject("Part::Fuse", nome) |
obj = DOC.addObject("Part::Fuse", nome) |
||
Line 141: | Line 141: | ||
return obj |
return obj |
||
}} |
|||
</nowiki> |
|||
anche qui nulla di eccezionale, notate però l'uso di molta uniformità nel codice, aiuta molto quando si vuole fare copia e incolla nella creazioni complesse. |
anche qui nulla di eccezionale, notate però l'uso di molta uniformità nel codice, aiuta molto quando si vuole fare copia e incolla nella creazioni complesse. |
||
Inseriamo dopo il metodo |
Inseriamo dopo il metodo {{incode|base_cyl}} le righe sopra e modifichiamo quelle sotto in modo da leggere: |
||
{{Code|code= |
|||
<nowiki> |
|||
# definizione oggetti |
# definizione oggetti |
||
Line 157: | Line 157: | ||
fuse_obj("Fusione", obj, obj1) |
fuse_obj("Fusione", obj, obj1) |
||
}} |
|||
</nowiki> |
|||
Lanciamo con il tasto freccia della '''barra strumenti macro''' e otteniamo: |
Lanciamo con il tasto freccia della '''barra strumenti macro''' e otteniamo: |
||
Line 166: | Line 166: | ||
== Posizionamento == |
== Posizionamento == |
||
Il concetto è relativamente complesso, vedere [[Aeroplane/it|Tutorial aeroplano]] per una trattazione più sistematica. |
Il concetto è relativamente complesso, vedere il [[Aeroplane/it|Tutorial aeroplano]] per una trattazione più sistematica. |
||
Possiamo aver bisogno di posizionare una geometria in una posizione relativa ad un'altra geometria, cosa abbastanza frequente, |
Possiamo aver bisogno di posizionare una geometria in una posizione relativa ad un'altra geometria, cosa abbastanza frequente, il modo più comune è usare la proprietà {{incode|Placement}} della geometria. |
||
Ovviamente le possibilità su come specificare questa proprietà sono molte, alcune complesse da capire, questa scrittura della |
Ovviamente le possibilità su come specificare questa proprietà sono molte, alcune complesse da capire, questa scrittura della proprietà {{incode|Placement}}, soprattutto per quanto riguarda la parte {{incode|Rotation}} è in linea con quanto spiegato nel Tutorial citato e sembra la più gestibile. |
||
{{Code|code= |
|||
<nowiki> |
|||
FreeCAD.Placement(Vector(0,0,0), FreeCAD.Rotation(10,20,30), Vector(0,0,0)) |
FreeCAD.Placement(Vector(0,0,0), FreeCAD.Rotation(10,20,30), Vector(0,0,0)) |
||
}} |
|||
</nowiki> |
|||
Esiste sempre un punto di criticità, |
Esiste sempre un punto di criticità, che è il punto di '''riferimento della costruzione''', cioè il punto in base al quale è costruito l'oggetto, come descritto in questa tabella, copiata da [[Placement/it|Posizionamento]]: |
||
Line 193: | Line 193: | ||
|Part::Torus||centro del toro |
|Part::Torus||centro del toro |
||
|- align="left" |
|- align="left" |
||
|Caratteristiche |
|Caratteristiche derivate da Sketch||la caratteristica eredita la posizione dello schizzo sottostante. Lo schizzo inizia sempre con Position = (0,0,0). |
||
|} |
|} |
||
Queste informazioni sono da tenere ben presente quando volete |
Queste informazioni sono da tenere ben presente quando volete applicare una rotazione. |
||
Facciamo qualche esempio, cancellate tutte le righe dopo il metodo |
Facciamo qualche esempio, cancellate tutte le righe dopo il metodo {{incode|base_cyl}} ed inserite queste righe: |
||
{{Code|code= |
|||
<nowiki> |
|||
def sfera(nome, rad): |
def sfera(nome, rad): |
||
Line 257: | Line 257: | ||
setview() |
setview() |
||
}} |
|||
</nowiki> |
|||
Analizziamo il codice: |
Analizziamo il codice: |
||
* Abbiamo definito un metodo per creare una sfera, abbiamo |
* Abbiamo definito un metodo per creare una sfera, abbiamo usato la definizione più semplice, definendo solo il raggio. |
||
* Abbiamo introdotto una seconda forma per l''''Unione''' quella multipla, niente di speciale, notate solo che alla proprietà |
* Abbiamo introdotto una seconda forma per l''''Unione''' quella multipla, niente di speciale, notate solo che alla proprietà {{incode|Shapes}} abbiamo passato una '''tupla''' |
||
* Abbiamo definito una forma complessa, in modo '''"parametrico"''', cioè definendo alcuni parametri e mettendo delle formule che calcolano in modo automatico molti dei valori da passare alla geometria finale. |
* Abbiamo definito una forma complessa, in modo '''"parametrico"''', cioè definendo alcuni parametri e mettendo delle formule che calcolano in modo automatico molti dei valori da passare alla geometria finale. |
||
* Abbiamo usato prima di ritornare l'oggetto un posizionamento usando la poprietà |
* Abbiamo usato prima di ritornare l'oggetto un posizionamento usando la poprietà {{incode|Rotation}} e il vettore finale del gruppo che definisce il '''centro di rotazione''', secondo la scrittura ''Yaw-Pitch-Roll'' |
||
Line 277: | Line 277: | ||
Potete facilmente notare che l'aereo ruota attorno al suo "baricentro" che ho fissato nel centro delle ali, in modo che la rotazione sia relativamente "naturale". |
Potete facilmente notare che l'aereo ruota attorno al suo "baricentro" che ho fissato nel centro delle ali, in modo che la rotazione sia relativamente "naturale". |
||
Notiamo però che se usiamo l'interfaccia grafica e visualizziamo la proprietà |
Notiamo però che se usiamo l'interfaccia grafica e visualizziamo la proprietà {{incode|Placement}} abbiamo i dati che abbiamo inserito, questo significa che ogni modifica della proprietà modificherà il posizionamento della geometria, l'osservazione sarà importante nel proseguimento del discorso. |
||
Revision as of 23:31, 2 March 2020
Introduzione allo Scripting
Per Scripting si intende l'uso dell'interprete Python interno di FreeCAD per generare oggetti. FreeCAD può essere usato come "ottimo" sostituto di OpenSCAD, perché possiede un vero e proprio interprete Python, con il pieno supporto per tutti i costrutti di un linguaggio di programmazione, quasi tutto quello che si può realizzare con l'interfaccia grafica è possibile realizzarlo anche attraverso un programma Python.
Le informazioni sullo scripting sono però sparse nella documentazione di FreeCAD, non c'è una uniformità di "scritture" e alcune cose sono spiegate in maniera complicata per chi comincia.
Primo assaggio
Purtroppo non esiste un modo per attivare l'editor di Python interno, però c'è un trucco, FreeCAD apre un file con estensione .py
nell'editor interno di Python, niente di più semplice che creare un file con il proprio editor di testo preferito, poi aprirlo con FreeCAD.
Il modo più semplice è quello di battere queste poche righe:
"""script.py Primo script per FreeCAD """
Salvarlo e caricarlo in FreeCAD.
Il minimo indispensabile per lavorare in modo proficuo con FreeCAD è scrivere queste righe, che potete tranquillamente usare come modello:
"""nome del file.py Dare un nome descrittivo di quello che fa lo script """ import FreeCAD from FreeCAD import Base, Vector import Part from math import pi, sin, cos DOC = FreeCAD.activeDocument() DOC_NAME = "Pippo" def clear_doc(): """ Clear the active document deleting all the objects """ for obj in DOC.Objects: DOC.removeObject(obj.Name) def setview(): """Rearrange View""" FreeCAD.Gui.SendMsgToActiveView("ViewFit") FreeCAD.Gui.activeDocument().activeView().viewAxometric() if DOC is None: FreeCAD.newDocument(DOC_NAME) FreeCAD.setActiveDocument(DOC_NAME) DOC = FreeCAD.activeDocument() else: clear_doc() # EPS= tolerance to use to cut the parts EPS = 0.10 EPS_C = EPS * -0.5
Alcuni trucchi che sono incorporati in questo codice:
import FreeCAD
Questo serve per importare FreeCAD all'interno dell'interprete Python, può sembrare superfluo, ma non lo èfrom FreeCAD import Base, Vector
Base e Vector sono molto usati, vi risparmiano molto testo da battere, e se non lo fate dovete scrivere ad esempioFreeCAD.Vector
ogni volta che usate unVector
Partiamo con un piccolo script che fa poco, ma illustra la potenza di questo approccio.
def cubo(nome, lung, larg, alt):
obj_b = DOC.addObject("Part::Box", nome)
obj_b.Length = lung
obj_b.Width = larg
obj_b.Height = alt
DOC.recompute()
return obj_b
obj = cubo("cubo_di_prova", 5, 5, 5)
setview()
Mettetelo dopo il primo codice e premete la freccia della Barra di strumenti Macro
e vedrete che si apre un nuovo file chiamato Pippo e si visualizza un cubo nella Vista 3D,
Qualcosa in più
Niente di eccezionale, quanto ci si può aspettare da un cubo, la stessa cosa possiamo fare con un cilindro, aggiungete queste linee dopo il metodo che crea il cubo e prima della riga obj = cubo(...
def base_cyl(nome, ang, rad, alt ):
obj = DOC.addObject("Part::Cylinder", nome)
obj.Angle = ang
obj.Radius = rad
obj.Height = alt
DOC.recompute()
return obj
Anche qui nulla di eccezionale, notiamo alcune cose nella costruzione del codice:
- L'assenza dei riferimenti usuali in molta documentazione ad
App.
, è pienamente voluto, in futuro si potrà riusare il codice per accedere a FreeCAD dall'esterno di FreeCAD, e sarà necessario importare FreeCAD come un normale modulo Python, con alcune accortezze. La scelta è voluta anche nel solco degli standard di Python per cui è meglio sapere sempre da dove arrivano le cose, ovviamente App è poco significativo. - La definizione all'inizio di una "costante" DOC, per contenere
FreeCAD.activeDocument()
, ovviamente il nome "costante" è solo considerando dal punto di vista semantico il nostro "documento attivo", da qui l'uso della convenzione del nome "TUTTO MAIUSCOLO" per le "costanti". - ogni metodo ritorna un geometria, questo diventerà importante fra poco.
- la creazione della geometria non comporta la proprietà
Placement
, se si utilizzano geometrie semplici per creare geometrie più complesse, la gestione della proprietàPlacement
è una cosa delicata.
Ora dobbiamo pur farci qualcosa con questi oggetti, quindi introduciamo le operazioni booleane. Un esempio di metodo che compie un'operazione di Unione è questo:
def fuse_obj(nome, obj_0, obj_1):
obj = DOC.addObject("Part::Fuse", nome)
obj.Base = obj_0
obj.Tool = obj_1
obj.Refine = True
DOC.recompute()
return obj
anche qui nulla di eccezionale, notate però l'uso di molta uniformità nel codice, aiuta molto quando si vuole fare copia e incolla nella creazioni complesse.
Inseriamo dopo il metodo base_cyl
le righe sopra e modifichiamo quelle sotto in modo da leggere:
# definizione oggetti
obj = cubo("cubo_di_prova", 5, 5, 5)
obj1 = base_cyl('primo cilindro', 360,2,10)
fuse_obj("Fusione", obj, obj1)
Lanciamo con il tasto freccia della barra strumenti macro e otteniamo:
Posizionamento
Il concetto è relativamente complesso, vedere il Tutorial aeroplano per una trattazione più sistematica.
Possiamo aver bisogno di posizionare una geometria in una posizione relativa ad un'altra geometria, cosa abbastanza frequente, il modo più comune è usare la proprietà Placement
della geometria.
Ovviamente le possibilità su come specificare questa proprietà sono molte, alcune complesse da capire, questa scrittura della proprietà Placement
, soprattutto per quanto riguarda la parte Rotation
è in linea con quanto spiegato nel Tutorial citato e sembra la più gestibile.
FreeCAD.Placement(Vector(0,0,0), FreeCAD.Rotation(10,20,30), Vector(0,0,0))
Esiste sempre un punto di criticità, che è il punto di riferimento della costruzione, cioè il punto in base al quale è costruito l'oggetto, come descritto in questa tabella, copiata da Posizionamento:
Geometria | Riferimento di Costruzione |
---|---|
Part::Box | vertice sinistro (minimo x), frontale (minimo y), in basso (minimo z) |
Part::Sphere | centro della sfera (centro del suo contenitore cubico) |
Part::Cylinder | centro della faccia di base |
Part::Cone | centro della faccia di base (o superiore se il raggio della faccia di base vale 0) |
Part::Torus | centro del toro |
Caratteristiche derivate da Sketch | la caratteristica eredita la posizione dello schizzo sottostante. Lo schizzo inizia sempre con Position = (0,0,0). |
Queste informazioni sono da tenere ben presente quando volete applicare una rotazione.
Facciamo qualche esempio, cancellate tutte le righe dopo il metodo base_cyl
ed inserite queste righe:
def sfera(nome, rad):
obj = DOC.addObject("Part::Sphere", nome)
obj.Radius = rad
DOC.recompute()
return obj
def mfuse_obj(nome, objs):
obj = DOC.addObject("Part::MultiFuse", nome)
obj.Shapes = objs
obj.Refine = True
DOC.recompute()
return obj
def aeroplano():
lung_fus = 30
diam_fus = 5
ap_alare = lung_fus * 1.75
larg_ali = 7.5
spess_ali = 1.5
alt_imp = diam_fus * 3.0
pos_ali = (lung_fus*0.70)
off_ali = (pos_ali - (larg_ali * 0.5))
obj1 = base_cyl('primo cilindro', 360, diam_fus, lung_fus)
obj2 = cubo('ali', ap_alare, spess_ali, larg_ali, True, off_ali)
obj3 = sfera("naso", diam_fus)
obj3.Placement = FreeCAD.Placement(Vector(0,0,lung_fus), FreeCAD.Rotation(0,0,0), Vector(0,0,0))
obj4 = cubo('impennaggio', spess_ali, alt_imp, larg_ali, False, 0)
obj4.Placement = FreeCAD.Placement(Vector(0,alt_imp * -1,0), FreeCAD.Rotation(0,0,0), Vector(0,0,0))
objs = (obj1, obj2, obj3, obj4)
obj = mfuse_obj("Forma esempio", objs)
obj.Placement = FreeCAD.Placement(Vector(0,0,0), FreeCAD.Rotation(0,0,0), Vector(0,0,0))
obj.Placement = FreeCAD.Placement(Vector(0,0,0), FreeCAD.Rotation(0,0,-90), Vector(0,0,pos_ali))
DOC.recompute()
return obj
aeroplano()
setview()
Analizziamo il codice:
- Abbiamo definito un metodo per creare una sfera, abbiamo usato la definizione più semplice, definendo solo il raggio.
- Abbiamo introdotto una seconda forma per l'Unione quella multipla, niente di speciale, notate solo che alla proprietà
Shapes
abbiamo passato una tupla - Abbiamo definito una forma complessa, in modo "parametrico", cioè definendo alcuni parametri e mettendo delle formule che calcolano in modo automatico molti dei valori da passare alla geometria finale.
- Abbiamo usato prima di ritornare l'oggetto un posizionamento usando la poprietà
Rotation
e il vettore finale del gruppo che definisce il centro di rotazione, secondo la scrittura Yaw-Pitch-Roll
Potete facilmente notare che l'aereo ruota attorno al suo "baricentro" che ho fissato nel centro delle ali, in modo che la rotazione sia relativamente "naturale".
Notiamo però che se usiamo l'interfaccia grafica e visualizziamo la proprietà Placement
abbiamo i dati che abbiamo inserito, questo significa che ogni modifica della proprietà modificherà il posizionamento della geometria, l'osservazione sarà importante nel proseguimento del discorso.
Alla prossima!