Ilkka Koivistoinen 13.02.2002

Edellinen

Seuraava

10.4 2D -oliot

2D piirto-oliot ovat tulleet Java 1.2 :n mukana. Niillä saa appletteihin helposti lisäefektejä. Tälläisiä ovat erilaiset monikulmioiden täyttökuviot ja liukuvärjäys, viivojen tyylit ja leveydet sekä erilaiset reunaviivojen pyöristysmetodit ja läpinäkyvyys.

2D -piirto -olioita varten tulee määriteltäväksi kaksi erilaista koordinaatiostoa. Näillä koordinaatistoilla on yleinen merkitys, eivätkä ne liity pelkästään 2D -olioihin.

Laitekoordinaateilla tarkoitetaan ikkunassa olevien pikselien paikkoja vasemman yläkulman suhteen aivan niinkuin aikaisemmin on opittu.

Käyttäjän koordinaatistolla tarkoitetaan mitä tahansa kaksi-ulotteista suorakulmaista (itse asiassa ei laisinkaan välttämättä) koordinaatistoa, johon käyttäjä kuvittelee piirtävänsä. Matematiikan numeeristen menetelmien kurssilla toivottavasti käydään läpi lineaarimuunnos, jossa muutetaan käyttäjäkoordinaatit laitekoordinaateiksi. Tästä lähin, ellei toisin mainita piirrokset tehdään aina käyttäjän koordinaatistossa.

Voit kuvitella käyttäjänkoordinaatistoa matematiikan tunnilla piirretyksi xy -koordinaatistoksi ja laitekoordinaatteja taulun vasemman yläkulman suhteen olevaksi koordinaatistoksi. Yritä nyt kuvitella piirtäväsi xy -koordinaatistoon paraabeli y=x2. Kummassa koordinaatistossa kuvaaja on helpompi piirtää?

Periaatteessa käyttäjäkoordinaatiston ideana on se, että piirtojärjestelmälle kerrotaan, mitkä käyttäjäkoordinaatiston x ja y -akselien arvot vastaavat laitekoordinaattiakselin ikkunan reunojen arvoja. Tämän jälkeen jokainen käyttäjän koordinaatiston piste (x,y) voidaan muuntaa laitekoordinaateiksi (x0,y0).

Java 2D piirrossa lähdetään siitä, että käyttäjä- ja laitekoordinaatistojen origot on alussa samassa paikassa ja eri koordinaatistojen koordinaattiakselit yhtyvät. Tämän jälkeen käyttäjäkoordinaatiston origoa voidaan siirtää laitekoordinaatiston origon suhteen ja toisaalta  käyttäjäkoordinaattiakseleita voidaan kiertää laitekoordinaattiakseleiden suhteen.

wpe21.jpg (23468 bytes)

Java2D -grafiikka käyttää aina käyttäjäkoordinaatteja ja koordinaatin tyyppi on aina float (siis ei int).

10.4.1 Oliomuunnokset Graphics olioista Graphics2D -olioiksi

Piirtämisen hoitaa edelleen paint() -metodi. Koska siihen on määritelty parametriksi Graphics -olio ja java 2D -piirto käyttää Graphics2D -olioita, joudutaan tekemään olion tyyppimuunnos seuraavalla tavalla (Graphics2D periytyy luokasta Graphics)

public void paint(Graphics screen){
  Graphics2D screen2D = (Graphics2D) screen;
}

Kaikki java2D -metodit ovat Graphics2D -luokan olioiden luokkametodeja ja ne löytyvät java.awt.Graphics2D -paketista..

10.4.2 2D -piirto -olion väri

Piirrettävän 2d -olion väri määrätään, samoin kuin aiemmin, metodilla 

setColor(Color.darkGray);

koska setColor() -metodi periytyy Graphics -luokasta.

(Huom. Nyt piirrettävän olion tulee olla Graphics2D -luokan olio!!!)

10.4.3 2D -olion täyttökuvio

Täyttökuvio määrää, miten piirrettävän kuvion sisään jäävä pinta piirretään. Vaihtoehtoina on liukuvärjäys (GradientPaint), värjäys (Color) tai täytekuvio (TexturePaint.). Kun täytekuvio on määrätty, se asetetaan voimaan setPaint() -metodilla.

Seuraavassa on käsitelty erilaiset täyttökuviovaihtoehdot

10.4.3.1 Liukuvärjäys

Liukuvärjäys toteutetaan siten, että täytettävän kuvion sisältä määrätään kaksi pistettä ja kaksi väriä. Väri vaihtuu Apletti E60. 2D -piirtoa ei toistaiseksi ole selaimessa, mutta kokeile tätä sivua appletviewerissä portaattomasti pisteen (x1,y1) värista  v1 pisteen (x2,y2) väriin v2, kuten oheisesta appletista E60 havaitaan. Liukuvärjäys tehdään seuraavasti

  GradientPaint pat = new GradientPaint(x1,y1,v1,x2,y2,v2);
  ikkuna2D.setPaint(pat); 

