package imseProc.proc.transform;

/** A single point on the 2D image and/or in 3D space.
 * 
 * These are used to fitting the transform, for fitting and displaying in the ray tracing
 * and some are just for info.
 * 
 * The mode specifies how the point will be used.
 *  
 * @author oliford
 */
public class TransformPoint {

	private final static int SIG_IMG_X = 0; //coordinates of feature in image, physical coordinates on CCD (in m)
	private final static int SIG_IMG_Y = 1;
	private final static int SIG_3D_X = 2; // coordinates of feature in vessel (cart)
	private final static int SIG_3D_Y = 3;
	private final static int SIG_3D_Z = 4;
	private final static int SIG_ANG_LON = 5; //longitude angle (0 // to x, +90° // to y)
	private final static int SIG_ANG_LAT = 6; //latitude angle (+ve up from horizontal plane)
	private final static int SIG_EN = 7; //enable
	private final static int SIG_BI_R = 8; //beam intersection R/Z for selected beam
	private final static int SIG_BI_Z = 9;
	private final static int nSIGEntries = 10;

	public final static String modeNames[] = new String[]{ 
		"Ignore", 
		"Cubic fit", 
		"Linear+Cubic fit", 
		"No fit", 
		"View pos", 
		"Limit" 
	};

	public final static int MODE_IGNORE = 0;			//Ignore entirely. Don't display or calculate with
	public final static int MODE_FIT = 1;				// Use in the full (cubic) fit.
	public final static int MODE_FIT_AND_MATRIX = 2;	// Use for the initial linear fit and in full fit
	public final static int MODE_BACK_TRANSLATE = 3;	// Display back transaltion but don't use in fits
	public final static int MODE_VIEW = 4; 			// the effective camera/view 'from' position (3D pos only)
	public final static int MODE_LIMIT = 5; 			// image limit: points around edge of the image that comes from inside the optics tube, no 3D pos 
	
	/** Some identifying name */
	public String name;
	
	/** Position in image (user selected) in range 0.0 - 1.0 */
	public double imgX, imgY;
	
	/** 3D position in machine coords */
	public double x, y, z;
	
	/** Longitude and latitude angles */
	public double lat, lon;
	
	/** R,Z of nearest intersection with selected beam */
	public double R, Z;
	
	/** Enable status */
	public int mode = TransformPoint.MODE_IGNORE;
	
	public TransformPoint(String name) {
		this.name = name;
	}
	
	public TransformPoint(String name, double[] data) {
		this.name = name;
		this.imgX = data[SIG_IMG_X];
		this.imgY = data[SIG_IMG_Y];
		this.x = data[SIG_3D_X];
		this.y = data[SIG_3D_Y];
		this.z = data[SIG_3D_Z];
		this.lon = data[SIG_ANG_LON];
		this.lat = data[SIG_ANG_LAT];
		this.mode = (int)data[SIG_EN];
		this.R = data[SIG_BI_R];
		this.Z = data[SIG_BI_Z];
					
		if(imgX > 1.0){ //some old data was in pixels (320x240 fixed)
			imgX /= 320;
			imgY /= 240;
		}			
	}
	
	public double[] toArray() {			
		return new double[]{
				imgX, imgY,
				x, y, z,
				lon, lat,
				mode, 
				R, Z
		};
	}

	public double[] getPosXYZ(){ return new double[]{ x, y, z }; }

	public void setField(int col, double val) {
		switch(col){
			case SIG_IMG_X: this.imgX = val; break;
			case SIG_IMG_Y: this.imgY = val; break;
			case SIG_3D_X: this.x = val; break;
			case SIG_3D_Y: this.y = val; break;
			case SIG_3D_Z: this.z = val; break;
			case SIG_ANG_LON: this.lon = val; break;
			case SIG_ANG_LAT: this.lat = val; break;
			case SIG_EN: this.mode = (int)val; break;
			case SIG_BI_R: this.R = val; break;
			case SIG_BI_Z: this.Z = val; break;
		}
		
	}

	public boolean includeInFit() {
		return mode == MODE_FIT || mode == MODE_FIT_AND_MATRIX;
	}
}
