#pragma once
#include<Camera.h>
#include<Drawing.h>
#include<xutility>
#include<vector>

namespace DXFW
{
class Figure;
class Complex;
class Point;
class Line;
class Circle;
class Rect;

/// <summary>説明</summary>
///	<example>
///	[サンプルコード:未完成]<BR>
/// サンプル説明<BR>
///	<code>
///	int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )<BR>
///	{<BR>
///		if( !Dx::Initialise() ) return -1;<BR>
///		Dx::End();<BR>
///		return 0;<BR>
/// }<BR>
/// </code>	
/// </example>
class Figure
{
protected:
	double zoomX;
	double zoomY;
			
	/// <summary>説明</summary>
	static bool RectRect( double x1 , double y1 , double x2 , double y2 , double x3 , double y3 , double x4 , double y4)
	{
		//x座標をラフチェック
		if ( x1 >= x2)
		{
			if ((x1 < x3 && x1 < x4) || (x2 > x3 && x2 > x4))
			{
				return false;
			}
		}
		else
		{
			if ((x2 < x3 && x2 < x4) || (x1 > x3 && x1 > x4))
			{
				return false;
			}
		}
		//y座標をラフチェック
		if (y1 >= y2)
		{
			if ((y1 < y3 && y1 < y4) || (y2 > y3 && y2 > y4))
			{
				return false;
			}
		}
		else
		{
			if ((y2 < y3 && y2 < y4) || (y1 > y3 && y1 > y4))
			{
				return false;
			}
		}

		return true;
	}
	
	/// <summary>説明</summary>
	static bool LineLine( double x1 , double y1 , double x2 , double y2 , double x3 , double y3 , double x4 , double y4)
	{
		//交差判定
		if ((double(x1 - x2) * (y3 - y1) + (y1 - y2) * (x1 - x3)) *
			(double(x1 - x2) * (y4 - y1) + (y1 - y2) * (x1 - x4)) > 0)
		{
			return false;
		}

		if ((double(x3 - x4) * (y1 - y3) + (y3 - y4) * (x3 - x1)) *
			(double(x3 - x4) * (y2 - y3) + (y3 - y4) * (x3 - x2)) > 0)
		{
			return false;
		}
		return true;

	}
			