Aluksi luodaan GradientPaint -objekti, jonka kaksi ensimmäistä pararametria ilmoittavat, mistä pisteessä väri v1 määritellään käytettäväksi ja vastaavasti (x2, y2) ilmoittaa missä pisteessä on väri v2. Näiden pisteiden välillä kulkevalla janalla väri vaihtuu portaattomasti. Seuraavassa lauseessa otetaan luotu olio käyttöön.

Jos appletti E60 näkyy selaimessasi, sinulla on java2D -grafiikkaa tukeva selain (keväällä 99 selaimet eivät vielä uusinta Linux -versiota lukuunottamatta 2D -ominaisuuksia). Jos se ei näy, katso tätä sivua appletviewer -ohjelmalla, niin saat liukuvärin näkyviin. Kun olet kopioinut tämän sivun omalle koneelleesesi, saat appletin näkyviin komennolla

appletviewer "10.4 2D -oliot.htm"

Esimerkki E60 ohjelmakoodi on seuraavanlainen. (Siinä on käytetty lisäominaisuuksia, joihin tutustutaan seuraavissa kappaleissa.)

import java.awt.*;
import java.awt.geom.*;
public class E60 extends java.applet.Applet {
public void paint(Graphics ikkuna){
  Graphics2D ikkuna2D = (Graphics2D) ikkuna;
  BasicStroke pen = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
  ikkuna2D.setStroke(pen);  // lisätään reunaviivam ominaisuudet
  GradientPaint pat = new GradientPaint(0f,0f,Color.pink,100f,45f,Color.blue);
  ikkuna2D.setPaint(pat);  //lisätään liukuvärjäys
  Rectangle2D.Float rc = new Rectangle2D.Float(10f,10f,100f,45f);
  ikkuna2D.fill(rc);  // piirretään suorakaide
}

Liukuvärjäys voidaan toteuttaa myös toistuvana, jossa väriliuku toistuu jokaiseen pisteen (x1,y1), (x2,y2) välisen janan pituisin välein, kuten appletissa E61 näkyy.

Koska tätä kirjoitettaessa selaimet eivät tukeneet vielä java2D -grafiikkaa (viereinen appletti ei toimi), on seuraavassa kuvassa esitetty appletit E60 ja E61

 

 

 

wpe15.jpg (11627 bytes)

E61 eroaa E60:stä ainoastaan ylikuormitetun GradientPaint() -muodostimen

GradientPaint pat = new GradientPaint(0f,0f,Color.pink,10f,10f,Color.blue,true);

suhteen (viimeisenä parametri true, jolla saadaan toistuva väriliuku).

10.4.3.2 Väri

Graphics2D -olion  väri voidaan asetaa setColor() -metodilla.

10.4.3.3 Reunaviiva (Stroke)

Reunaviiva -olio  luodaan seuraavasti

BasicStroke pen = BasicStroke(reunanLeveys, reunanPäänMuoto, reunaviivanKulmanMuoto);

ja se otetaan käyttöön lauseella

ikkuna2D.setStroke(pen);

Muodostimen parametrit ovat

reunanLeveys on float luku, joka ilmoittaa reunaviivan paksuuden pikseleissä (0 = ei reunaviivaa)
reunanPäänMuoto ilmoittaa viivan lopun muodon. Se voi olla CAP_BUTT eli katkastu, CAP_ROUND eli pyöristetty tai CAP_SQUARE eli katkaistu suorassa kulmassa viivaan nähden.
reunaviivanKulmanMuoto ilmoittaa reunaviivassa esiintyvän kulman muodon. Se voi olla JOIN_MITER, eli terävä pyöristämätön kulma, JOIN_ROUND eli pyöristetty kulma tai JOIN_BEVEL eli kuten JOIN_MITER siten, että terävä kulma on leikattu pois.

Kun 2D -piirto -oliolle on määrätty täytetyyli ja reunaviiva, voidaan luoda erilaisia 2D -piirto -olioita. Ne löytyvät java.awt.geom -paketista.

10.4.4 2D -piirto -oliot

Seuraavissa esimerkeissä oletetaan, että paint() -metodin muodollisena parametrista on tyyppimuunoksen jälkeen Graphics2D olio nimeltä ikkuna2D.

10.4.4.1 2D -viiva

Java2D -grafiikassa viiva muodostuu Line2D.Float -luokan oliosta. Se muodostetaan seuraavasti:

Line2D.Float viiva = new Line2D.Float(x1,y1,x2,y2);

Muistettakoon, että parametrit ovat float tyyppiä. Siis olio sisältää viivan pisteestä (x1,y1) pisteeseen (x2,y2).

Viiva saadaan näkyviin draw() -metodilla seuraavasti

ikkuna2D.draw(viiva);

Siis ensin luodaan viiva -olio ja sitten se näytetään draw() -metodilla. Tätä ennen on viivatyyppiolit voitu luoda ja ottaa käyttöön.

10.4.4.2 2D -suorakulmio

Java2D -grafiikassa suorakulmio muodostuu Rectangle2D.Float -luokan oliosta. Se muodostetaan seuraavasti:

Rectangle.Float sk = new Rectangle2D.Float(x1,y1,leveys,korkeus);

Suorakulmion vasemman yläkulman koordinaatit ovat (x1,y1) ja leveys sekä korkeus määräytyvät kahdella viimeisellä parametrilla

Suorakaide voidaan ottaa käyttöön joko draw() -metodilla, joka piirtää pelkät suorakaiteen ääriviivat tai fill() -metodilla, joka lisäksi täyttää kuvion. Siis joko

ikkuna2D.draw(sk);

tai

ikkuna2D.fill(sk);

10.4.4.3 2D -ellipsi

Soikiot on java2D -grafiikassa korvattu ellipseillä. Se muodostuu Ellipse2D.Float -luokan oliosta seuraavasti.

Ellipse2D.Float e = new Ellipse2D.Float(x1,y1,leveys,korkeus);
ikkuna2D.draw(e); // tai
ikkuna2D.fill(e)

Parametrit ovat samassa merkityksessä, mitä soikioitten tapauksessa on aiemmin kerrottu.

10.4.4.4 2D -kaaret

Kaaret piirretään java2D -grafiikassa samoin kuin aikaisemmin on opittu. Kaari on luokan Arc2D.Float -luokan olio ja se otetaan käyttöön seuraavasti..

Arc2D.Float kaari = new Arc2D.Float(x1,y1,leveys,korkeus,alitusKulma,lopetusKulma,muoto);
ikkuna2D.draw(e); // tai
ikkuna2D.fill(e)

Viimeistä parametria muoto lukuunottamatta parametrit ovat kuten aiemmin on opittu.

Parametri muoto saa seuraavat arvot

Arc2D.OPEN tarkoittaa pelkkää kaarta
Arc2D.CHORD tarkoittaa kaarta ja sen päitä yhdistävää sekanttia
Arc2D.PIE yhdistää kaaren päät ympyrän keskuskulman, jolloin saadaan piirakan viipalekuvio (sektori + sektorin ympyrästä eroittama ympyrän kaari)

10.4.4.5 2D -monikulmiot

2D -monikulmiot tehdään aivan eri tekniikalla, mitä aiemmin on opittu.

Monikulmio syntyy samalla tavalla, mitä se syntyy paperille piirrettäessä. Kynää siiirretään viiva kerrallaan kärjestä seuraavaan kärkeen. Esimerkiksi kolmio muodostetaan seuraavasti

GeneralPath kulmio = new GeneralPath();
kulmio.moveTo(5F,0F); // siirretään kynä pisteeseen (5,0)
kulmio.lineTo(205F, 0F); // piirretään viiva edellisestä paikasta pisteeseen (205,0)
kulmio.lineTo(100F,50F); ) // piirretään viiva edellisestä paikasta pisteeseen (100,50)
kulmio.closePath() // suljetaan monikulmio
ikkuna2D.draw(kulmio); // tai
ikkuna2D.fill(kulmio)

