Matrisestakk
Børre Stenseth
Å tegne:>Rognebær

Rognebær

Hva
tree1
Demonstrasjon av bruk av matrisestakken ved uttegning av en en kvist med bær

Vi ønsker å tegne en trestruktur, med en "tilfeldig" forgrening. Når vi har kalt modulen rognebære, er det fordi noen små røde kuler i enden på grenene i treet assosierer til en klase rognebær.

Modulen demonstrerer bruk av matrisestakken og supplerer modulen Planetarium. Modulen viser også en enkel teknikk for å spare tid ved animasjon.

Rekursjon

Vi lager løsningen rekursiv. Hovedkomponenten i løsningen er en funksjon som er bygget opp slik:


void DrawOneBranch(...)
{
  if(< end of branchdepth >)
  {
    < draw berry >
    return;
  }

  < draw a single stem >
  glTranslate( < to the end of this stem >);
  for ( < all subbranches >)
  {
     glPushMatrix();
     < rotate for next branch >
     DrawOneBranch(...);
     glPopMatrix();
  }
}

Tidsoptimering

I løsningen er det valgt å bruke sylindere til grenene. Dette kan fort bli tidkrevende og det er lagt opp til en strategi der det tegnes ut en forenklet figur basert på streker, uten rognebær, når figuren manipuleres. Dette gjør det mulig for brukeren å se treets struktur mens manipuleringen pågår. Når manipuleringen opphører tegnes treet komplett ut.

tree1 tree2

Det er introdusert et flagg

boolean is_moving;

som settes når museknappen presses ned og frigjøres når den slippes.

Tegnekode

Denne strategien er realisert ved følgende metoder

Display metoden

_Rogn.java

og selve uttegningen

_Rogn.java

Tilfeldighet

Som det framgår av koden ovenfor brukes metoden rand_rot.nextFloat() ,der rand_rot er et objekt av typen java.util.Random, til å bestemme hvordan forgreiningene er fra en delstamme.

Det er et forhold som det er viktig å merke seg. Siden vår framstilling retegnes ofte, feks. ved resizing av vinduet og ved interkativ manipulering, vil treets struktur endre seg ved hver uttegning dersom vi lar rand() plukke tilfeldige tall kontinuerlig. Dersom vi ønsker å beholde treets struktur ved retegning, må vi sørge for at randomgeneratoren gjentar seg selv. Vi må kunne rekonstruere en sekvens av "tilfeldige" tall. Vi må starte sekvensen av tilfeldige tall på samme sted ved hver retegning.

Dette kan vi oppnå ved å kalle rutina rand_rot.setSeed(m_rand_seed) ved hver uttegning. m_rand_seed er en medlemsvariabel som vi kan sette til et heltall.

Vi kan administrere dette ved en menystyrt endring av m_rand_seed for det tilfellet at vi ønsker å endre treets struktur. Dette er gjort når vi høyreklikker i vinduet:

    public void mouseClicked(MouseEvent e) 
    {
        if(e.getButton()==MouseEvent.BUTTON3)
            m_rand_seed=rand_rot.nextLong();
    }

Vi bruker altså randomgeneratoren til å lage et nytt "seed"-tall til randomgeneratoren. Tallteoretisk er dette en tvilsom løsning. Men for vårt enkle eksempel gjør det jobben. Det har den konsekvensen at programmet alltid kommer opp med den samme sekvensen av trær.

Referanser
Programmet(JOGL/Netbeans): https://svn.hiof.no/svn/psource/JOGL/rogn
Vedlikehold
Revidert april 2010, Børre Stenseth
(Velkommen) Å tegne:>Rognebær (Påskeegg)