# komplexe Flächen ausfüllen



## Xym (10. Mai 2011)

Hi Leute, 

ich wollte meinem Zeichenprogramm die Möglichkeit hinzufügen jede Fläche die man zeichnen auszufüllen, wie bei Paint.

Dazu habe ich schon ein paar Gedanken gemacht und habe versuch zu vor zu gehen : 

1)  Die Farbe des Pixel beschaffen aus dem man klickt.

```
//Der Teil ist in der mousePressed-Methode
try 
{
        Robot robot = new Robot();
        
        // pos.x und pos.y sind die Postion des Fenster aus dem Bildschirm, 
        // weil die Methode den Punkt 0, 0 links oben ist.
        color = robot.getPixelColor(e.getX() + pos.x, e.getY() + pos.y);
        
        // Rekursive Methode			 
        füllen(e.getX(), e.getY(), color);
} 
catch (AWTException e) 
{
        e.printStackTrace();
}
```

2) Eine rekursive Methoder schreiben. In der soll von dem 1. Pixel an nach alle Pixel neben an gesucht werden und in der anderen Farbe ausfüllen. Und dann vom nächsten Pixel.
Doch hier ist auch mein Problem.
Ich habe versucht die Methode zu schreiben doch ich weiß nicht nach dem ich 1 Pixel geprüft habe, in welche Richtung ich weiter gehen soll.

Hoffe ihr könnt mir helfen!


----------



## Maik639 (10. Mai 2011)

ich würde dir vorschlagen so zu gehen:
|-----------------
|
|
|
|
danach so:
|-----------------
||----------------
||
||
||

usw...

Grüße Maik


----------



## Xym (10. Mai 2011)

Irgendwie verstehe ich nicht was du damit sagen willst..
Kann mir bitte das wer mit Worten erklären ?


----------



## Akeshihiro (10. Mai 2011)

Er meint damit, dass du Zeile für Zeile vorgehen sollst, jedenfalls vermute ich das.


----------



## Xym (10. Mai 2011)

Ach so , aber ich will mit der Methode jede Form ausfüllen die geschlossen ist. Und ich glaube das es so nicht funktioniert.
Als Beispiel habe ich ein Bild im Anhang. Wenn man dort hinklick wo das Kreuz soll sich alles ausfüllen.

Hoffe nun, dass klar ist was ich meine.


----------



## MiMi (11. Mai 2011)

1. von X aus, nach rechts bis zu der Line. 
2. von X aus, nach links bis zur Linie. 
Danach schaust ob unter dem Punkt der Pixel auch frei ist, dann 1 und 2 nochmal. 

Ob das effektiv ist? Keine Ahnung ^^


----------



## Maik639 (11. Mai 2011)

Ich denke ich habe die lösung 

Man soltle so vorgehen, wie es auf diesem Bild zu sehen ist:
http://root-space.eu/file/6wvf8itn

Der weiße Punkt ist der Punkt auf den der User gelickt hat, nun betrachtet man die 8 (orange) Pixel daneben und überprüft diese wieder auf Farbgleichheit, sollten diese auch gleich sein, so ändert man die Farbe.
Nun überprüft man von jedem der 8 Pixel die Pixel daneben, dies sieht dann so aus:
http://root-space.eu/file/bgoafwzg

Danach wiederholt man das ganze, dann wird es so aussehen:
http://root-space.eu/file/7564n016

und das wiederholt man immer wieder.

So sollte es klappen.

Grüße Maik


----------



## MiMi (11. Mai 2011)

Kannst du die Bilder nicht einfach als Anhang machen? Ich kann die Links zb nicht oeffnen oder es dauert ewig? Keine Ahnung.


----------



## SE (11. Mai 2011)

Dann nützt dir ein Anhang auch nichts weil das auch ein Link ist den du öffnen musst der dann auch so ewig braucht xD


----------



## MiMi (11. Mai 2011)

Nein, direkt uebers Forum als Anhang, mein ich. Bei externen Hostern ist wird es ja sowieso geloescht nach einer Zeit.
Wie Xym das mit seinem "Beispiel" gemacht hat


----------



## Maik639 (11. Mai 2011)

Hier sind die Datein als Anhänge.

Grüße Maik


----------



## SE (11. Mai 2011)

MiMi hat gesagt.:


