Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Annäherung an Pi mit Monte carlo, paintbox (https://www.delphipraxis.net/165862-annaeherung-pi-mit-monte-carlo-paintbox.html)

Borgschüler 19. Jan 2012 10:12

Annäherung an Pi mit Monte carlo, paintbox
 
Guten Tag!

Habe morgen matura, habe ein Problem mit unserem Monte carlo Beispiel!

Und zwar schaut der Quelltext für mich ganz richtig aus, aber es wird nur die Hälfte von der Paintbox belegt und ich weis absolut nicht warum!

aber seht selbst:
Code:
procedure TForm1.Button1Click(Sender: TObject);
var i, count,x,y : integer;
begin
randomize;
count := 0;
for i := 1 to 100000 do
 begin
  x:= random(200);
  y:= random(200);
   if (sqrt(x*x+y*y) < 200) then
        paintbox1.canvas.pixels[x,y] := clred
     else
        paintbox1.canvas.pixels[x,y] := clgreen;
 end;
end;
Also die paintbox hat width/length jeweils 200. Das Problem ist nur, das Programm belegt nur exakt linke Hälfte, die eig ganz richtig ausschaut. Wenn ich duie paintbox 100 mal 100 mache (length width), dann scheint es zu funktionieren, problem ist nur dass es dann plötzlich kein richtiges quadrat mehr ist sondern ein rechteck.
Angefangen hab ich mit length/width 400/400, dann hate ich links einen streifen wo es funktioniert und rechts.

Ich dreh langsam durch. Kann es sein das width/length nicht die Pixel angibt?

Bitte dringend um Lösungsvorschläge und bitte nicht kleine Hinweise, damit ich dann selber draufkommen muss, weil ich probier schon verdammt lang um und komm einfach nicht auf die lösung... und morgen ist ja matura...


Pi ausgerechnet hab ich noch nicht, aber das dürfte dann kein problem sein.

einbeliebigername 19. Jan 2012 10:25

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Hallo,

nimm mal lieber ein TImage statt dem TPaintBox. Bei einer PaintBox verschwindet das was man nicht im OnPaint zeichnet wieder, wenn es neugezeichnet werden soll. Das könnte schon dein Problem sein, weil irgend was die PaintBox zum teilweisen Neuzeichnen bringt.

Einbeliebigername.

Klaus01 19. Jan 2012 10:34

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Hallo,

bitte randomize nur einmal (beim Programmstart) aufrufen.

Was bezweckst du mit?
Delphi-Quellcode:
if sqrt(x*x + y*y) < 200 then
Grüße
Klaus

Borgschüler 19. Jan 2012 10:37

AW: Annäherung an Pi mit Monte carlo, paintbox
 
hmm in der schule haben wir das immer mit der paintbox gemacht.

randomize wird im button eh nur einmal aufgerufen. wenn ich es bei formcreate reinschreibe, ändert isch leider garnichts. er macht irgendwie immer nur die hälfte von der paintbox. es sei denn du machst die paintbox richtig klein, aber das kanns auch nicht sein!

Klaus01 19. Jan 2012 10:41

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Delphi-Quellcode:
 if (sqrt(x*x+y*y) < 200)
->
Delphi-Quellcode:
if sqrt(sqr(x)+sqr(y)) <= sqrt(sqr(paintbox.width)+(sqr(paintbox.heigth)) then
  //im radius
else
 //asserhalb des Radius


Grüße
Klaus

einbeliebigername 19. Jan 2012 10:53

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Hallo,

Zitat:

Zitat von Klaus01 (Beitrag 1146639)
Delphi-Quellcode:
if sqrt(sqr(x)+sqr(y)) <= sqrt(sqr(paintbox.width)+(sqr(paintbox.heigth)) then

Das ist aber nicht im Sinne des Erfinders. Denn damit ist der Radius des Kreis so groß wie die Diagonale der PaintBox. Das hat dann die Folge, dass alle Punkte, die man sieht, innerhalb des Kreises liegen. Besser ist das:
Delphi-Quellcode:
  R:= Min(paintbox.width, paintbox.heigth)
  ...
    x:= random(R);
    y:= random(R);
    if (sqrt(x*x+y*y) < R) then
  ...
Einbeliebigername.

TiGü 19. Jan 2012 10:53

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Liste der Anhänge anzeigen (Anzahl: 1)
Wie soll es denn richtig aussehen?
Wenn ich deinen Code ausführe, dann kommt das bei rum:

guinnes 19. Jan 2012 11:10

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Zitat:

Zitat von TiGü (Beitrag 1146642)
Wie soll es denn richtig aussehen?

Genau so ! : http://de.wikipedia.org/wiki/Monte-Carlo-Simulation

Borgschüler 19. Jan 2012 11:16

AW: Annäherung an Pi mit Monte carlo, paintbox
 
tigü ja genau, so soll es aussehen!
tigü, hast du meinen quelltext imn ersten beitrag eins zu eins übernommen?
hmm, dann probier ich mal, den radius mit paintbox width auszudürcken!

EDIT: Ich werd noch wahnsinnig, jetzt hab ich < paintbox1.width und es geht immer noch nicht!


übrigens:

als zum berechnen von pi dachte ich mir

K/Q = 200²Pi/200²

erklärung: Verhältnis der punkte von Kreis und Quadrat(gesamtes) = verhältnis von Viertelkreisgleichung mit festgelegtem radius und fläche von quadrat

und daraus drück ich mir aus:

K/Q mal 4 = Pi

Borgschüler 19. Jan 2012 11:21

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Liste der Anhänge anzeigen (Anzahl: 1)
so so schaut das aus bei mir, siehe anhang

Valle 19. Jan 2012 11:27

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Kann es sein dass die Paintbox auf dem Formular einfach zu klein ist?

Liebe Grüße,
Valentin

DeddyH 19. Jan 2012 11:32

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Vielleicht legt sich kurz ein anderes Fenster drüber. Verschieb das Zeichnen doch mal ins OnPaint der PaintBox, da gehört es ja auch hin. Bei mir wird die Grafik auch korrekt dargestellt.

[edit] Meine Änderungen:
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure PaintBox1Paint(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
    FPainting: Boolean;
  public
    { Public-Deklarationen }
  end;

...

procedure TForm1.Button1Click(Sender: TObject);
begin
  paintbox1.Width := 200;
  paintbox1.Height := 200;
  FPainting := not FPainting;
  PaintBox1.Invalidate;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  randomize;
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
  i,x,y : integer;
begin
  if FPainting then
    for i := 1 to 100000 do
      begin
        x:= random(200);
        y:= random(200);
        if (sqrt(x*x+y*y) < 200) then
          paintbox1.canvas.pixels[x,y] := clred
        else
          paintbox1.canvas.pixels[x,y] := clgreen;
      end
  else
    PaintBox1.Canvas.FillRect(Rect(0, 0, PaintBox1.Width, PaintBox1.Height));
end;
[/edit]

Borgschüler 19. Jan 2012 11:47

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Liste der Anhänge anzeigen (Anzahl: 3)
Liebe Leute, je nach dem wo die paintbox platziert ist, ist ein anderer teil zu sehn, bzw an einer stelle sieht man wirklich ein perfektes quadrat! aber seht selbst.

Wie kann das bitte sein? geht garnicht in meinen kopf!

ich werde jetzt die pi berechnung durchführen, und dann das ergebnis präsentieren.

einbeliebigername 19. Jan 2012 12:04

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Hallo,

Zitat:

Zitat von DeddyH (Beitrag 1146651)
Vielleicht legt sich kurz ein anderes Fenster drüber.

Das sehe ich auch so. Denn wenn man folgendes liest, kann es doch nur so sein das die Paintbox teilweise neugezeichnet wird.
Zitat:

Zitat von Borgschüler (Beitrag 1146628)
Angefangen hab ich mit length/width 400/400, dann hate ich links einen streifen wo es funktioniert und rechts.

Und dieses mögliche Problem sollte gelöst werden.

Zitat:

Zitat von DeddyH (Beitrag 1146651)
Delphi-Quellcode:
procedure TForm1.PaintBox1Paint(Sender: TObject);
var
  i,x,y : integer;
begin
  if FPainting then
    for i := 1 to 100000 do
      begin
        x:= random(200);
        y:= random(200);
        if (sqrt(x*x+y*y) < 200) then
          paintbox1.canvas.pixels[x,y] := clred
        else
          paintbox1.canvas.pixels[x,y] := clgreen;
      end
  else
    PaintBox1.Canvas.FillRect(Rect(0, 0, PaintBox1.Width, PaintBox1.Height));
end;

Gut das ist jetzt eine der aufwendigeren Lösungen. Diese hat aber einige Probleme. Da
Delphi-Quellcode:
random(200)
immer wieder andere Werte liefert, würde bei jedem neuzeichnen sich das Bild ändern. Dann dauert ein Neuzeichnen wegen
Delphi-Quellcode:
for i := 1 to 100000 do
auch etwas länger. Und ich denkt der TE ist mit dem Algorithmus auch noch nicht fertig. Es ist ja erst mal nur die Visualisierung. Da fehlt ja noch das Ausrechnen von PI.

Zitat:

Zitat von Borgschüler (Beitrag 1146653)
Liebe Leute, je nach dem wo die paintbox platziert ist, ist ein anderer teil zu sehn, bzw an einer stelle sieht man wirklich ein perfektes quadrat! aber seht selbst.

Wie kann das bitte sein? geht garnicht in meinen kopf!

ich werde jetzt die pi berechnung durchführen, und dann das ergebnis präsentieren.

Da wird vermutlich ein Streifen des Formulars, mit allem was sich in diesem befinde, nach dem Button1Click fertig ist neugezeichnet. Probiere doch mal in deiner Variante die PaintBox durch ein Image zu ersetzen. Die TImage-Komponente hat auch eine Canvas Eigenschaft und lässt sich in deinem Fall wie eine PaintBox verwenden. Hat aber den Vorteil, dass sie sich merkt was gezeichnet wurde und beim Neuzeichen das wieder herstellt.

Einbeliebigername.

Borgschüler 19. Jan 2012 12:10

AW: Annäherung an Pi mit Monte carlo, paintbox
 
OK es klappt, Pi ist zwar relativ ungenau, aber das hat die monte carlo methode so ansich!

Aber kann mir vl jemand erklären, warum ich soviel rumprobieren musste, damit das ganze quadrat zu sehen ist?

Code:
procedure TForm1.Button1Click(Sender: TObject);
var i, count,x,y : integer;
pi : real;
begin
count := 0;
for i := 1 to 100000 do
 begin
  x:= random(200);
  y:= random(200);
   if (sqrt(x*x+y*y) < paintbox1.width) then
      begin
        count := count +1;
        paintbox1.canvas.pixels[x,y] := clred;
      end
      else
        paintbox1.canvas.pixels[x,y] := clgreen;
 end;
 pi := (4*count/100000);
 Label1.caption:= floattostr(pi);

TiGü 19. Jan 2012 12:34

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Zitat:

Zitat von Borgschüler (Beitrag 1146659)
Aber kann mir vl jemand erklären, warum ich soviel rumprobieren musste, damit das ganze quadrat zu sehen ist?

Sollen wir jetzt schreiben, dass du es vorher nicht gerafft hast, oder wie? :twisted:

1. war bei dir wahrscheinlich die Eigenschaften Width und Height (Length gibts nicht!) der Paintbox nicht auf 200 gesetzt (gut in den Screenshots weiter oben zu sehen) und du aber
2. immer konstant auf 200 anstatt wie jetzt auf Width verglichen hast.

Würde übrigens an der Stelle der If-Abfrage das Ergebnis der Wurzel noch per Round() runden, ansonsten werden Gleitkommazahlen mit Integerzahlen
verglichen, was nicht immer gut gehen muss. Der Kompiler castet zwar, aber ich hätte ein sicherers Gefühl.

Ansonsten die anderen Vorschläge mit einarbeiten!

einbeliebigername 19. Jan 2012 12:47

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Hallo,

Zitat:

Zitat von Borgschüler (Beitrag 1146659)
Aber kann mir vl jemand erklären, warum ich soviel rumprobieren musste, damit das ganze quadrat zu sehen ist?

Ich habe doch schon geschrieben was vermutlich passiert. Und ansonsten liegt es an der falschen Benutzung der PaintBox. Schreib mal am Ende von Button1Click noch die Zeile
Delphi-Quellcode:
paintbox1.Invalidate;
(bzw.
Delphi-Quellcode:
paintbox1.Repaint;
kannst du auch mal ausprobieren) hin. Und dann schreib hier mal was passiert und was du denkst wieso.

Einbeliebigername.

Borgschüler 19. Jan 2012 12:59

AW: Annäherung an Pi mit Monte carlo, paintbox
 
ok wenn ich paintbox1.invalidate oder paintbox1.repaint schreibe, verschwindet das gezeichnete. ich erklär mir das dadurch, dass die paintbox in den urzustand versetzt wird??

auf jedenfall danke leute, für die ganzen vorschläge!

einbeliebigername 19. Jan 2012 13:35

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Hallo,

Zitat:

Zitat von Borgschüler (Beitrag 1146681)
ich erklär mir das dadurch, dass die paintbox in den urzustand versetzt wird??

Ne, Falsch. Invalidate und Repaint bewirken das sich die PaintBox neuzeichnet. Beim Neuzeichnen geht die PaintBox immer wie folg vor:
1. Füllen der Zeichenfläche mit der Farbe, die bei Color angegeben ist
2. Auslösen des Ereignisses OnPaint

Da bei dir aber keine Behandlung dieses Ereignisses existiert wird auch nichts gezeichnet und die PaintBox bleibt leer. Das was man mit Invalidate und Repaint selbst auslösen kann, stößt auch Windows von sich aus an. Windows lässt sich an dieser Stelle aber nur schwer kontrollieren. Man muss immer daran denken, dass jederzeit Windows auf die Idee kommen kann, das komplette oder teilweise Neuzeichen eines Fensters anzustoßen. Auch die VCL löst unter Umständen das Neuzeichnen aus

Einbeliebigername.

Aphton 19. Jan 2012 14:23

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Nenenenene..

Also es liegt daran, weil deine Paintbox nicht quadratisch ist (die Positionierung hat damit also nichts zu tun, sondern die Dimensierung)

Mach einfach folgendes irgendwo zu Beginn der Anwendung (FormCreate)
Delphi-Quellcode:
  PaintBox1.Width := 250;
  PaintBox1.Height := PaintBox1.Width;
Edit (Erklärung, warum):
Zitat:

Delphi-Quellcode:
   if (sqrt(x*x+y*y) < 200) then

Heißt soviel wie, wenn die Länge des Richtungsvektors A (x, y) (x, y relativ zum Ursprung -> bei der Paintbox ist es die linke obere Ecke) < 200, dann markiereden Pixel bei aX, aY rot, sonst grün.

200 ist dein Radius. Wenn du eine Paintbox benützen willst, die nicht quadratisch ist (was ja, wenn man ein Kreis "einzeichnen" will, sinnlos ist), dann müsstest statt 200 die kleinere Dimensionskomponente der Paintbox nehmen - sei es nun Width oder Height -> damit der ganze Kreis anschließend auch sichtbar wird!

shmia 19. Jan 2012 15:33

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Mal was ganz Grundsätzliches

Eine Paintbox ist eine flüchtige Zeichenfläche.
Sobald eine Paintbox durch ein anderes Fenster überdeckt und wieder aufgedeckt wird,
ist der aufgedeckte Bereich "kaputt".

Will man eine TPainbox für die Ausgabe von Monte Carlo Punkten verwenden
muss man alle bisherigen Punkte in einem Array oder Liste zwischenspeichern.
Wenn dann das OnPaint-Event ausgelöst wird, muss man alle Punkte aus dem Array neu zeichnen.

Die Lösung von DeddyH geht auch in Ordnung; nur bekommt man nach jedem Aufdecken eine
neue Punktewolke.

Will man diesen Aufwand nicht betreiben sollte man TImage für die Ausgabe verwenden.

Borgschüler 19. Jan 2012 18:03

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Hallo!

Also das komische ist, ich seh kein fenster das über der paintbox auch nur kurz sein könnte. Zudem wird ja erst durch den button klick gezeichnet.

Ich habe jetzt das selbe problem bei einem sierpinski dreieck, man sieh wenn überhaupt nur 3 pixel und wenn ich den befehl paintbox1.repaint gebe, dann flackern die drei punkte einfach nur!

in der schule (windows xp) hats die probleme nie gegeben...

überhaupt versteh ich hier die meisten vorschläge nicht, kann mir einer bitte sagen wie ich das mit deiner paintbox hinbekomme und nicht mit einem image, weil das wird bei mir vom lehrer verlangt...

einbeliebigername 19. Jan 2012 19:51

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Hallo,
Zitat:

Zitat von Borgschüler (Beitrag 1146749)
Also das komische ist, ich seh kein fenster das über der paintbox auch nur kurz sein könnte.

Muss ja auch kein Fenster darüber sein. Eine Aufforderung von Windows reicht aus damit sich die PaintBox neuzeichnet.

Zitat:

Zitat von Borgschüler (Beitrag 1146749)
Ich habe jetzt das selbe problem bei einem sierpinski dreieck, man sieh wenn überhaupt nur 3 pixel und wenn ich den befehl paintbox1.repaint gebe, dann flackern die drei punkte einfach nur!

Wie sieht denn da jetzt der Sourcecode aus?

Zitat:

Zitat von Borgschüler (Beitrag 1146749)
in der schule (windows xp) hats die probleme nie gegeben...

Unter welchem Betriebssystem arbeitest du denn jetzt? Und mit welcher Delphi-Version?

Zitat:

Zitat von Borgschüler (Beitrag 1146749)
überhaupt versteh ich hier die meisten vorschläge nicht, kann mir einer bitte sagen wie ich das mit deiner paintbox hinbekomme und nicht mit einem image, weil das wird bei mir vom lehrer verlangt...

Was hat euch den der Lehrer gezeigt, wie ihr mit der Paintbox arbeiten sollt? Er wird euch doch mal Beispiel-Sourcecode gezeigt haben.


Einbeliebigername.

Luckie 19. Jan 2012 20:02

AW: Annäherung an Pi mit Monte carlo, paintbox
 
Zitat:

Zitat von shmia (Beitrag 1146728)
Wenn dann das OnPaint-Event ausgelöst wird, muss man alle Punkte aus dem Array neu zeichnen.

Üblicherweise zeichnet man aber auf ein Bitmap im Speicher und kopiert es bei Bedarf auf die Zeichenfläche.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:19 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz