using System;
using System .Collections .Generic;
using System .ComponentModel;
using System .Drawing;
using System .Drawing .Drawing2D;
using System .Windows .Forms;
using MoveGraphLibrary;
namespace TheoryOfMoveableObjects
{
// asymmetrical resizing
public class RectangleRsRt : ElementRsRt
{
PointF [] pts = new PointF [4];
SolidBrush brush;
double compensation; // only between MouseDown and MouseUp
PointF center; // only between MouseDown and MouseUp
int radiusCorner = 6;
static int minSide = 20;
// -------------------------------------------------
public RectangleRsRt (PointF ptC, float w, float h, double angleDegree, Color color)
{
id = Auxi_Common .UniqueID;
idParent = 0;
figure = Figure .Rectangle;
bResize = true;
bRotate = true;
w = Math .Max (minSide, Math .Abs (w));
h = Math .Max (minSide, Math .Abs (h));
angle = Auxi_Convert .DegreeToRadian (angleDegree);
double radius = Math .Sqrt (w * w + h * h) / 2;
double angle_plus = Math .Atan2 (h, w);
pts = new PointF [4] {Auxi_Geometry .PointToPoint (ptC, angle + angle_plus, radius),
Auxi_Geometry .PointToPoint (ptC, angle - angle_plus + Math .PI, radius),
Auxi_Geometry .PointToPoint (ptC, angle + angle_plus + Math .PI, radius),
Auxi_Geometry .PointToPoint (ptC, angle - angle_plus, radius) };
brush = new SolidBrush (color);
}
// ------------------------------------------------- Copy
public override ElementRsRt Copy (PointF pt)
{
RectangleRsRt figure = new RectangleRsRt (pt, Width, Height, Auxi_Convert .RadianToDegree (angle), GetColor ());
figure .Resizable = bResize;
figure .Rotatable = bRotate;
return ((ElementRsRt) figure);
}
// ------------------------------------------------- Draw
public override void Draw (Graphics grfx)
{
grfx .FillPolygon (brush, pts);
}
// ------------------------------------------------- Radius
private double Radius
{
get { return (Auxi_Geometry .Distance (pts [0], pts [2]) / 2); }
}
// ------------------------------------------------- Apexes
private PointF [] Apexes
{
get { return (pts); }
}
// ------------------------------------------------- Width
public float Width
{
get { return (Convert .ToSingle (Auxi_Geometry .Distance (pts [0], pts [1]))); }
}
// ------------------------------------------------- Height
public float Height
{
get { return (Convert .ToSingle (Auxi_Geometry .Distance (pts [0], pts [3]))); }
}
// ------------------------------------------------- Center
public override PointF Center ()
{
return (Auxi_Geometry .Middle (pts [0], pts [2]));
}
// ------------------------------------------------- MinimumSide
static public int MinimumSide
{
get { return (minSide); }
}
// ------------------------------------------------- RectAround
public override RectangleF RectAround ()
{
return (Auxi_Geometry .RectAroundPoints (pts));
}
// ------------------------------------------------- SetAngle
public override void SetAngle (double angleNew)
{
angle = Auxi_Common .LimitedRadian (angleNew);
double angle_plus = Math .Atan2 (Height, Width);
PointF ptC = Center ();
double radius = Radius;
pts = new PointF [4] {Auxi_Geometry .PointToPoint (ptC, angle + angle_plus, radius),
Auxi_Geometry .PointToPoint (ptC, angle - angle_plus + Math .PI, radius),
Auxi_Geometry .PointToPoint (ptC, angle + angle_plus + Math .PI, radius),
Auxi_Geometry .PointToPoint (ptC, angle - angle_plus, radius) };
DefineCover ();
}
// ------------------------------------------------- GetColor
public override Color GetColor ()
{
return (brush .Color);
}
// ------------------------------------------------- SetColor
public override void SetColor (Color color)
{
brush = new SolidBrush (color);
}
// ------------------------------------------------- StartRotation
public override void StartRotation (Point ptMouse)
{
center = Center ();
double angleMouse = Auxi_Geometry .Line_Angle (center, ptMouse);
compensation = Auxi_Common .LimitedRadian (angleMouse - angle);
}
// ------------------------------------------------- DefineCover
public override void DefineCover ()
{
CoverNode [] nodes;
if (bResize)
{
nodes = new CoverNode [9];
for (int i = 0; i < 4; i++)
{
nodes [i] = new CoverNode (i, pts [i], radiusCorner);
}
for (int i = 0; i < 4; i++)
{
nodes [i + 4] = new CoverNode (i + 4, pts [i], pts [(i + 1) % 4]);
}
nodes [8] = new CoverNode (8, pts);
}
else
{
nodes = new CoverNode [] { new CoverNode (0, pts) };
}
cover = new Cover (nodes);
}
// ------------------------------------------------- Move
public override void Move (int dx, int dy)
{
SizeF size = new SizeF (dx, dy);
for (int i = 0; i < 4; i++)
{
pts [i] += size;
}
}
// ------------------------------------------------- MoveNode
public override bool MoveNode (int i, int dx, int dy, Point ptM, MouseButtons catcher)
{
bool bRet = false;
double angleMouse;
if (catcher == MouseButtons .Left)
{
if (bResize)
{
double newD, newW, newH;
PointF ptOpposite, ptA_oppositeside, ptB_oppositeside;
switch (i)
{
case 0:
ptOpposite = pts [2];
angleMouse = Auxi_Geometry .Line_Angle (ptOpposite, ptM);
newD = Auxi_Geometry .Distance (ptOpposite, ptM);
newW = Math .Abs (newD * Math .Cos (angleMouse - angle));
newH = Math .Abs (newD * Math .Sin (angleMouse - angle));
if (newW >= minSide && newH >= minSide && NotInverted (i, ptM))
{
pts = new PointF [4] { ptM,
Auxi_Geometry .PointToPoint (ptM, angle + Math .PI, newW),
ptOpposite,
Auxi_Geometry .PointToPoint (ptM, angle - Math .PI / 2, newH) };
DefineCover ();
bRet = true;
}
break;
case 1:
ptOpposite = pts [3];
angleMouse = Auxi_Geometry .Line_Angle (ptOpposite, ptM);
newD = Auxi_Geometry .Distance (ptOpposite, ptM);
newW = Math .Abs (newD * Math .Cos (angleMouse - angle));
newH = Math .Abs (newD * Math .Sin (angleMouse - angle));
if (newW >= minSide && newH >= minSide && NotInverted (i, ptM))
{
pts = new PointF [4] { Auxi_Geometry .PointToPoint (ptOpposite, angle + Math .PI / 2, newH),
ptM,
Auxi_Geometry .PointToPoint (ptOpposite, angle + Math .PI, newW),
ptOpposite };
DefineCover ();
bRet = true;
}
break;
case 2:
ptOpposite = pts [0];
angleMouse = Auxi_Geometry .Line_Angle (ptOpposite, ptM);
newD = Auxi_Geometry .Distance (ptOpposite, ptM);
newW = Math .Abs (newD * Math .Cos (angleMouse - angle));
newH = Math .Abs (newD * Math .Sin (angleMouse - angle));
if (newW >= minSide && newH >= minSide && NotInverted (i, ptM))
{
pts = new PointF [4] { ptOpposite,
Auxi_Geometry .PointToPoint (ptOpposite, angle + Math .PI, newW),
ptM,
Auxi_Geometry .PointToPoint (ptOpposite, angle - Math .PI / 2, newH) };
DefineCover ();
bRet = true;
}
break;
case 3:
ptOpposite = pts [1];
angleMouse = Auxi_Geometry .Line_Angle (ptOpposite, ptM);
newD = Auxi_Geometry .Distance (ptOpposite, ptM);
newW = Math .Abs (newD * Math .Cos (angleMouse - angle));
newH = Math .Abs (newD * Math .Sin (angleMouse - angle));
if (newW >= minSide && newH >= minSide && NotInverted (i, ptM))
{
pts = new PointF [4] { Auxi_Geometry .PointToPoint (ptM, angle + Math .PI / 2, newH),
ptOpposite,
Auxi_Geometry .PointToPoint (ptM, angle + Math .PI, newW),
ptM };
DefineCover ();
bRet = true;
}
break;
case 4:
ptA_oppositeside = pts [2];
ptB_oppositeside = pts [3];
newH = Auxi_Geometry .DistanceToLine (ptM, ptA_oppositeside, ptB_oppositeside);
if (newH >= minSide)
{
pts [0] = Auxi_Geometry .PointToPoint (pts [3], angle + Math .PI / 2, newH);
pts [1] = Auxi_Geometry .PointToPoint (pts [2], angle + Math .PI / 2, newH);
DefineCover ();
bRet = true;
}
break;
case 5:
ptA_oppositeside = pts [0];
ptB_oppositeside = pts [3];
newW = Auxi_Geometry .DistanceToLine (ptM, ptA_oppositeside, ptB_oppositeside);
if (newW >= minSide)
{
pts [1] = Auxi_Geometry .PointToPoint (pts [0], angle + Math .PI, newW);
pts [2] = Auxi_Geometry .PointToPoint (pts [3], angle + Math .PI, newW);
DefineCover ();
bRet = true;
}
break;
case 6:
ptA_oppositeside = Apexes [0];
ptB_oppositeside = Apexes [1];
newH = Auxi_Geometry .DistanceToLine (ptM, ptA_oppositeside, ptB_oppositeside);
if (newH >= minSide)
{
pts [2] = Auxi_Geometry .PointToPoint (pts [1], angle - Math .PI / 2, newH);
pts [3] = Auxi_Geometry .PointToPoint (pts [0], angle - Math .PI / 2, newH);
DefineCover ();
bRet = true;
}
break;
case 7:
ptA_oppositeside = pts [1];
ptB_oppositeside = pts [2];
newW = Auxi_Geometry .DistanceToLine (ptM, ptA_oppositeside, ptB_oppositeside);
if (newW >= minSide)
{
pts [0] = Auxi_Geometry .PointToPoint (pts [1], angle, newW);
pts [3] = Auxi_Geometry .PointToPoint (pts [2], angle, newW);
DefineCover ();
bRet = true;
}
break;
case 8:
Move (dx, dy);
bRet = true;
break;
}
}
else
{
Move (dx, dy);
bRet = true;
}
}
else if (catcher == MouseButtons .Right && bRotate)
{
angleMouse = Auxi_Geometry .Line_Angle (center, ptM);
angle = angleMouse - compensation;
double radius = Radius;
double w = Auxi_Geometry .Distance (pts [0], pts [1]);
double h = Auxi_Geometry .Distance (pts [0], pts [3]);
double angle_plus = Math .Atan2 (h, w);
pts = new PointF [4] {Auxi_Geometry .PointToPoint (center, angle + angle_plus, radius),
Auxi_Geometry .PointToPoint (center, angle - angle_plus + Math .PI, radius),
Auxi_Geometry .PointToPoint (center, angle + angle_plus + Math .PI, radius),
Auxi_Geometry .PointToPoint (center, angle - angle_plus, radius) };
DefineCover ();
bRet = true;
}
return (bRet);
}
// ------------------------------------------------- IntoMover
public override void IntoMover (Mover mover, int iPos)
{
mover .Insert (iPos, this);
}
// ------------------------------------------------- NotInverted
private bool NotInverted (int iCorner, Point ptM)
{
return (Auxi_Geometry .SameSideOfLine (pts [(iCorner + 1) % 4], pts [(iCorner + 2) % 4], pts [(iCorner + 3) % 4], ptM) &&
Auxi_Geometry .SameSideOfLine (pts [(iCorner + 2) % 4], pts [(iCorner + 3) % 4], pts [(iCorner + 1) % 4], ptM));
}
}
}