Vectori si matrici

De Mircea PANTEA

După cum am mentionat în materialele anterioare, uneltele de dezvoltare ARX sînt clar directionate spre geometria vectorială, spre deosebire de ADS în care uneltele de lucru trag spre geometria analitică. Pentru a pune în evidentă aceste mici-mari deosebiri în abordarea programării vă propun un exemplu în care ne vom juca cu matrici si vectori, iar la final va rezulta un mic program utilitar care va roti entităti după o axă în spatiu.

Fisierele Main.cpp, 3dRotate.h si 3dRotate.def sînt de acum clasice si nu avem ce să comentăm asupra continutului lor. Ne vom focaliza exclusiv asupra continutului fisierului 3dRotate.cpp.

Functia transformAll este simplă deoarece rolul său este să deschidă fiecare entitate din lista de identificatori si să aplice asupra sa transformarea definită de matricea din argument. Deoarece entitătile au fost deja filtrate de functia principală, nu este nevoie de nici o validare. Cu alte cuvinte mergem la sigur, deoarece nu prea are ce să se întîmple dacă lucrăm corect. Singurele erori pot apare la acdbOpenAcDbEntity, dar această metodă esuează numai dacă în altă zonă a codului am uitat să invocăm metoda close() pe vreo entitate. Este de remarcat faptul că metoda "transformBy" se poate aplica pe orice entitate grafică AutoCAD si pe orice obiect creat de noi, bineînteles dacă acesta are suprascrisă această metodă. Matricea folosită ca argument permite translatia (move), rotatia si scalarea entitătilor. Modul în care matricea este setată poate fi urmărit în continuare.

În functia Rotate3D vom crea un set de selectie ss din care vom avea grijă să excludem entitatea AcDbViewport, pe care nu se poate aplica o matrice de transformare. Ne putem trezi cu o asemenea entitate în setul de selectie dacă la promptul “Select objects:” răspundem cu optiunea ALL. În această situatie AutoCAD-ul baleiază linear baza de date si face un set de selectie cu tot ce întîlneste acolo. După bucla “for” trebuie să apelăm explicit ads_ssfree( ss), deoarece în caz contrar fiecare set de selectie rămîne în memorie si pe lîngă faptul că ocupă locul degeaba, mai poate si să genereze erori. Asadar, scopul primei bucle FOR este să convertească setul de selectie într-o listă de identificatori cu care ARX-ul va opera în mod convenabil mai departe.

Pentru a seta matricea de transformare avem nevoie de versorii care definesc sistemul de coordonate curent. Versorii OX si OY sînt obtinuti cu ajutorul metodelor ucsxdir() si ucsydir() din acdbCurDwg(). Produsul lor vectorial ne va da vectorul OZ.

Programul va cicla într-o buclă fără sfîrsit "while( 1 )", din care vom iesi în mod controlat, dacă utilizatorul dă un răspuns nul sau apasă Escape. Dacă utilizatorul alege optiunea “X”, singurul lucru pe care îl avem de făcut este să setăm matricea la valori corespunzătoare rotirii cu unghiul dat, în jurul axei OX, avînd ca punct de rotatie valoarea originii. La prima buclare valoarea unghiului este initializată la 0.0, asa că dacă nu se dă o valoare din linia de comandă, nu vom observa nici un rezultat.

În mod absolut asemănător se face rotirea în jurul axelor OY si OZ. Pentru a translata grupul de entităti vom cere două puncte pe ecran, le vom converti din sistemul de referintă curent la WCS si apoi le vom transforma din ads_point în AcGePoint3d. De mentionat lipsa unei metode a obiectului AcGePoint3d care să permită asignarea elegantă a valorilor x,y si z din forma ads_point. Translatia este exact vectorul care se obtine din diferenta celor două puncte cu pricina. De data aceasta se apelează metoda "setToTranslation" cu argumentul vector de translatie. Celelalte optiuni ale liniei de comandă sînt evidente. De fapt toată comanda este relativ clară pentru cine este familiarizat cu tehnicile ADS si 90% din cod este de fapt ADS curat. Motivul este simplu, si anume, ARX-ul nu are nici un fel de obiecte/metode care să permită comunicarea cu mediul AutoCAD. În schimb, dacă ar fi să obtinem aceeasi functionalitate cu matrici clasice, ar trebui să scriem destul de mult cod pentru calculul valorilor pentru diverse transformări si cod pentru asignarea acestor valori. Lucrul cu matrici si vectori ca obiecte ARX este concis si intuitiv. Oricum ceea ce vedeti aici este doar un element de pornire spre masinăria de calcul vectorial. De asemenea, acest exemplu este mai putin reprezentativ pentru adevărata programare orientată obiect în sens ARX. Această comandă mai poate fi garnisită cu functionalitate. De e xemplu se pot memora undeva ultimele valori pentru unghi si origine pentru a fi refolosite la o nouă pornire a comenzii. De asemenea, se poate adăuga functionalitate care să permită re-orientarea triedrului X-Y-Z pentru a face rotiri după alte plane decît cele rezultate din sistemul de coordonate curent, sau se poate prevedea o optiune care să permită definirea unei axe arbitrare după care să se facă rotirea 3D. Mai rămîne de adăugat faptul că setările pentru compilare si linkeditare sînt cele prezentate în numerele anterioare.

***

Autorul este implicat într-un proiect de anvergură care are drept scop elaborarea unei aplicatii CAD orientată obiect

Pentru relatii suplimentare, autorul poate fi contactat prin e-mail la adresa: mpantea@cadsoft.ro

(C) Copyright Computer Press Agora