从用于计算三角形和圆周的swingworker重新绘制applet

cha*_*nya 3 java graphics swing swingworker computational-geometry

我试图复制这里发现的小程序作为练习的一部分.小程序正在使用Fortune的算法来生成两者; Voronoi图和Delaunay三角剖分.我只对在平面中生成Delaunay三角剖分感兴趣,因此,将使用增量算法,即一次添加1个点.我打算在添加采样点时显示在每个阶段生成的三角形.

我正在使用SwingWorker类来创建包含算法的Triangulate类的实例.我在for循环中调用triangulate方法,当单击GUI上的开始按钮时,它会遍历一组采样点.

这是代码:

JButton startButton = new JButton("Start");
        startButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                SwingWorker<List<Triangle>, Triangle> worker = new SwingWorker<List<Triangle>, Triangle>() {
                    @Override
                    protected List<Triangle> doInBackground() throws Exception {
                        Triangulate dt = new Triangulate(drawingPanel.pointsList());
                        dt.preTriangulate(); //Set-up a bounding triangle and obtain a random permutation of the points
                        List<PlanarPoint> pointsList = dt.pointsList();
                        for (int i = 0; i < pointsList.size(); i++) {
                            PlanarPoint sample = pointsList.get(i);
                            dt.triangulate(sample); 
                            List<Triangle> list = dt.trianglesList(); //Obtaining the list of triangles at every stage. Good Idea??
                            for (int j = 0; j < list.size(); j++) {
                                publish(list.get(j));
                            }
                            Thread.sleep(500);
                        }
                        dt.removeTriangles(dt.trianglesList()); // Remove all the triangles containing bounding-triangle vertices
                        return dt.trianglesList();
                    }

                    protected void process(List<Triangle> triangles) {
                        for (Triangle triangle : triangles) {
                            g = drawingPanel.getGraphics();
                            PlanarPoint p1 = triangle.getVertex1();
                            PlanarPoint p2 = triangle.getVertex2();
                            PlanarPoint p3 = triangle.getVertex3();
                            g.drawLine((int) Math.ceil(p1.x), (int) Math.ceil(p1.y),
                                    (int) Math.ceil(p2.x), (int) Math.ceil(p2.y));
                            g.drawLine((int) Math.ceil(p2.x),(int) Math.ceil(p2.y),
                                    (int) Math.ceil(p3.x),(int) Math.ceil(p3.y));
                            g.drawLine((int) Math.ceil(p3.x),(int) Math.ceil(p3.y),
                                    (int) Math.ceil(p1.x),(int) Math.ceil(p1.y));
                        }
                    }
                };
                worker.execute();
            }
        });
Run Code Online (Sandbox Code Playgroud)

这是Triangulate类,它计算一组点的Delanuay三角剖分:

public class Triangulate {

    private List<PlanarPoint> pointsList;
    private List<Triangle> triangleList;
    private Triangle boundingTriangle;
    private List<Edge> edgeList;

    public Triangulate(List<PlanarPoint> pointsList) {
        this.pointsList = pointsList;
        this.triangleList = new ArrayList<Triangle>();
        this.edgeList = new ArrayList<Edge>();
    }

    public List<Triangle> trianglesList() {
        return triangleList;
    }

    public List<PlanarPoint> pointsList() {
        return pointsList;
    }

    public void preTriangulate() {
        boundingTriangle = getBoundingTriangle(pointsList);
        triangleList.add(boundingTriangle);
        randomPermutation(pointsList);
    }

    public void triangulate(PlanarPoint samplePoint) {
        // A procedure implementing the Bowyer - Watson algorithm
        // to calculate the DT of a set of points in a plane.
    }

    public void removeTriangles(List<Triangle> trianglesList) {
        // A procedure to remove all triangles from the list sharing
        // edges with the bounding-triangle
    }

    private Triangle getBoundingTriangle(List<PlanarPoint> pointsList) {
        //Obtains a bounding-triangle for a set of points
    }

    public void randomPermutation(List<PlanarPoint> pointsList) {
        //Obtains a random permutation of a set of points
    }
}
Run Code Online (Sandbox Code Playgroud)

我有3个其他课程

  1. PlanarPoint - Point2D.Double的子类,它实现Comparable以提供基于y坐标的排序
  2. 三角形 - 确定三角形的圆周和圆周半的类,并确定一个点是否位于三角形的外接圆内
  3. Edge - 将Edge表示为具有2个PlanarPoints作为其端点的类.
  4. DrawingPanel - 一个类,用作在点击事件中添加点并在屏幕上绘制的曲面.

    现在,我有一些问题

    1. 是否有更好的方法通过迭代一组点然后调用Triangulate类的函数来获得现有的圆周和三角形来显示三角形和可能的圆周
    2. 是否所有绘图都限制在DrawingPanel类中,因为在上面的代码片段中,我在扩展JApplet/JFrame的类中进行绘制,因此每当调整窗口大小时,绘制的三角形都会丢失?我可以遵循一种设计模式吗?
    3. 除了计算一组点的DT的时间是一项耗时的任务这一事实之外,SwingWorker的使用是否会产生另一个在此处证明合理的线程?

如果我遗漏了任何细节,请告诉我

谢谢,Chaitanya

Hov*_*els 5

建议:

  • 不要使用getGraphics()获取Graphics对象,因为如果执行任何重绘(不受控制),获取的Graphics对象将不会持久存在.而是绘制到BufferedImage并让JPanel或JComponent在其paintComponent覆盖中绘制BufferedImage,或者将图像数据添加到某种Collection的集合中,并让paintComponent覆盖方法使用绘制图像的信息迭代Collection.
  • 不要直接在顶级窗口(如JFrame或JApplet)中绘制,而是在从JComponent派生的组件中绘制,通常是JComponent本身或JPanel.
  • 阅读Swing图形教程,因为他们将解释所有这些以及更多.
  • SwingWorker是完全合理的,因为你想要创建一个作为Swing应用程序背景但仍与Swing应用程序交互的线程 - 这是为SwingWorkers创建的情况.