Алгоритм / метод штамповки кистью - PullRequest
2 голосов
/ 23 мая 2011

Я играю с небольшой краской.Я хочу создавать разные советы кисти (не только простые линии).Основная идея состоит в том, чтобы повторять (штамповать) кончик кисти вдоль движений мыши.Поскольку движения мыши не отправляют требуемое событие для каждого пикселя, который перемещает мышь.Мой текущий подход заключается в том, что я использую алгоритм Брезенхэма, чтобы получить пиксели, в которых я хочу рисовать, а затем нанести кончик кисти на каждый пиксель.Это, однако, не очень эффективно, потому что размер кончика кисти составляет, например, 30x30 пикселей.Я хочу штамповать на 25% ширины кисти, но я не знаю, как это сделать хорошим способом.Я мог определять расстояние и штамповать только до тех пор, пока расстояние кисти не достигнет 25%.

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

Спасибо за чтение!

Ответы [ 2 ]

1 голос
/ 23 июня 2012

Немного опоздал с ответом, но если кто-то ищет ответы здесь, я реализую его в своем коде для проекта на Java.

Шаг - это процент кисти, поэтому, если это кисть 20x20, тогда 25шаг 5 пикселей, который является пробелом.

Затем я создаю нормализованный вектор из последней и текущей позиции мыши.

После first, который является первым щелчком.Когда dist больше, чем пространство, создается итератор для обработки всего расстояния, потому что иногда мышь может двигаться быстро, поэтому в этом домене есть несколько dib (или «штампов», dibs)

iter=space-remn предназначен для выравнивания его с предыдущей меткой.

Предыдущая позиция, добавленная с помощью vector*iter, возвращает нам позицию для метки.

После того, как мы нарисуем их все, появляются важные биты.

remn = dist-iter+space-remn; Остаток (remn) собирается из предыдущего процесса, добавленного к dist (расстоянию) от начального этапа.

Чтобы понять математику, давайте покажем пример.

brush = 30x30, step = 25%, remn = 2.5, dist = 28.5 (включая remn), space = 7.5 (30 * 25/100)

Следующий remn = 28.5 (dist) -27.5 (5 изначально + 7,5 * 3 раза, поскольку проверка (<28,5-2,5) выполняется после обновления iter) +7,5 (пробел) -2,5 (предыдущий остаток) = 6 пикселей </p>

Таким образом, мышь должна перемещаться 1,5пикселей для следующей метки, так как 6 пикселей уже пройдены.

В другом случае это evи более просто.

dist (в который уже добавлен remn) терпит неудачу в remn = dist.

Например, если у нас есть 2 пикселя с прошлого раза, мы добавляем расстояние, пройденное мышью, скажем 3пикселей, поэтому нам нужно проехать еще 2,5 пикселя для следующей метки.

    int size =(Integer) tool.getAttribute("size");
        int step = (Integer) tool.getAttribute("step");
        double space = size*step/100.0f; //what is actualy need for the check algorithm for the step rate to work
        double dist = Point.distance(pZero.getX(),pZero.getY(),last.getX(),last.getY());
        int bleed = (int) (size/tilemap[0].getWidth()+size/tilemap[0].getHeight());
        Point2D.Double vec = new Point2D.Double(pZero.getX()-last.getX(),pZero.getY()-last.getY());
        vec.x /= dist;
        vec.y /= dist;
        dist+=remn;
        if(first){
            //System.out.println("First ");
            for(int y=0; y < tilesHigh; ++y) {
                for(int x=0; x < tilesWide; ++x) {

                    int pos = x+y*tilesWide;
                    // This should never exceed tilemap.length.
                    BufferedImage tile = tilemap[pos];
                    //tool.operate(tile.getGraphics(), new Point(pZero.x-x*tile.getWidth(), pZero.y-y*tile.getHeight()));
                    tool.operate(tile.getGraphics(), tilemapPointToTilePoint(pZero, pos));

                }
            }
            first = false;
        }else {
            if(dist>=space){//check to see if the mouse distance is enoght for a step(space)
                iter=space-remn;
                //test=0;
                //System.out.println("pZero="+pZero);
                while(iter<dist-remn){//fills the gap between with at the rate of step(space),if you move the mouse fast you use to get those
                    //do stuff
                    pZero.x =(int) Math.round(last.x + (vec.x*iter));
                    pZero.y =(int) Math.round(last.y + (vec.y*iter));
                    //int pos = xyToIndex(pZero.x, pZero.y);
                    //test++;
                    //System.out.println("iter = "+iter+" remn="+remn+" space="+space);
                    //System.out.println("pIter="+pZero);
                    //System.out.println("Second ");

                    for(int y=0; y < tilesHigh; ++y) {//bleed
                        for(int x=0; x < tilesWide; ++x) {
                            int pos = x+y*tilesWide;
                            // This should never exceed tilemap.length.
                            BufferedImage tile = tilemap[pos];
                            //tool.operate(tile.getGraphics(), new Point(pZero.x-x*tile.getWidth(), pZero.y-y*tile.getHeight()));
                            tool.operate(tile.getGraphics(), tilemapPointToTilePoint(pZero, pos));
                        }
                    }
                    iter += space;
                }
                //System.out.println("last = "+last);
                //System.out.println("test="+test);
                remn = dist-iter+space-remn;
            }else remn = dist;
        }
0 голосов
/ 23 мая 2011

Brasenham - это алгоритм аппроксимации, поскольку вы уже аппроксимируете вместо псевдонимов, вы можете пойти дальше ...

С небольшой модификацией алгоритма, где вы получаете ширину кисти в качестве параметра(или еще лучше, расстояние печати):

  • Порог - это расстояние печати * множитель векторной ориентации (45 135 225 315 градусов = sqrt (2))
  • вместо рисования пикселей в X,Y -> считать пиксели
  • , когда pixelCount> = пороговая кисть для печати в точке X, Y и сбросить pixelCount

Использовать плавающее число для счетчика, а если пиксели не квадратные, то добавитьразное количество для каждой дельты или дельты, которую вы проходите, и учитывайте векторную ориентацию от x1, y1 до x2, y2, чтобы получить реальное расстояние, добавляемое для каждого пикселя.

Довольно простая модификация ...

...