Entwickler-Ecke

Multimedia / Grafik - Floodfill darstellen


roKR-91 - Do 10.12.09 21:37
Titel: Floodfill darstellen
hi...wir sollen inner schule (12te klasse) den FloodFill-algorithmus grafisch darstellen

einmal mir 4er nachbarschaft und dann mit 8er nachbarschaft...
hab das formular soweit fertig...jetz brauch ich "nur noch" das raster zeichnen (was nich das prob is) und dann ein objekt ausfüllen...und genau daran scheitert's das theoretische...also das was man rechnet geht alles soweit...ich weiß nur nich wie ich das grafisch umsetzen soll...hab i-wie keinen ansatz...

wär echt super wenn mir jemand sagen könnte wie ich das machen kann...danke schonmal im voraus ;)


Horst_H - Fr 11.12.09 12:54

Hallo,

wenn Du schon ein Raster hast und mit Floodfill loslegst, mußt Du doch nur innerhalb der floodfill-Routine ein paar Zeichenoperationen ausführen.
Wenn ein Feld getestet wird, die Farbe merken, das Feld auf dem Bildschirm zum Beispiel schwarz umranden ( Rechteck) ,etwas warten ~200 ms, Umrandung mit gemerkter Farbe löschen und weiter im Text, wenn das Feld eingefärbt wird, dies auch auf dem Bildschirm machen.

Gruß Horst


ene - Fr 11.12.09 13:08

Moin,

Für das Raster gilt doch, dass jedes Element 3 Zustände haben kann. 0 = Nicht aktiv, 1 = aktiv, 2 = Grenze. Wenn die Grenze wegfällt wirds noch einfacher.

