vineri, mai 22

Introducere in programarea AutoLISP

In prima postare despre AutoLISP (Introducere in AutoLISP) am vorbit despre cum putem folosi programe AutoLISP in AutoCAD fara a sti mai nimic despre programare.
Articolul de astazi vorbeste despre programarea si notiunile de baza AutoLISP. De aceasta data am apelat la cineva mai in masura sa scrie un astfel de articol si anume Robert Green care mi-a permis sa traduc si public pe blog o postare excelenta a sa despre introducerea in programarea AutoLISP.
Articolul original in limba engleza poate fi gasit aici. Pentru a afla mai multe despre Robert Green puteti vizita site-ul sau http://www.cad-manager.com/ sau ii puteti citi articolele publicate in fiecare saptamana la Cadalyst.
To Robert Green: If you somehow read this, thank you again.
Note: Following article is Property of Robert Green and CAD-Manager.com
quotes_web

Notiuni de baza in AutoLisp

AutoLisp este cel mai vechi limbaj de programare in AutoCAD si vei fi uimit de cate instrumente de programare gasesti pe Internet. Cu ceva cunostinte de Autolisp poti integra rutinele deja existente in propriile programe castigand astfel un control superior asupra AutoCAD-ului.
Primul lucru care trebuie stiut este ca AutoLisp are doua fisiere cheie si o functie importanta care excuta diferite actiuni la pornirea AutoCAD-ului. Cele doua fisiere se numesc: ACAD.LSP si ACADDOC.LSP iar functia este S::STARTUP, acestea sunt descrise mai jos:
ACAD.LSP - Acest fisier se incarca la pornirea AutoCAD-ului. Toate programele/rutinele pe care le puneti in acest fisier se vor incarca automat de fiecare data cand se lanseaza programul AutoCAD. Fisierul ACAD.LSP se afla in mod normal in directorul SUPPORT al instalarii AutoCAD.
ACADDOC.LSP - acest fisier se incarca de fiecare data cand se creeaza un desen nou in AutoCAD 2000, 2000i, 2002. Orice programe sau rutine adaugate in acest fisier se vor incarca automat la inceperea fiecarui desen. A se retine ca ACAD.LSP se incarca doar la crearea primului desen si ACADDOC.LSP se va incarca la crearea urmatoarelor desene in sesiunea respectiva de lucru. In AutoCAD R14 nu este nevoie de fisierul ACADDOC.LSP deoarece ACAD R14 nu permitea deschiderea mai multor desene in aceeasi sesiune de lucru. Fisierul ACADDOC.LSP se afla si el, in mod normal, in directorul SUPPORT al instalarii AutoCAD.
functia S::STARTUP - aceasta functie se foloseste de obicei in fisierul ACADDOC.LSP (sau ACAD.LSP pentru R14) si nu face altceva decat sa ruleze comenzi pe care vrei sa le folosesti la inceperea oricarui desen nou. Aceasta functie este ideala pentru setarea variabilelor de sistem cum ar fi DIMSCALE, parametri VIEWRES, layerul curent la inceperea desenului etc. Puterea functiei S::STARTUP sta in faptul ca ruleaza automat si iti da posibilitatea sa controlezi mediul de lucru in care incepi desenele noi.


Exemple

Ce crezi ca se va intampla daca creezi un fisier ACADDOC.LSP, in directoul SUPPORT, si pui in el urmatorul text?
(defun s::startup ()
(alert “Salut!”)
(princ)
)
Ei bine cu DEFUN nu facem altceva decat sa DEfinim o FUNctie (de aici si numele) care se numeste S:STARTUP si despre care stim deja ca va rula de fiecare data cand incepem/deschidem un desen in AUTOCAD. Continutul functiei e reprezentat de o fereastra de notificare (ALERT box) in care va scrie "Salut!" urmata de PRINC care e recomandat sa fie ultima linie a oricarui program AutoLisp.
Salveaza noul fisier ACADDOC.LSP, verifica sintaxa ca sa fii sigur ca nu s-au strecurat greseli si porneste AutoCAD. Intelegi rezultatul si cum a aparut?
Sa avansam putin cu exemplul incercand:
(defun s::startup ()
(setvar “textsize” 0.125)
(setvar “dimtxt” 0.125)
(princ)
)
In acest exemplu setam marimea textului (textsize) si marimea textului de la cote (dimtext) la o valoare prestabilita de 0.125 (sau 1/8" daca preferati) de fiecare data cand deschidem sau incepem un desen. Motivul pentru care am folosit valori zecimale este ca nu intotdeauna desenele vor fi in sistem de coordonate arhitectural sau fractional asa ca valoarea zecimala este cel mai comun mod de a introduce date. <n.t.: articolul se adreseaza preponderent cititorilor din tari cu sistem Imperial (USA, UK, Australia) si de aceea autorul explica introducerea datelor ca numere zecimale. Pe noi nu ne deranjeaza deloc pentru ca oricum folosim sistemul zecimal>
Sa continuam exemplul si sa spunem ca, de fapt, am vrea ca TEXTSIZE (marimea textului) sa fie 0.125 din valoarea DIMSCALE care exista deja in desen. Pentru a face asta ne va trebui o comanda noua numita GETVAR care ne permite sa obtinem valorile deja existente ale variabilelor (in loc sa le dam o noua valoare) si o functie de inmultire (semnul obisnuit *) ambele folosite in aceeasi secventa cod. Cu putina imaginatie va iesi urmatorul program:
(defun s::startup ()
(setvar “textsize” (* 0.125 (getvar “dimscale”)))
(setvar “dimtxt” 0.125)
(princ)
)
De retinut ca secventa de cod care atribuie o noua valoare pentru marimea textului interogheaza valoare curenta a DIMSCALE pe care o inmulteste cu 0.125 si apoi atribuie rezultatul variabilei TEXTSIZE. Ordinea in care executa operatiile aflate intre paranteze este de la interior spre interior. De asemenea de tinut minte ca fiecare paranteza deschisa trebuie apoi inchisa.


Fisiere si functii LSP

Pe masura ce incepi sa-ti scrii propriile programe devine logic sa salvezi codul in fisiere separate care pot fi editate individual. Aceste fisiere au intotdeauna extensia .LSP si se  editeaza in Notepad/WordPad sau in editorul VisualLisp. Fisierel LSP pot fi salvate oriunde dar cel mai simplu si sigur e sa le salvezi tot in directorul SUPPORT. Astfel poti fi sigur ca AutoCAD va stii sa le gaseasca cand vei dori sa le folosesti.
In fisierele LSP create poti pastra rutine simple de programare pe care le poti folosi de cate ori ai nevoie. O anumita functie, functia C: , iti permite sa adaugi comenzi celor deja existente in AutoCAD. Adaugand comenzi noi sau functii C:,  setului de comenzi deja existent, utilizatorii le vor considera pur si simplu ca o comanda noua pe care o pot folosii. Doar tu vei stii ca de fapt ei folosesc un program facut de tine.
Pe masura ce creezi propriile functii si le salvezi ca fisiere LSP va trebui sa le incarci in AutoCAD pentru a te asigra ca pot fi folosite. Odata verificata integritatea codului functiile pot fi adaugate in ACAD.LSP depre care am vorbit.


Un exemplu concret.

Imi plac scurtaturile comenzilor din taste precum L pentru line sau E pentru erase. Acum ceva timp am vrut sa creez o comanda numita FZ care imi va face de fiecare data fillet cu raza zero (pentru colturi nerotunjite) dar fara sa lase zero ca valoare setata pentru raza de fillet la urmatoarele utilizari ale comenzii. <n.t.: in versiunile mai noi Fillet cu Shift apasat are acum acest efect>
Prin urmare programul scris de mine ar trebui sa faca urmatoarele:
  • sa tina minte ultima raza de fillet (stocata in variabila de sistem FILLETRAD)
  • sa seteze noua raza de fillet la zero
  • sa ruleze comanda FILLET si sa ma lase sa selectez obiectele
  • sa seteze raza de fillet inapoi la cat era inainte
Am codat aceasta functie in felul urmator:
(defun c:fz () ; line 1
(setq old_radius (getvar “filletrad”)) ; line 2
(setvar “filletrad” 0) ; line 3
(command “.fillet” pause pause) ; line 4
(setvar “filletrad” old_radius) ; line 5
) ; line 6

Explicatia exemplului

In exemplul de mai sus am adaugat comentarii la sfarsitul liniilor de cod pentru a-i da fiecarei linii cate un numar. Veti observa ca fiecare comentariu e precedat de semnul punct si virgula al caurui efect este ca interpretorul AutoLISP ignora tot ce se afla dupa el. Aceasta posibilitate de a comenta iti da posibiltatea sa pastrezi diferite note despre program salvate chiar in cod.
Acum sa vedem ce face fiecare linie din program:
  1. Defineste o functie(comanda) numita FZ folosind instructiunea DEFUN
  2. Stocheaza valoarea curenta a razei de fillet atribuind-o unei variabile numita OLD_RADIUS folosind instructiunile SETQ si GETVAR <n.t.: GETVAR pentru a afla valoarea si SETQ pentru a o atribui>
  3. Seteaza raza de fillet  la 0 folosind instructiunea SETVAR
  4. Apeleaza comanda FILLET si apoi are doua PAUSE (pauza) pentru a astepta input de la utilizator sub forma selectiei a doua linii. De retinut ca comezile AutoCAD se scriu intre ghilimele iar instructiunea PAUSE nu.
  5. Seteaza raza de fillet inapoi la valoarea initiala folosind valoarea variabilei OLD_RADIUS si instructiunea SETVAR.
  6. Ultima paranteza inchide instructiunea DEFUN inceputa in linia 1


Sa testam

Acum puteti crea un fisier numit FZ.LSP care contine codul programului de mai sus si sa il salvati in directorul SUPPORT al AutoCAD-ului. Asigurati-va ca nu sunt greseli inainte de a salva fisierul.
Acum deschideti AutoCAD-ul si tastati urmatoarele in CommandLine:
(load “fz.lsp”)
Odata ce programul s-a incarcat veti primi confirmarea in CommandLine sub forma textului C:FZ care este numele functiei.
Puteti testa functia tastand FZ in command line. Inainte de a incerca noua comanda FZ folositi comanda fillet de cateva ori, setand alta raza decat 0, pentru a va asigura ca ultima valoare retinuta de AutoCAD este diferita de zero. Acum ar trebui sa puteti folosi comanda FILLET pentru a face operatiunea cu raza de fillet normala si comanda FZ pentru fillet cu raza zero.
N-a fost asa greu nu?
Daca vrei poti acum adauga instructiunea de incarcare (load "fz.lsp") in functia S::STARTUP (despre care am vorbit mai devreme) si noua comanda FZ se va incarca automat de cate ori e deschis programul AutoCAD. Incarcand comanda din S:STARTUP  utilizatorii vor avea o noua comanda fara sa stie de unde vine de fapt.


Comenzile cu "-"

Anumite comenzi AutoCAD vor avea nevoie de "-" (cratima) in fata lor pentru a fi apelate in AutoLisp pentru ca in mod normal respectivele comenzi functioneaza cu ferestre de dialog. Comanda Layer este un prim exemplu pe care il puteti verifica foarte simplu tastand -LAYER in command line. Acum tastati LAYER simplu si rezultatul va fi cu totul altul, nu?
Deoarece comenzile AutoCAD trec prin interpretorul AutoLISP ca input tastat comanda pentru layere va fi totdeauna apelata cu -LAYER dupa cum urmeaza:
(command “-layer”) in loc de (command “layer”)
Daca nu ma credeti, puteti incerca in command line si vedeti care merge. Alte comenzi des folosite care folosesc "-" ca prefix sunt -STYLE pentru stilurile de text si -PLOT pentru a apela comanda de plotare prin AutoLISP. Aceste comenzi pot fi examinate mai departe prin simpla tastare in command line si apoi notarea succesiunii de input-uri pe care le solicita si optiunile disponibile.
Aproape in toate cazurile in care comenzi AutoCAD sunt folosite in AutoLisp, va trebui sa stiti foarte bine secventa de parametri si optiuni pe care comanda respectiva le solicita respectiv ofera in command line. Daca ai mai folosit comezile respective in versiunea linie de comanda atunci stii ce ai de facut, daca nu atunci vei avea de explorat de acum incolo. Un mod simplu de a documenta comezile este copierea textelor aparute in command line folosind fereastra de text care se apeleaza cu F2 si copy/paste in Notepad.


Erori

Cand uiti sa inchizi paranteze, uiti ghlimelele sau alte parti cheie ale codului din fisierul tau LSP, vei avea probleme. Incearca sa incarci urmatoarele exemple de programe si vezi ce se intampla.
(defun c:fz ()
(setq old_radius (getvar “filletrad))
(setvar “filletrad” 0)
(command “.fillet” pause pause)
(setvar “filletrad” old_radius)
)
Eroarea este aici lipsa unor ghilimele " dupa FILLETRAD in linia a doua. Ar trebui sa vedeti interpretorul AutoLisp intreband de ele.
(defun c:fz ()
(setq old_radius (getvar “filletrad”))
(setvar “filletrad” 0)
(command “.fillet” pause pause)
(setvar “filletrad” old_radius)
Eroarea este aici o paranteza ) lipsa la sfarsitul programului pentru a inchide instructiunea DEFUN. Ar trebui ca interpretorul AutoLisp sa intrebe de ea.
(defun c:fz ()
(setq old_radius (getvar “filletrad”))
(setvar “filletrad” 0)
(command “.filllet” pause pause)
(setvar “filletrad” old_radius)
)
Eroarea aici este un L in plus in cuvantul FILLLET. Veti observa ca functia va rula dar se va opri cand va ajunge la comanda fillet.


Introducerea de date si seturi de selectie

In primele doua parti ale introducerii in programarea AutoLisp am discutat despre cum stocam valori folosind variabile, despre cum manipulam variabilele de sistem si despre cum folosim instructiunea COMMAND pentru a trimite comenzi catre AutoCAD. Acestea sunt elementele de baza pentru a scrie programe simple dar pentru programe mai flexibile va trebui sa puteti sa:
  • cereti utilizatorilor sa introduca date (numere, texte, puncte)
  • cereti utilizatorilor sa introduca seturi de date (folosind seturi de selectie)
  • filtrati baza de date a AutoCAD-ului pentru a obtine doar anumite tipuri de obiecte
  • lucrati cu anumite puncte din obiecte (capete de linie, centru cercurilor, etc)
Comezile pe care le vom folosi pentru a obtine aceste rezultate sunt:
  • GETREAL (pentru a obtine(GET) de la utilizator un numar REAL)
  • GETINT (pentru a obtine de la utilizator un numar INTreg)
  • GETSTRING (pentru a obtine de la utilizator un anumit text)
  • GETPOINT (pentru a obtine de la utilizator un punct)
  • SSGET (pentru a obtinede la utilizator un set de selectie)
  • SSGET cu optiunea “X” (pentru a filtra baza de date de anumite obiecte)
  • CAR, CADR and CADDR (pentru a desparti punctele in valori X, Y and Z)
Ca si pana acum voi folosi programe mici pentru a ilustra conceptele si apoi voi creste gradual nivelul de complexitate pentru a intelege si exemple mai avansate.


Obtinerea de valori de la utilizator

Obtinerea de valori de la utilizator este destul de directa in AutoLISP dupa cum se poate vedea in exemplele ce urmeaza:
(setq var1 (getreal “\nIntroduceti un numar REAL: “))
(setq var2 (getint “\nIntroduceti un numar INTREG: “))
(setq var3 (getstring “\nIntroduceti un text “))
Incercati copy/paste cu aceste exemple in AutoCAD command line pentru a rula interactiv instructiunile si veti vedea imediat ce se intampla. De remarcat ca folosind instructiunea GETINIT nu puteti intoduce un numar real sau text. De asemenea se poate observa ca in command line apare un text care il informeaza pe utilizator ce informatie este asteptata de la el.
Nota: Caracterul \n este in cod doar pentru ca textul pentru utilizator sa apaa pe o noua linie in command prompt si nu in continuarea liniei anterioare!
Rezultatul acestor instructiuni este atribuirea valorilor introduse de utilizator variabilelor VAR1 VAR2 sau VAR3, valori care pot fi apoi folosite in alte programe. Iata un exemplu de programe pe care il puteti rula interactiv si care solicita de la utilizator o valoare, o stocheaza intr-o variabila si apoi o foloseste.
(setq dimtxt_height (getreal “\nInaltimea textului de cotare: “))
(setvar “dimtxt” dimtxt_height)
Desi este un exemplu foarte simplu acesta ilustreaza perfect conceptul. Se ia o valoare de la user si se foloseste apoi in program in loc de valori fixe introduse direct in cod (vezi exemplul al doilea de sus daca nu stii ce face intructiunea SETVAR).

Solicitarea si lucrul cu punctele

In timp ce obtinerea de puncte de la utilizator este foarte simpla folosing urmatoarea secventa:
(setq point1 (getreal “\nSelectati locatia punctului: “))
Lucrul cu punctele nu e asa usor deoarece punctul e definit de fapt de trei valori care trebuie separate. Punctele sunt in realitate o lista de coordonate X Y si Z puse la un loc care pot fi descompuse folosind instructiunile CAR, CADR si CADDR dupa cum urmeaza:
(setq point1_x (car point1))
(setq point1_y (cadr point1))
(setq point1_z (caddr point1))
Observati ca o variabila intermediara numita POINT1 a retinut punctul in timp ce variabilele POINT1_X, POINT1_Y si POINT1_Z retin valorile coordonatelo x, y si z.
Aceasta abordare a punctelor cu CAR, CADR, CADDR necesita in egala masura memorarea corecta a secventelor cat si obisnuirea cu sistemul, dar veti vedea ca va veti acomoda cu acest gen de folosire a punctelor mai repede decat credeti.


Lucrul cu seturi

Un alt aspect al programarii in AutoCAD este faptul ca AutoCAD lucreaza cu seturi de obiecte (asa numitele seturi de selectie). Utilizatorii folosesc seturi de selectie cu comenzi ca MOVE, COPY, ROTATE, ERASE, etc. Regula e ca de cate ori o comanda iti cere sa selectezi obiecte(Select objects:) inseamna ca respectiva comanda foloseste un set de selectie.
Pentru a solicita seturi de selectie  cu ajutorul programelor va trebui sa folositi comanda SSGET. In forma ei cea mai simpla functioneaza asa:
(setq set1 (ssget))
sau:
(setq set2 (ssget “\nSelectati obiectele: “))
singura diferenta fiind textul adresat utilizatorului in varianta a doua.
Setul de selectie rezultat va fi pastrat in variabile (SET1 sau SET2 in exemplele de mai sus) care pot fi apoi folosite impreuna cu o functie tip COMMAND. Iata un program simplu ca exemplu:
(setq erase_set (ssget “\nSelectati obiectele de sters: “))
(command “.erase” erase_set “”)
Acest exemplu ilustreaza cum se obtine de la utilizator un set de selectie care e apoi stocat si procesat cu doar doua linii de cod.
Nota: Ultima pereche de ghilimele "" este echivalentul unui ENTER care trebuie apasat in mod normal pentru a incheia comanda ERASE in AutoCAD.

Mai mult despre seturi

Sa zicem ca ai vrea sa faci un program care sa stearga automat toate textele dintr-un desen. Va trebui sa folosesti comanda SSGET dar nu pentru a obtine obiectele de la utilizator ci pentru a le obtine prin filtrarea obiectelor tip TEXT din desen. Exemplul de cod de mai jos arata destul de incurcat dar va trebui sa ma credeti pe cuvant ca in Autolisp standard nu exista o metoda mai buna:
(setq text_set (ssget “x” (list (cons 0 “TEXT”))))
  • Parametrul "x" marcheaza folosirea unui filtru
  • Parametrul "0" este indicatorul tipului de obiect (entity type flag)
  • Parametrul "TEXT" este tipul de obiecte pe care il selectezi
Un alt exemplu in care vei selecta doar textul aflat pe layerul ADNOTARI va arata asa:
(setq text_set (ssget “x” (list (cons 0 “TEXT”) (cons 8 “ADNOTARI”))))
Recunosc ca sintaxa nu e chiar cea mai prietenoasa dar va veti obisnui cu ea. Acum combinam una din secventele de mai sus cu comanda ERASE si vom avea un program care sterge automat un anumit tip de entitati din desen:
(setq text_set (ssget “x” (list (cons 0 “TEXT”))))
(command “.erase” text_set “”)
Putem merge mai departe si adaugam si obiectele MTEXT pe langa cele TEXT prin simpla folosie a inca unei functii SSGET si modificarea comenzii ERASE dupa cum urmeaza:
(setq text_set (ssget “x” (list (cons 0 “TEXT”))))
(setq mtext_set (ssget “x” (list (cons 0 “MTEXT”))))
(command “.erase” text_set mtext_set “”)
Dupa cum se poate vedea, in acest exemplu, am castigat control serios asupra AutoCAD-ului folosind doar cateva linii de cod. Pentru mai multe informatii despre cum sa filtrati seturi complexe de selectie puteti cauta functia SSGET in sectiunea "Developer's Help" a Help-ului din AutoCAD - veti gasi acolo destule exemple de sintaxa.quotes_web

Acesta a fost articolul lui Robert Green despre primii pasi in AutoLISP. Tradus de Theodor L. pentru agoracad.blogspot
Codare placuta!
Printeaza aceast articol

1 comments:

  1. articolul este super

    de mult cautam un articol pt începatori

    acum ma apuc de facut programele

    vreau sa incerc sa introduc niste blocuri la anumite coordonate



    ar trebui creat un forum

    RăspundețiȘtergere