Baum (in der Art eines binären Baums) darstellen

Tobias K.

Erfahrenes Mitglied
moin


Ich möchte einen Baum in der Art wie Bild1 zeichnen.
Ich habe schon versucht das Problem rekursiv zu lösen (jede Rekursiv aufgerufene Funktion hat auch gleich gezeichnet), was aber zu einer Ausgabe in nur eine Richtung fürhte, siehe Bild 2.

Meine Frage:
Kann euch einer von euch konkrete Vorschläge geben wie das zu lösen ist, oder brauchbares Textmaterial (egal ob reine Theorie oder mit CodeBeispielen).

Ich habe kein Problem das per WinApi auszugeben, Linien oder Pixel zeichnen kein Problem, darum gehts auch nicht. Nur die Vorgehensweise interessiert mich.


mfg
umbrasaxum
 

Anhänge

  • Unbenannt.JPG
    Unbenannt.JPG
    3,6 KB · Aufrufe: 45
Ich habe schon versucht das Problem rekursiv zu lösen (jede Rekursiv aufgerufene Funktion hat auch gleich gezeichnet),was aber zu einer Ausgabe in nur eine Richtung fürhte, siehe Bild 2.

Verstehe nicht ganz,
welche Rekursion hast du verwendet?

Schaumla hier, muesste eigentlich so funktionieren:
Code:
enum direction{ 0GRAD, 90GRAD, 180GRAD, 270GRAD};

void zeichneBaum(direction degrees, double width){        
        if(width > 0.5){        //abbruchbedingung je nachdem wie weit der Bauem gezeichnet werden soll
                switch(degrees){
                        case 0GRAD:
                                //zeichne den Strich in der angegebenen Länge im 0 grad Winkel<-- Pseudocode
                                zeichneBaum(90GRAD, width / 2);
                                zeichneBaum(270GRAD, width / 2);
                                break;
                        case 90GRAD:
                                //zeichne den Strich in der angegebenen Länge im 90 Grad Winkel<-- Pseudocode
                                zeichneBaum(0GRAD, width / 2);
                                zeichneBaum(180GRAD, width / 2);
                                break;
                        case 180GRAD:
                                //zeichne den Strich in der angegebenen Länge im 180 grad Winkel<-- Pseudocode
                                zeichneBaum(270GRAD, width / 2);
                                zeichneBaum(90GRAD, width / 2);
                                break;
                        case 270GRAD:
                                //zeichne den Strich in der angegebenen Länge im 270 grad Winkel<-- Pseudocode
                                zeichneBaum(180GRAD, width / 2);
                                zeichneBaum(0GRAD, width / 2);
                                break;
                }
        }       
}

int main(){
        zeichneBaum(180GRAD, 200);
}

Gruß

RedWing
 
moin


So im Prinzip hatte ich es auch gemacht.