Du beginnst als an einem Startpunkt und markierst eben die Punkte als aktiv, die es werden können:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
Procedure FloodFill(Const x,y: Integer);
Begin
  Raster[x, y] := 1;
  If (Raster[x+1,y  ]= 0Then FloodFill(X+1, Y  );
  If (Raster[x-1,y  ]= 0Then FloodFill(X-1, Y  );
  If (Raster[x  ,y+1]= 0Then FloodFill(X  , Y+1);
  If (Raster[x  ,y-1]= 0Then FloodFill(X  , Y-1);
End;


Das ist Rekursiv und ruft alle umliegenden Punkte, die 0 sind auf. Beim Eintritt in dieses Element wird es zu 1. Was dabei noch fehlt ist die Begrezung da x und y nicht kleiner 0 sein können und nicht größer als dein Raster.


roKR-91 - Di 05.01.10 17:39

also ich hab mich in den ferien damit jetz gründlich beschäftigt...ich denk den rest krieg ich hin...lediglich an einer sache bin ich am verzweifeln...ich hab hier jetz son gebilde wo ich das floodfill drin ausführe...siehe bild...und da soll jetz halt noch ne diagonale (rote makierung) um die 8er nachbarschaft darzustellen...aber wie zeichne ich möglichst kurz ne diagonale??? klar ich könnte jetz jeden punkt einzeln füllen aber ich würd das gern so kurz wie möglich halten...


ub60 - Di 05.01.10 18:36

Da empfehle ich mal Bresenham http://de.wikipedia.org/wiki/Bresenham-Algorithmus

ub60


roKR-91 - Di 05.01.10 19:22

so ich hab jetz den wiki-bresenham der in basic geschrieben war in delphi geschrieben

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure p_brese (xa, xe, ya, ye : integer);
var x, y, dx, dy : integer;
    fehler : real;
    begin
      dx := xe - xa;
      dy := ye - ya;

      x := xa;
      y := ya;
      setpixel(x,y);
      fehler := dx/2;

      while x < 423 do
        x := x+1;
        fehler := fehler - dy;
        if fehler < 0 then
         begin y := y + 1;
               fehler := fehler + dx end;
      setpixel (x,y);
end;

und als aufruf :


Delphi-Quelltext
1:
p_brese(330,423,220,313);                    


jetz krieg ich aber die fehlermeldungen:

"[Fehler]Unit1.pas(10): Nicht genügend wirkliche Parameter" und
"[Fehler]Unit1.pas(19): Nicht genügend wirkliche Parameter"


Flamefire - Di 05.01.10 19:38

ich nehme mal an (sry meine zauberkugel ist etwas verstaubt) das zeile 10 und 19 die setPixel() aufrufe sind
es wäre also gut, wenn du die zugehörige funktionen noch mit postest.
ebenfalls angenommen (wieder die zauberkugel) ist, dass da einfach nur die farbe fehlt.

wenn du aber nur direkt diagonale linien zeichen willst (also abstand in x und y richtung ist gleich) brauchst du das nicht...
dann gehst du einfach in jedem schritt je 1 pixel in richtung des ziels in auf jeder achse


Christian S. - Di 05.01.10 19:40

Damit die while-Schleife einen Sinn ergibt, dürfte da auch noch ein begin .. end hingehören.


roKR-91 - Di 05.01.10 20:28

erstens: danke wegen der while schleife^^
zweitens: wie dumm kann man sein die farbe zu vergessen :D omg mein fehler...zumal es ja in der eingabehilfe steht :D
allerdings will die eingabehilfe folgendes : DC:HDC; x : integer; y : integer; color : cardinal

was is DC:HDC ???
und welche funktion meinst du? den aufruf hatte ich doch mit drin?

hier der ganze quelltext...


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, Buttons, ExtCtrls;

type
  TForm1 = class(TForm)
    PageControl1: TPageControl;
    BitBtn1: TBitBtn;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    BitBtn2: TBitBtn;
    RadioGroup1: TRadioGroup;
    Button1: TButton;
    Linie1: TPanel;
    Kreis1: TPanel;
    ComboBox1: TComboBox;
    Panel1: TPanel;
    Button2: TButton;
    bild: TImage;
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure p_figur (a,b : integer);
begin
  with form1.bild.Canvas do
  begin brush.color := clblack;
        Floodfill(a,b,clblack,fsBorder);
        end;
end;

procedure p_brese (xa, xe, ya, ye : integer);
var x, y, dx, dy : integer;
    fehler : real;
    begin
      dx := xe - xa;
      dy := ye - ya;

      x := xa;
      y := ya;
      setpixel(
      fehler := dx/2;

      while x < 423 do
        begin x := x+1;
              fehler := fehler - dy;
              if fehler < 0 then
                begin y := y + 1;
                      fehler := fehler + dx end;
              setpixel (x,y,clblack);
        end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var xa,xe, ya, ye, x, y, i : integer;
begin
  with form1.bild.Canvas do
    begin
  //zuweisen der Werte
  xa := 0;
  ya := 0;
  xe := bild.width;
  ye := bild.height;
  x := 8;
  y := 8;

  Rectangle(0,0,bild.Width,Bild.Height);
  //horizontale linien
  while y < Bild.Height do
    begin
      moveto(xa,y);
      lineto(xe,y);
      y := y+8;
     end// of while
  //vertikale linien
  while x < Bild.Width do
    begin
      moveto(x,ya);
      lineto(x,ye);
      x := x+8;
     end;//of while
    // FIGUR ZEICHNEN

  for i := 51 to 313 do
    p_figur (141,i);
  for i := 141 to 470 do
    p_figur (i,313);
  for i := 313 downto 220 do
    p_figur (470,i);
  for i := 470 downto 245 do
    p_figur (i,220);
  for i := 220 downto 51 do
    p_figur (245,i);
  for i := 245 downto 141 do
    p_figur (i,51);
  // begrenzungen innerhalb der figur
  for i := 141 to 245 do
    p_figur (i,130);
  p_brese(330,423,220,313);    // diagonale linie für 8er nachbarschaft

  end//of canvas

end;// of procedure

end.


"[Fehler]Unit1.pas(55): Nicht genügend wirkliche Parameter" und
"[Fehler]Unit1.pas(64): Nicht genügend wirkliche Parameter


Flamefire - Di 05.01.10 20:39

ich glaube dc ist das handle der bitmap. also bitmap.handle
oder es gibt direkt ein bitmap.dc

probiers aus ^^

alternativ: bitmap.pixels[x,y]:=clBlack; (oder bitmap.canves.pixels hab grad kein delphi da)


roKR-91 - Di 05.01.10 20:58

super...habs jetz hinbekommen...soll heißen er zeichnet jetz eine dünne linie...muss da jetz bloß noch n bissl mit floodfill rumexperimentieren und dann passt das schon...danke jungs...vorallem dir flamefire :)


roKR-91 - Mi 06.01.10 21:42

kann mir mal bitte jmd den post von ene erklären??? was soll das "raster" da sein ???? da blick ich nich durch...außerdem...warum geht das nich? :

Delphi-Quelltext
1:
2:
3:
4:
5:
begin
if form1.bild.Canvas.Pixels[x,y] = clwhite then
 repeat Floodfill(x,y,clblack,fsBorder);
        x := x+8;
 until form1.bild.Canvas.Pixels[x,y]= clblack;


der meckert bei der zeile mit dem floodfill rum..."inkompatible typen: 'Cardinal' und 'TFillStyle' "

weiter oben hab ich die zeile mit dem floodfill genau so stehen und da geht...und funzt auch im programm


Flamefire - Mi 06.01.10 22:23

"Raster ist einfach die pixelmatrix. in dem fall also die "pixels" eigenschaft.
als erstes würde ich floodfill in eine neue zeile schreiben

wie sieht denn die deklaration von floodfill und fsBorder aus? ich vermute da stimmt was nicht.
oder die argumente vertauscht.


roKR-91 - Do 07.01.10 09:01

also mit dem floodfil geht jetz...es fehlte das "form1.bild.canvas." und dann einfach floodfill(x,y,clblack,fsborder)


roKR-91 - Di 09.02.10 00:14

ich weiß nich woran es liegt...kriegs einfach nich hin...sitz da jetz bestimmt schon 5-6 stunden dran...es will einfach nich...soweit bin ich bis jetz gekommen


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure p_flood4 (x,y : integer);
var dx, dy : integer;
begin
  //dx und dy dem raster anpassen
  dx := form1.UpDown1.position + 8;
  dy := form1.UpDown1.position + 8;

if form1.bild.Canvas.Pixels[x,y] = clwhite then
  begin
    form1.bild.Canvas.brush.color := clblack;
    form1.bild.Canvas.Floodfill(x,y,clblack,fsBorder);
   repeat
     begin p_flood4[x+dx, y];
           p_flood4[x-dx, y];
           p_flood4[x, y+dy];
           p_flood4[x, y-dy]
     end// of repeat

   until form1.bild.Canvas.Pixels[x,y]= clblack;
  end;
end;//of procedure p_flood4


prozeduraufruf sieht so aus


Delphi-Quelltext
1:
p_flood4(170,200);                    



die zeilen

p_flood4[x+dx, y];
p_flood4[x-dx, y];
p_flood4[x, y+dy];
p_flood4[x, y-dy]

bemängelt er das er nich genügend parameter hat...ich weiß echt nichmehr was er von mir will...eig dachte ich das ich das so rekursiv geschrieben hab...aber es klappt einfach nich... -.-
wenn ihr noch nähere infos braucht fragt einfach...ich werd euch gern mein projekt näher bringen...


platzwart - Di 09.02.10 00:25

( anstatt [ verwenden...


roKR-91 - Di 09.02.10 13:22

lol...tatsächlich...son scheiß :D immer solche kleinigkeiten...ohoh...schlimm schlim...dank dir


roKR-91 - Do 11.03.10 18:51

hey ich hab nochmal ne schönheits frage zum floodfill...also das funzt bei mir jetz vollständig...hab jetz auch mit einer pause zwischen den schritten gearbeitet um das etwas anschaulicher zu machen...jetz fehlt nur noch das sahnehäubchen.

und zwar hab ich mir überlegt das es doch schön wäre wenn der pixel (bzw. das kästchen) wo sich der algorithmus grade befindet in einer anderen farbe dargestellt wird...wollte das so machen das der 2x floodfill ausführt (das zweite zeitversetzt)...und das dann übereinander zeichnet...somit wäre das erste kästchen sagen wir mal hellblau und die anderen dunkelblau...wo muss ich dann den 2ten lauf des floodfill hinschreiben ???

hier mal mein floodfill mir 4er nachbarschaft:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
procedure p_flood4 (x,y : integer);
var dx, dy : integer;
begin
  //dx und dy dem raster anpassen
  dx := form1.UpDown1.position + 8;
  dy := form1.UpDown1.position + 8;

if form1.bild.Canvas.Pixels[x,y] = clwhite then
  begin
    form1.bild.Canvas.brush.color := claqua;
    form1.bild.Canvas.Floodfill(x,y,clblack,fsBorder);
   repeat
     begin 
           p_pause(30);
           p_flood4(x+dx, y);
           p_pause(30);
           p_flood4(x-dx, y);  
           p_pause(30);
           p_flood4(x, y+dy);  
           p_pause(30);
           p_flood4(x, y-dy);   
           p_pause(30);
     end// of repeat

   until form1.bild.Canvas.Pixels[x,y]= claqua;
  end// of if
end;//of p_flood4


platzwart - Do 11.03.10 19:03


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
procedure p_flood4 (x,y : integer);
var dx, dy : integer;
begin
  //dx und dy dem raster anpassen
  dx := form1.UpDown1.position + 8;
  dy := form1.UpDown1.position + 8;

if form1.bild.Canvas.Pixels[x,y] = clwhite then
  begin
    form1.bild.Canvas.brush.color := claqua;
    form1.bild.Canvas.Floodfill(x,y,clblack,fsBorder);
    p_pause(30);
    form1.bild.Canvas.brush.color := clRed;
    form1.bild.Canvas.Floodfill(x,y,clblack,fsBorder);
    p_pause(30);
    form1.bild.Canvas.brush.color := claqua;
    form1.bild.Canvas.Floodfill(x,y,clblack,fsBorder);
    p_pause(30);

   repeat
     begin 
           p_pause(30);
           p_flood4(x+dx, y);
           p_pause(30);
           p_flood4(x-dx, y);  
           p_pause(30);
           p_flood4(x, y+dy);  
           p_pause(30);
           p_flood4(x, y-dy);   
           p_pause(30);
     end// of repeat

   until form1.bild.Canvas.Pixels[x,y]= claqua;
  end// of if
end;//of p_flood4



Vielleicht so probieren? Dann blinkt der Pixel einmal Rot...


roKR-91 - Do 11.03.10 21:14

hey das is soweit schonmal sehr gut...danke...nur leider sieht man es nich mehr blinken wenn er das 2te mal über ein kästchen geht...aber sonst is das schonmal so wie ich mir das gedacht hab