wiki:graphicsdevel
Last modified 7 years ago Last modified on 2010-06-28 10:28:01

Grafiikkakirjaston ideointia

Testaamisesta

Mites graphics-kirjasto testataan?                                                                                                                            

Jos tuohon liittyen tekee LuK:ia, niin
tuostahan pitäisi saada mallikelpoinen ohjelma.
Tietysti toistaiseksi kaikki piirtäminen menee
Graphics g-olion kautta, jolloin siitä voisi tehdä mock-olion,                                                                                                
jolla on tarvittavat metodit.
Harmittavasti g vaan ei ole rajapinta.

Toimiiko jos tuon perii ja tekee mock-metodit
kaikkien tilalle?
Vai pitääkö vaihtaa tilalle IGraphics                                                                                                                         
joka on itse tehty rajapinta ja sitten
tehdä oma luokka Graphicsista joka toteuttaa
tuon ja sitten oma MockGraphics?

Niin tai näin, niin testit ComTestilla tyyliin:

  Line line = new Line(100,100,200,200);
  MockGraphics g = new MockGraphics();                                                                                                                        
  Matrix a = new Matrix();
  
  line.draw(g,a);
  
  g.getOperation(0) == "drawLine 100,100,200,200";
  g.getState(0).getColor() == Color.BLACK;
  
  a = a.scale(0.5);  // vai miten tehtiinkään)
  line.setColor(Color.RED);
  line.draw(g,a);
  
  g.getOperation(1) == "drawLine 50,50,100,100";
  g.getState(1).getColor() == Color.RED;                                                                                                                      
  
  
jne...


Eli MockGraphics kerää talteen kaikki operaatiot
joita suoritetaan ja niitä voi sieltä sitten indeksoiduti
pyytää.


Yleistä ideointia

vesal 17.8.2008 klo 10:00:

> pois. Olisiko parempi jos akselit olisivat kuten muutkin komponentit ja
> lisättäisiin samalla tavalla?
> 

Oikeastaan asia on ehkä niin, että meillä on kaksi                                                                          
asiaa:
  - avaruus (space) johon kuva kuuluu, mutta siihen                                                                         
    ei kuulu akseleita.                                                                                                     

  - ikkuna (window) josta avaruutta katsotaan ja joka
    ehkä voi haluta piirtää sinne tilanteen selventämiseksi                                                                 
    akselit (joiden leikkauskohdan ja pituuden voi määrittää
    kiinakohtaisesti).  Myös z-akseli mahdollista piirtää.

  - ikkunan kaveriksi voisi olla JRobotin idean mukaan
    http://pclc.pace.edu/~bergin/KarelJava2ed/karelexperimental.html
      new RemoteControl(5, 3, East, 0, Color.red);

    http://www.mit.jyu.fi/vesal/kurssit/winohj/delphi/comps/piirto/

    sin3d.exe:n mukaisesti 
      1) "touch pad" jossa hiirtä liikuttamalla
          avaruus pyörii
      2) näppäimistö jossa on kullekin koordinaatille erikseen
         kiertonäppäin. 

    Lisään tästä vielä oman kohdan käyttöideoinnista
    
  - ikkunan muoto pitäneen olla valinnainen
      1) x/y/z ovat samansuuruisia aina (oletus?)
         isotrophic
      2) x/y ovat suhteessa ikkunan leveyteen ja korkeuteen
         (tämänhetkinen tilanne)
         unisotrophic 

