Creare comando con più variabili

Ciao a tutti, volevo domandare come si può con python script creare un comando con più variabili da modificare di volta in volta. Un po’ come funziona il comando “_Convert” che dopo ha delle impostazioni da settare (( Output=Linee SemplificaInput=Sì CancellaInput=Sì TolleranzaAngolare=5 Tolleranza=0.01 LunghezzaMin=0 LunghezzaMax=0 LivelloDiOutput=Input )) e per accettarle si preme invio. A me servirebbe per creare dei layer con un codice particolare per creare percorsi fresa da importare al CNC. Ciao e grazie.

Ciao Federico

Per le opzioni nei comandi si usa RhinoCommon
Cerca le classi in Rhino.Input.Custom:
http://developer.rhino3d.com/api/RhinoCommonWin/html/N_Rhino_Input_Custom.htm

I metodi per le opzioni sono gli stessi per le varie classi GetObject, GetString, GetOption ecc.

Per gli esempi … adesso non riesco a trovare granche’

Alcuni dei metodi delle classi di cui sopra contengono degli esempi, come:

http://developer.rhino3d.com/api/RhinoCommonWin/html/M_Rhino_Input_Custom_GetBaseClass_AddOptionDouble_2.htm

Poi penso che dovrebbe esserci degli esempi anche in


… ma per ora non li trovo …

Se puoi specificare meglio l’operazione da fare nello script, proviamo a … restringere il campo … :wink:

Ciao Emilio, grazie per la risposta.
Per esempio io dovrei creare un layer che riporta nel nome un concatenamento di stringhe date dai vari dati della fresata come il codice utensile, la profondità, la correzione utensile, passate verticale ecc… Sarebbe bello se poi nel comando quando clicco il codice utensile mi venisse fuori la lista degli utensili presenti in macchina; per la correzione le tre opzioni: centrale ,destra e sinistra. Ovviamente per la profondità basterà dare un numero reale… Al momento faccio questo con GH ma volevo provare con Python script. Tanto per fare un esempio questo è un nome di un layer: “TCHROUT0(DP)14.62(TNM)FRESA6F(CRC)2(DIN)0(DOU)0(OVM)0(SHP)0(VTR)5(OTR)0(SVR)0.0(THR)0(AIN)0(AOU)0(PRP)0(TIN)0(TOU)0(NEBS)0(BDR)0”.
Ad esempio (TNM) sta ad indicare il codice utensile, (CRC) la correzione, (DP) la profondità…

Se capisco bene, potresti usare GetOption, visto che non devi selezionare oggetti o altro, e inserire tutte le opzioni che ti servono.
Se c’e’ bisogno. alcune opzioni possono poi rimandare ad altre azioni di input, ma forse nel tuo caso non e’ necessario.
Forse basta usare le opzioni adatte.

Se puo’ servire, allego uno dei miei quick&dirty script (per uso strettamente personale :slight_smile: )
E’ uno script che serve semplicemente per dare il ritiro, ed e’ un esempio di GetOption con alcune opzioni di diverso tipo.

A mio parere, l’input con le opzioni e’ una delle cose meno semplici da fare in uno script, ma c’e’ un buon motivo: la sua grande flessibilita’ che consente di costruirsi input personalizzati molto utili, per cui secondo me va affrontato con calma, imparando pezzo per pezzo come funziona … ma forse queste sono solo difficolta’ mie … :slight_smile:

Tanto per dare un’idea, lo script allegato inizia con un GetObject semplice semplice, solo per selezionare gli oggetti da trasformare, poi setta alcuni valori iniziali e dopo, verso la riga 50, inizia il ciclo di input che ci interessa
Ci trovi un bel GetOption ecc. ecc.

c5-addshrink.py (5,1 KB)

Qua devo studiare eheh :sweat_smile:

Ciao Emilio, questo è quello che ho realizzato layer_fresata_2.py (4,0 KB).
So che l’ho scritto in maniera un po’ tanto confusionale, però fa quello che deve fare. Ho altre due domande per te. La prima è che non iesco a gestire l’annullamento del comando in questo caso come si fa? La seconda è come fare per avere, come in certi comandi di Rhino, un comando che accetta sia un valore numerico che una distanza digitando due punti per esempio. Ciao e grazie ancora.

Ciao Federico

Ottimo ! Bel lavoro. :slight_smile:

