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

import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

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


/**
 *
 */

public class SGDrawingElementLine2D extends SGDrawingElementLine
	implements SGIDrawingElementJava2D
{



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


	/**
	 *
	 */
	public SGDrawingElementLine2D(
		final SGTuple2f start,
		final SGTuple2f end )
	{
		super( start, end );
	}



	/**
	 *
	 */
	public SGDrawingElementLine2D(
		final float x1, final float y1,
		final float x2, final float y2 )
	{
		super( x1, y1, x2, y2 );
	}



	/**
	 * The minimum line width used in "contains" method.
	 */
	public static final float MINIMUM_LINE_WIDTH = 2.0f;


	/**
	 *
	 */
	public boolean contains( final int x, final int y )
	{
		float lw = this.mLineWidth*this.mMagnification;
		if( lw<MINIMUM_LINE_WIDTH )
		{
			lw = MINIMUM_LINE_WIDTH;
		}
		SGTuple2f start = this.getStart();
		SGTuple2f end = this.getEnd();
		final double lensq = Line2D.ptSegDistSq(
			start.x, start.y, end.x, end.y, x, y );
		return ( lensq < lw*lw );
	}
	
	
	
	/**
	 * 
	 */
	public boolean paintElement( final Graphics2D g2d )
	{
		if( g2d==null )
		{
			return false;
		}

		g2d.setPaint(this.getColor(0));

		final float width = this.mMagnification*this.mLineWidth;

		// set stroke
		Stroke stroke = SGUtilityJava2D.getBasicStroke(
			this.mLineType, width, this.mCap,
			this.mJoin, this.mMiterLimit, this.mDashPhase );
		g2d.setStroke( stroke );
		
		g2d.draw( this.getShape() );

		return true;
	}



	/**
	 * 
	 */
	public Rectangle2D getElementBounds()
	{
		SGTuple2f start = this.getStart();
		SGTuple2f end = this.getEnd();
		Rectangle2D rect = new Rectangle2D.Float( start.x, start.y, 0.0f, 0.0f );
		rect.add( new Point2D.Float( end.x, end.y ) );
		return rect;
	}



	/**
	 * 
	 */
	public Shape getShape()
	{
		Line2D line = new Line2D.Float(
			this.getStart().x, this.getStart().y,
			this.getEnd().x, this.getEnd().y );
		return line;
	}



	/**
	 * 
	 * @param line
	 * @return
	 */
	public static Line2D getLine( final SGDrawingElementLine line )
	{
		SGTuple2f start = line.getStart();
		SGTuple2f end = line.getEnd();
		Line2D sh = new Line2D.Float( start.x, start.y, end.x, end.y );
		return sh;
	}



	/**
	 * 
	 */
	public ArrayList getShapeList()
	{
		ArrayList list = new ArrayList();
		list.add( this.getShape() );
		return list;
	}



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


	protected boolean setForCopy( SGDrawingElementLine2D el )
	{
		el.setProperties( this.getProperties() );
		SGTuple2f start = this.getStart();
		SGTuple2f end = this.getEnd();
		el.setTermPoints( start.x, start.y, end.x, end.y );
		el.setMagnification( this.mMagnification );
		return true;
	}



	/**
	 * 
	 * @return
	 */
	public Shape getShapeWithThickness()
	{
		SGTuple2f start = this.getStart();
		final float mag = this.getMagnification();
		final float len = mag*this.getMagnitude();

		AffineTransform af = new AffineTransform();
		af.translate( start.x, start.y );
		final float angle
			= this.getAngle() - 0.50f*(float)Math.PI;
		af.rotate(angle);

		final float width = mag*this.getLineWidth();
		Rectangle2D rect
			= new Rectangle2D.Float(
				- width/2.0f, 0.0f, width, len );
		Shape shape = af.createTransformedShape( rect );
		return shape;
	}


	public float getAngle()
	{
		SGTuple2f start = this.getStart();
		SGTuple2f end = this.getEnd();
		return SGUtilityJava2D.getAngle(
			start.x, start.y, end.x, end.y );
	}


}

