Java 使用swingworker设置递归三角剖分算法的动画

Java 使用swingworker设置递归三角剖分算法的动画,java,swing,computational-geometry,swingworker,Java,Swing,Computational Geometry,Swingworker,这是一个关于如何在使用SwingWorker时绘制小程序/窗口的问题的后续问题 在这个特殊的例子中,我使用了Guibas和stolfi提出的分治算法来计算一组点(比如p)的Delaunay三角剖分 算法如下: 1.如果sizeof(p)=2,则添加边;返回 2.如果sizeof(p)=3,则添加一个逆时针方向的三角形;返回 3.如果sizeof(p)>3, 将(p)分成左右两半。 对每个部分进行三角剖分 把两半合在一起 我有一个三角剖分类,其三角剖分方法(如代码块所示)将实现分治算法(根据Gui

这是一个关于如何在使用SwingWorker时绘制小程序/窗口的问题的后续问题

在这个特殊的例子中,我使用了Guibas和stolfi提出的分治算法来计算一组点(比如p)的Delaunay三角剖分

算法如下: 1.如果sizeof(p)=2,则添加边;返回 2.如果sizeof(p)=3,则添加一个逆时针方向的三角形;返回 3.如果sizeof(p)>3, 将(p)分成左右两半。 对每个部分进行三角剖分 把两半合在一起

我有一个三角剖分类,其三角剖分方法(如代码块所示)将实现分治算法(根据Guibas和Stolfi提供的伪代码)

公共四边形[]分区(列表){
QuadEdge[]ConvexHullEdge=新的QuadEdge[2];
if(list.size()==2){
//添加边
}else if(list.size()==3){
//添加一个逆时针方向的三角形
}else if(list.size()>3){
List leftHalf=new ArrayList();
List rightHalf=新建ArrayList();
//将点列表分成两半
四边形[]leftDelaunay=三角形化(leftHalf);
四边形ldo=leftDelaunay[0];
QuadEdge ldi=leftDelaunay[1];
四边形[]rightDelaunay=三角形化(右半部分);
四边形rdi=rightDelaunay[0];
四边形rdo=rightDelaunay[1];
//合并两半
合并(ldo、ldi、rdi、rdo);
}
返回凸面边缘;
}
我有一个DrawingPanel,它充当画布类,在绘图表面上绘制三角形和点

我在主三角剖分类中使用SwingWorker调用三角剖分方法

以下是SwingWorker的代码:

private class GuibasStolfiWorker extends
            SwingWorker<List<QuadEdge>, PlanarPoint> {

        @Override
        protected List<QuadEdge> doInBackground() throws Exception {
           // retrieve the points added by the user on the drawing surface
            List<PlanarPoint> list = drawingPanel.pointsList();
            Trinagulation dt = new Triangulation(list);
            dt.preprocess(); // removes duplicate points
            dt.triangulate();// calls the recursive divide and conquer algorithm
            return dt.edgeList(); //returns the list of edges which form the final triangulation.
        }

        protected void process(List<PlanarPoint> chunks) {
            drawingPanel.repaint();
        }

        public void done() {
            try {
                List<QuadEdge> triangles = get();
                drawingPanel.setTrianglesList(triangles);
                drawingPanel.repaint();
            } catch (InterruptedException e) {

            } catch (ExecutionException e) {

            }
        }
    };
私有类GuibasStolfiWorker扩展
摇摆工人{
@凌驾
受保护列表doInBackground()引发异常{
//检索用户在图形表面上添加的点
列表=drawingPanel.pointsList();
TrinaGration dt=新三角测量(列表);
dt.preprocess();//删除重复点
dt.triangulate();//调用递归分治算法
return dt.edgeList();//返回形成最终三角剖分的边的列表。
}
受保护的无效进程(列表块){
drawingPanel.repaint();
}
公众假期结束(){
试一试{
列出三角形=get();
drawingPanel.SetTriangleList(三角形);
drawingPanel.repaint();
}捕捉(中断异常e){
}捕获(执行例外){
}
}
};
现在,我想通过显示递归调用triangulate和merge函数之后出现的三角剖分来设置这个三角剖分的动画

有没有人有一些可以帮助我实现解决方案的指针

我曾考虑在SwingWorker类中使用publish and process方法,但后来发现这是多余的,因为分治算法直接生成最终的三角剖分


提前感谢。

评论是正确的。我会尝试让
partition()
方法将它计算的每个三角形(每次经过3个点)报告给SwingWorker,然后SwingWorker将
publish()
三角形。大概是这样的:

public interface TriangleListener {
    public void reportTriangle(final QuadEdge triangle);
}

public QuadEdge[] partition(List<PlanarPoint> list, TriangleListener listener) {
    QuadEdge[] convexHullEdges = new QuadEdge[2];
    if (list.size() == 2) {
        //Add edge
    } else if (list.size() == 3) {
        //Add a counter-clockwise oriented triangle
        listener.reportTriangle(new QuadEdge(list));
    }
    ...
}

private class GuibasStolfiWorker extends
        SwingWorker<Void, QuadEdge> implements TriangleListener 
{
    ...
    protected void process(List<QuadEdge> chunks) {
        drawingPanel.addTrianglesToList(chunks);

        drawingPanel.repaint();
    }

    public void done() {
        // Nothing to do - panel has all triangles already
    }

    @Override
    public void reportTriangle(final QuadEdge triangle) {
        publish(triangle);
    }
}

public interface TriangleLsitener {
    public void reportTriangle(final QuadEdge triangle);
}
公共接口三角形Listener{
公共三角形(最终四边形三角形);
}
公共四边形[]分区(列表、三角形侦听器侦听器){
QuadEdge[]ConvexHullEdge=新的QuadEdge[2];
if(list.size()==2){
//添加边
}else if(list.size()==3){
//添加一个逆时针方向的三角形
reportTriangle(新的四边形(列表));
}
...
}
私有类GuibasStolfiWorker扩展
SwingWorker实现了TriangleListener
{
...
受保护的无效进程(列表块){
drawingPanel.AddTriangalSolist(块);
drawingPanel.repaint();
}
公众假期结束(){
//无事可做-面板已包含所有三角形
}
@凌驾
公共三角形(最终四边形三角形){
出版(三角);
}
}
公共接口TriangleSitener{
公共三角形(最终四边形三角形);
}
抱歉,如果我没有正确理解细微差别-我假设
四边形是三角形,所有这些


并且一定要考虑@kleopatra的建议——也许SwingWorker的构造函数可以考虑
列表
,而不是从
doInBackground()

中的面板中获取与您的问题无关的内容,只是要注意:不要访问doInBackground中的非同步ui属性(你的情况可能是,也可能不是:-)也许是盲目的,但是:看起来你没有在doInBackground中的任何地方调用publish-这意味着从未调用过进程…@kleopatra我尝试调用publish,但没有帮助。感谢您提供的非同步访问提示。我将更改它。这不是一个答案-只是一个提示:如果你不调用publish,则实现进程没有意义:-)将侦听器用作接口。非常聪明!我试试看。谢谢你的提示!只是一个问题,您将如何定义TriangleListener?好的,我编辑了答案以显示TriangleListener是如何定义的。。。祝你好运谢谢你告诉我这个定义。我用类似的方式定义了它。让我感到困惑的是侦听器作为一个参数传递给了配分函数。在java中,无法实例化接口,因此我使用新的TriangleListener()传递了一个匿名内部类
public interface TriangleListener {
    public void reportTriangle(final QuadEdge triangle);
}

public QuadEdge[] partition(List<PlanarPoint> list, TriangleListener listener) {
    QuadEdge[] convexHullEdges = new QuadEdge[2];
    if (list.size() == 2) {
        //Add edge
    } else if (list.size() == 3) {
        //Add a counter-clockwise oriented triangle
        listener.reportTriangle(new QuadEdge(list));
    }
    ...
}

private class GuibasStolfiWorker extends
        SwingWorker<Void, QuadEdge> implements TriangleListener 
{
    ...
    protected void process(List<QuadEdge> chunks) {
        drawingPanel.addTrianglesToList(chunks);

        drawingPanel.repaint();
    }

    public void done() {
        // Nothing to do - panel has all triangles already
    }

    @Override
    public void reportTriangle(final QuadEdge triangle) {
        publish(triangle);
    }
}

public interface TriangleLsitener {
    public void reportTriangle(final QuadEdge triangle);
}