Nur das bei mir eine Funktion nciht mehr zur vorherigen Funktion zurückgekehrt ist, sodass z.B. bei
Code:
switch(degrees){
                        case 0GRAD:
                                //zeichne den Strich in der angegebenen Länge im 0 grad Winkel<-- Pseudocode
                                zeichneBaum(90GRAD, width / 2);
                                zeichneBaum(270GRAD, width / 2);
                                break;
nur das erste zeichneBaum aufgerufen wurde und es nie zum zweiten zeichneBaum Aufruf in dem Beispiel kommt. UNd das führt dann dazu das nur in eine Richtung gezeichnet wird.

Wie würdest du denn eine Abbruchbedingung einfügen, sodass die Äste z.B. nur bis zum 4 "Stück" fortgeführt würden.
Da könnte bei mir der Fehler gelegen haben.


mfg
umbrasaxum
 
nur das erste zeichneBaum aufgerufen wurde und es nie zum zweiten zeichneBaum Aufruf in dem Beispiel kommt. UNd das führt dann dazu das nur in eine Richtung gezeichnet wird.
Dann solltest du aber auch eine endlose Rekursion bekommen?
Wie würdest du denn eine Abbruchbedingung einfügen, sodass die Äste z.B. nur bis zum 4 "Stück" fortgeführt würden.
Da könnte bei mir der Fehler gelegen haben.

Der Funktion als Parameter mit übergeben...
Code:
void zeichneBaum(direction degrees, double width, int depth)

Code:
if(depth > 0){
...
   switch(degrees){
                        case 0GRAD:
                                //zeichne den Strich in der angegebenen Länge im 0 grad Winkel<-- Pseudocode
                                zeichneBaum(90GRAD, width / 2, depth - 1);
                                zeichneBaum(270GRAD, width / 2, depth - 1);
                                break;
...
}


Gruß

RedWing
 
moin


Mit
Code:
if(depth > 0){
ist es nicht getan, das muss man schon genauer machen/beschreiben.

Hatte dazu auch grad die Idee, das mein Fehler war nicht die Tiefe zu nehmen, bzw. hoch zu zählen, sondern die Anzahl der "Arbeitsschritte" zu zählen.

Also danke erstmal für deine Hilfe, werde das gleich mal umsetzen.


mfg
umbrasaxum
 
moin


Es geht!
Ich bin nach ein paar Versuchen drauf gekommen, dann hab ich gesehen das du oben schon die Lösung des Problems beschrieben hattest hab es nur leider erst übersehen.
Naja es funktioniert super!

Funktion:
Code:
void zeichnen(HDC hDC, int x, int y, int richtung, float weite, float div)
{
	int i=0;

	if(weite > 0.5)
	switch(richtung)
	{
	case 1:
		for(i=0; i < weite; i++)
			SetPixel(hDC, x, y-i, RGB(0,0,0));
		zeichnen(hDC, x, y-i, 3, weite/div, div);
		zeichnen(hDC, x, y-i, 4, weite/div, div);
		break;
	case 2:
		for(i=0; i < weite; i++)
			SetPixel(hDC, x, y+i, RGB(0,0,0));
		zeichnen(hDC, x, y+i, 3, weite/div, div);
		zeichnen(hDC, x, y+i, 4, weite/div, div);
		break;
	case 3:
		for(i=0; i < weite; i++)
			SetPixel(hDC, x-i, y, RGB(0,0,0));
		zeichnen(hDC, x-i, y, 1, weite/div, div);
		zeichnen(hDC, x-i, y, 2, weite/div, div);
		break;
	case 4:
		for(i=0; i < weite; i++)
			SetPixel(hDC, x+i, y, RGB(0,0,0));
		zeichnen(hDC, x+i, y, 1, weite/div, div);
		zeichnen(hDC, x+i, y, 2, weite/div, div);
		break;
	}
}

Aufruf:
Code:
case WM_PAINT:
	{
		HDC hDC;
		PAINTSTRUCT ps;
		hDC = BeginPaint(hWnd, &ps);
		{
			zeichnen(hDC, 400, 500, 1, 200, 1.35);
		}
		EndPaint(hWnd, &ps);
		ReleaseDC(hWnd, hDC);
			
		return 0;
	}

Man sollte mit dem Parameter div gut aufpassen hab ich gemerkt, da der Computer ganz schnell sehr viel zu tun hat!
Bei weite = 200 und div = 1.35 werden 2097151 Linien gezeichnet....unten das Beispiel wie es dann aussieht ;)


mfg
umbrasaxum
 

Anhänge

  • Unbenannt.JPG
    Unbenannt.JPG
    172,5 KB · Aufrufe: 40
Zuletzt bearbeitet:
Hi ...

Sowas haben wir auch mal in der Schule gemacht mit Delphi ... grafische Rekursion ...
ist find ich ne hübsche Sache wenn die Figuren immer komplexer werden ...
Aber so ein Baum sieht um einiges Besser aus wenn du die Äste in Winkeln von z.B. 45° abgehen lässt ...

Warum benutzt du eigentlich nicht LineTo um die Linien zu zeichnen ?

Gruß
Shai
 
moin


Code:
Aber so ein Baum sieht um einiges Besser aus wenn du die Äste in Winkeln von z.B. 45° abgehen lässt ...
Ja sieht wohl auch nicht schlecht aus. Sollte auch kein Ding sein das eben so zu ändern. Dann könnte man auch noch Farbe ins Spiel bringen und und und


Warum benutzt du eigentlich nicht LineTo um die Linien zu zeichnen ?
Hmm ja, eigentlich zufall, aber würden MoveToEx und LineTo in diesem was anderes machen als meine Schleife?


mfg
umbrasaxum
 
Zurück