/*
 * PolarChartConstraints.java
 *
 * Created on 25 grudzień 2004, 19:13
 */

package JSciDraw.physics.forces;

import JSci.maths.*;
import JSciDraw.physics.*;
/**
 *
 * @author  Barbara
 */
public abstract class PolarChartConstraints extends Constraints{
    
    protected AbstractDoubleVector center;
    
    /** Creates a new instance of PolarChartConstraints */
    public PolarChartConstraints(AbstractDoubleVector center) {
      this.center=center;
    }
    
    protected abstract double getRadius(double ang);
    
    protected AbstractDoubleVector toEuclidean(AbstractDoubleVector generic)
    {
        double r = generic.getComponent(0);
        double ang = generic.getComponent(1);
        double x = r*Math.sin(ang) + center.getComponent(0);
        double y = r*Math.cos(ang) + center.getComponent(1);
        return new Double2Vector(x,y);

    }
    protected AbstractDoubleVector getRadialVersor(AbstractDoubleVector generic)
    {
        double ang=generic.getComponent(1);
        return new Double2Vector(Math.sin(ang), Math.cos(ang));
    }

    protected AbstractDoubleVector getAngularVersor(AbstractDoubleVector generic)
    {
        double ang=generic.getComponent(1);
        return new Double2Vector(Math.cos(ang), -1.*Math.sin(ang));
    }
    
    protected AbstractDoubleVector toGeneric(AbstractDoubleVector euclidean)
    {
       AbstractDoubleVector rw = euclidean.subtract(center);
       double r =rw.norm();
       double cosin =rw.getComponent(1)/r;
       double sin =rw.getComponent(0)/r;
       double ang=0;
       if ((sin>=0)&&(cosin>=0)){ 
          ang = Math.acos(cosin);
       }
       if ((sin>=0)&&(cosin<0)){ 
          ang = Math.acos(cosin);
       }
       if ((sin<0)&&(cosin<0)){ 
           ang = Math.PI+Math.acos(-cosin);
       }
       if ((sin<0)&&(cosin>=0)){ 
          ang = Math.PI+Math.acos(-cosin);
       }
       if (ang>Math.PI)
             ang-=2*Math.PI;
       rw.setComponent(0, r);
       rw.setComponent(1, ang);
       return rw;
    }
    public AbstractDoubleVector setAngPosition(double degrees)
    {
        return setAngularPosition(degrees*Math.PI/180);
    }
 
    protected AbstractDoubleVector setAngularPosition(double ang)
    {
        return toEuclidean(new Double2Vector(getRadius(ang),ang));
    }
        
    public void move(ClassicalParticleV2D p, AbstractDoubleVector force, double dt)
    {
        AbstractDoubleVector pos=p.getPosition();
        AbstractDoubleVector gen=toGeneric(pos);
        AbstractDoubleVector eS=getTangent(pos);
        AbstractDoubleVector eFi=getAngularVersor(gen);
        double ang=gen.getComponent(1);
        double radius=gen.getComponent(0);
        double angAcc=(eFi.scalarProduct(eS.scalarMultiply(eS.scalarProduct(force))))/(p.getMass()*radius);
        double angV=(eFi.scalarProduct(eS.scalarMultiply(eS.scalarProduct(p.getVelocity())))/radius)+dt*angAcc;
        ang+=angV*dt;
        pos=setAngularPosition(ang);
        eS=getTangent(pos);
        p.setVelocity(eS.scalarMultiply(angV*radius));
        p.setPosition(pos);
    }
    
    public void setPosition(AbstractDoubleVector x) {
        center=x;
    }    

    public AbstractDoubleVector getPosition() {
        return center;
    }    

}
