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 Polygon_Chatoyant : GraphicalObject
{
int m_version = 620;
Form form;
Mover supervisor;
PointF m_center;
PointF [] ptVertices;
Color clrCenter;
Color [] clrVertices;
bool bAuxiLines;
double angle;
bool bRotate;
double distInitial, angleBeam;
PointF ptNearestToCenter, ptFarAway;
// 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 Polygon_Chatoyant (Form frm, Mover mvr, PointF ptC, PointF [] ptA, Color clrC, Color [] clrA)
{
form = frm;
supervisor = mvr;
m_center = ptC;
clrCenter = clrC;
if (ptA != null && clrA != null && ptA .Length >= 3 && ptA .Length == clrA .Length)
{
ptVertices = new PointF [ptA .Length];
for (int i = 0; i < ptVertices .Length; i++)
{
ptVertices [i] = new PointF (ptA [i] .X, ptA [i] .Y);
}
clrVertices = clrA;
}
else
{
ptVertices = 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) };
clrVertices = new Color [4] { Color .Red, Color .Green, Color .Blue, Color .Yellow };
}
bAuxiLines = false;
radii = new double [ptVertices .Length];
scaling = new double [ptVertices .Length];
compensation = new double [ptVertices .Length];
angles = new double [ptVertices .Length];
angle = Auxi_Geometry .Line_Angle (m_center, ptVertices [0]);
bRotate = true;
}
// ------------------------------------------------- VerticesNum
public int VerticesNum
{
get { return (ptVertices .Length); }
}
// ------------------------------------------------- Center
public PointF Center
{
get { return (m_center); }
}
// ------------------------------------------------- Vertices
public PointF [] Vertices
{
get { return (ptVertices); }
}
// ------------------------------------------------- Colors
public Color [] Colors
{
get { return (clrVertices); }
set
{
for (int i = 0; i < clrVertices .Length; i++)
{
clrVertices [i] = value [i];
}
}
}
// ------------------------------------------------- RectAround
new public RectangleF RectAround
{
get
{
RectangleF rc = Auxi_Geometry .RectAroundPoints (Vertices);
float cxL = Math .Min (m_center .X, rc .Left);
float cxR = Math .Max (m_center .X, rc .Right);
float cyT = Math .Min (m_center .Y, rc .Top);
float cyB = Math .Max (m_center .Y, rc .Bottom);
return (RectangleF .FromLTRB (cxL, cyT, cxR, cyB));
}
}
// ------------------------------------------------- Rotatable
public bool Rotatable
{
get { return (bRotate); }
set { bRotate = value; }
}
// ------------------------------------------------- Angle
public double Angle
{
get { return (angle); }
set
{
VerticesArrays ();
double angleDif = value - angles [0];
for (int i = 0; i < ptVertices .Length; i++)
{
angles [i] = Auxi_Common .LimitedRadian (angles [i] + angleDif);
ptVertices [i] = Auxi_Geometry .PointToPoint (m_center, angles [i], radii [i]);
}
DefineCover ();
}
}
// ------------------------------------------------- VerticesArrays
private void VerticesArrays ()
{
for (int i = 0; i < VerticesNum; i++)
{
radii [i] = Auxi_Geometry .Distance (m_center, ptVertices [i]);
angles [i] = Auxi_Geometry .Line_Angle (m_center, ptVertices [i]);
}
}
// ------------------------------------------------- GetVertexColor
public Color GetVertexColor (int iVertex)
{
return (clrVertices [iVertex % VerticesNum]);
}
// ------------------------------------------------- SetVertexColor
public void SetVertexColor (int iVertex, Color clr)
{
clrVertices [iVertex % VerticesNum] = clr;
}
// ------------------------------------------------- ColorCenter
public Color CenterColor
{
get { return (clrCenter); }
set { clrCenter = value; }
}
// ------------------------------------------------- AuxiLines
public bool AuxiLines
{
get { return (bAuxiLines); }
set { bAuxiLines = value; }
}
// ------------------------------------------------- Draw
public void Draw (Graphics grfx)
{
Auxi_Drawing .FillChatoyantPolygon (grfx, m_center, ptVertices, clrCenter, clrVertices);
if (bAuxiLines)
{
foreach (PointF pt in ptVertices)
{
grfx .DrawLine (Pens .DarkGray, m_center, pt);
}
}
}
// ------------------------------------------------- StartReconfiguration
public void StartReconfiguration (int iNode)
{
if (iNode == ptVertices .Length)
{
Cursor .Position = form .PointToScreen (Point .Round (m_center));
}
else
{
Cursor .Position = form .PointToScreen (Point .Round (ptVertices [iNode]));
}
}
// ------------------------------------------------- StartResizing
public void StartResizing (Point ptMouse, int iNode)
{
VerticesArrays ();
PointF ptOnBorder;
Auxi_Geometry .Line_Crossing (m_center, ptMouse, ptVertices [(iNode - (VerticesNum + 1)) % VerticesNum],
ptVertices [(iNode - VerticesNum) % VerticesNum], out ptOnBorder);
Cursor .Position = form .PointToScreen (Point .Round (ptOnBorder));
distInitial = Auxi_Geometry .Distance (m_center, ptOnBorder);
angleBeam = Auxi_Geometry .Line_Angle (m_center, ptOnBorder);
ptNearestToCenter = Auxi_Geometry .PointToPoint (m_center, angleBeam, Math .Min (10, distInitial));
ptFarAway = Auxi_Geometry .PointToPoint (m_center, angleBeam, 4000);
}
// ------------------------------------------------- StartRotation
public void StartRotation (Point ptMouse)
{
VerticesArrays ();
double angleMouse = Auxi_Geometry .Line_Angle (m_center, ptMouse);
for (int i = 0; i < VerticesNum; i++)
{
compensation [i] = Auxi_Common .LimitedRadian (angleMouse - angles [i]);
}
}
// ------------------------------------------------- DefineCover
// order of nodes:
// [VerticesNum] - circular nodes in vertices
// 1 - circular node in ptCenter
// [VerticesNum] - strip nodes, covering each segment of the perimeter
// [VerticesNum] - big triangular nodes
//
public override void DefineCover ()
{
CoverNode [] nodes = new CoverNode [3 * VerticesNum + 1];
for (int i = 0; i < VerticesNum; i++)
{
nodes [i] = new CoverNode (i, ptVertices [i], 6);
}
nodes [VerticesNum] = new CoverNode (VerticesNum, m_center, 6);
int k0 = VerticesNum + 1;
for (int i = 0; i < VerticesNum; i++)
{
nodes [k0 + i] = new CoverNode (k0 + i, ptVertices [i], ptVertices [(i + 1) % VerticesNum]);
}
k0 = 2 * VerticesNum + 1;
for (int i = 0; i < VerticesNum; i++)
{
PointF [] pts = new PointF [3] { ptVertices [i], ptVertices [(i + 1) % VerticesNum], m_center };
nodes [k0 + i] = new CoverNode (k0 + i, pts);
}
cover = new Cover (nodes);
}
// ------------------------------------------------- Move
public override void Move (int dx, int dy)
{
Size size = new Size (dx, dy);
for (int i = 0; i < VerticesNum; i++)
{
ptVertices [i] += size;
}
m_center += size;
}
// ------------------------------------------------- MoveNode
public override bool MoveNode (int i, int dx, int dy, Point ptM, MouseButtons catcher)
{
if (catcher == MouseButtons .Left)
{
if (i < VerticesNum)
{
ptVertices [i] = ptM;
}
else if (i == VerticesNum)
{
m_center = ptM;
}
else if (i >= 2 * VerticesNum + 1)
{
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));
double coef = Auxi_Geometry .Distance (m_center, ptNearest) / distInitial;
for (int j = 0; j < VerticesNum; j++)
{
ptVertices [j] = Auxi_Geometry .PointToPoint (m_center, angles [j], radii [j] * coef);
}
}
return (true);
}
else if (catcher == MouseButtons .Right && bRotate)
{
double angleMouse = -Math .Atan2 (ptM .Y - m_center .Y, ptM .X - m_center .X);
for (int j = 0; j < VerticesNum; j++)
{
ptVertices [j] = Auxi_Geometry .PointToPoint (m_center, Auxi_Common .LimitedRadian (angleMouse - compensation [j]), radii [j]);
}
DefineCover ();
return (true);
}
return (false);
}
const string nameMain = "ChatoyantPolygon_";
// ------------------------------------------------- IntoRegistry
public void IntoRegistry (RegistryKey regkey, string strAdd)
{
try
{
int nPts = Vertices .Length;
string [] strs = new string [3 + 2 * nPts + 4 + 4 * nPts + 1];
strs [0] = m_version .ToString ();
strs [1] = m_center .X .ToString ();
strs [2] = m_center .Y .ToString ();
int jPts = 3;
for (int i = 0; i < nPts; i++)
{
strs [jPts + i * 2] = Vertices [i] .X .ToString ();
strs [jPts + i * 2 + 1] = Vertices [i] .Y .ToString ();
}
int k = jPts + 2 * nPts;
strs [k] = ((int) (clrCenter .A)) .ToString ();
strs [k + 1] = ((int) (clrCenter .R)) .ToString ();
strs [k + 2] = ((int) (clrCenter .G)) .ToString ();
strs [k + 3] = ((int) (clrCenter .B)) .ToString ();
k += 4;
Color clr;
for (int i = 0; i < nPts; i++)
{
clr = clrVertices [i];
strs [k + i * 4] = ((int) (clr .A)) .ToString ();
strs [k + i * 4 + 1] = ((int) (clr .R)) .ToString ();
strs [k + i * 4 + 2] = ((int) (clr .G)) .ToString ();
strs [k + i * 4 + 3] = ((int) (clr .B)) .ToString ();
}
k += 4 * nPts;
strs [k] = bAuxiLines .ToString ();
regkey .SetValue (nameMain + strAdd, strs, RegistryValueKind .MultiString);
}
catch
{
}
finally
{
}
}
// ------------------------------------------------- FromRegistry
public static Polygon_Chatoyant FromRegistry (Form frm, Mover mvr, RegistryKey regkey, string strAdd)
{
try
{
string [] strs = (string []) regkey .GetValue (nameMain + strAdd);
if (strs == null || strs .Length < 26 || Convert .ToInt32 (strs [0]) != 620)
{
return (null);
}
int nVertices = (strs .Length - 8) / 6;
PointF [] ptsA = new PointF [nVertices];
Color [] clrsA = new Color [nVertices];
int jPts = 3;
int jClrCenter = jPts + 2 * nVertices;
int jClrs = jClrCenter + 4;
int jAuxi = jClrs + 4 * nVertices;
for (int i = 0; i < nVertices; i++)
{
ptsA [i] = Auxi_Convert .ToPointF (strs, jPts + i * 2);
clrsA [i] = Auxi_Convert .ToColor (strs, jClrs + i * 4);
}
Polygon_Chatoyant poly = new Polygon_Chatoyant (frm, mvr,
Auxi_Convert .ToPointF (strs, 1), ptsA,
Auxi_Convert .ToColor (strs, jClrCenter), clrsA);
if (poly != null)
{
poly .AuxiLines = Convert .ToBoolean (strs [jAuxi]);
}
return (poly);
}
catch
{
return (null);
}
finally
{
}
}
}
}