Растеризация треугольника в Java с использованием 2D-массива

Я создаю средство 3D-рендеринга на Java, но у меня возникла проблема при попытке отобразить многоугольники с заливкой сплошным цветом. Он работает отлично, но время от времени он рвется, но я не уверен, потому ли это, что алгоритм неэффективен, или это что-то еще, потому что он рвется только в вершинах. Вот картинка:

пример

Каркас: введите здесь описание изображения Вы можете видеть, что рядом с вершинами или, вернее, точками полигонов оно рвется. Я сохраняю цвет пикселей в двумерном массиве, а затем просматриваю его и визуализирую. Он все еще рвется, даже когда я делаю полигон очень маленьким, поэтому я не думаю, что это проблема производительности. Я использую алгоритм Брешема и сохраняю пиксели в двумерном массиве, затем в многоугольнике я получаю пиксели и превращаю их в один большой массив, который я циклически перебираю по y, а затем по x, пока не наткнусь на пиксель. Это устанавливается как beginLine, а затем последний устанавливается как endLine. Затем я рисую линию между точками.

public void render()
{
    int tempPixels[][] = new int[(int) Math.max(vertex_1.getX(), Math.max(vertex_2.getX(), vertex_3.getX())) + 30][(int) Math.max(vertex_1.getY(), Math.max(vertex_2.getY(), vertex_3.getY())) + 30];

    for (int x = 0; x < vector_1.getWidth(); x++)
    {
        for (int y = 0; y < vector_1.getHeight(); y++)
        {
            if (vector_1.getPixels()[x][y] == 1)
            {
                tempPixels[(int) (x + Math.min(vertex_1.getX(), vertex_2.getX()))][(int) (y + Math.min(vertex_1.getY(), vertex_2.getY()))] = 1;
            }
        }
    }

    for (int x = 0; x < vector_2.getWidth(); x++)
    {
        for (int y = 0; y < vector_2.getHeight(); y++)
        {
            if (vector_2.getPixels()[x][y] == 1)
            {
                tempPixels[(int) (x + Math.min(vertex_2.getX(), vertex_3.getX()))][(int) (y + Math.min(vertex_2.getY(), vertex_3.getY()))] = 1;
            }
        }
    }

    for (int x = 0; x < vector_3.getWidth(); x++)
    {
        for (int y = 0; y < vector_3.getHeight(); y++)
        {
            if (vector_3.getPixels()[x][y] == 1)
            {
                tempPixels[(int) (x + Math.min(vertex_3.getX(), vertex_1.getX()))][(int) (y + Math.min(vertex_3.getY(), vertex_1.getY()))] = 1;
            }
        }
    }

    for (int y = 0; y < (int) Math.max(vertex_1.getY(), Math.max(vertex_2.getY(), vertex_3.getY())) + 4; y++)
    {
        int beginLine = -1;

        int endLine = -1;

        for (int x = 0; x < (int) Math.max(vertex_1.getX(), Math.max(vertex_2.getX(), vertex_3.getX())) + 4; x++)
        {
            if (tempPixels[x][y] == 1)
            {
                if (beginLine == -1)
                {
                    beginLine = x;
                }
                else
                {
                    endLine = x;
                }
            }
        }

        for (int i = beginLine; i < endLine; i++)
        {
            pixels[i][y] = 1;
            colors[i][y] = Color.PINK;
        }
    }

    vector_1.render();
    vector_2.render();
    vector_3.render();

    vertex_1.render();
    vertex_2.render();
    vertex_3.render();
}

Итак, в основном мои вопросы: является ли этот алгоритм неэффективным, если да, то что было бы лучше? Почему рвется только около вершин?


person Hyden    schedule 08.08.2015    source источник


Ответы (2)


