Что я делаю неправильно, из-за чего этот график прокручивается неправильно? - PullRequest
1 голос
/ 23 сентября 2019

Я пытаюсь создать простую Java-программу, которая принимает математическую функцию в качестве входных данных и отображает 2D (x и y) график в JPanel.У меня график отображается правильно изначально.Я попытался добавить прокрутку к холсту (я назвал подкласс JPanel, я сделал GraphCanvas), и я имею в виду, что когда мышь перетаскивается по ней, прокручивается и 2D-плоскость, и график обновляется для вновь выявленных областей.Чтобы отобразить эту фактическую функцию, я использую объект Path2D, который состоит из сегментов, соединяющих достаточно точек, чтобы график находился в максимальном разрешении, и я использовал AffineTransforms для перевода пути.Стоит отметить, что я до сих пор тестировал программу только с функциями в форме f (x), а не с параметрическими, хотя я создал класс и поддерживающий код в классе GraphedInstance для параметрических функций.Я не хотел включать весь код для проекта, но я поместил его в репозиторий GitHub здесь (я очень мало знаю о том, как работает GitHub, но это должно быть правильно).

Моя проблема в том, что в данный момент, когда я пытаюсь прокрутить график, функция просто делает свое дело и неправильно соединяется с инициализированной частью.Он не отображает вновь сгенерированные части правильно.

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

Это метод, который должен создавать и объединять новые части пути функции, и именно в этом, я думаю, проблема, возможно, кроется.Этот и остальной проект также можно найти в репозитории GitHub.Кроме того, извините за любой грязный код и / или отсутствие комментариев, я только новичок в колледже и на самом деле не имел никакого официального обучения Java, я просто как-то поднял его на ходу.Я был бы рад принять любые предложения или рекомендации о лучших способах сделать что-нибудь также!


import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;

public class Minimal {

    private static int[] lastPointer = new int[2];
    private static double xMin, xMax, yMin, yMax;
    private static double xScale, yScale;
    private static double minXGraphed, maxXGraphed;

    public static Path2D.Double function;

    //The frame enclosing the graphing canvas
    private static JFrame frame;
    //The graphing canvas
    private static JPanel canvas = new JPanel() {
        private static final int DEFAULT_CANVAS_SIZE = 600;

        //Ensures the frame initialized to the right size
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(DEFAULT_CANVAS_SIZE, DEFAULT_CANVAS_SIZE);
        }

        //Paints the graph whenever it needs updating
        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            super.paintComponent(g2);

            xScale = getWidth() / (xMax - xMin);
            yScale = getHeight() / (yMax - yMin);

            g2.setColor(Color.BLUE);
            try {
                g2.draw(function);
            } catch (NullPointerException e) {
                e.printStackTrace();
            }
        }

    };

    /**
     * I'm using the function y = exp(x) as an example. Feel free to replace it.
     * @param x the x-value
     * @return exp(x), the y-value
     */
    private static double getYVal(double x) {
        return Math.exp(x);
    }

    //Initializes the function path
    public static void initPath() {
        final double STEP_X = (xMax - xMin) / canvas.getWidth();

        function = new Path2D.Double();

        double x = xMin;
        double y = getYVal(x);

        function.moveTo(getGraphX(x), getGraphY(y));
        for(x = xMin + STEP_X; x <= xMax; x += STEP_X) {
            y = getYVal(x);
            function.lineTo(getGraphX(x), getGraphY(y));
        }
    }

    /**
     * Gets the pixel x-coordinate on the canvas
     * that corresponds to a given x-value of the function
     * @param x the x-value of the function
     * @return the adjusted x-coordinate
     */
    private static int getGraphX(double x) {
        return (int) (canvas.getWidth() * (x - xMin) / (xMax - xMin));
    }

    //Same thing as getGraphX except for y-coords
    private static int getGraphY(double y) {
        return (int) (canvas.getHeight() * (yMax - y) / (yMax - yMin));
    }

    /*
     * This is probably where the problem is, this extends the path so that it
     *      covers the entire visible range
     */
    public static void updateFunctionBounds(double dx) {

        double newXMin = xMin - dx / xScale;
        double newXMax = xMax - dx / xScale;

        final int WIDTH = canvas.getWidth();
        final double STEP_X = (xMax - xMin) / WIDTH;
        double drawTo;

        if((drawTo = newXMin) < xMin && drawTo < minXGraphed) {
            minXGraphed = drawTo;

            double x = drawTo;
            function.moveTo(getGraphX(x), getGraphY(getYVal(x)));

            for(x = drawTo + STEP_X; x < xMin; x += STEP_X) {
                function.lineTo(getGraphX(x), getGraphY(getYVal(x)));
            }

            x = xMin;
            function.lineTo(getGraphX(x), getGraphY(getYVal(x)));

        } else if((drawTo = newXMax) > xMax && drawTo > maxXGraphed) {
            maxXGraphed = drawTo;

            double x = xMax;
            function.moveTo(getGraphX(x), getGraphY(getYVal(x)));

            for(x = xMax + STEP_X; x < drawTo; x += STEP_X) {
                function.lineTo(getGraphX(x), getGraphY(getYVal(x)));
            }

            x = drawTo;
            function.lineTo(getGraphX(x), getGraphY(getYVal(x)));

        }
    }

    public static void main(String[] args) {
        initBounds();
        initFrame();
    }

    //Initializes the graph boundaries. Feel free to change this
    private static void initBounds() {
        xMin = yMin = minXGraphed = -10;
        xMax = yMax = maxXGraphed = 10;
    }

    //Initializes the frame and a MouseAdapter that controls the scrolling
    private static void initFrame() {
        MouseAdapter adapter = new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                super.mousePressed(e);
                lastPointer[0] = e.getX();
                lastPointer[1] = e.getY();
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                super.mouseDragged(e);
                AffineTransform t = new AffineTransform();
                double dx = e.getX() - lastPointer[0];
                double dy = e.getY() - lastPointer[1];
                t.translate(dx, dy);

                updateFunctionBounds(dx);
                function.transform(t);

                xMin -= dx / xScale;
                xMax -= dx / xScale;
                yMin -= dy / yScale;
                yMax -= dy / yScale;

                canvas.repaint();

                lastPointer[0] = e.getX();
                lastPointer[1] = e.getY();
            }
        };
        canvas.addMouseListener(adapter);
        canvas.addMouseMotionListener(adapter);

        frame = new JFrame("Minimal Reproducible Approach");
        frame.setContentPane(canvas);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.pack();
        frame.setVisible(true);

        initPath();
        canvas.repaint();
    }
}

Если бы это работало правильно, сшивание было бы бесшовным, и функция плавно прокручивалась, как указатель мыши былперетаскивали по холсту, как в Desmos.На самом деле он не сохраняет правильную высоту (значение y) и фактически не соединяется с предыдущими сегментами во всех случаях.

Спасибо за любую помощь!

Редактировать: я обновил код до минимального воспроизводимого примера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...