> Nein, direkt uebers Forum als Anhang, mein ich. Bei externen Hostern ist wird es ja sowieso geloescht nach einer Zeit.
> Wie Xym das mit seinem "Beispiel" gemacht hat



Achso ... ja sorry ... ich war wieder doof =D


----------



## Xym (11. Mai 2011)

Danke für die Antworten!

Ich habe mich entschieden den Vorschlag von MiMi umzusetzen , denn bei Maik's Vorschlag glaube ich , dass es zu Problem bei Kreisen kommt.

Doch wenn ich nur alle Pixel nach x ausfülle dauter es ewig! 

hier der Quellcode:

Aus der mousePressed - Methode

```
try 
{  
    //Farbe vom den Pixel auf den man klickt      			
    color = r.getPixelColor(e.getX() + pos.x, e.getY() + pos.y);
        			 
     füllen(e.getX(), e.getY(), color);
}
```

füllen-Mehtode

```
public void füllen(int x, int y, Color color) throws AWTException
    {
    	
    	if(suchXrechts == true)
    	{
                //Vergleich der Farben
    		if(pixelfarbe(x+1, y).equals(color))
    		{
    			gOffScreen.setColor(farbe);
                        //Pixel wird auf's BufferedImage gemalt
    			gOffScreen.fillRect(x+1, y, 1, 1);
    			x++;
    			System.out.println(x);
    			füllen(x, y, color);
    		}
    		else
    			suchXrechts = false;
    	} 
    }
```

und wie ich and die pixelfarbe komme

```
public Color pixelfarbe(int x, int y) throws AWTException 
    {
		Color pixelcolor = r.getPixelColor(x + pos.x, y + pos.y);
		
    	return pixelcolor;
    }
```

Ich hoffe ihr habt eine Idee wie es schneller geht!
Denn wenn ich die ganze Methode so zu Ende schreibe dauert es am Ende Minuten! Und dann kann ich es komplett vergessen.

PS: Es liegt auf keinen Fall an meinem PC!!


----------



## Maik639 (11. Mai 2011)

Nunja es hat gedauert bis ich mich zu meiner Methode entschlossen habe, mit der die du jetzt nutzen willst, wirst du vermutlich diese Form nicht ausfüllen können....
http://root-space.eu/file/irw8kqvu
oder diese 
http://root-space.eu/file/kb1bwn1e


----------



## Xym (11. Mai 2011)

Stimmt... an solche Formen dachte ich nicht...
Nur ich habe keine Idee wie ich dann die Methode aufbauen soll..
Könnt ihr mir da helfen ?


----------



## SE (11. Mai 2011)

Na warum soll man denn solche Formen nicht ausfüllen können ?
Mit Rekursion wäre das kein Problem. Warum denn nur vom MousePoint ausgehen ? einfach so lange rekursiv durchgehen bis man die Ränder erreicht hat. Das funktioniert in jede Richtung.


----------



## Muepe32 (11. Mai 2011)

Dieses Konzept hier ist ein simpler Ansatz wie du beliebige auf Polygonen basierende Flächen (das sind natürlich alle, da du ja Pixel als finite Minimalgrösse hast) füllen kannst:
http://www.cosc.canterbury.ac.nz/mukundan/cogr/Fill.html

Hier findest du noch einen anderen bekannten Ansatz via Flood Fill:
http://www.codeproject.com/KB/GDI/QuickFill.aspx


----------



## MiMi (12. Mai 2011)

@ externe Hoster
Funktioniert immer noch nicht, warum nicht foruminterne Anhaenge -.-

@Muepe
Ja der erste Link, das sieht relativ logisch aus


----------



## Xym (12. Mai 2011)

Danke Muepe32 für die Links! Waren echt hilfreich.

Habe die Methode so übernommen:


```
public void füllen(int x, int y, Color color) throws AWTException
    {
    	if(pixelfarbe(x,y).equals(color))
    	{
    		gOffScreen.setColor(farbe);
    		gOffScreen.fillRect(x, y, 1, 1);
    		System.out.print(x+"     ");
    		System.out.println(y);
    		füllen(x+1,y,color);
    		füllen(x-1,y,color);
    		füllen(x,y+1,color);
    		füllen(x,y-1,color);
    	}
    }
```

