Click here to Skip to main content
15,896,201 members
Articles / Programming Languages / C#

What can be simpler than graphical primitives? Part 3

Rate me:
Please Sign up or sign in to vote.
5.00/5 (8 votes)
8 Apr 2013CPOL43 min read 23.9K   560   32  
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 Ring_SimpleCover : GraphicalObject
    {
        int m_version = 620;
        Form form;
        Mover supervisor;
        PointF m_center;
        float rOuter;
        float rInner;
        double m_angle;

        double [] vals;
        List<Color> clrs = new List<Color> ();          // one color per each sector
        Rotation dirDrawing;
        double [] sweep;

        double compensation;
        PointF ptInnerLimit, ptOuterLimit;

        Color clrBorder;

        static int minInner = 10;
        static int minWidth = 15;
        int delta = 4;  // 3;

        // -------------------------------------------------
        public Ring_SimpleCover (Form frm, Mover mvr, PointF ptC, float rOut, float rIn, double angleDegree, double [] fVals)
        {
            form = frm;
            supervisor = mvr;
            m_center = ptC;
            rInner = Math .Max (rIn, minInner);
            rOuter = Math .Max (rOut, rInner + minWidth);
            vals = CheckedValues (fVals);
            DefaultColors ();

            clrBorder = Color .DarkGray;

            dirDrawing = Rotation .Clockwise;
            m_angle = Auxi_Convert .DegreeToRadian (angleDegree);
            sweep = new double [vals .Length];
            SweepAngles ();
        }
        // -------------------------------------------------
        public Ring_SimpleCover (Form frm, Mover mvr, PointF ptC, float rOut, float rIn, Color clr)
            : this (frm, mvr, ptC, rOut, rIn, 0, new double [] { 5 })
        {
            clrs [0] = clr;
        }
        // -------------------------------------------------
        public Ring_SimpleCover (Form frm, Mover mvr, PointF ptC, float rOut, float rIn, double [] fVals, Color clr_0, Color clr_1)
            : this (frm, mvr, ptC, rOut, rIn, 0, fVals)
        {
            SetColors (Auxi_Colours .SmoothColorsList (fVals .Length, clr_0, clr_1));
        }
        // -------------------------------------------------        CheckedValues
        private double [] CheckedValues (double [] fVals)
        {
            if (fVals == null || fVals .Length < 1 || Auxi_Common .SumArray (fVals, true) == 0.0)
            {
                return (new double [] { 1, 2, 3, 4 });
            }
            else
            {
                double [] vs = new double [fVals .Length];
                for (int i = 0; i < vs .Length; i++)
                {
                    vs [i] = Math .Abs (fVals [i]);
                }
                return (vs);
            }
        }
        // -------------------------------------------------        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;
                }
            }
        }
        // -------------------------------------------------        Copy
        public Ring_SimpleCover Copy (PointF pt)
        {
            double [] valsNew = new double [vals .Length];
            for (int i = 0; i < vals .Length; i++)
            {
                valsNew [i] = vals [i];
            }
            Ring_SimpleCover elem = new Ring_SimpleCover (form, supervisor, pt, rOuter, rInner, Auxi_Convert .RadianToDegree (m_angle), valsNew);
            for (int i = 0; i < vals .Length; i++)
            {
                elem .SetColor (i, clrs [i]);
            }
            elem .DrawingDirection = DrawingDirection;
            return (elem);
        }
        // -------------------------------------------------        Center
        public PointF Center
        {
            get { return (m_center); }
            set
            {
                m_center = value;
                DefineCover ();
            }
        }
        // -------------------------------------------------        InnerRadius
        public float InnerRadius
        {
            get { return (rInner); }
            set
            {
                if (minInner <= value && value + minWidth <= rOuter)
                {
                    rInner = value;
                    DefineCover ();
                }
            }
        }
        // -------------------------------------------------        OuterRadius
        public float OuterRadius
        {
            get { return (rOuter); }
            set
            {
                if (rInner + minWidth <= value)
                {
                    rOuter = value;
                    DefineCover ();
                }
            }
        }
        // -------------------------------------------------        MinimumInnerRadius
        static public int MinimumInnerRadius
        {
            get { return (minInner); }
        }
        // -------------------------------------------------        MinimumWidth
        static public int MinimumWidth
        {
            get { return (minWidth); }
        }
        // -------------------------------------------------        RectAround
        new public RectangleF RectAround
        {
            get { return (new RectangleF (m_center .X - rOuter, m_center .Y - rOuter, 2 * rOuter, 2 * rOuter)); }
        }
        // -------------------------------------------------        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)
        {
            for (int i = 0; i < clrs .Count; i++)
            {
                clrs [i] = colors [i % clrs .Count];
            }
        }
        // -------------------------------------------------        SetColors
        public void SetColors (Color [] clrsNew)
        {
            if (clrs .Count == clrsNew .Length)
            {
                for (int i = 0; i < clrs .Count; i++)
                {
                    clrs [i] = clrsNew [i];
                }
            }
        }
        // -------------------------------------------------        SetColor
        public void SetColor (int i, Color clr)
        {
            if (0 <= i && i < clrs .Count)
            {
                clrs [i] = clr;
            }
        }
        // -------------------------------------------------        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)
        {
            DrawSectors (grfx);
        }
        // -------------------------------------------------        DrawSectors
        public void DrawSectors (Graphics grfx)
        {
            Rectangle rcIn = new Rectangle (Convert .ToInt32 (m_center .X - rInner), Convert .ToInt32 (m_center .Y - rInner),
                                            Convert .ToInt32 (2 * rInner), Convert .ToInt32 (2 * rInner));
            Rectangle rcOut = new Rectangle (Convert .ToInt32 (m_center .X - rOuter), Convert .ToInt32 (m_center .Y - rOuter),
                                             Convert .ToInt32 (2 * rOuter), Convert .ToInt32 (2 * rOuter));
            Pen penBorder = new Pen (clrBorder);
            Point pt0, pt1;
            SolidBrush brush;
            GraphicsPath path = new GraphicsPath ();
            // for Drawing fStart[] and fSweep[] are used in Microsoft way, which means changing of sign
            float fStartDegree, fSweepDegree;
            fStartDegree = -(float) Auxi_Convert .RadianToDegree (m_angle);
            for (int i = 0; i < vals .Length; i++)
            {
                brush = new SolidBrush (clrs [i]);
                fSweepDegree = -(float) Auxi_Convert .RadianToDegree (sweep [i]);

                path .AddArc (rcIn, fStartDegree, fSweepDegree);
                path .AddArc (rcOut, fStartDegree + fSweepDegree, -fSweepDegree);
                grfx .FillPath (brush, path);
                path .Reset ();

                grfx .DrawArc (penBorder, rcIn, fStartDegree, fSweepDegree);
                grfx .DrawArc (penBorder, rcOut, fStartDegree, fSweepDegree);
                pt0 = Auxi_Geometry .EllipsePoint (rcIn, -fStartDegree, 1);
                pt1 = Auxi_Geometry .EllipsePoint (rcOut, -fStartDegree, 1);
                grfx .DrawLine (penBorder, pt0, pt1);

                fStartDegree += fSweepDegree;
            }
        }
        // -------------------------------------------------        StartResizing
        public void StartResizing (Point ptMouse, int iNode)
        {
            double angleBeam = Auxi_Geometry .Line_Angle (Center, ptMouse);
            float rad;
            if (iNode == 1)
            {
                rad = InnerRadius;
                ptInnerLimit = Auxi_Geometry .PointToPoint (Center, angleBeam, MinimumInnerRadius);
                ptOuterLimit = Auxi_Geometry .PointToPoint (Center, angleBeam, OuterRadius - MinimumWidth);
            }
            else
            {
                rad = OuterRadius;
                ptInnerLimit = Auxi_Geometry .PointToPoint (Center, angleBeam, InnerRadius + MinimumWidth);
                ptOuterLimit = Auxi_Geometry .PointToPoint (Center, angleBeam, 4000);
            }
            Cursor .Position = form .PointToScreen (Point .Round (Auxi_Geometry .PointToPoint (Center, angleBeam, rad)));
        }
        // -------------------------------------------------        StartRotation
        public void StartRotation (Point ptMouse)
        {
            double angleMouse = Auxi_Geometry .Line_Angle (m_center, ptMouse);
            compensation = Auxi_Common .LimitedRadian (angleMouse - m_angle);
        }
        // -------------------------------------------------        DefineCover
        // order of nodes (all circular):  (rInner - delta), (rInner + delta), (rOuter - delta), (rOuter + delta)
        public override void DefineCover ()
        {
            CoverNode [] nodes = new CoverNode [] { new CoverNode (0, Center, InnerRadius - delta, Behaviour .Transparent), 
                                                    new CoverNode (1, Center, InnerRadius + delta), 
                                                    new CoverNode (2, Center, OuterRadius - delta, Cursors .SizeAll), 
                                                    new CoverNode (3, Center, OuterRadius + delta)};
            cover = new Cover (nodes);
            cover .SetClearance (false);
        }
        // -------------------------------------------------
        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 (i == 2)
                {
                    Move (dx, dy);
                }
                else
                {
                    PointF ptBase, ptNearest;
                    PointOfSegment typeOfNearest;
                    Auxi_Geometry .Distance_PointSegment (ptM, ptInnerLimit, ptOuterLimit, out ptBase, out typeOfNearest, out ptNearest);
                    if (i == 1)             // inner border
                    {
                        InnerRadius = Convert .ToSingle (Auxi_Geometry .Distance (Center, ptNearest));
                    }
                    else                    // outer border
                    {
                        OuterRadius = Convert .ToSingle (Auxi_Geometry .Distance (Center, ptNearest));
                    }
                    Cursor .Position = form .PointToScreen (Point .Round (ptNearest));
                    bRet = true;
                }
            }
            else if (catcher == MouseButtons .Right)
            {
                double angleMouse = Auxi_Geometry .Line_Angle (Center, ptM);
                Angle = angleMouse - compensation;
                bRet = true;
            }
            return (bRet);
        }

        const string nameMain = "RingSimple_";
        // -------------------------------------------------        IntoRegistry
        public void IntoRegistry (RegistryKey regkey, string strAdd)
        {
            try
            {
                string [] strs = new string [6 + vals .Length + 4 * vals .Length + 1];
                strs [0] = m_version .ToString ();
                strs [1] = m_center .X .ToString ();                            // center
                strs [2] = m_center .Y .ToString ();
                strs [3] = rOuter .ToString ();                                 // rOuter
                strs [4] = rInner .ToString ();                                 // rInner
                strs [5] = Auxi_Convert .RadianToDegree (Angle) .ToString ();   // angle
                for (int i = 0; i < vals .Length; i++)                          // vals
                {
                    strs [6 + i] = vals [i] .ToString ();
                }
                int k = 6 + 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 Ring_SimpleCover 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 < 12 || Convert .ToInt32 (strs [0]) != 620)
                {
                    return (null);
                }
                int nVals = (strs .Length - 7) / 5;
                double [] fVals = new double [nVals];
                List<Color> colors = new List<Color> ();
                int j_vals = 6;
                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));
                }
                Ring_SimpleCover ring = new Ring_SimpleCover (frm, mvr,
                                                              Auxi_Convert .ToPointF (strs, 1),                 // center
                                                              Convert .ToSingle (strs [3]),                     // rOuter
                                                              Convert .ToSingle (strs [4]),                     // rInner
                                                              Convert .ToDouble (strs [5]),                     // angle
                                                              fVals);
                if (ring != null)
                {
                    ring .SetColors (colors);
                    ring .DrawingDirection = (Rotation) Convert .ToInt32 (strs [j_dir]);
                }
                return (ring);
            }
            catch
            {
                return (null);
            }
            finally
            {
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions