/*
 * 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 Physics2D;

import Physics2D.Objects.Body;

/**
 *
 * @author bowen
 */
public class SpaceIntegrator {
    final public static double G = 6.67408E-11; //m^3 * kg^-1 * s^-2
    
    private Body[] objects;
    private double momentumSum;
    
    public SpaceIntegrator(Body... objects) {
        this.objects = objects;
        momentumSum = getMomentumSum(objects);
    }
    
    public static Vector2 getForce(Body other, Body target) {
        Vector2 forceVector = Vectors2.sub(target.position(), other.position());
        double normSquared = forceVector.normSquared();
        forceVector.setNorm(1);
        double scalar = (-G * other.mass() * target.mass())/normSquared;
        forceVector.prod(scalar);
        return forceVector;
    }
    
    private static double getMomentumSum(Body[] objects) {
        double sum = 0;
        for (int i=0; i<objects.length; i++) {
            sum += objects[i].momentum();
        }
        return sum;
    }
    
    private double getMomentumSum() {
        return getMomentumSum(objects);
    }
    public void update(double time) {
        update(time, 1E20);
    }
    
    public void update(double time, double precision) {
        double remainingTime = time;
        while (remainingTime > 0) {
            System.out.println(remainingTime);
            for (int i=0; i<objects.length; i++) {
                Vector2[] forceVectors = new Vector2[objects.length];
                for (int n=0; n<objects.length; n++) {
                    if (i != n) {
                        forceVectors[n] = getForce(objects[n], objects[i]);
                    } else {
                        forceVectors[n] = new Vector2(0);
                    }
                }
                Vector2 sumForces = Vectors2.add(forceVectors);
                objects[i].setForce(sumForces);
            }

            for (int i=0; i<objects.length; i++) {
                objects[i].update(remainingTime);
            }

            double newMomentum = getMomentumSum();
            if (Math.abs(momentumSum - newMomentum) > precision) {
                double newTime = remainingTime;
                while (Math.abs(momentumSum - newMomentum) > precision) {
                    //System.out.println(Math.abs(momentumSum - newMomentum));
                    for (int i=0; i<objects.length; i++) {
                        objects[i].revert();
                    }
                    newTime /= 2;
                    System.out.println(newTime);
                    for (int i=0; i<objects.length; i++) {
                        objects[i].update(newTime);
                    }
                    newMomentum = getMomentumSum();
                }
                remainingTime -= newTime;
                System.out.println("step");
            } else {
                remainingTime = 0;
            }
            momentumSum = newMomentum;
        }
    }
}

@@ -1448,55 +1448,8 @@
 ) %7B%0A
-            System.out.println(remainingTime);%0A
     
@@ -2210,32 +2210,173 @@
  %3E precision) %7B%0A
+                %0A                if (time == remainingTime) System.out.print(%22%7COops, timeStep too big, using Ministeps!%7C%22);%0A                %0A
                 
@@ -2732,32 +2732,34 @@
                 
+//
 System.out.print
@@ -3052,16 +3052,162 @@
 rint
-ln(%22step
+(%22%7CMinistep%7C%22);%0A                //System.out.print(newTime + %22%7C%22);%0A                //System.out.println(%22%7CMinistep, remaining time: %22 + remainingTime + %22%7C
 %22);%0A
@@ -3258,24 +3258,75 @@
 ngTime = 0;%0A
+                System.out.println(%22%7CFull Step%7C%22);%0A
             

print ministeps