Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
Jefo
Založen: 02. 07. 2011 Příspěvky: 58
|
Zaslal: 23. srpen 2015, 17:38:24 Předmět: Algoritmus Flood Fill |
|
|
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 |
|
|
Mem
Založen: 28. 07. 2007 Příspěvky: 1959 Bydliště: Olomouc
|
Zaslal: 23. srpen 2015, 18:11:36 Předmět: |
|
|
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 |
|
|
Jefo
Založen: 02. 07. 2011 Příspěvky: 58
|
Zaslal: 23. srpen 2015, 21:48:52 Předmět: |
|
|
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 |
|
|
Jefo
Založen: 02. 07. 2011 Příspěvky: 58
|
Zaslal: 24. srpen 2015, 00:32:27 Předmět: |
|
|
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 |
|
|
mar
Založen: 16. 06. 2012 Příspěvky: 608
|
Zaslal: 24. srpen 2015, 07:51:30 Předmět: |
|
|
Nepomohlo by
kód: |
if (cells[(int)n.getX()][(int)n.getY()].getColor() != oldColor) continue;
|
|
|
Návrat nahoru |
|
|
Radis
Založen: 29. 03. 2014 Příspěvky: 235
|
Zaslal: 24. srpen 2015, 09:43:22 Předmět: |
|
|
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 |
|
|
Jefo
Založen: 02. 07. 2011 Příspěvky: 58
|
Zaslal: 24. srpen 2015, 15:21:05 Předmět: |
|
|
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 |
|
|
mar
Založen: 16. 06. 2012 Příspěvky: 608
|
Zaslal: 24. srpen 2015, 15:41:48 Předmět: |
|
|
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 |
|
|
Jefo
Založen: 02. 07. 2011 Příspěvky: 58
|
Zaslal: 24. srpen 2015, 17:40:34 Předmět: |
|
|
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 |
|
|
Jefo
Založen: 02. 07. 2011 Příspěvky: 58
|
Zaslal: 24. srpen 2015, 17:45:19 Předmět: |
|
|
uz som to prerobil a ide to. dík |
|
Návrat nahoru |
|
|
|