/* * 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; 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(" "); } } }