Programmeren Fractals tekenen

Het forum voor overige vragen betreffende wiskunde uit het hoger onderwijs.
Plaats reactie
BusinessMath
Vast lid
Vast lid
Berichten: 57
Lid geworden op: 23 feb 2014, 15:14

Programmeren Fractals tekenen

Bericht door BusinessMath » 31 mar 2014, 16:20

Ik heb nu een opdracht gekregen dat ik met programmeren moet gaan tekenen

Je kan met Delphi figuren tekenen op het programmascherm. Hiervoor gebruik je de property Canvas van Form.

Dit vind ik echt heel lastig, hopelijk kunnen jullie mij een beetje op weg helpen. :mrgreen:

Dit is de opdracht::

Afbeelding
Afbeelding
Afbeelding

De bedoeling is om een Sierpinski driehoek te maken, en de gebruiker voert het aantal stappen n in.
n geeft aan hoeveel witte vierkanten er op het scherm komen.

Dit is wat ik tot nu toe heb gemaakt::

Code: Selecteer alles

procedure tekenvierkantje (n, x1, y1, x2, y2: real);
var bovenhalf, rechtshalf: real;
    p,q,r: integer;

begin
  bovenhalf:= p+((1/2)*(q-p));
  rechtshalf:= r+((1/2)*(q-r));
  p:= 0;
  q:= form1.ClientWidth;
  r:= form1.ClientHeight;

  form1.Canvas.Pen.Color:=clblack;        {maak de pen zwart}
  form1.Canvas.Pen.Width:=2;              {geef de pen breedte 2}
  form1.Canvas.Brush.Color:=Clwhite;      {geef de brush de kleur wit}
  form1.Canvas.Rectangle(p,0,q,r);
             {teken een rechthoek}

end ;

procedure TForm1.Button1Click(Sender: TObject);
var bovenhalf, rechtshalf, p,q,r: real;
   n,i: integer;

begin
  bovenhalf:= p+((1/2)*(q-p));
  rechtshalf:= r+((1/2)*(q-r));
  n:= StrToInt (edit1.Text);
  p:= 0;
  q:= form1.ClientWidth;
  r:= form1.ClientHeight;


  Canvas.Pen.Color:=clWhite;
  Canvas.Pen.Width:=2;
  Canvas.Brush.Color:=Clblack;
  Canvas.Rectangle(0,0,ClientWidth,ClientHeight);



Met deze code krijg je een zwarte rechthoek op het scherm te zien. Dit is het begin. nu moet je telkens de rechthoek opsplitsen in 4 gedeeltes. rechts bovenin komt dan een wit vierkant en de rest wordt zwart. dan bij de volgende stap worden in die 3 zwarte vierkanten de rechter bovenhoeken ook weer wit en dan de rest zwart enzovoort.

Afbeelding

Ik vind het lastig wat je in die procedure tekenvierkantje moet zetten, en met welke waarden en hoe je die dan weer moet aanroepen.
Kun je dat met een herhaling doen? Die herhaling moet dat in de procedure buttonclicck toch?
Maar het worden toch steeds weer andere waarden, moet je ze dan allemaal ophogen?

Hopelijk kunnen jullie mij op weg helpen :mrgreen:
Bedankt!
Durf te vragen!

arie
Moderator
Moderator
Berichten: 3911
Lid geworden op: 09 mei 2008, 09:19

Re: Programmeren Fractals tekenen

Bericht door arie » 31 mar 2014, 23:56

procedure TForm1.Button1Click() heeft 3 taken:
[1] lees de waarde van n in
[2] maak het hele canvas zwart
[3] roep procedure tekenvierkantje aan voor de gegeven n en de canvas afmetingen

Je procedure krijgt dan deze vorm:

Code: Selecteer alles

procedure TForm1.Button1Click(Sender: TObject);
begin
  { 1. lees de waarde van n in: }
  n:= StrToInt (edit1.Text);

  { 2. maak het hele canvas zwart: }
  Canvas.Brush.Color:=ClBlack;
  { doe hier iets met FillRect(Rect(0, 0, ClientWidth, ClientHeight)) }
  Canvas.Brush.Color:=clWhite; { we zullen vanaf nu alleen nog een witte brush nodig hebben }

  { 3. roep procedure tekenvierkantje aan voor gegeven n en de canvas afmetingen: }
  tekenvierkantje(n, 0, 0, ClientWidth, ClientHeight);
