Unity 3D - алгоритм заливки / заливки продолжает сбивать двигатель - PullRequest
0 голосов
/ 03 марта 2012

Я пытался написать алгоритм заливки, который будет работать в Unity. Идея состоит в том, чтобы раскрасить участки рисунка черным по белому на основе цвета, выбранного пользователем. Я пробовал несколько реализаций алгоритма заливки, но все они приводят к зависанию единицы при вызове.

Любая помощь по этому вопросу высоко ценится, это необходимо в рамках важного проекта. Будем весьма благодарны за любые предложения по пересмотру кода, конструкции алгоритма или любых альтернативных способов заставить это работать:)

Код:

// FloodFill function
void FloodFill()
{
    // TEST - colour the clicked pixel
    //_tex.SetPixel( (int)_pixelUV.x, (int)_pixelUV.y, m_fillColour );
    //_tex.SetPixel( _pixelX, _pixelY, m_fillColour );


    // FLOOD FILL 
    // ----------

    // Create WestEast
    List<Point> m_WestEast;

    //get the pixel's colour
    Color PC = new Color(_tex.GetPixel(m_StartNode.X, m_StartNode.Y).r, _tex.GetPixel(m_StartNode.X, m_StartNode.Y).g, _tex.GetPixel(m_StartNode.X, m_StartNode.Y).b);

    //Record clicked pixel as point
    Point node = new Point(m_StartNode.X, m_StartNode.Y);

    //if the pixel's colour is boundary colour (black), return.
    if(PC == Color.black)
    {
        return;
    }

    //else continue

    // Create a list Q[]
    m_List = new List<Point>();

    //add clicked pixel to Q[]
    m_List.Add(node);

    //for each element in Q[]
    for(int i=0; i<m_List.Count; i++)
    {
        //create new WE[] and add Q[n] to it
        m_WestEast = new List<Point>();
        m_WestEast.Add(node);

        //get pixel 1 to left (w) of Q[n]
        Point w = new Point(node.X + 1, node.Y);
        //get colour of w
        Color wCol = new Color(_tex.GetPixel(w.X, w.Y).r, _tex.GetPixel(w.X, w.Y).g, _tex.GetPixel(w.X, w.Y).b);    

        while(wCol != Color.black)
        {        
            //add pixel to WE[] and repeat
            m_WestEast.Add(w);

            //get new w
            w = new Point(w.X + 1, w.Y);

            //get colour of w
            wCol = new Color(_tex.GetPixel(w.X, w.Y).r, _tex.GetPixel(w.X, w.Y).g, _tex.GetPixel(w.X, w.Y).b);    

            //else if colour is boundary colour
                //go to next step
        }

        //get pixel 1 to right (e) of Q[n]
        Point e = new Point(node.X - 1, node.Y);
        //get colour of w
        Color eCol = new Color(_tex.GetPixel(e.X, e.Y).r, _tex.GetPixel(e.X, e.Y).g, _tex.GetPixel(e.X, e.Y).b);    

        while(eCol != Color.black)
        {        
            //add pixel to WE[] and repeat
            m_WestEast.Add(e);

            //get new e
            e = new Point(e.X - 1, e.Y);

            //get colour of e
            eCol = new Color(_tex.GetPixel(e.X, e.Y).r, _tex.GetPixel(e.X, e.Y).g, _tex.GetPixel(e.X, e.Y).b);    

            //else if colour is boundary colour
                //go to next step
        }

        //for each pixel in WE[]
        for(int j=0; j<m_WestEast.Count; j++)
        {
            //set the pixel to replacement colour
            _tex.SetPixel(m_WestEast[j].X, m_WestEast[j].Y, m_fillColour);

            //get pixel 1 to north (n) of Q[n]
            Point n = new Point(m_WestEast[j].X, m_WestEast[j].Y - 1);    

            //get colour of n
            Color nCol = new Color(_tex.GetPixel(n.X, n.Y).r, _tex.GetPixel(n.X, n.Y).g, _tex.GetPixel(n.X, n.Y).b);

            //if colour is not boundary colour
            if(nCol != Color.black)
            {
                //add pixel to Q[]
                m_List.Add(n);
            }

            //get pixel 1 to south (s) of Q[n]
            Point s = new Point(m_WestEast[j].X, m_WestEast[j].Y + 1);    

            //get colour of s
            Color sCol = new Color(_tex.GetPixel(s.X, s.Y).r, _tex.GetPixel(s.X, s.Y).g, _tex.GetPixel(s.X, s.Y).b);

            //if colour is not boundary colour
            if(sCol != Color.black)
            {
                //add pixel to Q[]
                m_List.Add(s);
            }
        }

    }

    // ----------

}

1 Ответ

1 голос
/ 03 марта 2012

Ваш алгоритм добавляет одни и те же пиксели снова и снова.У него есть и другие проблемы, но именно это заставляет его работать вечно и пожирать всю вашу память.Я думаю, что вы пытаетесь реализовать третий алгоритм здесь: http://en.wikipedia.org/wiki/Flood_fill

Очевидное различие, которое у вас есть, состоит в том, что алгоритм Wikipedia имеет:

11. Если цвет узла соответствуетк северу от n находится целевой цвет, добавьте этот узел в Q.
12. Если цвет узла к югу от n - целевой, добавьте этот узел в Q.

...однако вы проводите тестирование на цвет границы, а не на целевой цвет.Ваш алгоритм будет обнаруживать одни и те же пиксели снова и снова, каждый раз отмечая, что они отличаются от цвета границы.

У вас есть и другие проблемы:

  1. Выпытаясь использовать список в качестве очереди, добавляя в конце.Это означает, что он все время растет и будет израсходовать много памяти без веской причины.Алгоритм в Википедии предполагает, что вы используете очередь, и цикл каждый раз удаляет один элемент.Это не должно мешать вашему алгоритму работать, но вы, вероятно, захотите исправить его, прежде чем использовать его широко.
  2. У вас много дублирования кода, что делает ваш алгоритм излишне трудным для чтения и приглашаетпроблемы, когда вы позже вносите изменения в одном месте и забыли дублировать их везде.
...