Using Math class

TrajectoryCalculator class utilizes the Math class in order to perform operations to find the equation.

More specifically, it uses Math.pow(), Math.cos(), Math.tan(), and Math.PI.

// The line below isn't necessary in Jupyter Notebook
//package com.hacks.trajectoryCalculator;

import org.jfree.data.function.Function2D;

/*
 * Actual math for calculating trajectory
 * 
 * Calculates equation as a string
 *  
 * Returns equation
 * 
 */

 public class TrajectoryMath implements Function2D {

    // Initialize variables
    private double velocity;
    private double degrees;
    private double height;
    private String equation;
    private double coefficientA;
    private double coefficientB;
    private double coefficientC;

    
    // Constructor
    public TrajectoryMath(double velocity, double degrees, double height) {
        this.velocity = velocity;
        this.degrees = degrees;
        this.height = height;

        this.calculateEquation();
    }

    // Getters and setters
    public double getVelocity() {
        return this.velocity;
    }

    public double getDegrees() {
        return this.degrees;
    }

    public double getHeight() {
        return this.height;
    }

    public String getEquation() {
        return this.equation;
    }

    public double getCoefficientA() {
        return this.coefficientA;
    }

    public double getCoefficientB() {
        return this.coefficientB;
    }

    public double getCoefficientC() {
        return this.coefficientC;
    }

    // Gets the root of the equation
    // There should be only one positive root, so the method will return that and discard the other
    // Returns 0.0 if none is found (which shouldn't happen usually)
    public double getRoot() {
        double rootOne = (-this.coefficientB + Math.sqrt(Math.pow(coefficientB, 2) - 4 * (-this.coefficientC) * this.coefficientA)) / (2 * (-this.coefficientC));
        double rootTwo = (-this.coefficientB - Math.sqrt(Math.pow(coefficientB, 2) - 4 * (-this.coefficientC) * this.coefficientA)) / (2 * (-this.coefficientC));

        if (rootOne > 0) {
            return rootOne;
        } else if (rootTwo > 0) {
            return rootTwo;
        } else {
            return 0.0;
        }
    }

    public void setVelocity(double velocity) {
        this.velocity = velocity;
    }

    public void setDegrees(double degrees) {
        this.degrees = degrees;
    }
    
    public void setHeight(double height) {
        this.height = height;
    }

    // Array should be in order of velocity, degrees, and height
    public void setParameters(double[] values) {
        this.velocity = values[0];
        this.degrees = values[1];
        this.height = values[2];
    }

    // Math for equation
    private void calculateEquation() {

        // Calculates coefficients for each part
        this.coefficientA = height;
        this.coefficientB = Math.tan(degrees * Math.PI/180);
        this.coefficientC = 9.8 / (2 * Math.pow(velocity, 2) * Math.pow(Math.cos(degrees * Math.PI/180), 2));

        // Makes string of equation just in case
        String precheckedEquation = "y = " + String.valueOf(coefficientA) + " + " + String.valueOf(coefficientB) + "x - " +
        String.valueOf(coefficientC) + "x^2";
        this.equation = precheckedEquation;
    }

    // Returns equation
    public double getValue(double v) {
        return coefficientA + coefficientB * v - coefficientC * Math.pow(v, 2);
    }

    /*
     * public static void main(String[] args) {
        TrajectoryMath example = new TrajectoryMath(15, 60, 4);
        System.out.println(example.getRoot());
     }
     */
     
   
 }

Using GUI

InputInitial creates the prompt for the user to enter inputs.

TrajectoryGraph outputs the graph for the user to visualize.

// Below line is unnecessary
//package com.hacks.trajectoryCalculator;

import javax.swing.JOptionPane; // library to display options
import javax.swing.JTextField; // library to create a text field to render on GUI

public class InputInitial {
    // instance variables to be used
    public static Double initialVelocity;
    public static Double initialDegrees;
    public static Double initialHeight;