vesal 17.8.2008 klo 12:35

  Ikkunaa ohjaavat "paneelit" toteutetaan seuraavasti:

    interface WindowController
      setWindow();
      getWindow();

     TouchPad implements WindowController extends Frame;  
       kun hiiri (nappi alhaalla?) liikahtaa tämän sisällä, tehdään ikkunan
       muunnosmatriisille seuraavaa (x,y = hiiren koordinaatit)
        dx := PanelRot.ClientHeight/2;         
        dy := PanelRot.ClientWidth/2;
        degz := Round((X - dx)/dx * 180);
        degx := Round((Y - dy)/dy * 180);
        A.Assign(AOrig);
        Rx.setdeg(0,degx);
        Rz.setdeg(2,degz);
        A.Mul(Rx);
        A.Mul(Rz);
        siirretään matriirisi ikkunalle ja redraw


     ControlButtons implements WindowController extends Frame;
       luodaan valmiiksi kiertomatriisit:

         R[0] := cRotMatrix.Create(0,5);
         R[1] := cRotMatrix.Create(1,5);
         R[2] := cRotMatrix.Create(2,5);
         R[3] := cRotMatrix.Create(0,-5);
         R[4] := cRotMatrix.Create(1,-5);
         R[5] := cRotMatrix.Create(2,-5);

       Sitten tietyn koordinaatin napin panalluksella
       otetaan ikkunan muunnosmatriisi ja kerrotaan
       se R[i]:llä.

    Yksi Controlleri voi kuulua vain yhdelle ikkunalle,
    mutta yhteen ikkunaan ovi kuulu monta Controlleria.
         
    Eli
      WindowController touchPad = new TouchPad(window);

    EasyWindow:n setTouchPad(true) tekee tämän.


vesal 17.8.2008 klo 12:35

  window, space ja DrawableCollection suhde

    space voi kytkeytyä moneen ikkunaan.
      yhdessä ikkunassa on max yksi space.
      Kun space muuttuu, se tiedottaa kaikille ikkunoille

    space <-> DrawableCollection (voi olla monta spacea)
      kun DrawableCollection muuttuu, se tiedottaa spacea 
 
    Jokainen Drawble voi kuulua yhteen DrawableCollection.
    Jos Drawable siirretään toiseen collectioon, se poistuu
    vanhasta.  Kun Drawable muuttuu, se tiedottaa DrawableCollection

    Jokainen Drawable sisältää yhden muunnosmatriisin.
    Piirrossa tehdään aina:
      Matrix tr = A;
      if ( this.matrix != null ) tr = A.multiply(this.matrix);

    (Toki iffien vähentämiseksi voisi olla että A.multiply(null)
     palauttaa A:n, eli null tulkitaan yksikkömatriisiksi).

     Tuo ansiosta esim. TikkuUkko voitaisiin piirtää:
     (vrt. [http://www.mit.jyu.fi/vesal/kurssit/winohj/html/winmon/m-3.htm#Heading51])
 
        space.moveTo(60,60);
        space.draw(new Circle(0,0,20));
        space.moveTo(20,20); // siirtyy edelliseen paikkaan 20 lisää
        space.draw(new Line(0,0,0,100));
        space.moveTo(0,10); space.rotate(2,30);
        space.draw(new Line(0,0,0,70));  // toinen käsi
        space.rotate(2,-60);
        space.draw(new Line(0,0,0,70));  // toinen käsi
        space.rotate(2,-30); // takaisin
        space.moveto(0,90); // haaroihin
        space.rotate(2,20);         
        space.draw(new Line(0,0,0,80));  // toinen jalka
        space.rotate(2,-40);         
        Drawable jalka = space.draw(new Line(0,0,0,80));  // toinen jalka
        space.ident(); // palauttaa space:n sisäisen muunnosmatriisin perustilaan (=null tai yksikkömatriisi)
       ...
        jalka.mulMatrix(rotz10degMatrix); // kertoo jalan nykyasennon 10 asteen matriisilla
                                          // ilmoittaa space objects taulukolle että muuttui
                                          // joka ilmoittaa space:lle että muuttui
                                          // joka ilmoittaa kaikille ikkunoille että muuttui
                                          // ja näin jalka piirretään uuteen asentoon kaikissa ikkunoissa. 



     Eli space.draw(object) toimii
        if ( this.matrix != null ) object.mulMatrix(this.matrix);
        objects.add(object);

     
    Edellä voi olla hieman virheitä siinä, kummaltako puolelta matriiseja
    kerrotaan.  Tämä pitää varmistaa toteutuksessa oikein päin.


Tuukka & vesal 17.8.2008 klo 19:00

On Sun, 17 Aug 2008, Tuukka Puranen wrote:
> -väritäyttö
täytyy tutkia mitä Java antaa tähän mahdollisuuksia.
3d:ssä ei ihan helppoa

> -muita väritystapoja (gradientit?)
tosi vaikea määritellä että mitä on 3d:ssä


> -z-järjestys (mitä piirretään ensin)
kaikilla kappaleilla on z-koordinaatti.
Sitähän ei voi vaihtaa enää tietyssä mielessä.
Tämä liittyy piiloviivan poistoon ja täytyy myöhemmin
miettiä miten piiretään, koska tuo riippu katseluikkunan
suunnasta ja voi samallekin avaruudelle olla erilainen.

> -läpinäkyvyys
Ei taida swt tukea :-)

> -jokaiselle otukselle oma matriisi?
tarkoitus olisi.

>
> w2.rotate(2, 45); -> w2.rotate(w2.z-axis, 45); tms
tuossa voisi olla järkeä.

> window.getSavedPath(); on aika jännä nimi metodille joka palauttaa
> piirto-objektikokoelman
Eikös joissakin piirtokisrjastoissa nimenomaan käytetä nimeä path
sille mitä on tullut piirrettyä?

Tosin uudessa versiossa space korvaa tuota aika pitkälle.

>
> kaikki metodit muotoa
>
> drawLine(double x1, double y1, double x2, double y2)
> tai
> drawPolygon(int[] xpoints, int[] ypoints)
>
> voi tottakai ylikuormittaa myös esim.
>
> drawLine(RPoint start, RPoint end)
> ja
> drawPolygon(Rpoint[] points)
Tuo on tarkoitus jossakin vaiheessa.

> Samoin värin hyväksyvät metodit voisivat ottaa Javan oman Color-olion(kin).
Varmaan ok.

> "Paradigma", jota voi harkita (toki vähän kryptisempi) on
> aliohjelmakutsujen ketjuttaminen (jokainen palauttaa this-viitteen),
> jolloin seuraava on validia:
>
> window.drawCircle( 0, 0, 50 )
>  .setColor( Color.RED )
>  .setStyle( Style.FILL )
>  .setTransparency( 0.5 )
>  .scale( Axis.X, 2.0 );

Tuo on jos osin käytössäkin.

vesal 18.8.2008 klo 7:47

> Olenko nyt ymmärtänyt oikein, että jos kutsun EasyWindow:n jotain
> drawKomponentti-metodia niin se kutsuu yliluokkansa (Window) attribuuttina
> olevan EasySpacen addAndDraw-metodia joka lisää komponentin yliluokkansa  
> (Spacen) attribuuttina olevaan DrawableCollectioniin?
> 

Et ehkä oikeastaan :-)                                                                                                                            

