Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

animating a recursive triangulation algorithm using swingworker

This is kind of a follow-up question to a question I asked over here regarding how to paint an applet/window while using SwingWorker

In this particular instance, I am using a divide and conquer algorithm proposed by Guibas and stolfi to compute a Delaunay triangulation of a set of points say P.

The algorithm is as follows: 1. If sizeof(p)==2, add an edge; return 2. If sizeof(p)==3, add a counter-clockwise oriented triangle; return 3. if sizeof(p) > 3, divide(p) into left and right halves. Triangulate the individual halves merge the halves together

I have a triangulation class whose triangulate method (as shown in the code block) will implement the divide and conquer algorithm (according to the pseudo-code provided by Guibas and Stolfi)

public QuadEdge[] partition(List<PlanarPoint> list) {
        QuadEdge[] convexHullEdges = new QuadEdge[2];
        if (list.size() == 2) {
            //Add edge
        } else if (list.size() == 3) {
            //Add a counter-clockwise oriented triangle
        } else if (list.size() > 3) {
            List<PlanarPoint> leftHalf = new ArrayList<PlanarPoint>();
            List<PlanarPoint> rightHalf = new ArrayList<PlanarPoint>();
            //Divide the list of points into 2 halves
            QuadEdge[] leftDelaunay = triangulate(leftHalf);
            QuadEdge ldo = leftDelaunay[0];
            QuadEdge ldi = leftDelaunay[1];

            QuadEdge[] rightDelaunay = triangulate(rightHalf);
            QuadEdge rdi = rightDelaunay[0];
            QuadEdge rdo = rightDelaunay[1];
            // Merge the two halves
            merge(ldo,ldi,rdi,rdo);
        }
        return convexHullEdges;
    }

I have a DrawingPanel which acts as a Canvas class and paints the triangles,points on the drawing surface.

I am using a SwingWorker in my main Triangulate class to call the triangulate method.

Here's the code for the 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) {

            }
        }
    };

Now, I would like to animate this triangulation, by showing the triangulation appearing after the recursive call to the triangulate and then the merge function.

Does anybody have some pointers which will help me implement the solution?

I thought about using the publish and process method in the SwingWorker class, but then figured out that would be redundant since the divide and conquer algorithm directly comes up with the final triangulation.

Thanks in advance.

like image 819
chaitanya Avatar asked Nov 04 '22 03:11

chaitanya


1 Answers

Comments are on the right track. I would try to have the partition() method report each triangle that it calculates (each time it is passsed 3 points) back to the SwingWorker, and which will then publish() the triangle. Something like this:

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);
}

Sorry if I didn't get the nuances right - I'm assuming a QuadEdge is a triangle, and all that...

And definitely take @kleopatra's advice into account - perhaps the constructor of your SwingWorker could take the List<PlanarPoint> rather than getting from the panel in doInBackground().

like image 101
Rob I Avatar answered Nov 11 '22 12:11

Rob I