.[ ČeskéHry.cz ].
Algoritmus Flood Fill

 
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> Obecné
Zobrazit předchozí téma :: Zobrazit následující téma  
Autor Zpráva
Jefo



Založen: 02. 07. 2011
Příspěvky: 58

PříspěvekZaslal: 23. srpen 2015, 17:38:24    Předmět: Algoritmus Flood Fill Odpovědět s citátem

Ahoj,
robím si v Jave 2D engine ktorého súčasťou je aj grafický editor. Ešte toho zatial veľa nemám napísaného ale zatial robím na grafickom editore. Potrebujem poradiť s algoritmom flood fill. Mám to napísané takto:
kód:

 private void FillArea(JCanvasCell [][] myCells, int x, int y, Color c)
    {
       
        if(myCells[x][y].getType() == JMyCellType.Line)
         {
            return;
         }
         if(myCells[x][y].getType() == JMyCellType.Brush && myCells[x][y].getColor() == c)
         {
           return; 
         }
        if(x <= 1 || x >= width-1)
        {
            return;
        }
       
        if(y <= 1 || y >= height-1)
        {
            return;
        }
       
        myCells[x][y] = new JCanvasCell(JMyCellType.Brush, c);
       
       
        FillArea(myCells,x-1, y, c); FillArea(myCells,x+1, y, c);
        FillArea(myCells,x, y-1, c); FillArea(myCells,x, y+1, c);
       
         
       
        return;
    }


Výsledok vyzerá asi takto:


Vzorku programu môžte stiahnuť tu www.uloz.to
Kreslí sa levým tlačítkom a pravým sa vyfarbuje.
Viete mi prosím poradiť kde mám chybu keď sa po kliknutí nevyplní celá oblasť?
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Mem



Založen: 28. 07. 2007
Příspěvky: 1959
Bydliště: Olomouc

PříspěvekZaslal: 23. srpen 2015, 18:11:36    Předmět: Odpovědět s citátem

V každém případě si přepiš tuhle rekurzivní verzi na iterativní, protože tohle žere paměť a to velmi rychle (na konci funkce ji rekurzivně zavoláš 4x, každá z nich zase zavolá 4x atd.).

V závislosti na nastavené velikosti stacku ti to pak může padat při vykreslování i relativně malých oblastí, což možná bude i tenhle případ.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Jefo



Založen: 02. 07. 2011
Příspěvky: 58

PříspěvekZaslal: 23. srpen 2015, 21:48:52    Předmět: Odpovědět s citátem

Zapísal som to takto a vykresluje mi to len nejaký trojuholník ako výplň.

kód:

private void FillArea(JCanvasCell [][] myCells, int x, int y, Color c, Color oldColor)
    {
     
  Queue<Point> points = new LinkedList<Point>();
  if (myCells[x][y].getColor() != oldColor)
    return;
  Point node = new Point(x,y);
  points.add(node);

  while (points.size() > 0)
  {
    Point n = points.remove();
    if (cells[(int)n.getX()][(int)n.getY()].getColor() == oldColor)
      cells[(int)n.getX()][(int)n.getY()] = new JCanvasCell(JMyCellType.Brush, c);

    if (n.getX() != 0)
    {
      if(cells[(int)n.getX() - 1][(int)n.getY()].getColor() == c)
        points.add(new Point(((int)n.getX()) - 1,(int)n.getY()));
    }

    if (n.getX() != width - 1)
    {
      if(cells[((int)n.getX()) + 1][(int)n.getY()].getColor() == oldColor)
        points.add(new Point(((int)n.getX()) + 1,(int)n.getY()));
    }

    if (n.getY() != 0)
    {
      if(cells[((int)n.getX())][((int)n.getY())-1].getColor() == oldColor)
        points.add(new Point(((int)n.getX()),((int)n.getY())-1));
    }

    if (n.getY() != height - 1)
    {
     if(cells[((int)n.getX())][((int)n.getY())+1].getColor() == oldColor)
        points.add(new Point(((int)n.getX()),((int)n.getY())+1));
    }
       
  }
 


Nie je to ešte finálna verzia ale myslím že to nebude správne. To "cells" a "myCells" sú identické.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Jefo



Založen: 02. 07. 2011
Příspěvky: 58

PříspěvekZaslal: 24. srpen 2015, 00:32:27    Předmět: Odpovědět s citátem

Ok. je tam chyba. Uz som ju opravil. teraz to kreslí kosoštvorec ako výplň.
Môžete to skúsiť tu uloz.to. Veľmi malú plochu to vyfarbí ale pri veľkej to mrzne.

prvú chybu som mal tu:
kód:

 if (n.getX() != 0)
    {
      if(cells[(int)n.getX() - 1][(int)n.getY()].getColor() == c) --->> má to byť .getColor() == oldColor)
        points.add(new Point(((int)n.getX()) - 1,(int)n.getY()));
    }
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
mar