Doch wenn man an das Ende kommt ( was man an der Ausgabe vom x und y sieht ) stellt man fest das der X Wert immer zwischen 2 Zahlen wechselt (z.B. 190 und 191 oder 3 und 4).
Wieso funktioniert es nicht ****


----------



## MiMi (12. Mai 2011)

Umlaute im Code? *wegrenn

Und wieso 

```
System.out.print(x+"     ");
            System.out.println(y);
```
machts doch direkt in eine Zeile? Oo


----------



## Xym (12. Mai 2011)

Das ist doch völlig egal !  
Wichtiger ist warum der Code nicht geht 
Kann es sein, dass es an der Bedinung bei if liegt ****
Ich weiß ja nicht genau wie die Methode getPixel(x, y) beim Link 
( http://www.cosc.canterbury.ac.nz/mukundan/cogr/Fill.html ) aussieht..


----------



## Xym (17. Mai 2011)

Weiß denn keiner eine Antwort ? ?


----------



## SE (17. Mai 2011)

Hmm .. also ich halte an meinem Vorschlag mit Rekursion fest. man beginnt z.B. beim Pixel UNTER dem aktuellem so lange bis man auf den Rand trifft. Da das ganze natürlich rekursiv ist wird dann beim Pixel am Rand damit weiter gemacht ... da dieses nun aber returnt nimmt man sich z.B. das Pixel rechts daneben ... durch die Rekursion kommt man dann auch wieder in weitere Holräume ...
wenn man nun rekursiv alle Pixel nach rechts *und zwangsläufig nach unten* durch hat beginnt man nun am aktuelle letztem Pixel von dort aus nach oben zu gehen und danach nach links ... wenn man nun also so "linksrum" bis zum rekursions-ende gekommen ist returnt alles was am Rand liegt und dann von dem pixel von dem aus man dann nach links gegangen ist geht man nun "rechtsrum" ... das in der rekursion weiter zurück sollte dann mit einigem Aufwand zum ausfüllen JEDER beliebigen GESCHLOSSENEN Form führen.

Ein Beispiel oder gar getestet hab ich das nicht .. wäre aber jetzt so der erste Ansatz den ich verfolgen würde.


----------



## Xym (17. Mai 2011)

Habe es ma so versucht :

```
//color ist die Farbe von dem 1. Pxiel. farbe ist die Farbe die man gerade ausgewählt hat.
if(pixelfarbe(x+1,y).equals(color) && pixelfarbe(x+1,y)!=(farbe))
    	{
    		gOffScreen.setColor(farbe);
    		gOffScreen.fillRect(x+1, y, 1, 1);
    		fuellen(x+1, y, color);
    	}
    	else if ( pixelfarbe(x, y+1).equals(color) && pixelfarbe(x,y+1)!=(farbe))
    	{
    		gOffScreen.setColor(farbe);
    		gOffScreen.fillRect(x, y+1, 1, 1);
    		fuellen(x, y+1, color);
    	}

    	else if( pixelfarbe ( x-1, y).equals(color) && pixelfarbe(x-1,y)!=(farbe))
    	{
    		gOffScreen.setColor(farbe);
    		gOffScreen.fillRect(x-1, y, 1, 1);
    		fuellen( x-1, y, color);
    	}   
    	else if ( pixelfarbe( x, y-1).equals(color) && pixelfarbe(x,y-1)!=(farbe))
    	{
    		gOffScreen.setColor(farbe);
    		gOffScreen.fillRect(x, y-1, 1, 1);
    		fuellen(x, y-1, color);
    	}
```

Problem sind nur die Ecken. Dort wechselt er immer zwischen den Pixeln (790, 550) und (791, 550).
Wie kann ich das Problem beheben ****


----------



## SE (17. Mai 2011)

Also mal davon abgesehen das deine IF's so auch garnicht sinnvoll sind *warum prüfst du erst mit equals() und dann auf != ? ... das ergibt keinen Sinn* sieht es an sich ganz gut aus ... dein Problem wird nur die Abbruchbedingung sein ... weil so wie das hier aussieht würdest du irgendwann eine Schnecke beschrieben ... das ist aber nicht das was ich meinte. Auch wäre die KOMPLETTE fuellen-Methode mit den aktuellen Änderungen hilfreich.


----------

