
package jp.riken.brain.ni.samuraigraph.data;

import jp.riken.brain.ni.samuraigraph.base.SGData;
import jp.riken.brain.ni.samuraigraph.base.SGTuple2d;


/**
 * (x,y)-type vector data.
 */

public class SGVXYData extends SGData
	implements SGITwoDimensionalData, Cloneable
{

	/**
	 *
	 */
	private SGTuple2d[] mStartArray = null;


	/**
	 * 
	 */
	private double[] mMagnitudeArray = null;


	/**
	 * 
	 */
	private double[] mAngleArray = null;



	/**
	 * 
	 */
	public SGVXYData()
	{
		super();
	}



	/**
	 * Constructor.
	 */
	public SGVXYData( final SGTuple2d[] positionArray, final double[] magnitudeArray, final double[] angleArray )
	{
		super();

// 引数チェック
		mStartArray = positionArray;
		setMagnitudeArray( magnitudeArray );
		setAngleArray( angleArray );

	}



	/**
	 * Constructor.
	 */
	public SGVXYData( final double[] xArray, final double[] yArray, final double[] magnitudeArray, final double[] angleArray )
	{
		super();

// 引数チェック
		int num = magnitudeArray.length;

		setStartArray( xArray, yArray );
		setMagnitudeArray( magnitudeArray );
		setAngleArray( angleArray );

	}

	/**
	 * 
	 * @return
	 */
	public SGVXYData( final SGData data )
	{
		super();
		this.setData( data );
	}


	/**
	 * 
	 */
	public boolean setData( final SGData data )
	{
		if( !(data instanceof SGVXYData) )
		{
			return false;
		}

		SGVXYData data_ = (SGVXYData)data;
		this.setStartArray( data_.getStartArray() );
		this.setMagnitudeArray( data_.getMagnitudeArray() );
		this.setAngleArray( data_.getAngleArray() );

		return true;
	}


	/**
	 * 
	 * @return
	 */
	public int getPointsNumber()
	{
		return this.mStartArray.length;
	}


	/**
	 * Returns the name of data type.
	 * @return
	 */
	public String getDataType()
	{
		return SGDataTypeConstants.VXY_DATA;
	}


	/**
	 * 
	 * @return
	 */
	private boolean setStartArray( final double[] xArray, final double[] yArray )
	{
		int num = xArray.length;

		mStartArray = new SGTuple2d[num];
		for( int ii=0; ii<num; ii++ )
		{
			mStartArray[ii] = new SGTuple2d();
			mStartArray[ii].x = xArray[ii];
			mStartArray[ii].y = yArray[ii];
		}
		
		return true;
	}



	/**
	 * 
	 * @return
	 */
	private boolean setMagnitudeArray( final double[] array )
	{
		int num = array.length;
		
		mMagnitudeArray = new double[num];
		for( int ii=0; ii<num; ii++ )
		{
			mMagnitudeArray[ii] = array[ii];
		}

		return true;
	}


	/**
	 * 
	 * @return
	 */
	private boolean setAngleArray( final double[] array )
	{
		int num = array.length;
		
		mAngleArray = new double[num];
		for( int ii=0; ii<num; ii++ )
		{
			mAngleArray[ii] = array[ii];
		}

		return true;
	}



	/**
	 * 
	 * @return
	 */
	private boolean setStartArray( final SGTuple2d[] array )
	{
		this.mStartArray = array;
		return true;
	}



	/**
	 * 
	 * @return
	 */
	public double getMinValueX()
	{
		double min = Double.MAX_VALUE;

		for( int ii=0; ii<mStartArray.length; ii++ )
		{
			double x = mStartArray[ii].x;
			if( x < min )
			{
				min = x;
			}

			double xx = mStartArray[ii].x + mMagnitudeArray[ii]*Math.cos(mAngleArray[ii]);
			if( xx < min )
			{
				min = xx;
			}
		}

		return min;
	}


	/**
	 * 
	 * @return
	 */
	public double getMaxValueX()
	{
		double max = - Double.MAX_VALUE;

		for( int ii=0; ii<mStartArray.length; ii++ )
		{
			double x = mStartArray[ii].x;
			if( x > max )
			{
				max = x;
			}

			double xx = mStartArray[ii].x + mMagnitudeArray[ii]*Math.cos(mAngleArray[ii]);
			if( xx > max )
			{
				max = xx;
			}
		}

		return max;
	}


	/**
	 * 
	 * @return
	 */
	public double getMinValueY()
	{
		double min = Double.MAX_VALUE;

		for( int ii=0; ii<mStartArray.length; ii++ )
		{
			double y = mStartArray[ii].y;
			if( y < min )
			{
				min = y;
			}

			double yy = mStartArray[ii].y + mMagnitudeArray[ii]*Math.sin(mAngleArray[ii]);
			if( yy < min )
			{
				min = yy;
			}

		}

		return min;
	}


	/**
	 * 
	 * @return
	 */
	public double getMaxValueY()
	{
		double max = - Double.MAX_VALUE;

		for( int ii=0; ii<mStartArray.length; ii++ )
		{
			double y = mStartArray[ii].y;
			if( y > max )
			{
				max = y;
			}

			double yy = mStartArray[ii].y + mMagnitudeArray[ii]*Math.sin(mAngleArray[ii]);
			if( yy > max )
			{
				max = yy;
			}
		}

		return max;
	}



	/**
	 * 
	 * @return
	 */
	public SGTuple2d[] getStartArray()
	{
		return mStartArray;
	}


	/**
	 * 
	 * @return
	 */
	public double[] getMagnitudeArray()
	{
		return mMagnitudeArray;
	}


	/**
	 * 
	 * @return
	 */
	public double[] getAngleArray()
	{
		return mAngleArray;
	}


	/**
	 * 
	 */
	public SGTuple2d[] getEndArray()
	{
		SGTuple2d[] valueArray = new SGTuple2d[mStartArray.length];
		for( int ii=0; ii<valueArray.length; ii++ )
		{
			valueArray[ii] = new SGTuple2d();
			valueArray[ii].x = mStartArray[ii].x + mMagnitudeArray[ii]*Math.cos(mAngleArray[ii]);
			valueArray[ii].y = mStartArray[ii].y + mMagnitudeArray[ii]*Math.sin(mAngleArray[ii]);
		}

		return valueArray;
	}


	/**
	 * 
	 */
	public Object clone()
	{
		try
		{
			return super.clone();
		}
		catch( CloneNotSupportedException ex )
		{
			// this shouldn't happen, since we are Cloneable
			throw new InternalError();
		}
	}


	/**
	 * Calling the clone method.
	 */
	public Object copy()
	{
		return this.clone();
	}


}