Vaikuttaisi että voi tehdä niin, että molemmat,
EasyWindow ja EasySpace toteuttavat saman rajapinnan:

  interface EasyDraw                                                                                                                              
    drawCircle  - useilla parametreillä
    drawPolygon - useilla parametreillä
    drawLine    - useilla parametreillä

ja sitten molemmissa luokissa
   drawXXX
     addAndDraw(new XXX(parametrit)

ja Window:n
   addAndDraw
     if ( space != null ) space.addAndRaw(object)

ja Space:
   addAndDraw                                                                                                                                     
     objects.add(shape);
     returs shape;

redraw:ta ei tarvita missään, sillä vasta tuo
object.add(shape) kutsuu sitä kaikille niille
jotka "tarkkailevat" sitä.                                                                                                                        



Valitettavasti Javassa ei ole mitään automaattista tapaa
toteuttaa tuota EasyXXX luokkaa vaan molempiin tulee
ihan kopioimalla sama koodi.  Eli kun koodi on kirjoitettu                                                                                        
toiseen, niin se tulee toiseen kopioimalla.
Helpointa tuo on tehdä Eclipsessä niin, että kirjoittaa
ensin toisen Easy-luokan, sitten käskee siitä Eclipsen tehdä
rajapinnan ja sitten molemmat laittaa toteuttamaan sen rajapinnan
ja sitten kopioi koodin toiseen...

Vesa


Ideoita vastaavista järjestelmistä

Seuraavia voisi kokeilla ja vilkuilla, josko niistä löytyisi ideoita lisää