content: /*
   * Copyright (C) 2010-2014 Andreas Maier
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
   */
  package edu.stanford.rsl.conrad.geometry.trajectories;
  
  import edu.stanford.rsl.conrad.geometry.General;
  import edu.stanford.rsl.conrad.geometry.Projection;
  import edu.stanford.rsl.conrad.geometry.Projection.CameraAxisDirection;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.Plane3D;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND;
  import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
  import edu.stanford.rsl.conrad.numerics.SimpleOperators;
  import edu.stanford.rsl.conrad.numerics.SimpleVector;
  import edu.stanford.rsl.conrad.utils.CONRAD;
  import edu.stanford.rsl.conrad.utils.Configuration;
  import edu.stanford.rsl.conrad.utils.RegKeys;
  
  public class CircularTrajectory extends Trajectory {
  
  	private static final long serialVersionUID = -3236098993706829039L;
  
  	public CircularTrajectory() {
  		super();
  	}
  
  	public CircularTrajectory(Trajectory source) {
  		super(source);
  		//		this.numProjectionMatrices = source.numProjectionMatrices;
  		//		this.detectorWidth = source.detectorWidth;
  		//		this.detectorHeight = source.detectorHeight;
  		//		this.pixelDimensionX = source.pixelDimensionX;
  		//		this.pixelDimensionY = source.pixelDimensionY;
  		//		this.sourceToDetectorDistance = source.sourceToDetectorDistance;
  		//		this.sourceToAxisDistance = source.sourceToAxisDistance;
  		//		this.averageAngularIncrement = source.averageAngularIncrement;
  		//		this.reconDimensions = Arrays.copyOf(source.reconDimensions, source.reconDimensions.length);
  		//		this.reconVoxelSizes = Arrays.copyOf(source.reconVoxelSizes, source.reconVoxelSizes.length);
  		//		this.projectionMatrices = source.projectionMatrices;
  		//		this.primaryAngles = source.primaryAngles;
  		//		this.projectionStackSize = source.projectionStackSize;
  		//		this.originInPixelsX = source.originInPixelsX;
  		//		this.originInPixelsY = source.originInPixelsY;
  		//		this.originInPixelsZ = source.originInPixelsZ;
  		//		this.detectorUDirection = source.detectorUDirection;
  		//		this.detectorVDirection = source.detectorVDirection;
  		//		this.rotationAxis = source.rotationAxis;
  	}
  
  	public void setTrajectory(int numProjectionMatrices, double sourceToAxisDistance, double averageAngularIncrement, 
  			double detectorOffsetX, double detectorOffsetY, CameraAxisDirection uDirection, 
  			CameraAxisDirection vDirection, SimpleVector rotationAxis) {
  		this.setTrajectory(numProjectionMatrices, sourceToAxisDistance, averageAngularIncrement, 
  				detectorOffsetX, detectorOffsetY, uDirection, vDirection, rotationAxis, 
  				new PointND(0,0,0), 0);
  	}
  	
  	public void setTrajectory(int numProjectionMatrices, double sourceToAxisDistance, double averageAngularIncrement, 
  			double detectorOffsetX, double detectorOffsetY, CameraAxisDirection uDirection, 
  			CameraAxisDirection vDirection, SimpleVector rotationAxis, PointND rotationCenter, double angleFirstProjection) {
  		this.projectionMatrices = new Projection[numProjectionMatrices];
  		this.primaryAngles = new double[numProjectionMatrices];
  		this.numProjectionMatrices = numProjectionMatrices;
  		this.sourceToAxisDistance = sourceToAxisDistance;
  		this.averageAngularIncrement = averageAngularIncrement;
  		this.detectorOffsetU = detectorOffsetX;
  		this.detectorOffsetV = detectorOffsetY;
  
  		double cosPhi = Math.cos(General.toRadians(angleFirstProjection));
  		double sinPhi = Math.sin(General.toRadians(angleFirstProjection));
  		SimpleMatrix rotMat = new SimpleMatrix(3,3);
  		rotMat.setElementValue(0,0, cosPhi);
  		rotMat.setElementValue(0, 1, sinPhi);
  		rotMat.setElementValue(1,0,-sinPhi);
  		rotMat.setElementValue(1, 1, cosPhi);
  		rotMat.setElementValue(2, 2, 1);
  
  		SimpleVector centerToCameraIdealAtInitialAngle = SimpleOperators.multiply(rotMat, new SimpleVector(sourceToAxisDistance, 0, 0));
  		Plane3D trajPlane = new Plane3D(rotationAxis,SimpleOperators.multiplyInnerProd(rotationAxis, rotationCenter.getAbstractVector()));
  		double distToPlane = trajPlane.computeDistance(new PointND(centerToCameraIdealAtInitialAngle));
  		SimpleVector centerToCameraDir = SimpleOperators.subtract(SimpleOperators.add(rotationAxis.multipliedBy(-1*distToPlane),centerToCameraIdealAtInitialAngle),rotationCenter.getAbstractVector());
  		centerToCameraDir.divideBy(centerToCameraDir.normL2());
  		SimpleVector centerToCameraInitialInPlane = centerToCameraDir.multipliedBy(sourceToAxisDistance);
  
  		for (int i=0; i< numProjectionMatrices; i++){
  			primaryAngles[i] = i*averageAngularIncrement + angleFirstProjection;
  			//System.out.println(primaryAngles[i] + " " + averageAngularIncrement + " " + this.reconDimensions[0] + " " + this.reconDimensions[1]);
  			projectionMatrices[i]= new Projection();
  			double rotationAngle = General.toRadians(primaryAngles[i]);
  			projectionMatrices[i].setRtFromCircularTrajectory(rotationCenter.getAbstractVector(), rotationAxis, sourceToAxisDistance, centerToCameraInitialInPlane, uDirection, vDirection, rotationAngle);
  			SimpleVector spacingUV = new SimpleVector(pixelDimensionX, pixelDimensionY);
  			SimpleVector sizeUV = new SimpleVector(detectorWidth, detectorHeight);
  			SimpleVector offset = new SimpleVector(detectorOffsetX, detectorOffsetY);	
  			projectionMatrices[i].setKFromDistancesSpacingsSizeOffset(sourceToDetectorDistance, spacingUV, sizeUV, offset, 1.0, 0);
  
  		}
  		this.projectionStackSize = numProjectionMatrices;
  		//System.out.println("Defined geometry with SDD " +sourceToDetectorDistance);
  	}
  	
  
  	public static void main(String[] args) {
  		CONRAD.setup();
  		Configuration config = Configuration.getGlobalConfiguration();
  		CircularTrajectory traj = new CircularTrajectory(config.getGeometry());
  		double[] startAngles = new double[]{0,20,40};
  		for (int j = 0; j < startAngles.length; j++) {
  			traj.setTrajectory(2,600,90,0,0,CameraAxisDirection.ROTATIONAXIS_PLUS,CameraAxisDirection.DETECTORMOTION_PLUS,
  					new SimpleVector(0,0,1),new PointND(0,0,0), startAngles[j]);
  			for (int i = 0; i < traj.getNumProjectionMatrices(); i++) {
  				System.out.println("Matrix: " + traj.getProjectionMatrix(i).toString());
  			}
  			System.out.println(" ");
  		}
  	}
  
  }
  