using System;
using System .Collections .Generic;
using System .ComponentModel;
using System .Drawing;
using System .Drawing .Drawing2D;
using System .Windows .Forms;
using Microsoft .Win32;
using MoveGraphLibrary;
namespace GraphicalPrimitives
{
public class Circle : GraphicalObject
{
int m_version = 620;
Form form;
Mover supervisor;
PointF m_center;
float m_radius;
double m_angle;
int nNodesOnBorder;
double [] vals;
double [] sweep;
List<Color> clrs = new List<Color> (); // one color per each sector
Rotation dirDrawing;
double compensation;
PointF ptNearestToCenter, ptFarAway;
int minRadius = 10; // min size is set to avoid disappearance while resizing
int nrSmall = 5;
int distanceNeighbours = 8;
Pen penInnerBorder;
// -------------------------------------------------
public Circle (Form frm, Mover mvr, PointF ptC, float rad, double angleDegree, double [] fVals)
{
form = frm;
supervisor = mvr;
m_center = ptC;
m_radius = Math .Max (rad, minRadius);
m_angle = Auxi_Convert .DegreeToRadian (angleDegree);
dirDrawing = Rotation .Clockwise;
penInnerBorder = new Pen (Color .DarkGray);
CheckedValues (fVals);
DefaultColors ();
NodesOnBorder ();
}
// -------------------------------------------------
public Circle (Form frm, Mover mvr, PointF ptC, float rad, Color clr)
: this (frm, mvr, ptC, rad, 0, new double [] { 5 })
{
clrs [0] = clr;
}
// -------------------------------------------------
public Circle (Form frm, Mover mvr, PointF ptC, float rad, double [] fVals, Color clr_0, Color clr_1)
: this (frm, mvr, ptC, rad, 0, fVals)
{
SetColors (Auxi_Colours .SmoothColorsList (fVals .Length, clr_0, clr_1));
}
// ------------------------------------------------- NodesOnBorder
private void NodesOnBorder ()
{
nNodesOnBorder = Convert .ToInt32 ((2 * Math .PI * m_radius) / distanceNeighbours);
}
// ------------------------------------------------- CheckedValues
private void CheckedValues (double [] fVals)
{
bool bCorrect = true;
if (fVals == null || fVals .Length < 1 || Auxi_Common .SumArray (fVals, true) == 0.0)
{
bCorrect = false;
}
else
{
foreach (double val in fVals)
{
if (val <= 0.0)
{
bCorrect = false;
break;
}
}
}
if (!bCorrect)
{
vals = new double [] { 1, 2, 3, 4 };
}
else
{
vals = new double [fVals .Length];
for (int i = 0; i < vals .Length; i++)
{
vals [i] = fVals [i];
}
}
sweep = new double [vals .Length];
SweepAngles ();
}
// ------------------------------------------------- DefaultColors
public void DefaultColors ()
{
clrs .Clear ();
for (int i = 0; i < vals .Length; i++)
{
clrs .Add (Auxi_Colours .ColorPredefined (i + 1));
}
}
// ------------------------------------------------- SweepAngles
private void SweepAngles ()
{
double fSum = Auxi_Common .SumArray (vals, false);
for (int i = 0; i < vals .Length; i++)
{
sweep [i] = 2 * Math .PI * vals [i] / fSum;
}
if (dirDrawing == Rotation .Clockwise)
{
for (int i = 0; i < vals .Length; i++)
{
sweep [i] *= -1;
}
}
}
// ------------------------------------------------- Center
public PointF Center
{
get { return (m_center); }
set
{
m_center = value;
DefineCover ();
}
}
// ------------------------------------------------- Radius
public float Radius
{
get { return (m_radius); }
set
{
m_radius = Math .Max (minRadius, value);
DefineCover ();
}
}
// ------------------------------------------------- RectAround
new public RectangleF RectAround
{
get { return (new RectangleF (m_center .X - m_radius, m_center .Y - m_radius, 2 * m_radius, 2 * m_radius)); }
}
// ------------------------------------------------- Values
public double [] Values
{
get { return (vals); }
}
// ------------------------------------------------- Angle
public double Angle
{
get { return (m_angle); }
set { m_angle = Auxi_Common .LimitedRadian (value); }
}
// ------------------------------------------------- Color
public Color Color
{
get { return (clrs [0]); }
set { clrs [0] = value; }
}
// ------------------------------------------------- Colors
public List<Color> Colors
{
get { return (clrs); }
}
// ------------------------------------------------- SetColors
public void SetColors (List<Color> colors)
{
if (colors != null)
{
for (int i = 0; i < Math .Min (clrs .Count, colors .Count); i++)
{
clrs [i] = colors [i];
}
}
}
// ------------------------------------------------- SetColors
public void SetColors (Color [] clrsNew)
{
if (clrs .Count == clrsNew .Length)
{
for (int i = 0; i < clrs .Count; i++)
{
clrs [i] = clrsNew [i];
}
}
}
// ------------------------------------------------- DrawingDirection
public Rotation DrawingDirection
{
get { return (dirDrawing); }
set
{
dirDrawing = value;
SweepAngles ();
}
}
// ------------------------------------------------- ChangeDrawingDirection
public void ChangeDrawingDirection ()
{
dirDrawing = (dirDrawing == Rotation .Clockwise) ? Rotation .Counterclock : Rotation .Clockwise;
SweepAngles ();
}
// ------------------------------------------------- Draw
public void Draw (Graphics grfx)
{
Rectangle rc = Rectangle .Round (RectAround);
float fStartDegree, fSweepDegree;
fStartDegree = -(float) Auxi_Convert .RadianToDegree (m_angle);
for (int i = 0; i < vals .Length; i++)
{
fSweepDegree = -(float) Auxi_Convert .RadianToDegree (sweep [i]);
grfx .FillPie (new SolidBrush (clrs [i]), rc, fStartDegree, fSweepDegree);
fStartDegree += fSweepDegree;
}
grfx .DrawLine (penInnerBorder, m_center, Auxi_Geometry .PointToPoint (m_center, m_angle, m_radius));
}
// ------------------------------------------------- StartResizing
public void StartResizing (Point ptMouse, int iNode)
{
double angleBeam = Auxi_Geometry .Line_Angle (m_center, ptMouse);
PointF ptOnBorder = Auxi_Geometry .PointToPoint (m_center, angleBeam, m_radius);
Cursor .Position = form .PointToScreen (Point .Round (ptOnBorder));
ptNearestToCenter = Auxi_Geometry .PointToPoint (m_center, angleBeam, minRadius);
ptFarAway = Auxi_Geometry .PointToPoint (m_center, angleBeam, 4000);
}
// ------------------------------------------------- StopResizing
public void StopResizing ()
{
NodesOnBorder ();
DefineCover ();
}
// ------------------------------------------------- StartRotation
public void StartRotation (Point ptMouse)
{
double angleMouse = Auxi_Geometry .Line_Angle (m_center, ptMouse);
compensation = Auxi_Common .LimitedRadian (angleMouse - m_angle);
}
// ------------------------------------------------- DefineCover
public override void DefineCover ()
{
CoverNode [] nodes = new CoverNode [nNodesOnBorder + 1];
for (int i = 0; i < nNodesOnBorder; i++)
{
nodes [i] = new CoverNode (i, Auxi_Geometry .PointToPoint (m_center, 2 * Math .PI * i / nNodesOnBorder, m_radius), nrSmall);
}
nodes [nNodesOnBorder] = new CoverNode (nNodesOnBorder, m_center, m_radius, Cursors .SizeAll);
cover = new Cover (nodes);
cover .SetClearance (false);
}
// -------------------------------------------------
public override void Move (int dx, int dy)
{
m_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 (i == nNodesOnBorder)
{
Move (dx, dy);
}
else
{
PointF ptBase, ptNearest;
PointOfSegment typeOfNearest;
Auxi_Geometry .Distance_PointSegment (ptM, ptNearestToCenter, ptFarAway, out ptBase, out typeOfNearest, out ptNearest);
Cursor .Position = form .PointToScreen (Point .Round (ptNearest));
m_radius = Convert .ToSingle (Auxi_Geometry .Distance (m_center, ptNearest));
bRet = true;
}
}
else if (catcher == MouseButtons .Right)
{
double angleMouse = Auxi_Geometry .Line_Angle (m_center, ptM);
m_angle = angleMouse - compensation;
bRet = true;
}
return (bRet);
}
const string nameMain = "Circle_";
// ------------------------------------------------- IntoRegistry
public void IntoRegistry (RegistryKey regkey, string strAdd)
{
try
{
string [] strs = new string [5 + vals .Length + 4 * vals .Length + 1];
strs [0] = m_version .ToString ();
strs [1] = m_center .X .ToString (); // ptC
strs [2] = m_center .Y .ToString ();
strs [3] = m_radius .ToString (); // radius
strs [4] = Auxi_Convert .RadianToDegree (Angle) .ToString (); // angleDegree
for (int i = 0; i < vals .Length; i++) // vals
{
strs [5 + i] = vals [i] .ToString ();
}
int k = 5 + vals .Length;
for (int i = 0; i < vals .Length; i++) // clrs
{
strs [k + i * 4] = ((int) (clrs [i] .A)) .ToString ();
strs [k + i * 4 + 1] = ((int) (clrs [i] .R)) .ToString ();
strs [k + i * 4 + 2] = ((int) (clrs [i] .G)) .ToString ();
strs [k + i * 4 + 3] = ((int) (clrs [i] .B)) .ToString ();
}
k += 4 * vals .Length;
strs [k] = ((int) dirDrawing) .ToString ();
regkey .SetValue (nameMain + strAdd, strs, RegistryValueKind .MultiString);
}
catch
{
}
finally
{
}
}
// ------------------------------------------------- FromRegistry
public static Circle FromRegistry (Form frm, Mover mvr, RegistryKey regkey, string strAdd)
{
try
{
string [] strs = (string []) regkey .GetValue (nameMain + strAdd);
if (frm == null || mvr == null ||
strs == null || strs .Length < 11 || Convert .ToInt32 (strs [0]) != 620)
{
return (null);
}
int nVals = (strs .Length - 6) / 5;
double [] fVals = new double [nVals];
List<Color> colors = new List<Color> ();
int j_vals = 5;
int j_clrs = j_vals + nVals;
int j_dir = j_clrs + 4 * nVals;
for (int i = 0; i < nVals; i++)
{
fVals [i] = Convert .ToDouble (strs [j_vals + i]);
colors .Add (Auxi_Convert .ToColor (strs, j_clrs + i * 4));
}
Circle circle = new Circle (frm, mvr,
Auxi_Convert .ToPointF (strs, 1), // ptC
Convert .ToSingle (strs [3]), // radius
Convert .ToDouble (strs [4]), // angle
fVals);
if (circle != null)
{
circle .SetColors (colors);
circle .DrawingDirection = (Rotation) Convert .ToInt32 (strs [j_dir]);
}
return (circle);
}
catch
{
return (null);
}
finally
{
}
}
}
}