content: package edu.stanford.rsl.conrad.geometry.motion;
  
  import Jama.EigenvalueDecomposition;
  import edu.stanford.rsl.conrad.geometry.Axis;
  import edu.stanford.rsl.conrad.geometry.Rotations;
  import edu.stanford.rsl.conrad.geometry.motion.timewarp.IdentityTimeWarper;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND;
  import edu.stanford.rsl.conrad.geometry.transforms.AffineTransform;
  import edu.stanford.rsl.conrad.geometry.transforms.ComboTransform;
  import edu.stanford.rsl.conrad.geometry.transforms.ScaleRotate;
  import edu.stanford.rsl.conrad.geometry.transforms.Transform;
  import edu.stanford.rsl.conrad.geometry.transforms.Translation;
  import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
  import edu.stanford.rsl.conrad.numerics.SimpleVector;
  
  /**
   * MotionField to handle affine rotation and translational motion.
   * 
   * @author berger
   *
   */
  public class AffineMotionField extends AbstractAffineMotionField {
  
  	/**
  	 * 
  	 */
  	private static final long serialVersionUID = 6748536919627679826L;
  	protected Translation toCenter;
  	protected Translation back;
  	protected SimpleVector axis;
  	protected double angle;
  	protected PointND center;
  	protected SimpleVector translation;
  	protected SimpleMatrix rotationMat;
  
  	/**
  	 * Creates a new rotational and translation MotionField. 
  	 * It transforms points with a rotation around the given axis and center and translates them afterwards. 
  	 * The angle is given in radians.
  	 *  
  	 * @param transformationCenter
  	 * @param axis
  	 * @param angle
  	 */
  	public AffineMotionField (PointND transformationCenter, SimpleVector axis, double angle, SimpleVector translation){
  		back = new Translation(transformationCenter.getAbstractVector());
  		toCenter = back.inverse();
  		warp = new IdentityTimeWarper();
  		center = transformationCenter;
  		this.axis = axis;
  		this.angle = angle;
  		this.rotationMat = null;
  		this.translation = translation;
  	}
  	
  	/**
  	 * Creates a new rotation motion field.
  	 * It transforms points with a rotation around the given axis and center and translates them afterwards. 
  	 * The angle is given in radians.
  	 *  
  	 * @param transformationCenter
  	 * @param axis
  	 * @param angle
  	 */
  	public AffineMotionField (PointND transformationCenter, SimpleVector axis, double angle){
  		this(transformationCenter, axis, angle, new SimpleVector(transformationCenter.getDimension()));
  	}
  
  	/**
  	 * Creates a new rotational and translation MotionField. 
  	 *  
  	 * @param transformationCenter the center point of the rotation
  	 * @param rotMat the rotation matrix
  	 * @param translation the translation
  	 */
  	public AffineMotionField (PointND transformationCenter, SimpleMatrix rotMat, SimpleVector translation){
  		back = new Translation(transformationCenter.getAbstractVector());
  		toCenter = back.inverse();
  		warp = new IdentityTimeWarper();
  		center = transformationCenter;
  		this.axis = null;
  		this.angle = 0;
  		this.rotationMat = rotMat;
  		this.translation = translation;
  	}
  
  	
  	/**
  	 * Returns the interpolated transform between initial time and time.
  	 * @param initialTime
  	 * @param time
  	 * @return the transform
  	 * @throws Exception 
  	 */
  	@Override
  	public Transform getTransform(double initialTime, double time) {
  
  		Transform affine = null;
  		if (axis != null){
  			affine = new AffineTransform(
  					Rotations.createRotationMatrixAboutAxis(new Axis(axis), angle * (warp.warpTime(time)-warp.warpTime(initialTime))),
  					translation.multipliedBy(warp.warpTime(time)-warp.warpTime(initialTime))
  					);
  		}
  		else{
  			// TODO: add support for rotation matrices (Use axis/angle representation)
  			try {
  				throw new Exception("Support for rotation matrices not yet implemented");
  			} catch (Exception e) {
  				e.printStackTrace();
  			}
  		}
  		affine = new ComboTransform(toCenter,affine,back);
  		return affine;
  	}
  
  
  
  }
  /*
   * Copyright (C) 2010-2014 Martin Berger 
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
  */