Založen: 16. 06. 2012
Příspěvky: 608

PříspěvekZaslal: 24. srpen 2015, 07:51:30    Předmět: Odpovědět s citátem

Nepomohlo by
kód:

if (cells[(int)n.getX()][(int)n.getY()].getColor() != oldColor) continue;
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Radis



Založen: 29. 03. 2014
Příspěvky: 235

PříspěvekZaslal: 24. srpen 2015, 09:43:22    Předmět: Odpovědět s citátem

Ty sousedy musis obarvovat uz v okamziku, kdyz je pridavas do te fronty. Ted tam porad dokola pridavas stejne body, protoze jeste nemaji zmenenou barvu, a proto ti to nefunguje.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Jefo



Založen: 02. 07. 2011
Příspěvky: 58

PříspěvekZaslal: 24. srpen 2015, 15:21:05    Předmět: Odpovědět s citátem

Ano Radis mal pravdu. Už to funguje. Tu je kód možno to niekomu pomôže:
kód:

private void FillArea(JCanvasCell [][] myCells, int x, int y, Color c, Color oldColor)
  {
     
  Queue<Point> points = new LinkedList<Point>();
  if (myCells[x][y].getColor() != oldColor)
    return;
  Point node = new Point(x,y);
  points.add(node);

  while (points.size() > 0)
  {
    Point n = points.remove();
    if (cells[(int)n.getX()][(int)n.getY()].getColor() == oldColor && cells[(int)n.getX()][(int)n.getY()].getType() != JMyCellType.Line )
    {
      cells[(int)n.getX()][(int)n.getY()] = new JCanvasCell(JMyCellType.Brush, c);
    }
    if (n.getX() != 0)
    {
      if(cells[(int)n.getX() - 1][(int)n.getY()].getColor() == oldColor && cells[(int)n.getX() - 1][(int)n.getY()].getType() != JMyCellType.Line)
      {
        points.add(new Point(((int)n.getX()) - 1,(int)n.getY()));
        myCells[(int)n.getX() - 1][(int)n.getY()] = new JCanvasCell(JMyCellType.Brush, c);
      }
    }

    if (n.getX() != width - 1)
    {
      if(cells[((int)n.getX()) + 1][(int)n.getY()].getColor() == oldColor && cells[(int)n.getX() + 1][(int)n.getY()].getType() != JMyCellType.Line)
      {
        points.add(new Point(((int)n.getX()) + 1,(int)n.getY()));
        myCells[((int)n.getX()) + 1][(int)n.getY()] = new JCanvasCell(JMyCellType.Brush, c);
      }
    }

    if (n.getY() != 0)
    {
      if(cells[((int)n.getX())][((int)n.getY())-1].getColor() == oldColor && cells[(int)n.getX()][(int)n.getY() - 1].getType() != JMyCellType.Line)
      {
        points.add(new Point(((int)n.getX()),((int)n.getY())-1));
        myCells[((int)n.getX())][((int)n.getY())-1] = new JCanvasCell(JMyCellType.Brush, c);
      }
    }

    if (n.getY() != height - 1)
    {
     if(cells[((int)n.getX())][((int)n.getY())+1].getColor() == oldColor && cells[(int)n.getX()][(int)n.getY() + 1].getType() != JMyCellType.Line)
     {
        points.add(new Point(((int)n.getX()),((int)n.getY())+1));
        myCells[((int)n.getX())][((int)n.getY())+1] = new JCanvasCell(JMyCellType.Brush, c);
     }
    }
       
  }
    }


Kto by to chcel vyskúšať tak tu je program uloz.to
Zatial vám všetkým ďakujem.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
mar



Založen: 16. 06. 2012
Příspěvky: 608

PříspěvekZaslal: 24. srpen 2015, 15:41:48    Předmět: Odpovědět s citátem

Když už ses rozhodl pro tuto variantu, měl bys vytáhnout obarvení x,y před smyčku, protože se zavolá pouze jednou pro první pixel.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Jefo



Založen: 02. 07. 2011
Příspěvky: 58

PříspěvekZaslal: 24. srpen 2015, 17:40:34    Předmět: Odpovědět s citátem

Premýšlal som nad tým ale to n.GetX() sa stále meni nie ? lebo zo stacku sa stále berie nové "n" ktoré má iné súradnice. No skúsim to dať pred.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Jefo



Založen: 02. 07. 2011
Příspěvky: 58

PříspěvekZaslal: 24. srpen 2015, 17:45:19    Předmět: Odpovědět s citátem

uz som to prerobil a ide to. dík
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zobrazit příspěvky z předchozích:   
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> Obecné Časy uváděny v GMT + 1 hodina
Strana 1 z 1

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra
Nemůžete odpovídat na témata v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete hlasovat v tomto fóru


Powered by phpBB © 2001, 2005 phpBB Group


Vzhled udelal powermac
Styl "vykraden" z phpBB stylu MonkiDream - upraveno by rezna