Из описания проблемы нельзя сделать вывод, что на прикрепленном изображении показано не то, что вы хотите. Технически розовая зона может отображать набор треугольников, которые вы «правильно» нарисовали (т.е. именно так, как вы хотели): p Вы можете пометить треугольники, которые вы хотели видеть на изображении, в качестве обновления. Подозреваю, что треугольников 4, хотя таких возможных комбинаций больше.

Прежде всего, поскольку часть, которая для каждого y определяет beginLine и endLine, кажется правильной, вам, вероятно, следует повторять до endLine при рисовании связанного вертикального сегмента (а не до endLine-1).

Но это, вероятно, не настоящая проблема. Попробуйте рисовать по одному треугольнику за раз. Если некоторые треугольники по-прежнему отображаются неправильно, также попробуйте посмотреть, что произойдет, если вы удалите последнюю часть (тот, который отображает векторы и вершины). Почему это?! Учитывая вашу реализацию, вы ожидаете только сегмент на каждый y. Предоставленное изображение указывает на то, что ваша реализация иногда отображает более одного сегмента. Таким образом, рендеринг векторов и вершин может быть неправильным, хотя рендеринг нескольких «не идеально выровненных» треугольников также может быть причиной этого.

Если это тоже не решит проблему, между вашими треугольниками может быть небольшое смещение. Попытайтесь понять, почему это так.

Что касается эффективности, это не вина. Как правило, эффективность и правильность не связаны таким образом.

ИЗМЕНИТЬ

Вы должны добавить endLine = x после beginLine = x. В вашей реализации, если у вас есть только один пиксель на вертикальной линии, вы его не рисуете (поскольку endLine останется -1). Это один из способов исправить эту проблему. Также перед началом рисования убедитесь, что beginLine больше -1. И не забудьте выполнить итерацию от beginLine ровно до endLine.

person cobarzan    schedule 08.08.2015
comment
Не совсем понял первую часть, но я предполагаю, что вы имеете в виду, что не видите, где находятся треугольники. Я добавил изображение с каркасом. - person Hyden; 08.08.2015
comment
Треугольники на своих местах. Сейчас я собираюсь протестировать отдельные полигоны. - person Hyden; 08.08.2015
comment
Кажется, это проблема при перемещении треугольника (так что код вращения). - person Hyden; 08.08.2015

Вы можете использовать метод fillPolygon.

Синтаксис

g.setColor(Color.*color you want*)
g.fillPolygon (new int[]{width Dimensions}, new int [] {Height Dimensions}, no. of co-ordinates);

Примечание: - 1-е значение имеет правую координату, 2-е — среднюю точку и 3-е — левую координату.

Окончательное программирование с классом, переменными и методами.

/*Import the following files: -*/   
import javax.swing.JPanel;         
import javax.swing.JFrame;            
import java.awt.Color;    
import java.awt.Graphics;  
import java.awt.event.ComponentListener;  
import java.awt.event.ComponentEvent;  
import java.awt.Font; 

public class Shapes extends JPanel
{
    public Shapes() 
    {
        this.addComponentListener(new ComponentListener(){
            public void componentShown(ComponentEvent arg0) {

            }

            public void componentResized(ComponentEvent arg0) {
                paintComponent(getGraphics());

            }               

            public void componentMoved(ComponentEvent arg0) {                   

            }

            public void componentHidden(ComponentEvent arg0) {
                // TODO Auto-generated method stub

            }
        });

    }

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        this.setBackground(Color.MAGENTA);
        g.setColor(Color.BLUE);
        g.fillPolygon (new int[]{250,135,10}, new int [] {160,15,160}, 3);

        g.setFont(new Font("TimesRoman", Font.PLAIN, 35));
        g.setColor(Color.GREEN);
        g.drawString("Triangle", 75,  120); 
    }
    public static void main(String[] args) 
    {   
        Shapes obj = new Shapes();   
        JFrame frame = new JFrame("Shapes");   
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   
        frame.add(obj);   
        frame.setSize(600, 500);   
        frame.setVisible(true);   
   }

}
person Eeshaan Sethia    schedule 21.06.2017