using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
/// SymmetricDrw
///
/// Written by Doug Mair
/// Copyright (c) 2004 - All rights reserved.
///
namespace SymmetricDraw
{
public class MyPoint
{
public double m_centerX, m_centerY;
public double m_angle, m_rad;
private double m_x, m_y;
public MyPoint()
{
x = 0;
y = 0;
}
public MyPoint(double nx, double ny)
{
x = nx;
y = ny;
}
public MyPoint rotated(double theta)
{
double c, s;
double nx, ny;
nx = x - m_centerX;
ny = y - m_centerY;
c = Math.Cos(theta);
s = Math.Sin(theta);
MyPoint Q = new MyPoint(c*nx - s*ny, s*nx + c*ny);
Q.x = Q.x + m_centerX;
Q.y = Q.y + m_centerY;
return(Q);
}
public void CalcRad()
{
double dx, dy;
dx = x - m_centerX;
dy = y - m_centerY;
m_rad = Math.Sqrt(dx * dx + dy * dy);
if (m_rad != 0)
m_angle = -Math.Acos(dx / m_rad);
else
m_angle = 0;
if (m_y > m_centerY)
m_angle = -m_angle;
}
public void SetCenter(ref MyPoint p)
{
m_centerX = p.x;
m_centerY = p.y;
CalcRad();
}
public void SetPos(double nx, double ny)
{
x = nx;
y = ny;
CalcRad();
}
public void SetRel(double dx, double dy)
{
x += dx;
y += dy;
CalcRad();
}
public double x
{
get { return m_x; }
set { m_x = value; }
}
public double y
{
get { return m_y; }
set { m_y = value; }
}
public int IX
{
get { return Convert.ToInt32(m_x); }
}
public int IY
{
get { return Convert.ToInt32(m_y); }
}
public int XR(double deltaAngle)
{
return Convert.ToInt32(m_centerX + m_rad * Math.Cos(m_angle + deltaAngle));
}
public int YR(double deltaAngle)
{
return Convert.ToInt32(m_centerY + m_rad * Math.Sin(m_angle + deltaAngle));
}
public int XRm(double dm, double deltaAngle)
{
return Convert.ToInt32(m_centerX + m_rad * Math.Cos(dm-m_angle + deltaAngle));
}
public int YRm(double dm, double deltaAngle)
{
return Convert.ToInt32(m_centerY + m_rad * Math.Sin(dm-m_angle + deltaAngle));
}
public bool PntInBnd(int nx, int ny, int nWidth)
{
if ((Math.Abs(nx-x) <= nWidth) && (Math.Abs(ny-y) <= nWidth))
return true;
else
return false;
}
}
/// <summary>
/// Summary description for SymmetryTool.
/// </summary>
public class SymmetryTool
{
public MyPoint[] p;
public const int PCenter = 0;
public const int PAxis = 1;
public const int PMid = 2;
public const int PRot = 3;
public const int PData = 4;
public const int PNone = -1;
public const int nPnts = 12;
public const int nGuideWidth = 4;
public Image drawImage;
public bool bImage;
public bool TextShape;
private double rotAngle = 0;
private double rotRadius = 20;
public SymmetryTool()
{
p = new MyPoint[PData + nPnts];
for (int i=0; i<nPnts; i++)
p[i] = new MyPoint();
cColor = System.Drawing.Color.Black;
bImage = false;
}
public int ClickOn(int x, int y)
{
for (int i=0; i<nPnts; i++)
if (p[i].PntInBnd(x,y, nGuideWidth))
return i;
return PNone;
}
public void SetCenter(double nx, double ny)
{
p[PCenter].SetPos(nx, ny);
}
private Color cColor;
public Color ShapeColor
{
get { return cColor; }
set { cColor = value; }
}
private int nAxes;
public int Axes
{
get { return nAxes; }
set { nAxes = value; }
}
private int nMaxDataPnts;
public int MaxDataPnts
{
get { return nMaxDataPnts; }
set { nMaxDataPnts = value; }
}
private int nDataPnts;
public int DataPnts
{
get { return nDataPnts; }
set { nDataPnts = value; }
}
private bool bMirror;
public bool Mirror
{
get { return bMirror; }
set { bMirror = value; }
}
private bool bText;
public bool Text
{
get { return bText; }
set { bText = value; }
}
private bool bCurve;
public bool Curve
{
get { return bCurve; }
set
{
/*
int x1, y1, x2, y2;
x1 = p[PData+0].IX; y1 = p[PData+0].IY;
x2 = p[PData+1].IX; y2 = p[PData+1].IY;
if (value)
{
p[PData+2].SetPos((x1+x2)/2, (y1+y2)/2);
p[PData+3].SetPos((x1+x2)/2, (y1+y2)/2);
}
*/
bCurve = value;
}
}
private bool bFilled;
public bool Filled
{
get { return bFilled; }
set { bFilled = value; }
}
public void SetPos(int pt, int nx, int ny, bool bRel)
{
double dx, dy;
int i;
i = (int)pt;
dx = p[i].x - (double)nx;
dy = p[i].y - (double)ny;
if (i == PAxis)
{
double a1, a2;
MyPoint pNew = new MyPoint();
a1 = p[PAxis].m_angle;
p[PAxis].SetPos((double)nx, (double)ny);
a2 = p[PAxis].m_angle;
for (i=0; i<MaxDataPnts; i++)
{
pNew = p[PData+i].rotated(a2-a1);
p[PData+i].SetPos(pNew.x, pNew.y);
}
}
else if (i == PRot)
{
double oldAngle;
MyPoint pNew = new MyPoint();
oldAngle = rotAngle;
p[PRot].SetCenter(ref p[PMid]);
p[PRot].SetPos((double)nx, (double)ny);
rotAngle = p[PRot].m_angle;
rotRadius = p[PRot].m_rad;
for (i=0; i<MaxDataPnts; i++)
{
p[PData+i].SetCenter(ref p[PMid]);
pNew = p[PData+i].rotated(rotAngle-oldAngle);
p[PData+i].SetPos(pNew.x, pNew.y);
}
}
else if (i == PCenter)
{
for (i=0; i<nPnts; i++)
p[i].SetRel(-dx, -dy);
}
else
{
if ((bRel && (i>=PData)) || (i==PMid))
{
for (i=0; i<MaxDataPnts; i++)
p[PData+i].SetRel(-dx, -dy);
}
else
p[i].SetPos((double)nx, (double)ny);
}
}
public void DrawGuides(Graphics drawingSurface)
{
int i;
double xt, yt;
double deltaAngle, angleSection;
Pen pen1 = new Pen(Color.Red);
Pen pen2 = new Pen(Color.Gray);
xt = 0;
yt = 0;
for (i=0; i<MaxDataPnts; i++)
{
drawingSurface.DrawEllipse(pen1, p[PData+i].IX-nGuideWidth, p[PData+i].IY-nGuideWidth, nGuideWidth*2, nGuideWidth*2);
xt += p[PData+i].x;
yt += p[PData+i].y;
}
p[PMid].x = xt / MaxDataPnts;
p[PMid].y = yt / MaxDataPnts;
p[PRot].x = p[PMid].x + rotRadius * Math.Cos(rotAngle);
p[PRot].y = p[PMid].y + rotRadius * Math.Sin(rotAngle);
drawingSurface.DrawRectangle(pen1, p[PMid].IX-nGuideWidth, p[PMid].IY-nGuideWidth, nGuideWidth*2, nGuideWidth*2);
drawingSurface.DrawEllipse(pen1, p[PRot].IX-nGuideWidth, p[PRot].IY-nGuideWidth, nGuideWidth*2, nGuideWidth*2);
drawingSurface.DrawLine(pen2, p[PMid].IX, p[PMid].IY, p[PRot].IX, p[PRot].IY);
for (i=1; i<MaxDataPnts; i++)
drawingSurface.DrawLine(pen2, p[PData+i].IX, p[PData+i].IY, p[PData+i-1].IX, p[PData+i-1].IY);
drawingSurface.DrawRectangle(pen2, p[PCenter].IX-nGuideWidth, p[PCenter].IY-nGuideWidth, nGuideWidth*2, nGuideWidth*2);
drawingSurface.DrawEllipse(pen2, p[PAxis].IX-nGuideWidth, p[PAxis].IY-nGuideWidth, nGuideWidth*2, nGuideWidth*2);
p[PAxis].SetCenter(ref p[PCenter]);
deltaAngle = Math.PI * 2 / (double)nAxes;
for (i=0; i<nAxes; i++)
{
angleSection = deltaAngle * i;
drawingSurface.DrawLine(pen2, p[PAxis].XR(angleSection), p[PAxis].YR(angleSection), p[PCenter].IX, p[PCenter].IY);
}
}
public double CalcRad(double w, double h)
{
return Math.Sqrt(w*w + h*h);
}
public float CalcAng(ref Point p1, ref Point p2, ref double nRad)
{
double dx, dy, nNewAngle;
dx = p2.X - p1.X;
dy = p2.Y - p1.Y;
nRad = CalcRad(dx, dy);
if (nRad != 0)
nNewAngle = -Math.Acos(dx / nRad);
else
nNewAngle = 0;
if (p1.Y > p2.Y)
nNewAngle = -nNewAngle;
return (float)((-nNewAngle - Math.PI/4) * 180 / Math.PI);
}
public void DrawSymShapes(Graphics drawingSurface)
{
int i, j;
double angleAxis, deltaAngle, angleSection;
#if (WINCE)
Pen pen = new Pen(ShapeColor);
#else
Pen pen = new Pen(ShapeColor, 2);
#endif
for (i=0; i<MaxDataPnts; i++)
p[PData+i].SetCenter(ref p[PCenter]);
deltaAngle = Math.PI * 2 / (double)nAxes;
Rectangle destRect = new Rectangle(0, 0, 1, 1);
double nImageRad = 0;
if (bImage || bText)
{
nImageRad = CalcRad(drawImage.Width, drawImage.Height);
destRect = new Rectangle(0, 0, drawImage.Width, drawImage.Height);
}
angleAxis = 2 * p[PAxis].m_angle;
for (i=0; i<nAxes; i++)
{
double nLineRad = 0;
SolidBrush brush = new SolidBrush(ShapeColor);
angleSection = deltaAngle * i;
Point[] cPnts = new Point[MaxDataPnts];
for (j=0; j<MaxDataPnts; j++)
cPnts[j] = new Point(p[PData+j].XR(angleSection), p[PData+j].YR(angleSection));
if (bImage || bText)
{
ImageAttributes imageAttr = new ImageAttributes();
float angleLine = CalcAng(ref cPnts[0], ref cPnts[1], ref nLineRad);
destRect.Width = Convert.ToInt32(drawImage.Width * nLineRad / nImageRad);
destRect.Height = Convert.ToInt32(drawImage.Height * nLineRad / nImageRad);
Color lowerColor = Color.FromArgb(255, 0, 255);
Color upperColor = Color.FromArgb(255, 0, 255);
imageAttr.SetColorKey(lowerColor, upperColor); //, ColorAdjustType.Default);
#if (WINCE)
destRect.Height *= 2;
destRect.Width *= 2;
destRect.X = Convert.ToInt32(cPnts[0].X-destRect.Width/2);
destRect.Y = Convert.ToInt32(cPnts[0].Y-destRect.Height/2);
drawingSurface.DrawImage(drawImage, destRect, 0, 0, drawImage.Width, drawImage.Height, GraphicsUnit.Pixel, imageAttr);
#else
drawingSurface.TranslateTransform(cPnts[0].X, cPnts[0].Y);
drawingSurface.RotateTransform(angleLine);
drawingSurface.DrawImage(drawImage, destRect, 0, 0, drawImage.Width, drawImage.Height, GraphicsUnit.Pixel,imageAttr);
drawingSurface.ResetTransform();
#endif
}
else if ((MaxDataPnts > 2) && (bCurve || bFilled))
{
#if (WINCE)
Point[] ps = new Point[0];
curve.addCurve(ref ps, cPnts[0], cPnts[1], cPnts[2], cPnts[3]);
if ((MaxDataPnts > 4) && (DataPnts > 4))
curve.addCurve(ref ps, cPnts[3], cPnts[4], cPnts[5], cPnts[6]);
curve.draw(ref drawingSurface, ref pen, ref brush, ref ps, bFilled);
#else
GraphicsPath gp = new GraphicsPath();
gp.AddBezier(cPnts[0], cPnts[1], cPnts[2], cPnts[3]);
if (MaxDataPnts > 4)
gp.AddBezier(cPnts[3], cPnts[4], cPnts[5], cPnts[6]);
if (bFilled)
drawingSurface.FillPath(brush, gp);
else
drawingSurface.DrawPath(pen, gp);
#endif
if (bMirror)
{
for (j=0; j<MaxDataPnts; j++)
cPnts[j] = new Point(p[PData+j].XRm(angleAxis, angleSection), p[PData+j].YRm(angleAxis, angleSection));
#if (WINCE)
ps = new Point[0];
curve.addCurve(ref ps, cPnts[0], cPnts[1], cPnts[2], cPnts[3]);
if ((MaxDataPnts > 4) && (DataPnts > 4))
curve.addCurve(ref ps, cPnts[3], cPnts[4], cPnts[5], cPnts[6]);
curve.draw(ref drawingSurface, ref pen, ref brush, ref ps, bFilled);
#else
gp = new GraphicsPath();
gp.AddBezier(cPnts[0], cPnts[1], cPnts[2], cPnts[3]);
if (MaxDataPnts > 4)
gp.AddBezier(cPnts[3], cPnts[4], cPnts[5], cPnts[6]);
if (bFilled)
drawingSurface.FillPath(brush, gp);
else
drawingSurface.DrawPath(pen, gp);
#endif
}
}
else
{
drawingSurface.DrawLine(pen,
p[PData+0].XR(angleSection), p[PData+0].YR(angleSection),
p[PData+1].XR(angleSection), p[PData+1].YR(angleSection));
if (bMirror)
{
drawingSurface.DrawLine(pen,
p[PData+0].XRm(angleAxis, angleSection), p[PData+0].YRm(angleAxis, angleSection),
p[PData+1].XRm(angleAxis, angleSection), p[PData+1].YRm(angleAxis, angleSection));
}
}
}
}
}
}