TlačiťTlačiť Slovenčina English Hľadať RSS

© 2005 – 2024 Roman Horváth, všetky práva vyhradené. Dnes je 2. 5. 2024.

Stránka sa načítava, prosím čakajte…

Dátum: 9. 9. 2020, pred štyrmi rokmi

~

void maska(int i)
{
	if (i >= -100)
	{
		dopredu(i);
		vpravo(i);
		maska(i - 20);
		vľavo(i * 2);
		maska(i - 20);
		vpravo(i);
		odskoč(i);
	}
}

Týchto pár riadkov dokáže vyprodukovať nasledujúci obrazec:

obrázok 
SVG obrázok vygenerovaný s pomocou vyššie uvedeného algoritmu. 
 

Problémom pri fraktálnych alebo iných rekurzívne kresliacich algoritmoch je, že keď sa zaoberáte niečím úplne novým (novým druhom/novou skupinou takýchto algoritmov), nedokážete odhadnúť, aký bude výsledok kreslenia, kým algoritmus nenapíšete a nespustíte.

Keď algoritmus poznáte a viete, aké výsledky produkuje, viete ho viac či menej úspešne prispôsobiť tak, aby ste získali želaný výsledok. Je však neuveriteľne náročné, ak nie nemožné, napísať nový/originálny/unikátny algoritmus a vopred vedieť, aký bude výsledok jeho kreslenia.

 


Definícia rekurzívnej metódy maska je úplná a predsa jej niečo chýba na to, aby fungovala. V Jave nemôže byť žiadna metóda definovaná (príp. deklarovaná) mimo triedy. Môže byť umiestnená v ľubovoľnej triede, ale každá metóda musí patriť do nejakej triedy (t. j. byť v rámci nej definovaná/deklarovaná). Toto je najjednoduchšia kostra takejto triedy:

~

import knižnica.*;

public class Maska extends GRobot
{
	// (Konštruktory.)

	// (Metódy.)

	public static void main(String[] args)
	{
		new Maska();
	}
}

Na získanie úplne rovnakého výsledku treba do šablóny pridať (okrem rekurzívnej metódy maska) nasledujúci konštruktor:

~

private Maska()
{
	super(700, 700);

	Svet.nekresli();
	Svet.zbaľ();
	Svet.vystreď();
	// Svet.farbaPozadia(papierová);

	farba(atramentová);
	hrúbkaČiary(0.75);
	// ohranič();
	odskoč(70);

	maska(100);

	Svet.kresli();
}

Farba pozadia bola pôvodne (pred exportom do SVG formátu) nastavená na papierovú a robot mal nastavené ohraničenie, aby nemohol opustiť kresliace plátno. V prípade záujmu môžete tieto riadky vyňať z komentárov a experimentovať s farbami pozadia, veľkosťou plátna, počiatočnou hodnotou rekurzívnej metódy maska a podobne.

 


Zostavenie úplnej triedy Maska je jednoduché, preto ho ponechávame na čitateľovi. Export do SVG súboru by však vyžadoval niekoľko ďalších zásahov. V prípade záujmu môžete nasledovať nasledujúce inštrukcie:

Medzi importy pridajte triedu java.awt.geom.Line2D:

~

// Túto triedu Javy reprezentujúcu 2D úsečku potrebujeme na pridávanie
// jednotlivých úsečiek do inštancie svgPodpora.
import java.awt.geom.Line2D;

Niekde do tela triedy (napríklad medzi definície metód maskamain) umiestnite všetky nasledujúce definície:

~

// Atribúty slúžiace na uchovanie súradníc úsečky.
private double x0, y0, x1, y1;

// Pomocná metóda na zaznamenanie aktuálnej polohy robota.
private void uložPolohu()
{
	x0 = x1 = Svet.prepočítajX(polohaX());
	y0 = y1 = Svet.prepočítajY(polohaY());
}

// Pomocná metóda na pridanie úsečky do SVG údajov.
private void pridajÚsečku()
{
	x0 = x1; x1 = Svet.prepočítajX(polohaX());
	y0 = y1; y1 = Svet.prepočítajY(polohaY());

	svgPodpora.pridaj(new Line2D.Double(x0, y0, x1, y1));
	svgPodpora.hrúbkaČiary(-1, hrúbkaČiary());
	svgPodpora.farbaČiary(-1, farba());
}

// Táto metóda slúži na uloženie vygenerovaného obrázka do SVG súboru.
private static void uložObrázok(String názov)
{
	try
	{
		if (-1 == svgPodpora.zapíš(názov + ".svg"))
			System.err.println("Chyba…");
	}
	catch (Throwable t)
	{
		// Oznámenie o prípadnej chybe:
		t.printStackTrace();
	}
}

Zariaďte volanie metódy uložPolohu pred kreslením každej úsečky a metódy pridajÚsečku po jej nakreslení. V tomto príklade kreslí úsečky príkaz robota dopredu, čiže zaznamenanie kreslenia úsečiek bude vyzerať takto:

~

uložPolohu();
dopredu(i);
pridajÚsečku();

Zariaďte volanie metódy uložObrázok po dokončení celého kreslenia. Napríklad na konci konštruktora alebo na konci metódy main (je to prípustné, lebo metóda uložObrázok je statická).

My sme export umiestnili do metódy main. Vo fáze testovania sme navyše umiestnili obidva riadky kódu do riadiacej štruktúry try­‑catch, takže výsledné telo metódy main vyzeralo takto:

~

try
{
	new Maska();
	uložObrázok("ciarova-maska");
}
catch (Throwable t)
{
	// Oznámenie o prípadnej chybe:
	t.printStackTrace();
}