перекраска апплета от работника качания, используемого для вычисления треугольников и окружностей - PullRequest
3 голосов
/ 26 января 2012

Я пытаюсь воспроизвести найденный апплет здесь как часть упражнения. Апплет использует алгоритм Fortune для генерации обоих; диаграмма Вороного и триангуляция Делоне. Я просто заинтересован в генерации триангуляции Делоне на плоскости и, следовательно, буду использовать инкрементные алгоритмы, то есть добавлять по 1 точке за раз. Я намереваюсь показать треугольники, генерируемые на каждом этапе, когда добавляется точка выборки.

Я использую класс SwingWorker для создания экземпляра класса Triangulate, который содержит алгоритм. Я вызываю метод triangulate внутри цикла for, который перебирает множество точек выборки при нажатии кнопки запуска в графическом интерфейсе.

Вот код для этого:

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

Вот класс Triangulate, который вычисляет триангуляцию Делануэя для набора точек:

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

У меня есть 3 других класса

  1. PlanarPoint - подкласс Point2D.Double, который реализует Comparable для обеспечения сортировки на основе y-координат
  2. Треугольник - класс, который определяет окружность и радиус окружности для треугольника и определяет, находится ли точка внутри окружности треугольника
  3. Edge - класс, который представляет Edge как класс, имеющий 2 PlanarPoints в качестве конечных точек.
  4. DrawingPanel - класс, который действует как поверхность, на которой точки добавляются при событиях щелчка и рисуются на экране.

    Теперь вот несколько проблем, которые у меня есть

    1. Есть ли лучший способ показать треугольники и, возможно, окружности, путем перебора набора точек и последующего вызова функции класса Triangulate для получения существующих окружностей и треугольников
    2. Должен ли весь рисунок быть ограниченным классом DrawingPanel, поскольку в приведенных выше фрагментах кода я рисую в классе, расширяющем JApplet / JFrame, и, таким образом, при изменении размера окна нарисованные треугольники теряются? Есть ли шаблон дизайна, которому я могу следовать?
    3. Оправдано ли использование SwingWorker для порождения другого потока, за исключением того факта, что время вычисления DT набора точек является трудоемкой задачей?

Если я пропустил какие-либо детали, пожалуйста, дайте мне знать

Спасибо, Chaitanya

1 Ответ

5 голосов
/ 26 января 2012

Предложения:

  • Не используйте getGraphics() для получения объекта Graphics, поскольку полученный объект Graphics не будет сохраняться, если будет выполнена какая-либо перекраска (что-то вне вашего контроля). Вместо этого нарисуйте в BufferedImage и попросите JPanel или JComponent нарисовать BufferedImage в его переопределении paintComponent или добавьте данные своего изображения в какую-либо коллекцию, а метод переопределения paintComponent перебирает коллекцию, используя информацию для рисования ваших изображений. 1005 *
  • Не рисуйте непосредственно в окне верхнего уровня, таком как JFrame или JApplet, а вместо этого в компоненте, производном от JComponent, часто либо в самом JComponent, либо в JPanel.
  • Прочитайте учебные руководства по Swing, поскольку они объяснят все это и многое другое.
  • SwingWorker полностью оправдан, поскольку вы хотите создать поток, который является фоном для приложения Swing, но взаимодействует с приложением Swing - той самой ситуацией, для которой был создан SwingWorkers.
...