Io resto sempre un po’ confuso quando devo fare queste cose … diciamo che la parte divertente e’ veder funzionare lo script … scrivere tutto cio’ che serve per le opzioni … mi diverte un po’ meno. :wink:

Se vuoi interrompere il comando con il tasto Esc, i bravi ragazzi di McNeel hanno previsto una soluzione :slight_smile:

  1. importi scriptcontext
import scriptcontext
  1. all’interno del ciclo di input, inserisci questo:
    scriptcontext.escape_test()

questa funzione verifica se e’ stato premuto Esc e in questo caso lancia una bella eccezione che blocca lo script

Per i particolari, vai a vedere il file scriptcontext.py.
Lo trovi insieme a rhinoscriptsyntax, ad esempio su questa macchina e’ in:

C:\Users\Pc\AppData\Roaming\McNeel\Rhinoceros\5.0\Plug-ins\IronPython (814d908a-e25c-493d-97e9-ee3861957f49)\settings\lib

(… Era tanto semplice quando trovavi tutto nella cartella di installazione di Rhino … adesso hanno nascosto le cose nei posti piu’ starni … Eeeeeeh, la Windows-dipendenza e’ una brutta cosa … )

Hehe … queste sono le cose che apprezzo di piu’ nell’input di RhinoCommon :wink: A mio parere e’ una vera figata !
( Non so chi abbia scritto le routine di input di Rhino, certo e’ qualcuno molto in gamba )

Puoi usare i metodi

AcceptNumber()  AcceptPoint()  AcceptString()

Che trovi nella classi

GetObject,  GetOption, ...

eccetera.

Ad esempio AcceptNumber consente l’input di un numero anche se stai selezionando oggetti o cliccando un punto.

Nel caso specifico dell’input della distanza, direi (cosi’, a prima vista) di usare
GetPoint con AcceptNumber
Se ottieni il numero, bene, se no dopo potresti usare GetLine ( che e’ una classe piu’ semplice, senza opzioni ), settando il punto iniziale.

Ma ci sono certamente anche altre soluzioni … con queste cose puoi sbizzarrirti :slight_smile:

Se qualcosa non e’ chiaro, dimmelo.

Ciao!

Mi piacerebbe veramenti chiederti un sacco di cose…ne avrei da imparare!
Tanto per cominciare :wink: ti chiedo una cosa che proprio non afferro, vedo scritto in script di esempio e anche in quello che mi hai gentilmente condiviso delle righe scritte ad esempio:
" shrinkind, shrinkopt = gop.AddOptionDouble( ‘PercentShrinkage’, opt )" (linea 53 del tuo c5-addshrink.py). Come si legge una riga così? Che significato ha la “,” in quel contesto? Ho provato a cercare ma non ho trovato spiegazione finora.
Poi, ho provato ad usare i metodi AcceptNumber() ecc ma finora senza successo. Io insisto perchè sono uno zuccone ma se hai un esempio da propormi te ne sarei grato, tanto per vedere la sintassi e come si usano. Grazie mille.

Ciao Federico

Gia’ … E’ una cosa a cui non avevo nemmeno accennato … :blush:
Rimediamo :slight_smile:

