using System;
using System .Collections .Generic;
using System .ComponentModel;
using System .Drawing;
using System .Drawing .Drawing2D;
using System .Windows .Forms;
using MoveGraphLibrary;
namespace TheoryOfMoveableObjects
{
public class ChatoyantPolygonRsRt : ElementRsRt
{
PointF center;
PointF [] ptApex;
Color [] clrApex;
Color clrCenter;
bool bAuxiLines;
// for rotation or scaling between MouseDown and MouseUp
double [] radii;
double [] angles;
double [] compensation; // only for rotation between MouseDown and MouseUp
double [] scaling; // only for scaling between MouseDown and MouseUp
// -------------------------------------------------
public ChatoyantPolygonRsRt (PointF ptC, PointF [] ptA, Color clrC, Color [] clrA)
{
id = Auxi_Common .UniqueID;
idParent = 0;
figure = Figure .ChatoyantPolygon;
bResize = true;
bRotate = true;
center = ptC;
clrCenter = clrC;
if (ptA != null && clrA != null && ptA .Length >= 3 && ptA .Length == clrA .Length)
{
ptApex = new PointF [ptA .Length];
for (int i = 0; i < ptApex .Length; i++)
{
ptApex [i] = new PointF (ptA [i] .X, ptA [i] .Y);
}
clrApex = clrA;
}
else
{
ptApex = new PointF [4] {new PointF (ptC .X + 160, ptC .Y), new PointF (ptC .X, ptC .Y + 120),
new PointF (ptC .X - 80, ptC .Y), new PointF (ptC .X, ptC .Y - 40) };
clrApex = new Color [4] { Color .Red, Color .Green, Color .Blue, Color .Yellow };
}
bAuxiLines = false;
radii = new double [ptApex .Length];
scaling = new double [ptApex .Length];
compensation = new double [ptApex .Length];
angles = new double [ptApex .Length];
angle = Auxi_Geometry .Line_Angle (center, ptApex [0]);
}
// ------------------------------------------------- Copy
public override ElementRsRt Copy (PointF pt)
{
ApexArrays ();
int nApexes = ptApex .Length;
PointF [] pts = new PointF [nApexes];
Color [] clrs = new Color [nApexes];
for (int i = 0; i < nApexes; i++)
{
pts [i] = new PointF (pt .X + (ptApex [i] .X - center .X), pt .Y + (ptApex [i] .Y - center .Y));
clrs [i] = clrApex [i];
}
ChatoyantPolygonRsRt figure = new ChatoyantPolygonRsRt (pt, pts, clrCenter, clrs);
figure .Resizable = bResize;
figure .Rotatable = bRotate;
return ((ElementRsRt) figure);
}
// ------------------------------------------------- ApexNum
public int ApexNum
{
get { return (ptApex .Length); }
}
// ------------------------------------------------- Center
public override PointF Center ()
{
return (center);
}
// ------------------------------------------------- Apexes
public PointF [] Apexes
{
get { return (ptApex); }
}
// ------------------------------------------------- RectAround
public override RectangleF RectAround ()
{
RectangleF rc = Auxi_Geometry .RectAroundPoints (Apexes);
float cxL = Math .Min (center .X, rc .Left);
float cxR = Math .Max (center .X, rc .Right);
float cyT = Math .Min (center .Y, rc .Top);
float cyB = Math .Max (center .Y, rc .Bottom);
return (new RectangleF (cxL, cyT, cxR - cxL, cyB - cyT));
}
// ------------------------------------------------- SetAngle
public override void SetAngle (double angleNew)
{
ApexArrays ();
double angleDif = angleNew - angles [0];
for (int i = 0; i < ptApex .Length; i++)
{
angles [i] = Auxi_Common .LimitedRadian (angles [i] + angleDif);
ptApex [i] = Auxi_Geometry .PointToPoint (center, angles [i], radii [i]);
}
DefineCover ();
}
// ------------------------------------------------- GetColor
public override Color GetColor ()
{
return (clrApex [0]);
}
// ------------------------------------------------- SetColor
public override void SetColor (Color color)
{
clrApex [0] = color;
}
// ------------------------------------------------- ColorApex
public Color ColorApex (int i)
{
return (clrApex [Math .Min (Math .Max (0, i), ApexNum - 1)]);
}
// ------------------------------------------------- SetColorApex
public void SetColorApex (int i, Color clr)
{
if (0 <= i && i < ApexNum)
{
clrApex [i] = clr;
}
}
// ------------------------------------------------- ColorCenter
public Color ColorCenter
{
get { return (clrCenter); }
set { clrCenter = value; }
}
// ------------------------------------------------- AuxiLines
public bool AuxiLines
{
get { return (bAuxiLines); }
set { bAuxiLines = value; }
}
// ------------------------------------------------- Draw
public override void Draw (Graphics grfx)
{
Auxi_Drawing .FillChatoyantPolygon (grfx, center, ptApex, clrCenter, clrApex);
if (bAuxiLines)
{
foreach (PointF pt in ptApex)
{
grfx .DrawLine (Pens .DarkGray, center, pt);
}
}
}
// ------------------------------------------------- DefineCover
// order of nodes:
// [ApexNum] - circular nodes in apexes
// 1 - circular node in ptCenter
// [ApexNum] - strip nodes, covering each segment of the perimeter
// [ApexNum] - big triangular nodes
//
public override void DefineCover ()
{
CoverNode [] nodes = new CoverNode [3 * ApexNum + 1];
for (int i = 0; i < ApexNum; i++)
{
nodes [i] = new CoverNode (i, ptApex [i], 6);
}
nodes [ApexNum] = new CoverNode (ApexNum, center, 6);
int k0 = ApexNum + 1;
for (int i = 0; i < ApexNum; i++)
{
nodes [k0 + i] = new CoverNode (k0 + i, ptApex [i], ptApex [(i + 1) % ApexNum]);
}
k0 = 2 * ApexNum + 1;
for (int i = 0; i < ApexNum; i++)
{
PointF [] pts = new PointF [3] { ptApex [i], ptApex [(i + 1) % ApexNum], center };
nodes [k0 + i] = new CoverNode (k0 + i, pts);
}
cover = new Cover (nodes);
}
// ------------------------------------------------- Move
public override void Move (int cx, int cy)
{
for (int i = 0; i < ApexNum; i++)
{
ptApex [i] += new Size (cx, cy);
}
center += new Size (cx, cy);
}
// ------------------------------------------------- MoveNode
public override bool MoveNode (int i, int cx, int cy, Point ptM, MouseButtons catcher)
{
if (catcher == MouseButtons .Left)
{
if (i < ApexNum)
{
ptApex [i] += new Size (cx, cy);
}
else if (i == ApexNum)
{
center += new Size (cx, cy);
}
else if (i >= 2 * ApexNum + 1)
{
Move (cx, cy);
}
else
{
double distanceMouse = Auxi_Geometry .Distance (center, ptM);
if (distanceMouse > 25)
{
for (int j = 0; j < ApexNum; j++)
{
ptApex [j] = Auxi_Geometry .PointToPoint (center, angles [j], distanceMouse * scaling [j]);
}
}
}
DefineCover ();
return (true);
}
else if (catcher == MouseButtons .Right && bRotate)
{
double angleMouse = -Math .Atan2 (ptM .Y - center .Y, ptM .X - center .X);
for (int j = 0; j < ApexNum; j++)
{
ptApex [j] = Auxi_Geometry .PointToPoint (center, Auxi_Common .LimitedRadian (angleMouse - compensation [j]), radii [j]);
}
DefineCover ();
return (true);
}
return (false);
}
// ------------------------------------------------- StartScaling
// the scaling is not used with the apexes, but only with the strips between them
//
public void StartScaling (Point ptMouse, NodeShape nodeshape)
{
if (nodeshape == NodeShape .Strip)
{
ApexArrays ();
double distanceMouse = Auxi_Geometry .Distance (center, ptMouse);
for (int i = 0; i < ApexNum; i++)
{
scaling [i] = radii [i] / distanceMouse;
}
}
}
// ------------------------------------------------- StartRotation
public override void StartRotation (Point ptMouse)
{
ApexArrays ();
double angleMouse = Auxi_Geometry .Line_Angle (center, ptMouse);
for (int i = 0; i < ApexNum; i++)
{
compensation [i] = Auxi_Common .LimitedRadian (angleMouse - angles [i]);
}
}
// ------------------------------------------------- ApexArrays
private void ApexArrays ()
{
for (int i = 0; i < ApexNum; i++)
{
radii [i] = Auxi_Geometry .Distance (center, ptApex [i]);
angles [i] = Auxi_Geometry .Line_Angle (center, ptApex [i]);
}
}
// ------------------------------------------------- IntoMover
public override void IntoMover (Mover mover, int iPos)
{
mover .Insert (iPos, this);
}
}
}