Click here to Skip to main content
15,894,646 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 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
            {
            }
        }
    }
}

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