    // create the GUI element that users input into
    public void spawnInputs() {
        // while the values have not changed yet, keep going (for error handling)
        while (initialVelocity == null || initialDegrees == null || initialHeight == null) {
            // text field initialization
            JTextField inputVelocity = new JTextField();
            JTextField inputDegrees = new JTextField();
            JTextField inputHeight = new JTextField();

            // organizing the input text to display + the text field in object
            Object[] inputs = {
                "Initial Velocity (m/s):", inputVelocity,
                "Initial Degrees:", inputDegrees,
                "Initial Height (m):", inputHeight
            };

            JOptionPane.showConfirmDialog(null, inputs, "Input the initial values for your object (numbers only):", JOptionPane.OK_CANCEL_OPTION); // creates the option menu with the 3 inputs

            // take the input, assign it to the public variables
            initialVelocity = parseInput(inputVelocity);
            initialDegrees = parseInput(inputDegrees);
            initialHeight = parseInput(inputHeight);
        }
        
    }

    // change JTextField into Double, also error handling
    public Double parseInput(JTextField inputValue) {
        String placeholder = inputValue.getText(); // get the string out of the input
        
        // error handling + edge cases
        try {
            double initialValue = Double.parseDouble(placeholder);

            // if negative, cannot be valid so throw error --> reinput values bc still null
            if (initialValue < 0.0) {
                JOptionPane.showMessageDialog(null, "Inputs must be greater than 0", "Invalid Input", JOptionPane.WARNING_MESSAGE);
                return null;
            } else { // if everything ok, return the value
                return initialValue;
            }
            
        } catch (Exception e) { // if cannot be cased as a double, throw error --> reinput values
            JOptionPane.showMessageDialog(null, "There was an invalid input for " + placeholder + ", please try again. " + e, "Unwanted Input", JOptionPane.WARNING_MESSAGE);
            return null;
        }
    }
}
// Below line is unnecessary
// package com.hacks.trajectoryCalculator; // maven build

// import the graphs
import org.jfree.data.function.Function2D;
import org.jfree.data.general.*;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYDataset;

// import the other files
import com.hacks.trajectoryCalculator.*;

// import swing and awt
import javax.swing.JFrame;
import java.awt.Dimension;

public class TrajectoryGraph extends JFrame {
    // Constructor of the graph that will be displayed
    public TrajectoryGraph() {
        InputInitial newInputs = new InputInitial(); // start input object from separate file
        newInputs.spawnInputs(); // start the process of collecting user input
       drawGraph(InputInitial.initialVelocity, InputInitial.initialDegrees, InputInitial.initialHeight); // call method to draw the graph with the user input taken
    }

    // graph drawer
    public void drawGraph(double velocity, double degrees, double height) {
        Function2D test = new TrajectoryMath(velocity, degrees, height); // TrajectoryMath implements function2d, so use those values create new function2d object
        TrajectoryMath testGetter = new TrajectoryMath(velocity, degrees, height); // creates TrajectoryMath object from the other file to call custom methods
        XYDataset dataset = DatasetUtils.sampleFunction2D(test, 0.0, testGetter.getRoot(), 50, "Function"); // generates the dataset of xy values with the function
        final JFreeChart chart = ChartFactory.createXYLineChart("Trajectory Equation", "X Position (meters)", "Y Position (meters)", dataset, PlotOrientation.VERTICAL, true, true, false); // creates the actual graph with attributes
        
        // initializing the display
        ChartPanel cp = new ChartPanel(chart) {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(500, 500); // set initial dimension
            }
        };

        // allow mouse wheel scrolling
        cp.setMouseWheelEnabled(true);
        add(cp);

        // Finalize the building of the graph
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack();
    }
    public static void main(String[] args) {
    
        // runs the creation of the graph with a queue in a different thread and posts the gui after events are processed
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                // initialize new TrajectoryGraph object, setvisible to display the graph
                new TrajectoryGraph().setVisible(true);
            }
        });
        
    }
}