package edu.stanford.rsl.conrad.phantom;
import java.util.ArrayList;
import java.util.Iterator;
import edu.stanford.rsl.conrad.geometry.AbstractShape;
import edu.stanford.rsl.conrad.geometry.motion.AbstractAffineMotionField;
import edu.stanford.rsl.conrad.geometry.motion.AffineMotionField;
import edu.stanford.rsl.conrad.geometry.motion.MotionField;
import edu.stanford.rsl.conrad.geometry.motion.timewarp.CombinedTimeWarper;
import edu.stanford.rsl.conrad.geometry.motion.timewarp.ConstantTimeWarper;
import edu.stanford.rsl.conrad.geometry.motion.timewarp.HarmonicTimeWarper;
import edu.stanford.rsl.conrad.geometry.motion.timewarp.PeriodicTimeWarper;
import edu.stanford.rsl.conrad.geometry.motion.timewarp.SigmoidTimeWarper;
import edu.stanford.rsl.conrad.geometry.motion.timewarp.TimeWarper;
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.Transform;
import edu.stanford.rsl.conrad.geometry.transforms.Translation;
import edu.stanford.rsl.conrad.numerics.SimpleOperators;
import edu.stanford.rsl.conrad.numerics.SimpleVector;
import edu.stanford.rsl.conrad.physics.PhysicalObject;
import edu.stanford.rsl.conrad.rendering.PrioritizableScene;
import edu.stanford.rsl.conrad.utils.CONRAD;
import edu.stanford.rsl.conrad.utils.UserUtil;
public class AffineMotionPhantom extends AnalyticPhantom4D {
private static final long serialVersionUID = -255412548002793134L;
private AnalyticPhantom staticPhantom = null;
private AbstractAffineMotionField mf = null;
@Override
public void configure() throws Exception {
staticPhantom = UserUtil.queryPhantom("Select Phantom", "Select Phantom");
staticPhantom.setBackground(this.getBackgroundMaterial());
staticPhantom.configure();
staticPhantom.setConfigured(true);
SimpleVector rotAxis = new SimpleVector(UserUtil.queryArray("Please provide rotation axis...", new double[]{1,0,0}));
double rotAngle = UserUtil.queryDouble("Please provide rotation angle (degree)", 0) * Math.PI / 180.0;
SimpleVector translation = new SimpleVector(UserUtil.queryArray("Please provide translation vector...", new double[]{1,1,1}));
mf = new AffineMotionField(new PointND(0,0,0), rotAxis, rotAngle, translation);
double rep = UserUtil.queryDouble("Please provide No. of harmonic repetitions", 1);
warper = new CombinedTimeWarper(new HarmonicTimeWarper(rep), new PeriodicTimeWarper(), new SigmoidTimeWarper());
max = staticPhantom.getMax();
min = staticPhantom.getMin();
this.setConfigured(true);
}
public void setStaticAnalyticPhantom(AnalyticPhantom phantom){
staticPhantom = phantom;
if (isConfigured() && !staticPhantom.isConfigured()) {
try {
staticPhantom.configure();
staticPhantom.setConfigured(true);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public AnalyticPhantom getStaticAnalyticPhantom(){
return staticPhantom;
}
@Override
public PointND getPosition(PointND initialPosition, double initialTime,
double time) {
double t = warper.warpTime(time);
return mf.getPosition(initialPosition, initialTime, t);
}
@Override
public ArrayList<PointND> getPositions(PointND initialPosition,
double initialTime, double... times) {
ArrayList<PointND> list = new ArrayList<PointND>();
for (int i=0; i< times.length; i++){
list.add(getPosition(initialPosition, initialTime, times[i]));
}
return list;
}
@Override
public String getBibtexCitation() {
return CONRAD.CONRADBibtex;
}
@Override
public String getMedlineCitation() {
return CONRAD.CONRADMedline;
}
@Override
public PrioritizableScene getScene(double time) {
PrioritizableScene scene = new PrioritizableScene();
double t = warper.warpTime(time);
//System.out.print(t);
//System.out.print(", ");
// apply motion to all physical object in static phantom and add to current scene
if (staticPhantom instanceof AffineMotionPhantom){
Iterator<PhysicalObject> objIt = ((AffineMotionPhantom) staticPhantom).getScene(t).iterator();
Transform tform = mf.getTransform(0, t);
tform = new AffineTransform(tform.getRotation(3), tform.getTranslation(3));
while (objIt.hasNext()) {
PhysicalObject obj = new PhysicalObject((PhysicalObject) objIt.next());
AbstractShape shape = obj.getShape().clone();
obj.setShape(shape);
obj.applyTransform(tform);
scene.add(obj);
}
}
else{
Iterator<PhysicalObject> objIt = staticPhantom.iterator();
Transform tform = mf.getTransform(0, t);
tform = new AffineTransform(tform.getRotation(3), tform.getTranslation(3));
while (objIt.hasNext()) {
PhysicalObject obj = new PhysicalObject((PhysicalObject) objIt.next());
AbstractShape shape = obj.getShape().clone();
obj.setShape(shape);
obj.applyTransform(tform);
scene.add(obj);
}
}
scene.setBackground(staticPhantom.getBackgroundMaterial());
// set scene limits
scene.setMin(min);
scene.setMax(max);
return scene;
}
@Override
public String getName() {
return "Affine Motion Phantom";
}
public void setMotionField(AbstractAffineMotionField mf) {
this.mf = mf;
}
@Override
public MotionField getMotionField() {
return mf;
}
}
/*
* Copyright (C) 2010-2014 Martin Berger
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/