RhinoCommon e’ nato in C# ( e VB.NET )
Nel C# le funzioni non possono restituire piu’ di un valore, cosa che puoi fare in Python.
Ma c’e’ un altro meccanismo: i parametri “ref” e “out”
(Te lo dico alla buona, cerca della documentazione C# per delle spiegazioni decenti)
I parametri “ref” funzionano nei due sensi: portano un valore dentro la funzione, ma lo riportano anche fuori. ( In idioma VBS sono ByRef )
I parametri “out” servono solo a portare valori fuori dalla funzione.
Portando RhinoCommon su Python, i maghi di McNeel (credo Steve in questo caso) hanno escogitato un modo ingegnoso per poter usare queste funzioni in Python, che non puo’ usare “ref” e “out”.
La regola dovrebbe essere questa:
Ogni parametro “ref” viene duplicato anche nel valore restituito dalla funzione tramite Return. Per cui il valore restituito diventa necessariamente una tuple.
I parametri “out” sono tolti dalla lista di parametri in ingresso e aggiunti a loro volta alla tuple restituita.

(Personalmente trovo piu’ semplice e logico il funzionamento di Python … questione di gusti)

Ad esempio, vediamo il metodo in questione:

http://developer.rhino3d.com/api/RhinoCommonWin/html/M_Rhino_Input_Custom_GetBaseClass_AddOptionDouble_2.htm

Nella istruzione che hai riportato sopra, il parametro numberValue e’ duplicato nella tuple restituita.
Qui in ingresso e’ il valore della variabile “opt” e in uscita va sulla variabile “shrinkopt”
OK, aver usato due variabili diverse non aiuta nella comprensione … sorry :wink:

Ricapitolando, il metodo AddOptionDouble, in Python resituisce una tuple contenente un “int” e un “OptionDouble” … e la virgola separa semplicemente le due variabili che ricevono i due valori restituiti.
E’ come scrivere:

result = gop.AddOptionDouble( … )
shrinkind, shrinkopt = result

Ma per fortuna Python ci consente in questo caso di essere concisi e scrivere il tutto con una sola istruzione :slight_smile:

E’ vero, questo non c’era nell’esempio.
Da zuccone a zuccone :laughing: … ti capisco, anch’io ho ravanato a lungo prima di cominciare a inquadrare queste cose … all’inizio non capivo proprio a cosa servissero i vari Accept* … adesso li trovo piu’ comodi delle opzioni (sia utilizzando lo script che scrivendolo)

Domani dall’ufficio vedo di postare un esempio.

'Notte

Ho trovato un esempio:

c5-prj2pla.py (2,5 KB)

Scriptino che serve a proiettare le curve su un piano.
Il piano e’ definito da un piano parallelo (o piano base), scelto tra CPlane, XY, YZ e ZX, piu’ un punto, per il quale usiamo un
GetPoint (linea 24).
Dato che lo script lo uso quasi sempre col piano XZ, c’e’ la possibilita’ aggiuntiva di definire il punto con un valore in Z
( per cui adesso se scrivo un numero avro’ sempre un punto sull’asse Z di World … andrebbe posizionato relativamente al piano base scelto … va beh … diciamo che lo script e’ da finire … :wink: .Sorvoliamo su questo :blush: )
In ogni caso l’idea e’ che in una operazione GetPoint, attivando AcceptNumber (linea 28), oltre a poter cliccare un punto ho la possibilita’ di scrivere un numero da tastiera.
Per cui dopo aver ottenuto il risultato dell’operazione di input (linee 35,36),
vado a vedere che tipo di risultato e’:

  1. se e’ una opzione (linea 37 … ), processiamo l’opzione
  2. se e’ un punto (linea 54 … ), salviamo il punto in “pnt”
  3. se e’ un numero (linea 57 … ), costruiamo il punto “pnt” di conseguenza
  4. se diamo Enter (linea 60 …), viene presa l’origine del piano base

Il caso 3 e’ reso possibile appunto dal’ AcceptNumber

( … dopodiche’ lo script fa il suo lavoro e proietta le curve … )

Il concetto e’ che possiamo costruirci una operazione di input su misura, aggiungendo i vari
AcceptNumber, AcceptPoint ecc. e poi naturalmente processando l’input ottenuto di conseguenza

… Se ho fatto casino, dimmelo e cerchero’ di essere piu’ chiaro … :slight_smile:

Ciao !

Grazie Emilio, sei stato gentilissimo. Ora sono oberato di lavoro ma appena ho tempo mi metterò di impegno a capire quello che mi hai scritto. Grazie ancora per il tuo preziosissimo aiuto.

Ho provato a farmi un programmino per vedere come funziona ma non sembra faccia niete. probabilmente sbaglio io… Boh?? prova3.py (233 Byte) Sia che io dia un numero che prema un punto o prema esc la risposta non cambia.

La funzione escape_test() e’ fatta per poter uscire da un loop (solitamente perche’ a causa di un bug il loop gira … in eterno)
E’ utile per prevenire quei casi un cui lo script non termina mai … obbligandoci a stoppare Rhino da task manager, con le pessime conseguenze del caso:
se non abbiamo salvato prima di lanciare lo script, perdiamo tutto il lavoro fatto in precedenza
(Perche’ Rhino da questo punto di vista e’ piuttosto … primitivo)

Se guardi lo script che avevo postato sopra, li’ escape_test() e’ usato e, a quanto ricordo, dovrebbe funzionare.

L’idea, a quanto capisco, e’ che inserendolo nel loop, la prima volta che il loop esegue escape_test(), dopo che tu hai premuto Esc, lo script si blocca, e ti permette di evitare lo scenario disdicevole di cui sopra.

Grazie Emilio, sono stato un po’ troppo precipitoso…