快速绘制任意点集合

时间:2016-06-07 20:58:19

标签: java swing graphics polygon

我正在编写一个飞镖应用程序,并实现了一个绘制为BufferedImage的Dartboard。

渲染飞镖时,我首先迭代BufferedImage的坐标并计算“'”段。我把它包装成一个DartboardSegment,它基本上只是一个点的集合,有一些额外的结构(它对应的板上的数字等)。

目前,要实际渲染飞镖靶,我会单独绘制每个点,如下所示:

    for (Point pt : allPoints)
    {
        DartboardSegment segment = getSegmentForPoint(pt);
        Color colour = DartboardUtil.getColourForSegment(segment);

        int rgb = colour.getRGB();
        int x = (int)pt.getX();
        int y = (int)pt.getY();
        dartboardImage.setRGB(x, y, rgb);
    }

显然这需要一些时间。这不是一个难以忍受的数量(绘制一个500x500区域约2-3个),但我想消除这个“延迟”。如果我能。在我的应用程序的其他方面,我遇到了更快的替代方法(如Graphics.fillRect())。

我已经看到Graphics类上有一个fillPolgyon()方法,但我不认为我可以很容易地将我的段转换为多边形,因为它们的形状不同(例如三元组的形状,一个圆形的靶心......)。有没有一种更快的方法在java中一次绘制任意数组的点,而不是循环绘制并单独绘制?

想要编写的代码类似于:

    for (DartboardSegment segment : allSegments)
    {
        Color colour = DartboardUtil.getColourForSegment(segment);
        Polgyon poly = segment.toPolygon();

        Graphics gfx = dartboardImage.getGraphics();
        gfx.setColor(colour);
        gfx.fillPolygon(poly);
    }

2 个答案:

答案 0 :(得分:1)

  

我不认为我可以轻松地将我的线段转换为多边形,因为它们的形状各不相同(例如三重形状,靶心圆形......)

这可能会给你一些想法。

您可以创建Shape对象来表示飞镖靶的每个区域:

import java.awt.*;
import java.util.*;
import javax.swing.*;
import java.awt.geom.*;

public class Dartboard extends JPanel
{
    private ArrayList<DartboardSegment> segments = new ArrayList<DartboardSegment>();
    private int size = 500;
    private int radius = size / 2;
    private int border = 25;
    private int doubleSize = size - (2 * border);
    private int tripleSize = size / 2;
    private int thickness = 10;

    public Dartboard()
    {
        createSegmentWedges();

        int innerRadius = size - (2 * border);
        Shape outer = new Ellipse2D.Double(0, 0, size, size);
        Shape inner = new Ellipse2D.Double(border, border, innerRadius, innerRadius);
        Area circle = new Area( outer );
        circle.subtract( new Area(inner) );
        segments.add( new DartboardSegment(circle, Color.BLACK) );

        createBullsEye();
    }

    private void createSegmentWedges()
    {
        int angle = -99;

        for (int i = 0; i < 20; i++)
        {
            //  Create the wedge shape

            GeneralPath path = new GeneralPath();
            path.moveTo(250, 250);

            double radians1 = Math.toRadians( angle );
            double x1 = Math.cos(radians1) * radius;
            double y1 = Math.sin(radians1) * radius;
            path.lineTo(x1 + 250, y1 + 250);

            angle += 18;
            double radians2 = Math.toRadians( angle );
            double x2 = Math.cos(radians2) * radius;
            double y2 = Math.sin(radians2) * radius;
            path.lineTo(x2 + 250, y2 + 250);

            path.closePath();

            Color wedgeColor = (i % 2 == 0) ? Color.BLACK : Color.WHITE;
            segments.add( new DartboardSegment(path, wedgeColor) );

            //  Create the double/triple shapes

            Color color = (i % 2 == 0) ? Color.RED : Color.GREEN;
            createShape(doubleSize, path, color);
            createShape(tripleSize, path, color);
        }
    }

    private void createShape(int outerSize, GeneralPath path, Color color)
    {
        int outerOffset = (size - outerSize) / 2;
        int innerSize = outerSize - (2 * thickness);
        int innerOffset = (size - innerSize) / 2;

        Shape outer = new Ellipse2D.Double(outerOffset, outerOffset, outerSize, outerSize);
        Shape inner = new Ellipse2D.Double(innerOffset, innerOffset, innerSize, innerSize);

        Area circle = new Area( outer );
        circle.subtract( new Area(inner) );
        circle.intersect( new Area(path) );

        segments.add( new DartboardSegment(circle, color) );
    }

    private void createBullsEye()
    {
            int radius1 = 40;
            int offset1 = (size - radius1) / 2;
            Ellipse2D.Double bullsEye1 = new Ellipse2D.Double(offset1, offset1, radius1, radius1);
            segments.add( new DartboardSegment(bullsEye1, Color.GREEN) );

            int radius2 = 20;
            int offset2 = (size - radius2) / 2;
            Ellipse2D.Double bullsEye2 = new Ellipse2D.Double(offset2, offset2, radius2, radius2);
            segments.add( new DartboardSegment(bullsEye2, Color.RED) );
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D)g.create();

        for (DartboardSegment segment: segments)
        {
            g2d.setColor( segment.getColor() );
            g2d.fill( segment.getShape() );
        }

    }

    @Override
    public Dimension getPreferredSize()
    {
        return new Dimension(500, 500);
    }

    class DartboardSegment
    {
        private Shape shape;
        private Color color;

        public DartboardSegment(Shape shape, Color color)
        {
            this.shape = shape;
            this.color = color;
        }

        public Shape getShape()
        {
            return shape;
        }

        public Color getColor()
        {
            return color;
        }
    }


    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("DartBoard");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new Dartboard());
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}

答案 1 :(得分:0)

经过一番挖掘之后,我认为解决这个问题的方法是做到以下几点。它不是最好的,但我认为它会起作用:

    int i = 0;
    for (int y=0; y<height; y++)
    {
        for (int x=0; x<width; x++)
        {
            Point pt = new Point(x, y);
            DartboardSegment segment = getSegmentForPoint(pt);
            Color colour = DartboardUtil.getColourForSegment(segment);

            pixels[i] = colorToUse.getRGB();
            i++;
        }
    }

    dartboardImage.setRGB(0, 0, width, height, pixels, 0, width);

然而,我愿意接受更好的建议!