Java Graphics.fillPolygon: как визуализировать правый и нижний края? - PullRequest
3 голосов
/ 09 октября 2011

При рисовании полигонов Java2D оставляет правые и нижние края. Я понимаю, почему это сделано. Тем не менее, я хотел бы нарисовать что-то, что включает эти края. Одна вещь, которая пришла мне в голову, состояла в том, чтобы следовать fillPolygon с drawPolygon с теми же координатами, но это, кажется, оставляет пробел. (См. Маленькое треугольное изображение внизу.) Есть две возможности, но я не могу сказать, какая именно. Чтобы включить сглаживание, я делаю это:

renderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
                  RenderingHints.VALUE_ANTIALIAS_ON);
renderHints.put(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHints(renderHints);

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

Как я могу это исправить?

Кроме того, я не уверен, но кажется, что контур многоугольника может быть СЛИШКОМ БОЛЬШИМ. То есть он может выходить за пределы правого и нижнего краев, которые я хочу включить.

Спасибо.

enter image description here

- ОБНОВЛЕНИЕ -

На основе очень приятного предложения от Hovercraft Full of Eels я сделал компилируемый пример:

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

public class polygon {
   private static final int WIDTH = 20;

   public static void main(String[] args) {
      BufferedImage img = new BufferedImage(WIDTH, WIDTH, BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = img.createGraphics();
      int[] xPoints = {WIDTH / 3, (2*WIDTH) / 3, WIDTH / 3};
      int[] yPoints = {0, WIDTH / 2, WIDTH};
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setColor(Color.green);
      g2.drawLine(0, WIDTH-1, WIDTH, WIDTH-1);
      g2.drawLine(0, 0, WIDTH, 0);
      g2.drawLine(WIDTH/3, 0, WIDTH/3, WIDTH);
      g2.drawLine((2*WIDTH/3), 0, (2*WIDTH/3), WIDTH);
      g2.setColor(Color.black);
      g2.drawPolygon(xPoints, yPoints, xPoints.length);
      g2.setColor(Color.black);
      g2.fillPolygon(xPoints, yPoints, xPoints.length);
      g2.dispose();

      ImageIcon icon = new ImageIcon(img);
      JLabel label = new JLabel(icon);

      JOptionPane.showMessageDialog(null, label);
   }
}

Если вы оставите закрашенный многоугольник красным, вы получите изображение ниже (увеличенное на 500%), которое показывает, что многоугольник не распространяется до правого края. То есть вертикальная зеленая линия соответствует x=(2*WIDTH)/2, и хотя красный многоугольник включает в себя эту координату, он не рисует там никаких пикселей.

enter image description here

Чтобы увидеть проблему с пропуском, я изменил red в программе на black. На этом изображении вы можете увидеть тонкий разрыв в правой нижней части, где контур, нарисованный drawPolygon, не совсем соответствует тому, что было нарисовано fillPolygon.

enter image description here

Ответы [ 2 ]

3 голосов
/ 09 октября 2011

Покажите нам свой код для вашего рисунка в простой скомпилированной исполняемой программе. Например, когда я пытаюсь имитировать ваше изображение и использовать RenderingHints, оно, похоже, создает изображение соответствующего размера с полными правыми / нижними краями:

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class Foo002 {
   private static final int WIDTH = 20;

   public static void main(String[] args) {
      BufferedImage img = new BufferedImage(WIDTH, WIDTH,
            BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = img.createGraphics();
      int[] xPoints = { WIDTH / 3, (2 * WIDTH) / 3, WIDTH / 3 };
      int[] yPoints = { 0, WIDTH / 2, WIDTH };
      g2.setColor(Color.black);
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setRenderingHint(RenderingHints.KEY_RENDERING,
            RenderingHints.VALUE_RENDER_QUALITY);
      g2.fillPolygon(xPoints, yPoints, xPoints.length);
      g2.dispose();

      ImageIcon icon = new ImageIcon(img);
      JLabel label = new JLabel(icon);
      label.setBorder(BorderFactory.createLineBorder(Color.black));
      JPanel panel = new JPanel();
      panel.add(label);

      JOptionPane.showMessageDialog(null, panel);
   }
}

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

2 голосов
/ 09 октября 2011

Мне нравится удобство ImageIcon, показанное @HFOE, но этот вариант может немного облегчить понимание того, что происходит.Из API Graphics

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

Напротив, Graphics2D должны следовать более сложным правилам сглаживания, которые позволяют емурисовать вне линий. "

PixelView

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;

/** @see http://stackoverflow.com/questions/7701097 */
public class PixelView extends JPanel {

    private static final int SIZE = 20;
    private static final int SCALE = 16;
    private BufferedImage img;

    public PixelView(Color fill) {
        this.setBackground(Color.white);
        this.setPreferredSize(new Dimension(SCALE * SIZE, SCALE * SIZE));
        img = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = img.createGraphics();
        int[] xPoints = {SIZE / 3, (2 * SIZE) / 3, SIZE / 3};
        int[] yPoints = {0, SIZE / 2, SIZE};
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(Color.green);
        g2.drawLine(0, SIZE - 1, SIZE, SIZE - 1);
        g2.drawLine(0, 0, SIZE, 0);
        g2.drawLine(SIZE / 3, 0, SIZE / 3, SIZE);
        g2.drawLine((2 * SIZE / 3), 0, (2 * SIZE / 3), SIZE);
        g2.setColor(Color.black);
        g2.drawPolygon(xPoints, yPoints, xPoints.length);
        g2.setColor(fill);
        g2.fillPolygon(xPoints, yPoints, xPoints.length);
        g2.dispose();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(img, 0, 0, getWidth(), getHeight(), null);
    }

    private static void display() {
        JFrame f = new JFrame("PixelView");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new GridLayout(1, 0));
        f.add(new PixelView(Color.black));
        f.add(new PixelView(Color.red));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                display();
            }
        });
    }
}
...