end;
De procedure tekenvierkantje() is beschreven in de probleembeschrijving, de invoerparameters zijn integers (want alle pixels op je canvas hebben geheeltallige coordinaten)

tekenvierkantje() moet eerst de door x1, y1, x2 en y2 gegeven rechthoek in 4 gelijke delen splitsen: linksboven, rechtsboven, linksonder en rechtsonder.
Je gebruikt hiervoor twee hulpvariabelen, bovenhalf en rechtshalf, dat is handig, maar deze kunnen dan ook integers zijn.
Verder heb je p en q niet nodig, maar kan je direct de invoerparameters gebruiken:
bovenhalf = (x1 + x2) / 2;
rechtshalf = (y1 + y2) / 2;

Vervolgens moet tekenvierkantje()
- het rechtsboven deel (= de Rect(bovenhalf, y1, x2, rechtshalf)) wit kleuren (met FillRect())
- ALS n>1 DAN voor elk van de overige 3 rechthoeken tekenvierkantje() opnieuw aanroepen, nu elk met nog maar n-1 keer te gaan, en met de afmetingen van de betreffende rechthoek. Hiermee werk je alle herhalingen automatisch af.

Hier een raamwerk:

Code: Selecteer alles

procedure tekenvierkantje (n, x1, y1, x2, y2: integer);
var bovenhalf, rechtshalf: integer;

begin
  bovenhalf = (x1 + x2) / 2;
  rechtshalf = (y1 + y2) / 2;

  { kleur de rechtsboven rechthoek wit: }


  if n>1 then  { roep tekenvierkantje 3 keer aan voor de overige rechthoeken: }
  begin
    tekenvierkantje(n-1, , , , ); { = linksboven deel }
    tekenvierkantje(n-1, , , , ); { = linksonder deel }
    tekenvierkantje(n-1, , , , ); { = rechtsonder deel }
  end;

end ;

BusinessMath
Vast lid
Vast lid
Berichten: 57
Lid geworden op: 23 feb 2014, 15:14

Re: Programmeren Fractals tekenen

Bericht door BusinessMath » 01 apr 2014, 10:00

Dat van die overige vierkanten de bovenhoek vullen heb ik even geprobeerd, alleen het hele stuk vanaf de rechter boven hoek wordt wit. Ik denk dat ik een verkeerde punten gebruik.

moet je ook niet canvas.moveto (x,y) gebruiken? dat je de pen eerst verplaatst naar het volgende stuk?
& hoe weet je dat je niet meer in hetzelfde vierkant bezig gaat, maar dat de overige vierkantjes wit worden? Moet er dan niet een herhaling in zitten?? anders moet je het toch voor elke waarde opnieuw invoeren? of zie ik dit verkeerd?

Dit is wat er bij mij nu uitkomt (ik heb het alleen nog maar geprobeerd voor Linksboven):

Afbeelding


& dit is wat ik heb ingevoerd:

Code: Selecteer alles

procedure tekenvierkantje (n, x1, y1, x2, y2: integer);
var bovenhalf, rechtshalf: integer;

begin
  bovenhalf:= (x1 + x2) div 2;
  rechtshalf:= (y1 + y2) div 2;

  {kleur de rechtsboven rechthoek wit:}
  form1.Canvas.Rectangle(bovenhalf, 0, form1.ClientWidth, rechtshalf);

  if n>1 then  { roep tekenvierkantje 3 keer aan voor de overige rechthoeken: }
  begin
    tekenvierkantje(n-1,((x1+x2) div 4 ),0 ,(bovenhalf div 4) ,((y1+y2) div 4) ); {= linksboven deel}

  end;

end ;

Durf te vragen!

arie
Moderator
Moderator
Berichten: 3911
Lid geworden op: 09 mei 2008, 09:19

Re: Programmeren Fractals tekenen

Bericht door arie » 01 apr 2014, 12:00

Afbeelding

In deze figuur zie je bovenaan de rechthoek waar we mee werken.
Die rechthoek loopt horizontaal van x1 naar x2 en vertikaal van y1 naar y2.
Het midden van lijnstuk x1_x2 is xm := (x1 + x2) div 2
Het midden van lijnstuk y1_y2 is ym := (y1 + y2) div 2
Dit zijn jouw waarden bovenhalf (= xm) en rechtshalf (= ym)

