content: package edu.stanford.rsl.conrad.phantom.xcat;
  
  import java.io.IOException;
  import java.util.ArrayList;
  
  import edu.stanford.rsl.conrad.geometry.General;
  import edu.stanford.rsl.conrad.geometry.bounds.HalfSpaceBoundingCondition;
  import edu.stanford.rsl.conrad.geometry.motion.ConstantMotionField;
  import edu.stanford.rsl.conrad.geometry.motion.DualMotionField;
  import edu.stanford.rsl.conrad.geometry.motion.MixedSurfaceBSplineMotionField;
  import edu.stanford.rsl.conrad.geometry.motion.MotionField;
  import edu.stanford.rsl.conrad.geometry.motion.MovingCenterRotationMotionField;
  import edu.stanford.rsl.conrad.geometry.motion.OpenCLParzenWindowMotionField;
  import edu.stanford.rsl.conrad.geometry.motion.PointBasedMotionField;
  import edu.stanford.rsl.conrad.geometry.motion.RotationMotionField;
  import edu.stanford.rsl.conrad.geometry.motion.timewarp.IdentityTimeWarper;
  import edu.stanford.rsl.conrad.geometry.motion.timewarp.TimeWarper;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.Plane3D;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND;
  import edu.stanford.rsl.conrad.geometry.splines.SurfaceBSpline;
  import edu.stanford.rsl.conrad.geometry.splines.TimeVariantSurfaceBSpline;
  import edu.stanford.rsl.conrad.geometry.trajectories.Trajectory;
  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.Configuration;
  
  /**
   * Class to simluate very simple knee joint motion in XCat.
   * Scene contains only the lower body as only the legs and hip are of interest for a squat.
   * 
   * @author akmaier
   *
   */
  public class SquatScene extends WholeBodyScene {
  
  	/**
  	 * 
  	 */
  	private static final long serialVersionUID = 5833963135277640258L;
  
  	MotionField lowerBodyMotionField = null;
  	boolean rotationOnly = false;
  	double sigmaParzen=10;
  	int numberOfNeighborsLinInterp = 5;
  	int numberOfBSplineTimePoints = 10;
  	double angleInDegrees = 45;
  	
  	public SquatScene (){
  	}
  	
  	public SquatScene (int numberOfNeighborsLinInterp, double sigmaParzen, int nrOfTimePoints, double maxAngle){
  		this.sigmaParzen = sigmaParzen;
  		this.numberOfNeighborsLinInterp = numberOfNeighborsLinInterp;
  		numberOfBSplineTimePoints = nrOfTimePoints;
  		angleInDegrees = maxAngle;
  	}
  
  	@Override
  	public void configure(){
  
  		String [] constants = {
  				"finger",
  				"pelvis"
  		};
  
  		String [] splinesToKeep = {
  				"body"
  		};
  
  
  		TimeWarper warper = new IdentityTimeWarper();
  
  		setName("Squat Scene");		
  		//init();
  
  		/*
  		Trajectory geom = Configuration.getGlobalConfiguration().getGeometry();
  		PointND currentOrigin = new PointND(269.3, 287.2, -638.3);
  		for (int i = 0; i < geom.getReconDimensions().length; i++) {
  			double size = geom.getReconDimensions()[i]*geom.getReconVoxelSizes()[i];
  			currentOrigin.set(i, currentOrigin.get(i)-(size/2.0-0.5));
  		}
  		setMin(currentOrigin);
  		SimpleVector volumeSize = new SimpleVector(
  				geom.getVoxelSpacingX()*geom.getReconDimensionX(),
  				geom.getVoxelSpacingY()*geom.getReconDimensionY(), 
  				geom.getVoxelSpacingZ()*geom.getReconDimensionZ()
  				);
  		setMax(new PointND(SimpleOperators.add(currentOrigin.getAbstractVector(),volumeSize)));
  		*/
  		splines = readSplines();
  		// remove splines outside the volume of interest using z axis
  		double maxZ = 0;
  		double minZ = 0;
  		for (int i=splines.size()-1; i >= 0; i--){
  			if (splines.get(i).getTitle().toLowerCase().contains("rightfemur")){
  				maxZ = splines.get(i).getMax().get(2)-100;
  				break;
  			}
  		}
  		for (int i=splines.size()-1; i >= 0; i--){
  			if (splines.get(i).getTitle().toLowerCase().contains("rightfibula")){
  				minZ = splines.get(i).getMin().get(2)+100;
  				break;
  			}
  		}
  		
  		for (int i=splines.size()-1; i >= 0; i--){
  			boolean keepSpline = false;
  			for (String s : splinesToKeep) {
  				if (splines.get(i).getTitle().toLowerCase().contains(s))
  					keepSpline = true;
  			}
  
  			if (!keepSpline){
  				if (splines.get(i).getMax().get(2) < minZ){// below VOI
  					splines.remove(i);
  				} else {
  					if (splines.get(i).getMin().get(2) > maxZ) { // above VOI
  						splines.remove(i);
  					}
  				}
  			}
  		}
  		
  		updateSceneLimits();
  
  
  		// define relevant points in scene
  
  		PointND leftFemurTop = new PointND(16.6, 273.6,-207.42);
  		//PointND leftFemurBottom = new PointND(21.1, 269.1,-631.92);
  		PointND leftPatellaRotCenter = new PointND(21.1, 269.1,-590.92);
  
  		//ScaleRotate femurTransform = new ScaleRotate(Rotations.createRotationMatrixAboutAxis(new SimpleVector(1,0,0), General.toRadians(-angleInDegrees)));
  
  		//Edge leftFemur = new Edge(leftFemurTop, leftFemurBottom);
  		//rotateAround(leftFemur, femurTransform, leftFemurTop);
  
  		//SimpleVector leftLowerLegShift = lib.subtract(leftFemur.getEnd().getAbstractVector(), leftFemurBottom.getAbstractVector());
  
  		PointND rightFemurTop = new PointND(269.3, 273.6,-207.42);
  		PointND rightFemurBottom = new PointND(264.8, 264.6,-631.92);
  		PointND rightPatellaRotCenter = new PointND(264.8, 264.6,-590.92);
  
  		//Edge rightFemur = new Edge(rightFemurTop, rightFemurBottom);
  		//rotateAround(rightFemur, femurTransform, rightFemurTop);
  
  		//SimpleVector rightLowerLegShift = lib.subtract(rightFemur.getEnd().getAbstractVector(), rightFemurBottom.getAbstractVector());
  
  		//AffineTransform leftTibiaFibulaTransform = new AffineTransform();
  		//leftTibiaFibulaTransform.setTransformer(Rotations.createRotationMatrixAboutAxis(new SimpleVector(1,0,0), General.toRadians(angleInDegrees)));
  		//leftTibiaFibulaTransform.setTranslator(leftLowerLegShift);
  
  		//PointND leftTibiaTop = new PointND(7.6, 269.1,-654.1+lowerZoffset);
  		PointND leftTibiaTop = new PointND(7.6, 287.2,-638.3);
  		//PointND leftTibiaBottom = new PointND(-33.0, 291.7,-1001.5);
  
  		PointND leftFibulaTop = new PointND(-24.0, 300.7,-667.6);
  		//PointND leftFibulaBottom = new PointND(-51.1, 318.8,-1015.0);
  
  		//Edge leftTibia = new Edge(leftTibiaTop, leftTibiaBottom);
  		//Edge leftFibula = new Edge(leftFibulaTop, leftFibulaBottom);
  
  		//rotateAround(leftFibula, leftTibiaFibulaTransform, leftFibulaTop);
  		//rotateAround(leftTibia, leftTibiaFibulaTransform, leftTibiaTop);
  
  		//AffineTransform rightTibiaFibulaTransform = new AffineTransform();
  		//rightTibiaFibulaTransform.setTransformer(Rotations.createRotationMatrixAboutAxis(new SimpleVector(1,0,0), General.toRadians(angleInDegrees)));
  		//rightTibiaFibulaTransform.setTranslator(rightLowerLegShift);
  
  		//PointND rightTibiaTop = new PointND(273.8, 269.1,-654.1+lowerZoffset);
  		PointND rightTibiaTop = new PointND(269.3, 287.2, -638.3);
  		//PointND rightTibiaBottom = new PointND(314.4, 291.7,-1001.5);
  
  		PointND rightFibulaTop = new PointND(309.9, 300.7,-667.6);
  		//PointND rightFibulaBottom = new PointND(337.0, 318.8,-1015.0);
  
  		//Edge rightTibia = new Edge(rightTibiaTop, rightTibiaBottom);
  		//Edge rightFibula = new Edge(rightFibulaTop, rightFibulaBottom);
  
  		//rotateAround(rightFibula, rightTibiaFibulaTransform, rightFibulaTop);
  		//rotateAround(rightTibia, rightTibiaFibulaTransform, rightTibiaTop);
  
  		// define cascading motion fields.
  
  		// define motion around femur bones.
  
  		RotationMotionField leftFemurMotion = new RotationMotionField(leftFemurTop, new SimpleVector(1,0,0), General.toRadians(-angleInDegrees));
  		leftFemurMotion.setTimeWarper(warper);
  
  		RotationMotionField rightFemurMotion = new RotationMotionField(rightFemurTop, new SimpleVector(1,0,0), General.toRadians(-angleInDegrees));
  		rightFemurMotion.setTimeWarper(warper);
  
  		// create lists for the complete motion field.
  
  		ArrayList<ArrayList<PointND>> lowerBodyMotion = new ArrayList<ArrayList<PointND>>();
  		for (int t=0; t<numberOfBSplineTimePoints; t++){
  			lowerBodyMotion.add(new ArrayList<PointND>());
  		}
  
  
  		// for each spline in the body
  		for (int i = splines.size()-1; i >= 0; i--){
  			// test whether the spline is constant.
  			boolean constantTest = false;
  			for (String s: constants){
  				if (splines.get(i).getTitle().toLowerCase().contains(s)){
  					constantTest = true;
  				}
  			}
  			// create a time-constant spline for constants
  			if (constantTest){
  				System.out.println("Creating time-constant spline for " + splines.get(i).getTitle());
  				TimeVariantSurfaceBSpline tSpline = new TimeVariantSurfaceBSpline(splines.get(i), new ConstantMotionField(), numberOfBSplineTimePoints, true);
  				for (int t=0; t<numberOfBSplineTimePoints; t++){
  					lowerBodyMotion.get(t).addAll(tSpline.getControlPoints(t));
  				}
  			}
  			// rotate right femur bone with the right femur motion field
  			if (splines.get(i).getTitle().toLowerCase().contains("rightfemur")){
  				System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  				variants.add(new TimeVariantSurfaceBSpline(splines.get(i), rightFemurMotion, numberOfBSplineTimePoints, true));
  				splines.remove(i);	
  			}
  			// rotate right femur bone marrow with the right femur motion field.
  			if (splines.get(i).getTitle().toLowerCase().contains("r_femur")){
  				System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  				variants.add(new TimeVariantSurfaceBSpline(splines.get(i), rightFemurMotion, numberOfBSplineTimePoints, true));
  				splines.remove(i);
  			}
  			// rotate left femur bone with the left femur motion field.
  			if (splines.get(i).getTitle().toLowerCase().contains("leftfemur")){
  				System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  				variants.add(new TimeVariantSurfaceBSpline(splines.get(i), leftFemurMotion, numberOfBSplineTimePoints, true));
  				splines.remove(i);
  			}
  			// rotate left femur bone marrow with the left femur motion field.
  			if (splines.get(i).getTitle().toLowerCase().contains("l_femur")){
  				System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  				variants.add(new TimeVariantSurfaceBSpline(splines.get(i), leftFemurMotion, numberOfBSplineTimePoints, true));
  				splines.remove(i);
  			}
  		}
  
  		// define motion field for lower body 1. iteration
  		// femurs move. constants are constant.
  		if (!rotationOnly){
  			lowerBodyMotionField = getSceneMotion(numberOfBSplineTimePoints, lowerBodyMotion, numberOfNeighborsLinInterp);
  			lowerBodyMotionField.setTimeWarper(warper);
  
  
  			// define cascading motion field
  			// i.e. Motion fields that have a moving center of rotation
  
  			// for tibiae
  
  			MovingCenterRotationMotionField leftTibiaMotion = new MovingCenterRotationMotionField(leftTibiaTop, lowerBodyMotionField, new SimpleVector(1,0,0), General.toRadians(angleInDegrees));
  			leftTibiaMotion.setTimeWarper(warper);
  			MovingCenterRotationMotionField rightTibiaMotion = new MovingCenterRotationMotionField(rightTibiaTop, lowerBodyMotionField, new SimpleVector(1,0,0), General.toRadians(angleInDegrees));
  			rightTibiaMotion.setTimeWarper(warper);
  
  			// for fibulae
  
  			MovingCenterRotationMotionField leftFibulaMotion = new MovingCenterRotationMotionField(leftFibulaTop, lowerBodyMotionField, new SimpleVector(1,0,0), General.toRadians(angleInDegrees));
  			leftFibulaMotion.setTimeWarper(warper);
  			MovingCenterRotationMotionField rightFibulaMotion = new MovingCenterRotationMotionField(rightFibulaTop, lowerBodyMotionField, new SimpleVector(1,0,0), General.toRadians(angleInDegrees));
  			rightFibulaMotion.setTimeWarper(warper);
  
  			// for patellae
  
  			MovingCenterRotationMotionField leftPatellaMotion = new MovingCenterRotationMotionField(leftPatellaRotCenter, lowerBodyMotionField, new SimpleVector(1,0,0), General.toRadians(angleInDegrees/2));
  			leftPatellaMotion.setTimeWarper(warper);
  			MovingCenterRotationMotionField rightPatellaMotion = new MovingCenterRotationMotionField(rightPatellaRotCenter, lowerBodyMotionField, new SimpleVector(1,0,0), General.toRadians(angleInDegrees/2));
  			rightPatellaMotion.setTimeWarper(warper);
  
  			SimpleMatrix FemurRotationCenterShifts_30 = new SimpleMatrix(6,3);
  			System.out.println("Left Tibia Center Translation: " + lowerBodyMotionField.getPosition(leftTibiaTop, 0, 0.55));
  			FemurRotationCenterShifts_30.setRowValue(0, lowerBodyMotionField.getPosition(leftTibiaTop, 0, 0.55).getAbstractVector());
  			System.out.println("Left Fibula Center Translation: " + lowerBodyMotionField.getPosition(leftFibulaTop, 0, 0.55));
  			FemurRotationCenterShifts_30.setRowValue(1, lowerBodyMotionField.getPosition(leftFibulaTop, 0, 0.55).getAbstractVector());
  			System.out.println("Left Patella Center Translation: " + lowerBodyMotionField.getPosition(leftPatellaRotCenter, 0, 0.55));
  			FemurRotationCenterShifts_30.setRowValue(2, lowerBodyMotionField.getPosition(leftPatellaRotCenter, 0, 0.55).getAbstractVector());
  			System.out.println("Right Tibia Center Translation: " + lowerBodyMotionField.getPosition(rightTibiaTop, 0, 0.55));
  			FemurRotationCenterShifts_30.setRowValue(3, lowerBodyMotionField.getPosition(rightTibiaTop, 0, 0.55).getAbstractVector());
  			System.out.println("Right Fibula Center Translation: " + lowerBodyMotionField.getPosition(rightFibulaTop, 0, 0.55));
  			FemurRotationCenterShifts_30.setRowValue(4, lowerBodyMotionField.getPosition(rightFibulaTop, 0, 0.55).getAbstractVector());
  			System.out.println("Right Patella Center Translation: " + lowerBodyMotionField.getPosition(rightPatellaRotCenter, 0, 0.55));
  			FemurRotationCenterShifts_30.setRowValue(5, lowerBodyMotionField.getPosition(rightPatellaRotCenter, 0, 0.55).getAbstractVector());
  			
  			SimpleMatrix FemurRotationCenterShifts_60 = new SimpleMatrix(6,3);
  			System.out.println("Left Tibia Center Translation: " + lowerBodyMotionField.getPosition(leftTibiaTop, 0, 1));
  			FemurRotationCenterShifts_60.setRowValue(0, lowerBodyMotionField.getPosition(leftTibiaTop, 0, 1).getAbstractVector());
  			System.out.println("Left Fibula Center Translation: " + lowerBodyMotionField.getPosition(leftFibulaTop, 0, 1));
  			FemurRotationCenterShifts_60.setRowValue(1, lowerBodyMotionField.getPosition(leftFibulaTop, 0, 1).getAbstractVector());
  			System.out.println("Left Patella Center Translation: " + lowerBodyMotionField.getPosition(leftPatellaRotCenter, 0, 1));
  			FemurRotationCenterShifts_60.setRowValue(2, lowerBodyMotionField.getPosition(leftPatellaRotCenter, 0, 1).getAbstractVector());
  			System.out.println("Right Tibia Center Translation: " + lowerBodyMotionField.getPosition(rightTibiaTop, 0, 1));
  			FemurRotationCenterShifts_60.setRowValue(3, lowerBodyMotionField.getPosition(rightTibiaTop, 0, 1).getAbstractVector());
  			System.out.println("Right Fibula Center Translation: " + lowerBodyMotionField.getPosition(rightFibulaTop, 0, 1));
  			FemurRotationCenterShifts_60.setRowValue(4, lowerBodyMotionField.getPosition(rightFibulaTop, 0, 1).getAbstractVector());
  			System.out.println("Right Patella Center Translation: " + lowerBodyMotionField.getPosition(rightPatellaRotCenter, 0, 1));
  			FemurRotationCenterShifts_60.setRowValue(5, lowerBodyMotionField.getPosition(rightPatellaRotCenter, 0, 1).getAbstractVector());
  
  			
  			System.out.println(FemurRotationCenterShifts_30);
  			System.out.println(FemurRotationCenterShifts_60);
  			
  			
  			// apply motion fields to splines.
  			for (int i = splines.size()-1; i >= 0; i--){
  				boolean constantTest = false;
  				for (String s: constants){
  					if (splines.get(i).getTitle().toLowerCase().contains(s)){
  						constantTest = true;
  					}
  				}
  				// constants remain constant.
  				if (constantTest){
  					System.out.println("Creating time-constant spline for " + splines.get(i).getTitle());
  					TimeVariantSurfaceBSpline tSpline = new TimeVariantSurfaceBSpline(splines.get(i), new ConstantMotionField(), numberOfBSplineTimePoints, true);
  					for (int t=0; t<numberOfBSplineTimePoints; t++){
  						lowerBodyMotion.get(t).addAll(tSpline.getControlPoints(t));
  					}
  					// apply respective motion to the respective bones.
  				} else if (splines.get(i).getTitle().toLowerCase().contains("lefttibia") || splines.get(i).getTitle().toLowerCase().contains("l_tibia")){
  					System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  					variants.add(new TimeVariantSurfaceBSpline(splines.get(i), leftTibiaMotion, numberOfBSplineTimePoints, true));
  					splines.remove(i);
  				} else if (splines.get(i).getTitle().toLowerCase().contains("righttibia") || splines.get(i).getTitle().toLowerCase().contains("r_tibia")){
  					System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  					variants.add(new TimeVariantSurfaceBSpline(splines.get(i), rightTibiaMotion, numberOfBSplineTimePoints, true));
  					splines.remove(i);
  				} else if (splines.get(i).getTitle().toLowerCase().contains("leftfibula") || splines.get(i).getTitle().toLowerCase().contains("l_fibula")){
  					System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  					variants.add(new TimeVariantSurfaceBSpline(splines.get(i), leftFibulaMotion, numberOfBSplineTimePoints, true));
  					splines.remove(i);
  				} else if (splines.get(i).getTitle().toLowerCase().contains("rightfibula") || splines.get(i).getTitle().toLowerCase().contains("r_fibula")){
  					System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  					variants.add(new TimeVariantSurfaceBSpline(splines.get(i), rightFibulaMotion, numberOfBSplineTimePoints, true));
  					splines.remove(i);
  				} else if (splines.get(i).getTitle().toLowerCase().contains("leftpatella") || splines.get(i).getTitle().toLowerCase().contains("l_patella")){
  					System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  					variants.add(new TimeVariantSurfaceBSpline(splines.get(i), leftPatellaMotion, numberOfBSplineTimePoints, true));
  					splines.remove(i);
  				} else if (splines.get(i).getTitle().toLowerCase().contains("rightpatella") || splines.get(i).getTitle().toLowerCase().contains("r_patella")){
  					System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  					variants.add(new TimeVariantSurfaceBSpline(splines.get(i), rightPatellaMotion, numberOfBSplineTimePoints, true));
  					splines.remove(i);
  				}
  			}
  
  			lowerBodyMotionField = new DualMotionField(new HalfSpaceBoundingCondition(new Plane3D(rightFemurBottom, new SimpleVector(0,0,1))), lowerBodyMotionField, leftTibiaMotion);
  			lowerBodyMotionField.setTimeWarper(warper);
  
  		}
  		else{
  			for (int i = splines.size()-1; i >= 0; i--){
  				if (splines.get(i).getTitle().toLowerCase().contains("lefttibia") || splines.get(i).getTitle().toLowerCase().contains("l_tibia")){
  					System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  					variants.add(new TimeVariantSurfaceBSpline(splines.get(i), leftFemurMotion, numberOfBSplineTimePoints, true));
  					splines.remove(i);
  				} else if (splines.get(i).getTitle().toLowerCase().contains("righttibia") || splines.get(i).getTitle().toLowerCase().contains("r_tibia")){
  					System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  					variants.add(new TimeVariantSurfaceBSpline(splines.get(i), rightFemurMotion, numberOfBSplineTimePoints, true));
  					splines.remove(i);
  				} else if (splines.get(i).getTitle().toLowerCase().contains("leftfibula") || splines.get(i).getTitle().toLowerCase().contains("l_fibula")){
  					System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  					variants.add(new TimeVariantSurfaceBSpline(splines.get(i), leftFemurMotion, numberOfBSplineTimePoints, true));
  					splines.remove(i);
  				} else if (splines.get(i).getTitle().toLowerCase().contains("rightfibula") || splines.get(i).getTitle().toLowerCase().contains("r_fibula")){
  					System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  					variants.add(new TimeVariantSurfaceBSpline(splines.get(i), rightFemurMotion, numberOfBSplineTimePoints, true));
  					splines.remove(i);
  				} else if (splines.get(i).getTitle().toLowerCase().contains("leftpatella") || splines.get(i).getTitle().toLowerCase().contains("l_patella")){
  					System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  					variants.add(new TimeVariantSurfaceBSpline(splines.get(i), leftFemurMotion, numberOfBSplineTimePoints, true));
  					splines.remove(i);
  				} else if (splines.get(i).getTitle().toLowerCase().contains("rightpatella") || splines.get(i).getTitle().toLowerCase().contains("r_patella")){
  					System.out.println("Creating affine-time-variant spline for " + splines.get(i).getTitle());
  					variants.add(new TimeVariantSurfaceBSpline(splines.get(i), rightFemurMotion, numberOfBSplineTimePoints, true));
  					splines.remove(i);
  				}
  			}
  
  			lowerBodyMotionField = getSceneMotion(numberOfBSplineTimePoints, lowerBodyMotion, (int)Math.round(numberOfNeighborsLinInterp));//new PointBasedMotionField(getVariants(), (int)Math.round(sigma));
  			//new MixedSurfaceBSplineMotionField(getVariants(), getSplines(), sigma);
  			lowerBodyMotionField.setTimeWarper(warper);
  
  			//lowerBodyMotionField = new MixedSurfaceBSplineMotionField(getVariants(), getSplines(), 10);//getSceneMotion(numberOfBSplineTimePoints, lowerBodyMotion, 5);
  		}
  
  		// 2nd estimate of the motion field to the lower body containing
  		// motion of femurs, tibiae, patellae, fibulae, and time constants. 
  		// use new motion field to interpolate the the remaining splines.
  		for (int i = splines.size()-1; i >= 0; i--){
  			boolean constantTest = false;
  			for (String s: constants){
  				if (splines.get(i).getTitle().toLowerCase().contains(s)){
  					constantTest = true;
  				}
  			}
  			if (!constantTest){
  				System.out.println("Creating time-variant spline for " + splines.get(i).getTitle());
  				variants.add(new TimeVariantSurfaceBSpline(splines.get(i), lowerBodyMotionField, numberOfBSplineTimePoints, true));
  				splines.remove(i);
  			}
  		}
  		//getSceneMotion(numberOfBSplineTimePoints, lowerBodyMotion, 5);
  		/*
  		lowerBodyMotionField = new ConstantShiftMotionField(lowerBodyMotionField, rightTibiaTop);
  		lowerBodyMotionField.setTimeWarper(warper);
  
  		for (int i = copyOfSplines.size()-1; i >= 0; i--){
  			System.out.println("Creating time-variant spline for " + copyOfSplines.get(i).getTitle());
  			variants.add(new TimeVariantSurfaceBSpline(copyOfSplines.get(i), lowerBodyMotionField, numberOfBSplineTimePoints, true));
  			copyOfSplines.remove(i);
  		}
  		 */	
  		createPhysicalObjects();
  		lowerBodyMotionField = new MixedSurfaceBSplineMotionField(getVariants(), getSplines(), sigmaParzen);
  		lowerBodyMotionField.setTimeWarper(warper);
  	}
  
  	@Override
  	public PointND getPosition(PointND initialPosition, double initialTime, double time) {
  		return lowerBodyMotionField.getPosition(initialPosition, initialTime, time);
  	}
  
  	@Override
  	public ArrayList<PointND> getPositions(PointND initialPosition,
  			double initialTime, double... times) {
  		return lowerBodyMotionField.getPositions(initialPosition, initialTime, times);
  	}
  
  	@Override
  	public void setTimeWarper(TimeWarper warper){
  		super.setTimeWarper(warper);
  		lowerBodyMotionField.setTimeWarper(warper);
  	}
  
  	@Override
  	public MotionField getMotionField() {
  		return lowerBodyMotionField;
  	};
  
  	@Override
  	public String getName() {
  		return "XCat Squat";
  	}
  }
  /*
   * Copyright (C) 2010-2014 Andreas Maier
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
  */