
package jp.riken.brain.ni.samuraigraph.figure.java2d;

import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import jp.riken.brain.ni.samuraigraph.base.SGTuple2f;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementSymbol;


/**
 *
 */
public class SGDrawingElementSymbol2D extends SGDrawingElementSymbol
	implements SGIDrawingElementJava2D
{

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


	/**
	 * Minimum size of symbol.
	 */
	public static final float MIN_SIZE = 6.0f;


	/**
	 *
	 */
	public boolean contains( final int x, final int y )
	{
		Rectangle2D rect = this.getShape().getBounds2D();
		final float min = MIN_SIZE;
		
		// if the symbol is too small, enlarge the rectangle
		if( rect.getWidth() < min | rect.getHeight() < min )
		{
			final float centerX = (float)rect.getCenterX();
			final float centerY = (float)rect.getCenterY();
			rect = new Rectangle2D.Float(
				centerX-min/2.0f, centerY-min/2.0f, min, min );
		}

		return rect.contains(x,y);
	}



	/**
	 * 
	 */
	public Rectangle2D getElementBounds()
	{
		return this.getShape().getBounds2D();
	}



	/**
	 * 
	 */
	public Shape getShape()
	{
		final float x = this.getX();
		final float y = this.getY();
		final float size = mMagnification*mSize;

		Shape sh = null;
		{
			if( mType == SYMBOL_TYPE_CIRCLE )
			{
				sh = new Ellipse2D.Float(
					x-0.50f*size, y-0.50f*size, size, size );
			}
			else if( mType == SYMBOL_TYPE_SQUARE )
			{
				sh = new Rectangle2D.Float(
					x-0.50f*size, y-0.50f*size, size, size );
			}
			else if( mType == SYMBOL_TYPE_TRIANGLE )
			{
				Point2D p1 = new Point2D.Float(
					x, y-size/(float)Math.sqrt(3.0) );
				Point2D p2 = new Point2D.Float(
					x+size/2.0f, y+size/(2.0f*(float)Math.sqrt(3.0)) );
				Point2D p3 = new Point2D.Float(
					x-size/2.0f, y+size/(2.0f*(float)Math.sqrt(3.0)) );

				Line2D line12 = new Line2D.Float( p1, p2 );
				Line2D line23 = new Line2D.Float( p2, p3 );
				Line2D line31 = new Line2D.Float( p3, p1 );

				GeneralPath gp = new GeneralPath();
				gp.append( line12, true );
				gp.append( line23, true );
				gp.append( line31, true );
				gp.append( line12, true );
				sh = gp;
			}
			else if( mType == SYMBOL_TYPE_INVERTEDTRIANGLE )
			{
				Point2D p1 = new Point2D.Float(
					x, y+size/(float)Math.sqrt(3.0) );
				Point2D p2 = new Point2D.Float(
					x+size/2.0f, y-size/(2.0f*(float)Math.sqrt(3.0)) );
				Point2D p3 = new Point2D.Float(
					x-size/2.0f, y-size/(2.0f*(float)Math.sqrt(3.0)) );

				Line2D line12 = new Line2D.Double( p1, p2 );
				Line2D line23 = new Line2D.Double( p2, p3 );
				Line2D line31 = new Line2D.Double( p3, p1 );

				GeneralPath gp = new GeneralPath();
				gp.append( line12, true );
				gp.append( line23, true );
				gp.append( line31, true );
				gp.append( line12, true );
				sh = gp;
			}
			else if( mType == SYMBOL_TYPE_CROSS )
			{
				Line2D line1 = new Line2D.Float(
					new Point2D.Double(
						x-0.50f*size, y-0.50f*size ),
					new Point2D.Double(
						x+0.50f*size, y+0.50f*size ) );

				Line2D line2 = new Line2D.Float(
					new Point2D.Float(
						x+0.50f*size, y-0.50f*size ),
					new Point2D.Float(
						x-0.50f*size, y+0.50f*size ) );
				GeneralPath gp = new GeneralPath();
				gp.append( line1, false );
				gp.append( line2, false );
				sh = gp;
			}
			else if( mType == SYMBOL_TYPE_PLUS )
			{
				Line2D line1 = new Line2D.Float(
					new Point2D.Float(
						x-0.50f*size, y ),
					new Point2D.Float(
						x+0.50f*size, y ) );

				Line2D line2 = new Line2D.Float(
					new Point2D.Float(
						x, y-0.50f*size ),
					new Point2D.Float(
						x, y+0.50f*size ) );
				GeneralPath gp = new GeneralPath();
				gp.append( line1, false );
				gp.append( line2, false );
				sh = gp;
			}
			else if( mType == SYMBOL_TYPE_TRANSVERSELINE )
			{
				sh = new Line2D.Float(
					new Point2D.Float(
						x-0.50f*size, y ),
					new Point2D.Float(
						x+0.50f*size, y ) );
			}
			else
			{
				System.out.println("symbol-type is not defined");
				return null;
			}

//System.out.println(mType);
			
		}


		return sh;
	
	}



	/**
	 *
	 */
	protected AffineTransform getAffineTransform()
	{
		AffineTransform af = new AffineTransform();


		// 平行移動
		af.translate( this.getX(), this.getY() );

		// 回転
		af.rotate(mAngle);

		// 平行移動
		af.translate( -this.getX(), -this.getY() );

		return af;		
	}


	/**
	 * 
	 */
	public Object copy()
	{
		SGDrawingElementSymbol2D el = new SGDrawingElementSymbol2D();
		return el;
	}


	public boolean setPropertiesForCopy( SGDrawingElementSymbol2D el )
	{
		el.setProperties( this.getProperties() );
		SGTuple2f pos = this.getLocation();
		el.setLocation( pos.x, pos.y );
		el.setMagnification( this.mMagnification );
		return true;
	}

}

