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.motion;
  
  import java.nio.FloatBuffer;
  import java.util.ArrayList;
  
  import com.jogamp.opencl.CLBuffer;
  import com.jogamp.opencl.CLCommandQueue;
  import com.jogamp.opencl.CLContext;
  import com.jogamp.opencl.CLDevice;
  import com.jogamp.opencl.CLMemory.Mem;
  
  import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND;
  import edu.stanford.rsl.conrad.geometry.splines.TimeVariantSurfaceBSpline;
  import edu.stanford.rsl.conrad.opencl.OpenCLEvaluatable;
  import edu.stanford.rsl.conrad.opencl.OpenCLUtil;
  import edu.stanford.rsl.conrad.utils.TessellationUtil;
  
  /**
   * Parzen-interpolating motion field. Source points are generated from an ArrayList of TimeVariantSurfaceBSplines.
   * @author akmaier
   *
   */
  public class TimeVariantSurfaceBSplineListMotionField extends
  ParzenWindowMotionField {
  
  	/**
  	 * 
  	 */
  	private static final long serialVersionUID = 7397812496219257524L;
  	private ArrayList<TimeVariantSurfaceBSpline> variants = null;
  	
  	public TimeVariantSurfaceBSplineListMotionField(
  			ArrayList<TimeVariantSurfaceBSpline> variants, double sigma) {
  		super(sigma);
  		this.variants = variants;
  	}
  	
  	@Override
  	PointND[] getRasterPoints(double time) {
  		PointND[] result = timePointMap.get(time);
  		if (result == null){
  			if (OpenCLUtil.isOpenCLConfigured()){
  				CLContext context = OpenCLUtil.getStaticContext();
  				CLDevice device = context.getMaxFlopsDevice();
  				double sampleTime = getTimeWarper().warpTime(time);
  				ArrayList<PointND> pointList = new ArrayList<PointND>();
  				for(int i=0; i< variants.size(); i++){
  					OpenCLEvaluatable os = OpenCLUtil.getOpenCLEvaluatableSubclass(variants.get(i), device);
  					int elementCountU = (int)TessellationUtil.getSamplingU(variants.get(i));
  					int elementCountV = (int)TessellationUtil.getSamplingV(variants.get(i));
  					CLBuffer<FloatBuffer> inputBuffer = OpenCLParzenWindowMotionField.generateTimeSamplingPoints((float)sampleTime, elementCountU, elementCountV, context, device);
  					CLBuffer<FloatBuffer> outputBuffer = context.createFloatBuffer(elementCountU*elementCountV*3, Mem.READ_WRITE);
  					os.evaluate(inputBuffer, outputBuffer);
  					CLCommandQueue clc = device.createCommandQueue();
  					clc.putReadBuffer(outputBuffer, true).finish();
  					clc.release();
  					for (int j = 0; j < elementCountU*elementCountV; j++){
  						PointND point = new PointND(outputBuffer.getBuffer().get(), outputBuffer.getBuffer().get(), outputBuffer.getBuffer().get());
  						pointList.add(point);
  					}
  					outputBuffer.getBuffer().rewind();
  					inputBuffer.release();
  					outputBuffer.release();
  				}
  				//OpenCLUtil.releaseContext(context);
  				result = new PointND[pointList.size()];
  				pointList.toArray(result);
  			}	else {
  				ArrayList<PointND[]> allPoints= new ArrayList<PointND[]>();
  				int sizes = 0;
  				for(int i=0; i< variants.size(); i++){
  					PointND [] current = variants.get(i).getRasterPoints(TessellationUtil.getSamplingU(variants.get(i)), TessellationUtil.getSamplingV(variants.get(i)), time);
  					allPoints.add(current);
  					sizes += current.length;
  				}
  				result = new PointND[sizes];
  				sizes = 0;
  				for(int i=0; i< allPoints.size(); i++){
  					PointND[] current = allPoints.get(i);
  					for (int j=0;j<current.length;j++){
  						result[j+sizes] = current[j];
  					}
  					sizes += current.length;
  				}
  
  			}
  			timePointMap.put(time, result);
  		}
  		return result;
  
  	}
  
  	/**
  	 * @return the variants
  	 */
  	public ArrayList<TimeVariantSurfaceBSpline> getVariants() {
  		return variants;
  	}
  
  	/**
  	 * @param variants the variants to set
  	 */
  	public void setVariants(ArrayList<TimeVariantSurfaceBSpline> variants) {
  		this.variants = variants;
  	}
  
  }
  