In Delphi definieren ze zo'n rechthoek op het canvas via de bovenlinkshoek, met coordinaten (x1, y1) en de benedenrechtshoek, met coordinaten (x2, y2), zie plaatje.

De procedure tekenvierkantje() krijgt deze rechthoek via die coordinaten binnen: dit zijn de invoerparameters x1, y1, x2 en y2.
Nu moet tekenvierkantje() die rechthoek in vier gelijke stukken delen, en daar wat mee doen.
Het maakt hierbij voor tekenvierkantje() niet meer uit hoe groot het canvas is (zo zijn bijvoorbeeld de afmetingen van ClientWidth en ClientHeight niet meer van belang). Het enige wat tekenvierkantje() moet doen is zijn eigen rechthoek verwerken.

De benodigde coordinaten daarvoor lees je af uit bovenstaand plaatje:
- de bovenrechts rechthoek moet wit gekleurd worden, deze rechthoek heeft
- - als bovenlinkshoek (xm, y1)
- - als benedenrechtshoek (x2, ym)
dus de Rect(xm, y1, x2, ym) moet je wit maken.

- de bovenlinks rechthoek moet je opnieuw verdelen en kleuren, dit doe je met tekenvierkantje() zelf (tekenvierkantje moet zichzelf dus aanroepen, dit is de recursie die we gebruiken)
Voor die rechthoek heb je alleen nog maar n-1 herhalingen te doen.
Deze rechthoek heeft:
- - als bovenlinkshoek (x1, y1)
- - als benedenrechtshoek (xm, ym)
Dus nu moeten we
tekenvierkantje(n-1, x1, y1, xm, ym); { linksboven rechthoek }
uitvoeren.

- evenzo voor de benedenlinks rechthoek en beneden rechts rechthoek:
tekenvierkantje(n-1, x1, ym, xm, y2); { linksonder rechthoek }
tekenvierkantje(n-1, , , , ); { rechtsonder rechthoek - vul zelf verder in }

Alleen moeten we de recursie stoppen als n=1 wordt, vandaar de if n>1 then ...


Wat er gebeurt:
Stel we hebben een canvas van 100 x 80 pixels en er is ingevoerd n=2.
Button1Click maakt het hele canvas zwart en roept tekenvierkantje() zo aan:
tekenvierkantje(2, 0, 0, 100, 80);

tekenvierkantje() berekent nu eerst:
xm = 50
ym = 40
en maakt de Rect(50,0, 100, 40) wit.

Vervolgens krijgen we de if-statement:
n=2, de conditie n>1 is WAAR, dus gaan we de if-statement binnen:
tekenvierkantje roept nu eerst zichzelf zo aan (voor de linksboven rechthoek):
tekenvierkantje(1, 0, 0, 50, 40);
dit tekenvierkantje() bepaalt eerst zijn eigen xm en ym:
xm = 25
ym = 20
en maakt Rect(25, 0, 50, 20) wit.
nu is n=1, dus gaan we "if n>1 then" NIET binnen, en keren terug naar het oorspronkelijke tekenvierkantje().

Die roept opnieuw zichzelf aan, nu voor de linksonder rechthoek:
tekenvierkantje(1, 0, 40, 50, 80);
dit tekenvierkantje bepaalt eerst zijn eigen xm en ym:
xm = 25
ym = 60
en maakt Rect(25, 40, 50, 60) wit.
nu is n=1, dus gaan we "if n>1 then" NIET binnen, en keren terug naar het oorspronkelijke tekenvierkantje().

Tenslotte soortgelijk voor de benedenrecht rechthoek.
Daarna is de oorspronkelijke tekenvierkantje() klaar en stopt het programma.

De herhaling wordt dus volledig verzorgd door de recursie: zolang n>1 handelt elke rechthoek zijn sub-rechthoeken zelf af door een nieuwe aanroep van tekenvierkantje().

BusinessMath
Vast lid
Vast lid
Berichten: 57
Lid geworden op: 23 feb 2014, 15:14

Re: Programmeren Fractals tekenen

Bericht door BusinessMath » 02 apr 2014, 18:10

Ik snap het!
Bedankt!

ik had nog een zelfde soort opdracht, maar dan een tapijt tekenen.
Ik snap nu ook hoe dat moet, gaat eigenlijk op dezelfde manier

:mrgreen:
Durf te vragen!

Plaats reactie