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 PerforatedPolygonRsRt : ElementRsRt
{
PointF center;
float rOuter, rInner;
int nApexes;
SolidBrush brush;
double scaling; // only for scaling between MouseDown and MouseUp
double compensation; // only for rotation between MouseDown and MouseUp
bool bShowEdges;
Color clrEdges;
int minW = 20;
int minRad = 20;
// -------------------------------------------------
public PerforatedPolygonRsRt (PointF ptC, float radiusOut, float radiusIn, int apexes, double angleDegree, Color color)
{
id = Auxi_Common .UniqueID;
idParent = 0;
figure = Figure .PerforatedPolygon;
bResize = true;
bRotate = true;
center = ptC;
float rBigger = Math .Max (Math .Abs (radiusOut), Math .Abs (radiusIn));
float rSmaller = Math .Min (Math .Abs (radiusOut), Math .Abs (radiusIn));
rInner = Math .Max (rSmaller, minRad);
rOuter = Math .Max (rBigger, rInner + minW);
nApexes = Math .Max (Math .Abs (apexes), 3);
angle = Auxi_Convert .DegreeToRadian (Auxi_Common .LimitedDegree (angleDegree));
brush = new SolidBrush (color);
bShowEdges = true;
clrEdges = Color .DarkGray;
}
// ------------------------------------------------- Copy
public override ElementRsRt Copy (PointF pt)
{
PerforatedPolygonRsRt figure = new PerforatedPolygonRsRt (pt, rOuter, rInner, nApexes,
Auxi_Convert .RadianToDegree (angle), GetColor ());
figure .Resizable = bResize;
figure .Rotatable = bRotate;
figure .ShowEdges = bShowEdges;
return ((ElementRsRt) figure);
}
// -------------------------------------------------
public override void Draw (Graphics grfx)
{
PointF [] ptOut = Auxi_Geometry .RegularPolygon (center, rOuter, nApexes, angle);
PointF [] ptIn = Auxi_Geometry .RegularPolygon (center, rInner, nApexes, angle);
GraphicsPath path = new GraphicsPath ();
path .AddPolygon (ptIn);
path .AddPolygon (ptOut);
grfx .FillPath (brush, path);
if (bShowEdges)
{
Pen pen = new Pen (clrEdges);
grfx .DrawPolygon (pen, ptIn);
grfx .DrawPolygon (pen, ptOut);
for (int i = 0; i < nApexes; i++)
{
grfx .DrawLine (pen, ptIn [i], ptOut [i]);
}
}
}
// ------------------------------------------------- Center
public override PointF Center ()
{
return (center);
}
// ------------------------------------------------- RadiusOut
public float RadiusOut
{
get { return (rOuter); }
}
// ------------------------------------------------- RadiusIn
public float RadiusIn
{
get { return (rInner); }
}
// ------------------------------------------------- ApexNumber
public int ApexNumber
{
get { return (nApexes); }
}
// ------------------------------------------------- ApexesOut
public PointF [] ApexesOut
{
get { return (Auxi_Geometry .RegularPolygon (center, rOuter, nApexes, angle)); }
}
// ------------------------------------------------- ApexesIn
public PointF [] ApexesIn
{
get { return (Auxi_Geometry .RegularPolygon (center, rInner, nApexes, angle)); }
}
// ------------------------------------------------- ShowEdges
public bool ShowEdges
{
get { return (bShowEdges); }
set { bShowEdges = value; }
}
// ------------------------------------------------- RectAround
public override RectangleF RectAround ()
{
return (Auxi_Geometry .RectAroundPoints (ApexesOut));
}
// ------------------------------------------------- SetAngle
public override void SetAngle (double angleNew)
{
angle = Auxi_Common .LimitedRadian (angleNew);
DefineCover ();
}
// ------------------------------------------------- GetColor
public override Color GetColor ()
{
return (brush .Color);
}
// ------------------------------------------------- SetColor
public override void SetColor (Color color)
{
brush = new SolidBrush (color);
}
// ------------------------------------------------- DefineCover
public override void DefineCover ()
{
PointF [] ptOut = Auxi_Geometry .RegularPolygon (center, rOuter, nApexes, angle);
PointF [] ptIn = Auxi_Geometry .RegularPolygon (center, rInner, nApexes, angle);
CoverNode [] nodes;
if (bResize)
{
// order of nodes:
// [0 - (nApexes - 1)] strip nodes, covering each segment of the inner border
// [nApexes - (2*nApexes - 1)] strip nodes, covering each segment of the outer border
// [2*nApexes - (3*nApexes - 1)] big polygon nodes
//
nodes = new CoverNode [3 * nApexes];
for (int i = 0; i < nApexes; i++)
{
nodes [i] = new CoverNode (i, ptIn [i], ptIn [(i + 1) % nApexes]);
}
for (int i = 0; i < nApexes; i++)
{
nodes [nApexes + i] = new CoverNode (nApexes + i, ptOut [i], ptOut [(i + 1) % nApexes]);
}
for (int i = 0; i < nApexes; i++)
{
int i1 = (i + 1) % nApexes;
nodes [2 * nApexes + i] = new CoverNode (2 * nApexes + i, new PointF [] { ptIn [i], ptIn [i1], ptOut [i1], ptOut [i] });
}
}
else
{
nodes = new CoverNode [nApexes];
for (int i = 0; i < nApexes; i++)
{
int i1 = (i + 1) % nApexes;
nodes [i] = new CoverNode (i, new PointF [] { ptIn [i], ptIn [i1], ptOut [i1], ptOut [i] });
}
}
cover = new Cover (nodes);
}
// -------------------------------------------------
public override void Move (int dx, int dy)
{
center += new Size (dx, dy);
}
// ------------------------------------------------- MoveNode
public override bool MoveNode (int i, int dx, int dy, Point ptM, MouseButtons catcher)
{
if (catcher == MouseButtons .Left)
{
if (bResize)
{
if (i >= 2 * nApexes)
{
Move (dx, dy);
}
else
{
double distanceMouse = Auxi_Geometry .Distance (center, ptM);
float rNew = Convert .ToSingle (distanceMouse * scaling);
if (i < nApexes)
{
if (minRad <= rNew && rNew + minW <= rOuter)
{
rInner = rNew;
}
}
else
{
if (rInner + minW <= rNew)
{
rOuter = rNew;
}
}
}
DefineCover ();
}
else
{
Move (dx, dy);
}
return (true);
}
else if (catcher == MouseButtons .Right && bRotate)
{
double angleMouse = Auxi_Geometry .Line_Angle (center, ptM);
angle = Auxi_Common .LimitedRadian (angleMouse - compensation);
DefineCover ();
return (true);
}
return (false);
}
// ------------------------------------------------- StartScaling
public void StartScaling (Point ptMouse, int nodeCaught)
{
double distanceMouse = Auxi_Geometry .Distance (center, ptMouse);
if (nodeCaught < nApexes)
{
scaling = rInner / distanceMouse;
}
else
{
scaling = rOuter / distanceMouse;
}
}
// ------------------------------------------------- StartRotation
public override void StartRotation (Point ptMouse)
{
double angleMouse = Auxi_Geometry .Line_Angle (center, ptMouse);
compensation = Auxi_Common .LimitedRadian (angleMouse - angle);
}
// ------------------------------------------------- IntoMover
public override void IntoMover (Mover mover, int iPos)
{
mover .Insert (iPos, this);
}
}
}