Joissakin yhteyksissä kynän hetkellistä paikkaa sanotaan kynän nykypisteeksi. Piirrettäessä nykypiste siirtyy kynän mukana. Java2D ei kuitenkaan tunne tälläistä käsitettä, vaan yleensä oletetaan, että käyttäjän koordinaatiston origo siirtyy kynän mukana ja piirto tapahtuu aina origosta annettuun pisteeseen. Voit testata origon paikkaa piirtämällä viivan tai suorakaiteen kesken kaiken tiettyyn paikkaan. Tuleeko kuvio oikeaan paikkaan? closePath() -metodi korjaa tilanteen (tutki). Tässä on siis ainakin yksi tapa siirtää käyttäjäkoordinaatiston origoa.

Mikäli java2D -luokissa vaihtaa Float -sana sanaan Double, saadaan muuten samalla tavalla toimivia olioita paitsi, että float -tyyppiset parametrit tulee korvata double -tyypillä.

10.4.5 Tehtäviä

  1. Tee appletti, joka piirtää kuusipuun (sellainen, mitä ala-asteella on opitttu) ja värjää sen vihreäksi. Rungon tyvi olkoon ruskea. Tee puita erilaisilla reunaviivoilla ja erilaisilla kulmien muotoilulla. Vastaus
  2. Tee appletti, joka piirtää olympiarenkaat. Vastaus
  3. Tee appletti, joka piirtää kuulantyöntöpaikan pituuskaarineen. Vastaus

Ilkka Koivistoinen 13.02.2002

Edellinen

Seuraava