Download and run(with java) the .jar
https://drive.google.com/file/d/1gQGtCntPb3NsV14_5K9qgR3ewU--5DzK/view?usp=sharing
NewtonRaphson method for solution x^4
or compile and run....
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package time2ballscollisionwithdeceleration;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
/**
*
* @author dimitrak
*/
public class Time2BallsCollisionWithDeceleration extends JFrame implements MouseListener,MouseMotionListener,MouseWheelListener{
public static void main(String[] args) {
new Time2BallsCollisionWithDeceleration();
Balla a=new Balla();
System.out.println("epibradynsi: "+a.a);
a.resetAtSpeed(8);
System.out.println("speed Arxiko "+a.sp);
System.out.println("distToStop "+a.Ddist(a.timeToStop));
System.out.println("timeNow : "+a.timeNow);
System.out.println("Now speed : "+a.spn);
}
Balla a=new Balla();
Balla b=new Balla();
Thread thrSim=new Thread(){
public void run(){
while(true){
runSimStep();
}
}
};
JLabel jlDt=new JLabel("DT-sim millis");
JSpinner jspDt=new JSpinner(new SpinnerNumberModel(100,10,1000,10));
JPanel jpDt=new JPanel(new BorderLayout());
JCheckBox jchPlayReturn=new JCheckBox("return trip",true);
JPanel jpn=new JPanel(new FlowLayout());
public Time2BallsCollisionWithDeceleration(){
super("Find TIME of Collision between 2 balls with (radius,speed,angle , AND DECELARATION from friction)");
a.col=Color.blue;
b.col=Color.magenta;
jpDt.add(BorderLayout.WEST,jlDt);
jpDt.add(BorderLayout.CENTER,jspDt);
jpn.add(jchPlayReturn);
jpn.add(jbPlay);
jpn.add(jbTimeZero);
jpn.add(jpDt);
getContentPane().add(BorderLayout.CENTER,jp);
getContentPane().add(BorderLayout.NORTH,jpn);
setBounds(0,0,777,666);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
jp.addMouseListener(this);
jp.addMouseMotionListener(this);
jp.addMouseWheelListener(this);
thrSim.start();
jbPlay.addActionListener(e->jbPlay());
jbTimeZero.addActionListener(e->jbTimeZero());
a.resetAtPos(350,140);
a.resetAtAngle(Math.toRadians(45));
a.resetAtSpeed(35);
b.resetAtPos(a.r,400);
b.resetAtAngle(-Math.toRadians(30));
b.resetAtSpeed(46);
recomputeCollisionTime();
}
Graphics2D g=null;
JPanel jp=new JPanel(){
public void paintComponent(Graphics gr){
super.paintComponent(gr);
g=(Graphics2D)gr;
paintingBalls();
}
};
Font font=new Font("Dialog",0,16);
void paintingBalls(){
g.setColor(Color.black);
g.setFont(font);
int x=10;
int y=font.getSize();
g.drawString("Press IN some ball and dragg mouse to change ball location", x,y);
y+=font.getSize();
g.drawString("Mouse Roll a)to change ball Speed ,b)+SHIFT to change ball Angle, c)+SHIFT+CNTRL to change ball DE-CELARATION(friction*g)", x,y);
y+=font.getSize();
g.drawString(" "+ex+a.timeCollision, x,y);
y+=font.getSize();
g.drawString("Solution/Collision Time : "+a.timeCollision, x,y);
if(a.timeCollision>a.timeToStop && a.timeCollision>b.timeToStop){
g.setColor(Color.red);
y+=font.getSize();
g.drawString("Solution/Collision is on RETURN TRIP...not valid on billiards", x,y);
}
y+=font.getSize();g.setColor(Color.black);
g.drawString("simTime:"+simTimeSecNow, x,y);
y+=font.getSize();g.setColor(a.col);
g.drawString("a timeToStop: "+a.timeToStop, x,y);
y+=font.getSize();g.setColor(b.col);
g.drawString("b timeToStop: "+b.timeToStop, x,y);
y+=font.getSize();g.setColor(a.col);
g.drawString("a dist till collision: "+a.distcol, x,y);
y+=font.getSize();g.setColor(b.col);
g.drawString("b dist till collision: "+b.distcol, x,y);
y+=font.getSize();g.setColor(a.col);
g.drawString("a acc: "+-a.a, x,y);
y+=font.getSize();g.setColor(b.col);
g.drawString("b acc: "+-b.a, x,y);
a.paint(g);
b.paint(g);
}
@Override
public void mouseClicked(MouseEvent e) {
}
boolean pressedLeft,pressedRight;
Balla ballNowPressed=a;
@Override
public void mousePressed(MouseEvent e) {
pressedLeft=e.getButton()==MouseEvent.BUTTON1;
pressedRight=e.getButton()==MouseEvent.BUTTON3;
ballNowPressed=null;
double dist1=a.dist(e.getX(),e.getY());
double dist2=b.dist(e.getX(),e.getY());
System.out.println(""+dist1+" , "+dist2);
if(dist1<=a.r && dist1<=dist2){
ballNowPressed=a;
}
if(dist2<=b.r && dist2<=dist1){
ballNowPressed=b;
}
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
if(ballNowPressed!=null){
ballNowPressed.resetAtPos(e.getX(),e.getY());
recomputeCollisionTime();
}
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
if(ballNowPressed!=null){
double mul=1;
if(e.isAltDown()){
mul*=10;
}
if(!e.isShiftDown()){
ballNowPressed.resetAtSpeedDif(-mul*e.getWheelRotation());
}
else{
if(!e.isControlDown()){
ballNowPressed.resetAtAngleDif(Math.toRadians(-5*e.getWheelRotation()));
}
else{
ballNowPressed.resetAtAccDif(-mul*0.1*e.getWheelRotation());
}
}
recomputeCollisionTime();
}
}
Pol ex=new Pol(4);
public double solNewtonRaphson(double Ax,double Ay,double Asp,double Aacc,double Aang,double Aradius,
double Bx,double By,double Bsp,double Bacc,double Bang,double Bradius){
double dx=Bx-Ax;
double dy=By-Ay;
double R=Aradius+Bradius;//dy^2 + dx^2 =R^2
double d=Aacc/2;
double c=Bacc/2;
double h=Asp;
double e=Bsp;
double m=Math.cos(Aang);
double k=Math.cos(Bang);
double f=Math.sin(Aang);
double l=Math.sin(Bang);
double ckdm=c*k-d*m;//coses
double ekhm=e*k-h*m;//coses
double cldf=c*l-d*f;//sins
double elhf=e*l-h*f;//sins
ex.p[0]=dx*dx + dy*dy - R*R;
ex.p[1]=2*dx*ekhm + 2*dy*elhf;
ex.p[2]=ekhm*ekhm + 2*dx*ckdm + elhf*elhf + 2*dy*cldf;
ex.p[3]=2*ekhm*ckdm + 2*elhf*cldf;
ex.p[4]=ckdm*ckdm + cldf*cldf;
ex.showAllDerivatives();
System.out.println("Possible: "+ex.findSomeQuickNewtonRoot());
return ex.NewtonRaphson(ex.findSomeQuickNewtonRoot(), 100, 0.0000001);
}
void recomputeCollisionTime(){
maxTimeSec=Math.max(a.timeToStop, b.timeToStop);
if(jchPlayReturn.isSelected()){
maxTimeSec*=2;
}
double t=solNewtonRaphson(
a.xf,a.yf,a.sp,-a.a,a.an,a.r
,b.xf,b.yf,b.sp,-b.a,b.an,b.r
);
System.out.println("Collision AT Time: "+t);
a.resetAtTimeCollision(t);
b.resetAtTimeCollision(t);
jp.repaint();
}
/**
* Searching t (collision time)
* AendX=AstartX+(t*Aspeed)cos(Aangle)
* AendY=AstartY+(t*Aspeed)sin(Aangle)
* BendX=BstartX+(t*Bspeed)cos(Bangle)
* BendY=BstartY+(t*Bspeed)sin(Bangle)
*
* (BendY-AendY)^2 +(BendX-AendX)^2 = (ARadius+BRadius)^2
*//*
void recomputeCollisionTime0(){
//System.out.println("recomputing collision time");
double tLess=-1;
double aco=a.sp*Math.cos(a.an);
double asi=a.sp*Math.sin(a.an);
double bco=b.sp*Math.cos(b.an);
double bsi=b.sp*Math.sin(b.an);
double dsi=bsi-asi;
double dco=bco-aco;
double dy=b.yf-a.yf;
double dx=b.xf-a.xf;
double A=dsi*dsi+dco*dco;
double B=2*((dsi)*(dy)+(dco)*(dx));
double C=dy*dy+dx*dx-Math.pow(a.r+b.r,2);
double D=B*B-4*A*C;//System.out.println("D = "+D);
if(D<0){System.out.println("No solutions");}
else{
double t1=(-B-Math.sqrt(D))/(2*A);
double t2=(-B+Math.sqrt(D))/(2*A);//System.out.println("t1 : "+t1+" , t2: "+t2);
tLess=t1;
if(t2<t1){tLess=t2;}
}
//a.resetAtTimeCollision(tLess*1000);
//b.resetAtTimeCollision(tLess*1000);
jp.repaint();
}*/
JButton jbPlay=new JButton("Play");
JButton jbTimeZero=new JButton("TimeZero");
boolean simPaused=true;
long pauseMillis=60000;
long stepMillis=(int)jspDt.getValue();
double stepSec=((double)stepMillis)/1000d;
double simTimeMillisNow=0;
double simTimeSecNow=0;
double maxTimeSec=10;
void runSimStep(){
long sl=pauseMillis;
if(!simPaused){
boolean simend=false;
sl=stepMillis;
if(jchPlayReturn.isSelected()){
a.resetAtTimeNow(simTimeSecNow);
b.resetAtTimeNow(simTimeSecNow);
}
else{
if(a.timeToStop>=simTimeSecNow){
a.resetAtTimeNow(simTimeSecNow);
}
if(b.timeToStop>=simTimeSecNow){
b.resetAtTimeNow(simTimeSecNow);
}
}
jp.repaint();
simTimeMillisNow+=stepMillis;
simTimeSecNow+=stepSec;
if(simTimeSecNow>maxTimeSec){
simend=true;
simPause();
jbTimeZero();
}
}
try{thrSim.sleep(sl);}catch(InterruptedException inter){}
}
void jbPlay(){
if(simPaused){
simUnPause();
}
else{
simPause();
}
}
void simPause(){
jbPlay.setText("Play");
simPaused=true;
}
void simUnPause(){
jbPlay.setText("Simulating");
simPaused=false;
thrSim.interrupt();
}
void jbTimeZero(){
simTimeMillisNow=0;
simTimeSecNow=0;
}
}
class Balla{
double coefFriction=0.2;
double mass=0.2;
double g=10;
double a=coefFriction*g;
Color col=Color.BLUE;
double r=50;
double d=2*r;
double xf=2*r+Math.random()*300,yf=2*r+Math.random()*300;
double an=Math.toRadians(Math.random()*360);
double sp=10+Math.random()*10;
double xl,yl;
double timeToStop=sp/a;
double xe,ye;
double timeNow=timeToStop/2;
double spn=sp-a*timeNow;
double xn,yn;
double timeCollision=-1;
double spcol=sp-a*timeCollision;
double distcol=(Ddist(timeCollision));
double xc,yc;
public Balla(){
resetAtPos();
}
void resetAtPos(){
resetAtPos(xf, yf);
}
void resetAtPosold(double x,double y){
xf=x;
yf=y;
xl=xf+r*Math.cos(an);
yl=yf+r*Math.sin(an);
//1000 millis sp
//timeEnd x?
double distMaxTime=(sp*timeToStop)/1000;
xe=xf+distMaxTime*Math.cos(an);
ye=yf+distMaxTime*Math.sin(an);
double distNowTime=(sp*timeNow)/1000;
xn=xf+distNowTime*Math.cos(an);
yn=yf+distNowTime*Math.sin(an);
if(timeCollision>0){
xc=xf+distcol*Math.cos(an);
yc=yf+distcol*Math.sin(an);
}
}
public double Ddist(double t){
double out=sp*t-((a*t*t)/2);
return out;
}
void resetAtPos(double x,double y){
xf=x;
yf=y;
xl=xf+r*Math.cos(an);
yl=yf+r*Math.sin(an);
//1000 millis sp
//timeEnd x?
double distMaxTime=(Ddist(timeToStop));
//System.out.println("distMaxTime: " +distMaxTime+" for timeToStop="+timeToStop);
xe=xf+distMaxTime*Math.cos(an);
ye=yf+distMaxTime*Math.sin(an);
double distNowTime=(Ddist(timeNow));
xn=xf+distNowTime*Math.cos(an);
yn=yf+distNowTime*Math.sin(an);
if(timeCollision>0){
double distAtCollision=(Ddist(timeCollision));
xc=xf+distAtCollision*Math.cos(an);
yc=yf+distAtCollision*Math.sin(an);
}
}
void resetAtAngle(double newAngle){
an=newAngle;
resetAtPos();
}
void resetAtAngleDif(double difAngle){
resetAtAngle(difAngle+an);
}
void resetAtSpeed(double newSpeed){
sp=newSpeed;
timeToStop=sp/a;
spn=sp-a*timeNow;
System.out.println(sp+" m/ss -> TimeToStop = "+timeToStop);
resetAtPos();
}
void resetAtSpeedDif(double difSpeed){
resetAtSpeed(difSpeed+sp);
}
void resetAtTimeNow(double newNowTime){
timeNow=newNowTime;
spn=sp-a*timeNow;
resetAtPos();
}
void resetAtTimeCollision(double newCollisionTime){
timeCollision=newCollisionTime;
spcol=sp-a*timeCollision;
distcol=(sp*timeCollision)/1000;
resetAtPos();
}
void resetAtAcc(double accNew){
accNew=Math.abs(accNew);
a=accNew;
timeToStop=sp/a;
spn=sp-a*timeNow;
resetAtPos();
}
void resetAtAccDif(double accDif){
resetAtAcc(a+accDif);
System.out.println(""+a);
}
public double dist(double x,double y){
return Point.distance(xf, yf, x, y);
}
static BasicStroke strokeNormal=new BasicStroke(1);
static BasicStroke strokeMoving=new BasicStroke(1,0,0,10,new float[]{10,10},0);
public void paint(Graphics2D g){
g.setStroke(strokeNormal);
g.setColor(col);
g.drawOval((int)(xf-r),(int)(yf-r), (int)(d),(int)( d));
g.drawLine((int)(xf),(int)(yf),(int)(xl),(int)(yl));
g.drawOval((int)(xe-r),(int)(ye-r), (int)(d),(int)( d));
g.drawLine((int)(xf),(int)(yf),(int)(xe),(int)(ye));
g.drawString("V0="+(nice(sp))+" m/s", (int)(xf),(int)(yf));
g.setStroke(strokeMoving);
g.drawOval((int)(xn-r),(int)(yn-r), (int)(d),(int)( d));
g.drawString("V="+(nice(spn))+" m/s", (int)(xn),(int)(yn));
if(timeCollision>0){
g.setColor(Color.RED);
g.setStroke(strokeNormal);
int ucx=(int)(xc-r);
int ucy=(int)(yc-r);
g.drawOval(ucx,ucy, (int)(d),(int)( d));
//g.drawLine(ucx,ucy,(int)(ucx+d),(int)(ucy+d));
}
}
static double nice(double d){
d*=1000;
d=(long)d;
d/=1000;
return d;
}
}
class JNewtonRaphson {
public static void main(String[] args) {
}
static void test(){
Pol p=new Pol(3,-7,1,2,-19);
System.out.println(""+p);
System.out.println(""+p.strf(-1));
System.out.println(""+p.strf(0));
System.out.println(""+p.strf(1));
System.out.println(""+p.hasSolutionAt(-100, 100, 1));
System.out.println(""+p.findSomeQuickNewtonRoot());
p.showAllDerivatives();
System.out.println("--------------");
p.NewtonRaphson(0, 100, 0.0000001);
}
}
class Pol{
double[]p;
public Pol(int maxPower){
p=new double[maxPower+1];
}
public Pol(double []ps){
this(ps,false);
}
public Pol(double []ps,boolean assign){
if(assign){
p=ps;
}
else{
p=new double[ps.length];
System.arraycopy(ps, 0, p, 0, ps.length);
}
}
public Pol(double p2,double p1,double c){
this(2);
p[0]=c;
p[1]=p1;
p[2]=p2;
}
public Pol(double p3,double p2,double p1,double c){
this(3);
p[0]=c;
p[1]=p1;
p[2]=p2;
p[3]=p3;
}
public Pol(double p4,double p3,double p2,double p1,double c){
this(4);
p[0]=c;
p[1]=p1;
p[2]=p2;
p[3]=p3;
p[4]=p4;
}
public double NewtonRaphson(double xPossible,int maxsteps,double epsilon){
Pol ft=getfDerivative();
double x=xPossible;
double h = fHorner(x) / ft.fHorner(x);
int i=0;
while (i<maxsteps && Math.abs(h) >= epsilon){
x -=h;
h = fHorner(x) / ft.fHorner(x);
//System.out.println(i+" : "+x);
++i;
}
//System.out.println("sol: "+x);
System.out.println(""+strf(x));
return x;
}
public void showAllDerivatives(){
Pol a=this;
int ton=0;
while(a.p.length>1){
System.out.println("f["+(ton)+"](x)="+a);
a=a.getfDerivative();
++ton;
}
System.out.println("f["+(ton)+"](x)="+a);
}
public Pol getfDerivative(){
int l=p.length;
if(p.length<2){
return new Pol(0);//y=0;
}
l-=1;
double ps[]=new double[l];
int pos=l-1;
while(l>0){
ps[pos]=p[l]*l;
--pos;
--l;
}
return new Pol(ps,true);
}
public double findSomeQuickNewtonRoot(){
double out=hasSolutionAt(-10, 10,0.1);//200 max
if(Double.isNaN(out)){
out=hasSolutionAt(-100, 100,1);//200 max
if(Double.isNaN(out)){
out=hasSolutionAt(-1000, 1000,10);//200 max
if(Double.isNaN(out)){
out=hasSolutionAt(-10000, 10000,100);//200 max
}
}
}
return out;
}
public double hasSolutionAt(double x1,double x2,double xstep){
if(x2<x1){
double temp=x2;
x2=x1;
x1=temp;
}
else if(x1<x2){
}
else{
}
if(xstep<0){
xstep=-xstep;
}
else if(xstep>0){}
else{
xstep=x2-x1;
xstep/=100;
}
double x=x1;
double y=fHorner(x);
boolean startNeg=false;
if(y<0){
startNeg=true;
}
else if(y>0){
}
else{
return x;
}
x+=xstep;
x2+=xstep;
while(x<x2){
y=fHorner(x);
if(y<0){
if(!startNeg){
return x-xstep/2;
}
}
else if(y>0){
if(startNeg){
return x-xstep/2;
}
}
else{
return x;
}
x+=xstep;
}
return Double.NaN;
}
public double fHorner(double x){
int i=p.length-1;
double out=p[i];
--i;
while(i>=0){
out*=x;
out+=p[i];
--i;
}
return out;
}
public double fOld(double x){
int i=0;
double v=p[i];
double out=v;
double xs=1;
++i;
while(i<p.length){
xs*=x;
out+=xs*p[i];
++i;
}
return out;
}
public double f(double x){
return fHorner(x);
}
public String strf(double x){
return "f("+x+") = "+f(x);
}
public String toString(){
String out="";
int i=p.length-1;
double v;
while(i>0){
v=p[i];
if(v>0){
out+="+"+v+"(x^"+i+") ";
}
else if(v<0){
out+=""+v+"(x^"+i+") ";
}
--i;
}
v=p[i];
if(v>0){
out+="+"+v;
}
else if(v<0){
out+=""+v;
}
else{
if(p.length==1){
out+="+0";
}
}
return out;
}
}