	/// <summary>説明</summary>
	static int PointPoint(double x1 , double y1 , double x2 , double y2)
	{
		return int((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
	}
			
public:
	Figure():
		zoomX(1),
		zoomY(1)
	{}
			
	/// <summary>説明</summary>
	virtual bool Hit(const Figure *figure) const = 0;
	virtual bool Hit(const Complex *figure) const = 0;
	virtual bool Hit(const Point *figure) const = 0;
	virtual bool Hit(const Line *figure) const = 0;
	virtual bool Hit(const Rect *figure) const = 0;
	virtual bool Hit(const Circle *figure) const = 0;
	
	/// <summary>説明</summary>
	virtual void SetPos(double x , double y) = 0;
			
	/// <summary>説明</summary>
	virtual Figure* Clone(double x , double y) const = 0;
			
	/// <summary>説明</summary>
	void SetZoom(double rateX , double rateY)
	{
		MultiZoom( rateX / zoomX , rateY / zoomY);
	}
			
	/// <summary>説明</summary>
	virtual void MultiZoom(double rate) = 0;
			
	/// <summary>説明</summary>
	virtual void MultiZoom(double rateX , double rateY) = 0;
			
	/// <summary>説明</summary>
	virtual void Move(double x , double y) = 0;
			
	/// <summary>説明</summary>
	void MoveA(double distance , double angle )
	{
		Move( distance * cos(angle) , distance * sin(angle) );
	}
			
	/// <summary>説明</summary>
	virtual void Draw(int rgb , int transRate , Camera *camera = 0) const = 0;
			
	/// <summary>説明</summary>
	virtual void Rotate(double angle) = 0;
			
	/// <summary>説明</summary>
	virtual void SetAngle(double angle) = 0;
			
	/// <summary>説明</summary>
	double GetDirect(Figure* figure)
	{
		return atan2( figure->GetY() - this->GetY() , figure->GetX() - this->GetX() );
	}
			
	/// <summary>説明</summary>
	double GetDistance(Figure* figure)
	{
		const double xd = this->GetX() - figure->GetX();
		const double yd = this->GetY() - figure->GetY();

		return sqrt( xd * xd + yd * yd );
	}
			
	/// <summary>説明</summary>
	virtual double GetX() const = 0;
	virtual double  GetY() const = 0;
	virtual double  GetW() const = 0;
	virtual double  GetH() const = 0;
};
	
/// <summary>説明</summary>
///	<example>
///	[サンプルコード:未完成]<BR>
/// サンプル説明<BR>
///	<code>
///	int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )<BR>
///	{<BR>
///		if( !Dx::Initialise() ) return -1;<BR>
///		Dx::End();<BR>
///		return 0;<BR>
/// }<BR>
/// </code>	
/// </example>
class Complex : public Figure
{
public:
	std::vector<Figure*> figures;

	Complex(){};

	Complex(Figure *figure)
	{
		figures.push_back( figure );
	}
			
	Figure* Clone(double x,double y) const
	{
		Complex *buf = new Complex();

		for( auto it: figures )
		{
			buf->figures.push_back( it );
		}

		return buf;
	}
			
	void SetPos(double x , double y)
	{
		for( auto it: figures )
		{
			it->SetPos( x , y );
		}		
	}

	void Move(double mX , double mY)
	{
		for( auto it: figures )
		{
			it->Move( mX , mY );
		}
	}

	double GetX() const
	{
		return figures[0]->GetX();
	}

	double GetY() const
	{
		return figures[0]->GetY();
	}
			
	double GetW() const
	{
		return figures[0]->GetW();
	}

	double GetH() const
	{
		return figures[0]->GetH();
	}

	void MultiZoom(double rate)
	{
		for( auto it: figures )
		{
			it->MultiZoom( rate );
		}
	}
			
	void MultiZoom(double rateX , double rateY)
	{
		for( auto it: figures )
		{
			it->MultiZoom( rateX , rateY );
		}
			
	}

	void Rotate(double angle)
	{
		for( auto it: figures )
		{
			it->Rotate( angle );
		}
	}

	void SetAngle(double angle)
	{
		for( auto it: figures )
		{
			it->SetAngle( angle );
		}
	}

	void Draw( int rgb , int transRate , Camera *camera = 0) const
	{
		for( auto it: figures )
		{
			it->Draw( rgb , transRate , camera );
		}
	}
		
	bool Hit(const Figure *figure) const
	{
		return figure->Hit( this );
	}
	bool Hit(const Complex *complex) const
	{
		for( auto itA : this->figures )
		{
			for( auto itB : this->figures )
			{
				if( itA->Hit(itB) ) return true;
			}
		}
		return false;
	}
	bool Hit(const Point *point) const;
	bool Hit(const Line *line) const;
	bool Hit(const Rect *rect) const;
	bool Hit(const Circle *circle) const;
};
	
///	<summary>クラス説明</summary>
///	<example>
///	[サンプルコード:未完成]<BR>
/// サンプル説明<BR>
///	<code>
///	int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )<BR>
///	{<BR>
///		if( !Dx::Initialise() ) return -1;<BR>
///		Dx::End();<BR>
///		return 0;<BR>
/// }<BR>
/// </code>	
/// </example>
class Point : public Figure
{
public:
	double x;
	double y;

	Point() :
		x(0),
		y(0)
	{};
			
	/// <summary>説明</summary>
	Point(double x , double y):
		x(x),
		y(y)
	{}

	Figure* Clone(double x,double y) const
	{
		return new Point( x , y );
	}

	void SetPos(double x , double y)
	{
		this->x = x;
		this->y = y;			
	}

	void Move(double mX , double mY)
	{
		this->x += mX;
		this->y += mY;
	}

	double GetX() const
	{
		return x;
	}

	double GetY() const
	{
		return y;
	}
			
	double GetW() const
	{
		return 1;
	}

	double GetH() const
	{
		return 1;
	}

	void MultiZoom(double rate){}
			
	void MultiZoom(double rateX , double rateY){}

	void Rotate(double angle){}

	void SetAngle(double angle){}

	void Draw( int rgb , int transRate , Camera *camera = 0) const
	{
		DxLib::SetDrawBlendMode( 1 , transRate);
		if( camera )
		{
			DxLib::DrawPixel( (int)camera->TranX(x) , (int)camera->TranY(y) , rgb );
		}
		else
		{
			DxLib::DrawPixel( (int)x , (int)y , rgb );
		}
		DxLib::SetDrawBlendMode( 0 , transRate);
	}
			
	bool Hit(const Figure *figure) const
	{
		return figure->Hit( this );
	}
	bool Hit(const Complex *complex) const
	{
		for( auto it : complex->figures )
		{
			if( it->Hit( this ) ) return true;
		}
		return false;
	}
	bool Hit(const Point *point) const
	{
		return ( point->x == this->x && point->y == this->y );
	}
	bool Hit(const Line *line) const;
	bool Hit(const Rect *rect) const;
	bool Hit(const Circle *circle) const;
};
	
/// <summary>説明</summary>
///	<example>
///	[サンプルコード:未完成]<BR>
/// サンプル説明<BR>
///	<code>
///	int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )<BR>
///	{<BR>
///		if( !Dx::Initialise() ) return -1;<BR>
///		Dx::End();<BR>
///		return 0;<BR>
/// }<BR>
/// </code>	
/// </example>
class Line : public Figure
{
private:
	virtual void CulParam()
	{
		CulLine();
	}

	void CulLine()
	{
		this->xA = x + cos( angle ) * lengthA;
		this->yA = y + sin( angle ) * lengthA;
		this->xB = x + cos( angle ) * lengthB;
		this->yB = y + sin( angle ) * lengthB;
		this->width = int(this->xB - this->xA);
		this->height =	int(this->yB - this->yA);
		this->thickHarf = int(this->thick / 2);
		this->thickPow = int(this->thick * this->thick / 4);
		this->minX = int( this->xA < this->xB ? this->xA:this->xB );
		this->maxX = int( this->xA > this->xB ? this->xA:this->xB );
		this->minY = int( this->yA < this->yB ? this->yA:this->yB );
		this->maxY = int( this->yA > this->yB ? this->yA:this->yB );
	}

	double x;
	double y;
	double xA;
	double yA;
	double xB;
	double yB;
	double thick;//半径

	double angle;//角度

	double lengthA;
	double lengthB;

	double width;
	double height;
	double thickHarf;//半径の二条
	double thickPow;
	double minX;
	double minY;
	double maxX;
	double maxY;

public:

	/// <summary>説明</summary>
	Line( double x , double y , double angle , double length , double thick):
		x(x),
		y(y),
		angle(angle),
		lengthA( length/2 ),
		lengthB( length/2 ),
		thick( thick )
	{
		this->CulLine();
	}
			
	virtual Figure* Clone(double x,double y) const
	{
		return new Line( x , y , this->angle , this->lengthA , this->thick);
	}

	double GetX() const
	{
		return x;
	}

	double GetY() const
	{
		return y;
	}			
			
	double GetW() const
	{
		return int(xA - xB);
	}
			
	double GetH() const
	{
		return int(yA - yB);
	}

	void SetPos(double x , double y )
	{
		this->x = x;
		this->y = y;
		this->CulParam();
	}

	void MultiZoom(double rate)
	{
		this->lengthA *= rate;
		this->lengthB *= rate;
		this->thick *= rate;

		this->zoomX *= rate;
		this->zoomY *= rate;
		this->CulParam();

		this->zoomX = rate;
		this->zoomY = rate;
	}
			
	void MultiZoom(double rateX , double rateY)
	{
		this->lengthA *= rateX;
		this->lengthB *= rateY;
		this->thick *= rateX;

		this->CulParam();

		this->zoomX = rateX;
		this->zoomY = rateY;
	}

	void Rotate(double angle)
	{
		this->angle += angle;
		this->CulParam();	
	}

	void SetAngle(double angle)
	{
		this->angle = angle;
		this->CulParam();	
	}

	void Move(double mX , double mY )
	{
		this->x += mX;
		this->y += mY;
		this->xA += mX;
		this->yA += mY;
		this->xB += mX;
		this->yB += mY;
				
		this->minX += mX;
		this->minY += mY;
		this->maxX += mX;
		this->maxY += mY;
	}

	void Draw( int rgb , int transRate , Camera *camera = 0 ) const
	{
		DxLib::SetDrawBlendMode( 1 , transRate);
		if( camera )
		{
			DxLib::DrawLine( (int)camera->TranX(xA) , (int)camera->TranY(yA) , (int)camera->TranX(xB) , (int)camera->TranY(yB) , rgb , (int)( camera->GetZoom() ) );
			DxLib::DrawCircle( (int)camera->TranX(xA) , (int)camera->TranX(yA) , (int)( thickHarf*camera->GetZoom() ) , rgb , true );
			DxLib::DrawCircle( (int)camera->TranX(xB) , (int)camera->TranX(yB) , (int)( thickHarf*camera->GetZoom() ) , rgb , true );
		}
		else
		{
			DxLib::DrawLine( (int)xA , (int)yA , (int)xB , (int)yB , rgb , (int)thick );
			DxLib::DrawCircle( (int)xA , (int)yA , (int)thickHarf , rgb , true );
			DxLib::DrawCircle( (int)xB , (int)yB , (int)thickHarf , rgb , true );
		}

		DxLib::SetDrawBlendMode( 0 , transRate);
	}
			
	double GetXA() const
	{
		return xA;
	}

	double GetYA() const
	{
		return yA;
	}

	double GetXB() const
	{
		return xB;
	}

	double GetYB() const
	{
		return yB;
	}

	double GetThick() const
	{
		return thick;
	}

	void SetThick(double thick)
	{
		this->thick = thick;
		this->thickHarf = int(this->thick / 2);
		this->thickPow = int(this->thick * this->thick / 4);
	}

	double GetAngle() const
	{
		return this->angle;
	}

	void MoveAngle(double angle)
	{
		this->angle += angle;
		this->CulParam();
	}

	double GetLength() const
	{
		return this->lengthA + this->lengthB;
	}

	double GetThickHarf() const
	{
		return this->thickHarf;
	}

	double GetThickPow() const
	{
		return this->thickPow;
	}
			
	double GetMinX() const
	{
		return minX;
	}

	double GetMinY() const
	{
		return minY;
	}

	double GetMaxX() const
	{
		return maxX;
	}

	double GetMaxY() const
	{
		return maxY;
	}

	bool Hit(const Figure *figure) const
	{
		return figure->Hit( this );
	}
	bool Hit(const Complex *complex) const
	{
		for( auto it : complex->figures )
		{
			if( it->Hit( this ) ) return true;
		}
		return false;
	}
	bool Hit(const Point *point) const
	{
		return LinePoint( point->GetX() , point->GetY() , this->GetThickPow() );
	}
	bool Hit(const Line *line) const
	{
			//四角形でラフチェック
			if( RectRect(this->GetXA() - this->GetThickHarf() ,this->GetYA() - this->GetThickHarf() , this->GetXB() - line->GetThickHarf() , this->GetYB() - line->GetThickHarf() ,
							line->GetXA() - this->GetThickHarf() ,line->GetYA() - this->GetThickHarf() , line->GetXB() - line->GetThickHarf() , line->GetYB() - line->GetThickHarf() ) )
			{
				return true;
			}
			//交差チェック
			if( LineLine(this->GetXA() ,this->GetYA() ,this->GetXB() ,this->GetYB() ,line->GetXA(),line->GetYA(),line->GetXB(),line->GetYB() ) )
			{
				return true;
			}
			//線と端のチェック
			//線が点になっているかで分ける
			if( this->GetLength() != 0)
			{
				if( this->LinePoint( line->GetXA() , line->GetYA() , (this->GetThickHarf() + line->GetThickHarf()) * (this->GetThickHarf() + line->GetThickHarf()) ) ) return true;
				if( this->LinePoint( line->GetXB() , line->GetYB() ,  (this->GetThickHarf() + line->GetThickHarf()) * (this->GetThickHarf() + line->GetThickHarf()) ) ) return true;	
			}
			if( line->GetLength() != 0 )
			{
				if( line->LinePoint( this->GetXA() , this->GetYA() ,  (this->GetThickHarf() + line->GetThickHarf()) * (this->GetThickHarf() + line->GetThickHarf()) ) ) return true;
				if( line->LinePoint( this->GetXB() , this->GetYB() ,  (this->GetThickHarf() + line->GetThickHarf()) * (this->GetThickHarf() + line->GetThickHarf()) ) ) return true;	
			}

			return false;
	}
	bool Hit(const Rect *rect) const;
	bool Hit(const Circle *circle) const;
	
	/// <summary>説明</summary>
	bool LinePoint(double px , double py , double range ) const
	{
		if ( this->GetLength() == 0 )
		{//線が点
			if( 
				( this->GetXA() - px ) *( this->GetXA() - px ) +
				( this->GetXA() - py ) *( this->GetXA() - py )
				< this->GetThickHarf() * this->GetThickHarf() ) return true;
			return false;
		}

		double t = double( -this->GetW() * (this->GetXA() - px) + this->GetH() *( this->GetYA() - py ) ) / this->GetLength();

		int tx = int(this->GetXA() + this->GetW() * t);
		int ty = int(this->GetYA() + this->GetH() * t);

		if(
			(
			tx > this->GetMinX() &&
			tx < this->GetMaxX() &&
			ty > this->GetMinY() &&
			ty < this->GetMaxY() 
			) || (
				PointPoint( px , py , this->GetXA() , this->GetYA() ) < range
			) || (
				PointPoint( px , py , this->GetXB() , this->GetYB() ) < range
			)
		)
		{
			double d = (px - tx) * (px - tx) + (py - ty) * (py - ty);

			if( d <= range ) return true;
		}

		return false;
	}
};
	
/// <summary>説明</summary>
///	<example>
///	[サンプルコード:未完成]<BR>
/// サンプル説明<BR>
///	<code>
///	int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )<BR>
///	{<BR>
///		if( !Dx::Initialise() ) return -1;<BR>
///		Dx::End();<BR>
///		return 0;<BR>
/// }<BR>
/// </code>	
/// </example>
class Rect : public Figure
{
public:
	double x;
	double y;

	double upLength;
	double downLength;
	double leftLength;
	double rightLength;
			
	/// <summary>説明</summary>
	Rect(double x,double y,double width,double height):
		x(x),
		y(y),
		upLength( height/2 ),
		downLength( height/2 ),
		leftLength( width/2 ),
		rightLength( width/2 )
	{}

	virtual Figure* Clone(double x,double y) const
	{
		return new Rect( x , y , GetW() , GetH() );
	}
			
	void SetPos(double x , double y)
	{
		this->x = x;
		this->y = y;
	}

	void Move(double mX , double mY )
	{
		this->x += mX;
		this->y += mY;
	}

	void MultiZoom(double rate)
	{
		upLength *= rate;
		downLength *= rate;
		leftLength *= rate;
		rightLength *= rate;
	}
			
	void MultiZoom(double rateX , double rateY)
	{
		upLength *= rateY;
		downLength *= rateY;
		leftLength *= rateX;
		rightLength *= rateX;
	}

	void Rotate(double angle)
	{
	}

	void SetAngle(double angle)
	{
	}

	void Draw( int rgb , int transRate , Camera *camera = nullptr) const
	{
		DxLib::SetDrawBlendMode( 1 , transRate);
		if( camera )
		{
			DxLib::DrawBox
			(
				(int)camera->TranX(x - leftLength) ,
				(int)camera->TranY(y - upLength) ,
				(int)camera->TranX(x + rightLength) ,
				(int)camera->TranY(y + downLength) ,
				rgb ,
				true 
			);
		}
		else
		{
			DxLib::DrawBox
			( 
				(int)( x - leftLength ) ,
				(int)( y - upLength ) ,
				(int)( x + rightLength ) ,
				(int)( y + downLength) ,
				rgb ,
				true 
			);
		}
		DxLib::SetDrawBlendMode( 0 , transRate);
	}

	double GetX() const
	{
		return x;
	}

	double GetY() const
	{
		return y;
	}

	double GetW() const
	{
		return upLength + downLength;
	}

	double GetH() const
	{
		return leftLength + rightLength;
	}
			
	virtual double GetLeft() const
	{
		return int(x - leftLength);
	}

	virtual double GetTop() const
	{
		return int(y - upLength);
	}

	virtual double GetRight() const
	{
		return int(x + rightLength);
	}

	virtual double GetBottom() const
	{
		return int(y + downLength);
	}
			
	bool Hit(const Figure *figure) const
	{
		return figure->Hit( this );
	}
	bool Hit(const Complex *complex) const
	{
		for( auto it : complex->figures )
		{
			if( it->Hit( this ) ) return true;
		}
		return false;
	}
	bool Hit(const Point *point) const
	{
		return (
					(
						point->x < this->GetRight()
					) && (
						point->x > this->GetLeft()
					) && (			
						point->y < this->GetBottom()
					) && (
						point->y > this->GetTop()
					)		
			);
	}
	bool Hit(const Line *line) const
	{				
		if( ! RectRect
			(
				line->GetMinX() - line->GetThickHarf(),
				line->GetMinY() - line->GetThickHarf(),
				line->GetMaxX() + line->GetThickHarf(),
				line->GetMaxY() + line->GetThickHarf(),
				this->GetLeft(),
				this->GetTop(),
				this->GetRight(),
				this->GetBottom()
			)
			)
		{
			return false;
		}

		//√２/2≒0.7

		if( LineLine( line->GetXA() , line->GetYA() , line->GetXB() , line->GetYB()
					,  this->GetLeft() - int(line->GetThickHarf() * 0.7) , this->GetTop() - int(line->GetThickHarf() * 0.7) , this->GetRight() + int(line->GetThickHarf() * 0.7) , this->GetBottom() + int(line->GetThickHarf() * 0.7)  ))
		{
			return true;
		}

		if( LineLine( line->GetXA() , line->GetYA() , line->GetXB() , line->GetYB()
					, this->GetRight() + int(line->GetThickHarf() * 0.7)  , this->GetTop() - int(line->GetThickHarf() * 0.7) , this->GetLeft() - int(line->GetThickHarf() * 0.7) , this->GetBottom() + int(line->GetThickHarf() * 0.7) ))
		{
			return true;
		}

		//端の丸い所以外判定
		if( 
			line->GetXA() + line->GetThickHarf() > this->GetLeft() && line->GetXA() - line->GetThickHarf() < this->GetRight() &&
			line->GetYA() + line->GetThickHarf() > this->GetTop() && line->GetYA() - line->GetThickHarf() < this->GetBottom() 
			)
		{
				//端の丸い所判定
				if(		  line->GetXA() < this->GetLeft()				&& line->GetYA() < this->GetTop() )
				{//左上
					
					if( (line->GetXA() - this->GetLeft()) * (line->GetXA() - this->GetLeft()) +
						(line->GetYA() - this->GetTop()) * (line->GetYA() - this->GetTop()) < line->GetThickPow() ) return true;
					
				}
				else if( line->GetXA() > this->GetRight() && line->GetYA() < this->GetTop() )
				{//右上
					
					if( (line->GetXA() - this->GetRight()) * (line->GetXA() - this->GetRight()) +
						(line->GetYA() - this->GetTop()) * (line->GetYA() - this->GetTop()) < line->GetThickPow() ) return true;

				}
				else if( line->GetXA() < this->GetLeft()				&& line->GetYA() > this->GetBottom() )
				{//左下
					
					if( (line->GetXA() - this->GetLeft()) * (line->GetXA() - this->GetLeft()) +
						(line->GetYA() - this->GetBottom()) * (line->GetYA() - this->GetBottom()) < line->GetThickPow() ) return true;
					
				}
				else if( line->GetXA() > this->GetRight() && line->GetYA() > this->GetBottom() )
				{//右下

					if( (line->GetXA() - this->GetRight()) * (line->GetXA() - this->GetRight()) +
						(line->GetYA() - this->GetBottom()) * (line->GetYA() - this->GetBottom()) < line->GetThickPow() ) return true;
					
				}
				else
				{	
					return true;
				}
		}

		if( 
			line->GetXB() + line->GetThickHarf()  > this->GetLeft() && line->GetXB() - line->GetThickHarf() < this->GetRight() &&
			line->GetYB() + line->GetThickHarf()  > this->GetTop() && line->GetYB() - line->GetThickHarf() < this->GetBottom()
			)
		{
			//端の丸い所判定
			if(		  line->GetXB() < this->GetLeft()				&& line->GetYB() < this->GetTop() )
			{//左上
				if( (line->GetXB() - this->GetLeft()) * (line->GetXB() - this->GetLeft()) +
					(line->GetYB() - this->GetTop()) * (line->GetYB() - this->GetTop()) < line->GetThickPow() ) return true;
					
			}
			else if( line->GetXB() > this->GetRight() && line->GetYB() < this->GetTop() )
			{//右上
					
				if( (line->GetXB() - this->GetRight()) * (line->GetXB() - this->GetRight()) +
					(line->GetYB() - this->GetTop()) * (line->GetYB() - this->GetTop()) < line->GetThickPow() ) return true;

			}
			else if( line->GetXB() < this->GetLeft()				&& line->GetYB() > this->GetBottom() )
			{//左下
					
				if( (line->GetXB() - this->GetLeft()) * (line->GetXB() - this->GetLeft()) +
					(line->GetYB() - this->GetBottom()) * (line->GetYB() - this->GetBottom()) < line->GetThickPow() ) return true;
					
			}
			else if( line->GetXB() > this->GetRight() && line->GetYB() > this->GetBottom() )
			{//右下
				if( (line->GetXB() - this->GetRight()) * (line->GetXB() - this->GetRight()) +
					(line->GetYB() - this->GetBottom()) * (line->GetYB() - this->GetBottom()) < line->GetThickPow() ) return true;
					
			}
			else
			{	
				return true;			
			}
		}

		return false;
	}
	bool Hit(const Rect *rect) const
	{
		return RectRect
			(
				this->GetLeft() , this->GetTop() , this->GetRight() , this->GetBottom() ,
				rect->GetLeft() , rect->GetTop() , rect->GetRight() , rect->GetBottom() 
			);
	}
	bool Hit(const Circle *circle) const;
};
	
/// <summary>説明</summary>
///	<example>
///	[サンプルコード:未完成]<BR>
/// サンプル説明<BR>
///	<code>
///	int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )<BR>
///	{<BR>
///		if( !Dx::Initialise() ) return -1;<BR>
///		Dx::End();<BR>
///		return 0;<BR>
/// }<BR>
/// </code>	
/// </example>
class Circle : public Figure
{
public:
	double x;
	double y;
	double radius;
			
	/// <summary>説明</summary>
	Circle(	double x , double y , double radius):
		x(x),
		y(y),
		radius(radius)
	{}

	Figure* Clone(double x,double y) const
	{
		return new Circle( x , y , this->radius );
	}

	void SetPos(double x , double y )
	{
		this->x = x;
		this->y = y;
	}

	void MultiZoom(double rate)
	{
		this->radius *= rate;
	}
			
	void MultiZoom(double rateX , double rateY)
	{
		this->radius *= rateX;
	}

	void Rotate(double angle){}

	void SetAngle(double angle){}

	void Move(double mX , double mY )
	{
		this->x += mX;
		this->y += mY;
	}

	double GetX() const
	{
		return int(x);
	}

	double GetY() const
	{
		return int(y);
	}
			
	double GetW() const
	{
		return int(radius*2);
	}

	double GetH() const
	{
		return int(radius*2);
	}

	void Draw( int rgb , int transRate , Camera *camera = 0) const
	{
		DxLib::SetDrawBlendMode( 1 , transRate);
		if( camera )
		{
			DxLib::DrawCircle( (int)camera->TranX(x) , (int)camera->TranY(y) , (int)(radius * camera->GetZoom()) , rgb , true );
		}
		else
		{
			DxLib::DrawCircle( (int)x , (int)y , (int)radius , rgb , true );
		}
		DxLib::SetDrawBlendMode( 0 , transRate);
	}
			
	bool Hit(const Figure *figure) const
	{
		return figure->Hit( this );
	}
	bool Hit(const Complex *complex) const
	{
		for( auto it : complex->figures )
		{
			if( it->Hit( this ) ) return true;
		}
		return false;
	}
	bool Hit(const Point *point) const
	{
		return
		(
			( point->x - this->x ) * ( point->x - this->x )  +
			( point->y - this->y ) * ( point->y - this->y )
			<=
			( this->radius * this->radius )
		);
	}
	bool Hit(const Line *line) const
	{
		return line->LinePoint( this->x , this->y , (line->GetThickHarf() + this->radius) * (line->GetThickHarf() + this->radius) );
	}
	bool Hit(const Circle *circle) const
	{
		return(
				(this->x - circle->x) * (this->x - circle->x) +
				(this->y - circle->y) * (this->y - circle->y) 			
				<=
				(this->radius + circle->radius) * (this->radius + circle->radius)
			);
	}
	bool Hit(const Rect *rect) const
	{
		return 
		(				
			(
				(
					(
						this->x + this->radius >= rect->GetLeft()						
					)&&(
						this->x - this->radius <= rect->GetRight()
					)
				)&&(
					(
						this->y >= rect->GetTop()
					)&&(
						this->y <= rect->GetBottom()
					)
				)
			) || (
				(
					(
						this->x >= rect->GetLeft()
					)&&(
						this->x <= rect->GetRight()
					)									
				)&&(
					(
						this->y + this->radius >= rect->GetTop()
					)&&(
						this->y - this->radius <= rect->GetBottom()
					)
				)
			) || (//四角形の四隅と円の判定
				(this->x - rect->GetLeft() ) * (this->x - rect->GetLeft() ) +
				(this->y - rect->GetTop() ) * (this->y - rect->GetTop() ) <=
				(this->radius * this->radius )
			) || (
				(this->x - rect->GetRight()) * (this->x - rect->GetRight()) +
				(this->y - rect->GetTop() ) * (this->y - rect->GetTop() ) <=
				(this->radius * this->radius )
			) || (
				(this->x - rect->GetLeft()) * (this->x - rect->GetLeft()) +
				(this->y - rect->GetBottom()) * (this->y -rect->GetBottom()) <=
				(this->radius * this->radius )
			) || (
				(this->x - rect->GetRight()) * (this->x - rect->GetRight()) +
				(this->y - rect->GetBottom()) * (this->y - rect->GetBottom()) <=
				(this->radius * this->radius )
			)
		);
	}
};
}
