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 CircleInsidePolyRsRt : ElementRsRt
{
PointF center;
float rOuter, rInner;
int nApexes;
SolidBrush brush;
int nNodesOnCircle;
double scaling; // only for scaling between MouseDown and MouseUp
double compensation; // only for rotation between MouseDown and MouseUp
int minW = 20;
int minRad = 20;
int nrSmall = 5;
int distanceNeighbours = 8;
// -------------------------------------------------
public CircleInsidePolyRsRt (PointF ptC, float radiusOut, float radiusIn, int apexes, double angleDegree, Color color)
{
id = Auxi_Common .UniqueID;
idParent = 0;
figure = Figure .CircleInsidePoly;
bResize = true;
bRotate = true;
nApexes = Math .Max (Math .Abs (apexes), 3);
angle = Auxi_Convert .DegreeToRadian (Auxi_Common .LimitedDegree (angleDegree));
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 = Convert .ToSingle (Math .Max (rBigger, (rInner + minW) / Math .Cos (Math .PI / nApexes)));
brush = new SolidBrush (color);
NodesOnCircle ();
}
// ------------------------------------------------- Copy
public override ElementRsRt Copy (PointF pt)
{
CircleInsidePolyRsRt figure = new CircleInsidePolyRsRt (pt, rOuter, rInner, nApexes, Auxi_Convert .RadianToDegree (angle), GetColor ());
figure .Resizable = bResize;
figure .Rotatable = bRotate;
return ((ElementRsRt) figure);
}
// ------------------------------------------------- NodesOnCircle
private void NodesOnCircle ()
{
if (bResize)
{
nNodesOnCircle = Convert .ToInt32 ((2 * Math .PI * rInner) / distanceNeighbours) + 1;
}
else
{
nNodesOnCircle = 0;
}
}
// -------------------------------------------------
public override void Draw (Graphics grfx)
{
GraphicsPath path = new GraphicsPath ();
path .AddPolygon (Apexes);
path .AddEllipse (center .X - rInner, center .Y - rInner, 2 * rInner, 2 * rInner);
grfx .FillPath (brush, path);
}
// ------------------------------------------------- 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); }
}
// ------------------------------------------------- Apexes
public PointF [] Apexes
{
get { return (Auxi_Geometry .RegularPolygon (center, rOuter, nApexes, angle)); }
}
// ------------------------------------------------- RectAround
public override RectangleF RectAround ()
{
return (Auxi_Geometry .RectAroundPoints (Apexes));
}
// ------------------------------------------------- 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);
}
// ------------------------------------------------- StartScaling
public void StartScaling (Point ptMouse, NodeShape nodeshape)
{
if (nodeshape == NodeShape .Strip)
{
scaling = rOuter / Auxi_Geometry .Distance (center, ptMouse);
}
}
// ------------------------------------------------- StartRotation
public override void StartRotation (Point ptMouse)
{
double angleMouse = Auxi_Geometry .Line_Angle (center, ptMouse);
compensation = Auxi_Common .LimitedRadian (angleMouse - angle);
}
// ------------------------------------------------- RedefineCover
public void RedefineCover ()
{
if (bResize)
{
NodesOnCircle ();
DefineCover ();
}
}
// ------------------------------------------------- DefineCover
public override void DefineCover ()
{
PointF [] pts = Apexes;
CoverNode [] nodes;
if (bResize)
{
// order of nodes:
// [nNodesOnCircle] small circular nodes on the hole's border Resizing
// [nApexes] strips on outer border Resizing
// 1 circular node, covering the hole
// 1 polygon, covering the whole polygon together with the hole Move
//
nodes = new CoverNode [nNodesOnCircle + nApexes + 2];
for (int i = 0; i < nNodesOnCircle; i++)
{
nodes [i] = new CoverNode (i, Auxi_Geometry .PointToPoint (center, 2 * Math .PI * i / nNodesOnCircle, rInner), nrSmall);
}
for (int i = 0, j = nNodesOnCircle; i < nApexes; i++, j++)
{
nodes [j] = new CoverNode (j, pts [i], pts [(i + 1) % nApexes]);
}
nodes [nNodesOnCircle + nApexes] = new CoverNode (nNodesOnCircle + nApexes, center, Convert .ToInt32 (rInner),
MovementFreedom .Transparent);
nodes [nNodesOnCircle + nApexes + 1] = new CoverNode (nNodesOnCircle + nApexes + 1, pts);
}
else
{
nodes = new CoverNode [2] { new CoverNode (0, center, Convert .ToInt32 (rInner), MovementFreedom .Transparent),
new CoverNode (1, pts)};
}
nodes [nodes .Length - 2] .Clearance = false;
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)
{
bool bRet = false;
if (catcher == MouseButtons .Left)
{
if (bResize)
{
double distanceMouse = Auxi_Geometry .Distance (center, ptM);
if (i < nNodesOnCircle)
{
// inner resizing
if (minRad <= distanceMouse && distanceMouse <= rOuter * Math .Cos (Math .PI / nApexes) - minW)
{
rInner = Convert .ToSingle (distanceMouse);
}
}
else if (cover .GetNodeShape (i) == NodeShape .Strip)
{
double radiusNew = distanceMouse * scaling;
if (radiusNew >= (rInner + minW) / Math .Cos (Math .PI / nApexes))
{
rOuter = Convert .ToSingle (radiusNew);
}
}
else
{
Move (dx, dy);
}
}
else
{
Move (dx, dy);
}
return (true);
}
else if (catcher == MouseButtons .Right && bRotate)
{
double angleMouse = Auxi_Geometry .Line_Angle (center, ptM);
angle = angleMouse - compensation;
bRet = true;
}
return (bRet);
}
// ------------------------------------------------- IntoMover
public override void IntoMover (Mover mover, int iPos)
{
mover .Insert (iPos, this);
}
}
}