Download Java source from study.zip
Opening screen | After pressing next button once | After pressing next button again |
Use mouse to locate new starting point and direction.
Also see Ball.java
study.java
import java.awt.*; import java.awt.geom.Rectangle2D; import javax.swing.*; import java.util.*; import java.awt.event.*; public class study extends JPanel { int qx = 220; int qy = 80; Ball circ1 = new Ball(qx,qy,0,0,new Color(0,190,0)); //Circle circ1 = new Circle(qx*s,qy*s,radius1*s); int px = 100; int py = 130; //Circle circ2 = new Circle(px*s,py*s,radius2*s); int vx = 80; int vy = -40; Ball circ2 = new Ball(px,py,vx,vy,Color.BLUE); //Line vec; double t1, t2; double wd,ht; JTextArea area; boolean flag = true; JButton button = new JButton("next"); int ns; study() { circ1.set_radius(15); circ2.set_radius(10); area = new JTextArea(6,20); //area.setPrefRowCount(6); area.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); area.setLineWrap(true); area.setEditable(false); area.append("Ball study"); solve(); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int n = (ns+1)%3; move(n); repaint(); } }); addMouseListener( new MouseClickHandler() ); } // inner class to handle mouse events private class MouseClickHandler extends MouseAdapter { public void mouseClicked( MouseEvent e ) { int x = e.getX(); int y = e.getY(); ns = 0; if (flag) { px = x; py = y; circ2.px = px; circ2.py = py; vx = 0; vy = 0; flag= false; } else { vx = x - px; vy = y - py; flag = true; } solve(); repaint(); } } public Dimension getPreferredSize() { return new Dimension(300,200); } public void solve() { double scl = 10.0; t1 = t2 = -1; // relative velocity double rx = vx/scl; double ry = vy/scl; // relative position double dx = (px - qx)/scl; double dy = (py - qy)/scl; // test radius double r = (circ1.radius + circ2.radius)/scl; double A = rx*rx+ry*ry; double B = rx*dx+ry*dy; double C = dx*dx + dy*dy - r*r; area.setText(""); area.append(String.format("A %g B %g C %g%n",A,B,C)); double radical = B*B-A*C; area.append(String.format("radical B*B - A*C = %g%n",radical)); if (C<0) { area.append(String.format("C<0, balls overlap at start%n")); } if (A<=0.0) { area.append(String.format("A==0, No motion%n")); return; } if (radical<0) { area.append(String.format("radical < 0, No solution%n")); return; } if (B>0) { area.append(String.format("B>0, balls moving away from one another%n")); return; } double R = Math.sqrt(radical); t1 = (-B-R)/A; t2 = (-B+R)/A; area.append(String.format("t1 = %g t2 = %g%n",t1,t2)); } public void move(int pos) { ns = pos; if (pos==0) { circ2.px = px; circ2.py = py; } if (pos==1 && t1>0) { circ2.px = px+vx*t1; circ2.py = py+vy*t1; } if (pos==2 && t2>0) { circ2.px = px+vx*t2; circ2.py = py+vy*t2; } } public void paintComponent(Graphics g) { super.paintComponent( g ); circ1.draw(g); circ2.draw(g); g.setColor(Color.BLACK); g.drawLine(px,py,px+vx,py+vy); } public static void main( String args[] ) { EventQueue.invokeLater(new Runnable() { public void run() { study panel = new study(); JFrame application = new JFrame("Ball Study"); application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); application.add(panel); application.add(panel.area,BorderLayout.SOUTH); JPanel top = new JPanel(); top.add(panel.button); application.add(top,BorderLayout.NORTH); application.pack(); application.setVisible(true); } }); } }
Maintained by John Loomis, updated Sat Feb 23 15:59:20 2019