Exemple #1
0
 /// <summary>
 /// Initializes a new instance of the ShapePoint class using a ShapePoint instance.
 /// </summary>
 /// <param name="point"></param>
 public ShapePoint(ShapePoint point)
     : base(point)
 {
     this.ControlPoint1 = new ShapePointBase(point.ControlPoint1);
     this.ControlPoint2 = new ShapePointBase(point.ControlPoint2);
     this.Bezier        = point.bezier;
 }
Exemple #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="nextPoint"></param>
        /// <returns></returns>
        public Point[] GetCurve(ShapePoint nextPoint)
        {
            double x1 = x, x2 = nextPoint.X, cx1 = controlPoint1.X, cx2 = controlPoint2.X;
            double y1 = y, y2 = nextPoint.Y, cy1 = controlPoint1.Y, cy2 = controlPoint2.Y;

            /* calculate the polynomial coefficients */
            double cx = 3.0 * (cx1 - x1);
            double bx = 3.0 * (cx2 - cx1) - cx;
            double ax = x2 - x1 - cx - bx;

            double cy = 3.0 * (cy1 - y1);
            double by = 3.0 * (cy2 - cy1) - cy;
            double ay = y2 - y1 - cy - by;

            /* calculate the curve point at parameter value t */
            Point[] points = new Point[10];
            for (int i = 0; i < 10; i++)
            {
                double t        = i / 9.0;
                double tSquared = t * t;
                double tCubed   = tSquared * t;

                points[i] = new Point(
                    (int)((ax * tCubed) + (bx * tSquared) + (cx * t) + x1),
                    (int)((ay * tCubed) + (by * tSquared) + (cy * t) + y1));
            }

            return(points);
        }
Exemple #3
0
 public bool IsVisible(ShapePoint nextPoint, Point pt, int width)
 {
     if (this.bezier)
     {
         return(this.IsCurveVisible(this.GetCurve(nextPoint), pt, (double)width));
     }
     return(this.IsLineVisible(this.GetPoint(), nextPoint.GetPoint(), pt, (double)width));
 }
Exemple #4
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="nextPoint"></param>
 /// <param name="pt"></param>
 /// <param name="width"></param>
 /// <returns></returns>
 public bool IsVisible(ShapePoint nextPoint, Point pt, int width)
 {
     if (bezier)
     {
         return(IsCurveVisible(GetCurve(nextPoint), pt, width));
     }
     else
     {
         return(IsLineVisible(GetPoint(), nextPoint.GetPoint(), pt, width));
     }
 }
        public RadShapeEditorControl()
        {
            snapToGrid      = new SnapToGrid();
            xoff            = yoff = 0;
            xOverflowOffset = yOverflowOffset = 0;
            maxWidth        = this.ClientRectangle.Width;
            maxHeight       = this.ClientRectangle.Height;
            minWidth        = 0;
            minHeight       = 0;

            //width of the guide line grid
            snapToGrid.FieldWidth    = FIELD_WIDTH;
            DRAWABLE_GRID_LINE_WIDTH = (int)snapToGrid.FieldWidth;
            //maximum distance from a guide line in pixels before snapping fires
            snapToGrid.SnapType  = SnapToGrid.SnapTypes.Fixed;
            snapToGrid.SnapFixed = 6;
            newSymmetricPoint    = referencePoint = null;
            dimensionPoints      = new ShapePoint[4];
            for (int i = 0; i < 4; ++i)
            {
                dimensionPoints[i] = new ShapePoint();
            }

            InitializeComponent();

            base.SetStyle(
                ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.Opaque |
                ControlStyles.ContainerControl |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.ResizeRedraw |
                ControlStyles.UserPaint, true);

            this.contextMenuPoint.RenderMode = ToolStripRenderMode.Professional;
            ((ToolStripProfessionalRenderer)this.contextMenuPoint.Renderer).ColorTable.UseSystemColors = true;

            this.contextMenuLine.RenderMode = ToolStripRenderMode.Professional;
            ((ToolStripProfessionalRenderer)this.contextMenuLine.Renderer).ColorTable.UseSystemColors = true;

            this.menuItemAddPoint.Click          += new EventHandler(menuItemAddPoint_Click);
            this.menuItemConvert.Click           += new EventHandler(menuItemConvert_Click);
            this.menuItemRemovePoint.Click       += new EventHandler(menuItemRemovePoint_Click);
            this.menuItemRemoveLine.Click        += new EventHandler(menuItemRemoveLine_Click);
            this.menuItemAnchorLeft.Click        += new EventHandler(menuItemAnchorLeft_Click);
            this.menuItemAnchorRight.Click       += new EventHandler(menuItemAnchorRight_Click);
            this.menuItemAnchorTop.Click         += new EventHandler(menuItemAnchorTop_Click);
            this.menuItemAnchorBottom.Click      += new EventHandler(menuItemAnchorBottom_Click);
            this.menuItemConvertLine.Click       += new EventHandler(menuItemConvert_Click);
            this.menuItemLeftTopCorner.Click     += new EventHandler(menuItemLeftTopCorner_Click);
            this.menuItemLeftBottomCorner.Click  += new EventHandler(menuItemLeftBottomCorner_Click);
            this.menuItemRightTopCorner.Click    += new EventHandler(menuItemRightTopCorner_Click);
            this.menuItemRightBottomCorner.Click += new EventHandler(menuItemRightBottomCorner_Click);
            this.menuItemLocked.Click            += new EventHandler(menuItemLocked_Click);
        }
 void menuItemConvert_Click(object sender, EventArgs e)
 {
     (point as ShapePoint).Bezier = !(point as ShapePoint).Bezier;
     if ((point as ShapePoint).Bezier)
     {
         int index = points.IndexOf(point as ShapePoint) + 1;
         if (index >= points.Count)
         {
             index = 0;
         }
         ShapePoint nextPoint = points[index];
         (point as ShapePoint).CreateBezier(nextPoint);
     }
     propertyGrid.Refresh();
     Refresh();
 }
Exemple #7
0
        private void verticallyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int index = this.points.IndexOf(this.point as ShapePoint) + 1;

            if (index >= this.points.Count)
            {
                index = 0;
            }
            Rectangle  dimension  = this.dimension;
            int        num        = dimension.Top + dimension.Height / 2;
            ShapePoint shapePoint = new ShapePoint();

            shapePoint.X = this.point.X;
            shapePoint.Y = this.point.Y + (float)(2.0 * ((double)num - (double)this.point.Y));
            this.points.Insert(index, shapePoint);
            this.point = (ShapePointBase)this.points[index];
            this.propertyGrid.SelectedObject = (object)this.point;
            this.Refresh();
        }
Exemple #8
0
 public override void DeserializeProperties(string propertiesString)
 {
     string[] strArray1 = propertiesString.Split(':');
     string[] strArray2 = strArray1[0].Split(',');
     this.dimension = new Rectangle(int.Parse(strArray2[0]), int.Parse(strArray2[1]), int.Parse(strArray2[2]), int.Parse(strArray2[3]));
     for (int index = 1; index < strArray1.Length; ++index)
     {
         string[] strArray3 = strArray1[index].Split(',');
         if (strArray3.Length > 2)
         {
             ShapePoint shapePoint = new ShapePoint(int.Parse(strArray3[0]), int.Parse(strArray3[1]));
             shapePoint.Bezier          = bool.Parse(strArray3[2]);
             shapePoint.ControlPoint1.X = (float)int.Parse(strArray3[3]);
             shapePoint.ControlPoint1.Y = (float)int.Parse(strArray3[4]);
             shapePoint.ControlPoint2.X = (float)int.Parse(strArray3[5]);
             shapePoint.ControlPoint2.Y = (float)int.Parse(strArray3[6]);
             shapePoint.Anchor          = (AnchorStyles)int.Parse(strArray3[7]);
             this.points.Add(shapePoint);
         }
     }
 }
Exemple #9
0
        public override GraphicsPath CreatePath(Rectangle bounds)
        {
            GraphicsPath graphicsPath = new GraphicsPath();

            for (int index = 0; index < this.points.Count; ++index)
            {
                ShapePoint point1     = this.points[index];
                ShapePoint shapePoint = index < this.points.Count - 1 ? this.points[index + 1] : this.points[0];
                Point      point2     = point1.GetPoint(this.dimension, bounds);
                Point      point3     = shapePoint.GetPoint(this.dimension, bounds);
                if (point1.Bezier)
                {
                    graphicsPath.AddBezier(point2, point1.ControlPoint1.GetPoint(this.dimension, bounds), point1.ControlPoint2.GetPoint(this.dimension, bounds), point3);
                }
                else
                {
                    graphicsPath.AddLine(point2, point3);
                }
            }
            graphicsPath.CloseAllFigures();
            return(graphicsPath);
        }
        private void verticallyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //creates a new point, symmetric to the given one on the other side of a horizontal symmetry line
            int index = points.IndexOf(point as ShapePoint) + 1;

            if (index >= points.Count)
            {
                index = 0;
            }
            //get the size of the drawable area and compute the coordinates of the new point
            Rectangle  r        = dimension;
            int        midy     = r.Top + r.Height / 2;
            ShapePoint newPoint = new ShapePoint();

            newPoint.X = point.X;
            newPoint.Y = point.Y + 2 * (midy - point.Y);

            //insert the point in the chain of points
            points.Insert(index, newPoint);
            point = points[index];
            propertyGrid.SelectedObject = point;
            Refresh();
        }
Exemple #11
0
        /// <summary>Deserializes properties. Required for telerik deserialization mechanism.</summary>
        public override void DeserializeProperties(string propertiesString)
        {
            string[] tokens = propertiesString.Split(':');

            string[] strdim = tokens[0].Split(',');
            dimension = new Rectangle(int.Parse(strdim[0]), int.Parse(strdim[1]),
                                      int.Parse(strdim[2]), int.Parse(strdim[3]));

            for (int i = 1; i < tokens.Length; i++)
            {
                string[] strpt = tokens[i].Split(',');
                if (strpt.Length > 2)
                {
                    ShapePoint point = new ShapePoint(int.Parse(strpt[0]), int.Parse(strpt[1]));
                    point.Bezier          = bool.Parse(strpt[2]);
                    point.ControlPoint1.X = int.Parse(strpt[3]);
                    point.ControlPoint1.Y = int.Parse(strpt[4]);
                    point.ControlPoint2.X = int.Parse(strpt[5]);
                    point.ControlPoint2.Y = int.Parse(strpt[6]);
                    point.Anchor          = (AnchorStyles)int.Parse(strpt[7]);
                    points.Add(point);
                }
            }
        }
Exemple #12
0
        private void RadShapeEditorControl_MouseDown(object sender, MouseEventArgs e)
        {
            this.Cursor    = Cursors.Cross;
            this.mouseDown = true;
            this.downPoint = new Point(e.X, e.Y);
            Point point1 = new Point((int)Math.Round((double)this.downPoint.X / Math.Pow((double)this.zoomFactor, 2.0)) + this.xOverflowOffset, (int)Math.Round((double)this.downPoint.Y / Math.Pow((double)this.zoomFactor, 2.0)) + this.yOverflowOffset);

            this.curPoint = this.downPoint;
            this.point    = (ShapePointBase)null;
            foreach (ShapePoint point2 in this.points)
            {
                if (point2.IsVisible(point1.X, point1.Y, (int)Math.Round(8.0 * (double)this.zoomFactor)))
                {
                    this.pointType = RadShapeEditorControl.PointTypes.Point;
                    this.point     = (ShapePointBase)point2;
                    break;
                }
                if (point2.Bezier)
                {
                    if (point2.ControlPoint1.IsVisible(point1.X, point1.Y, (int)Math.Round(8.0 * (double)this.zoomFactor)))
                    {
                        this.pointType = RadShapeEditorControl.PointTypes.ControlPoint;
                        this.point     = point2.ControlPoint1;
                        break;
                    }
                    if (point2.ControlPoint2.IsVisible(point1.X, point1.Y, (int)Math.Round(8.0 * (double)this.zoomFactor)))
                    {
                        this.pointType = RadShapeEditorControl.PointTypes.ControlPoint;
                        this.point     = point2.ControlPoint2;
                        break;
                    }
                }
            }
            if (this.isSymmetricPointMode)
            {
                if (this.point == null)
                {
                    this.isSymmetricPointMode = false;
                }
                else
                {
                    this.referencePoint = this.point;
                    Rectangle dimension = this.dimension;
                    int       num1      = dimension.Top + dimension.Height / 2;
                    int       num2      = dimension.Left + dimension.Width / 2;
                    if (this.isVerticalSymmetry)
                    {
                        this.newSymmetricPoint.Y = this.referencePoint.Y + (float)(2.0 * ((double)num1 - (double)this.point.Y));
                    }
                    else
                    {
                        this.newSymmetricPoint.X = this.referencePoint.X + (float)(2.0 * ((double)num2 - (double)this.point.X));
                    }
                    this.isSymmetricPointMode = false;
                    this.Refresh();
                }
            }
            else
            {
                if (this.point == null)
                {
                    for (int index = 0; index < this.points.Count; ++index)
                    {
                        ShapePoint point2    = this.points[index];
                        ShapePoint nextPoint = index < this.points.Count - 1 ? this.points[index + 1] : this.points[0];
                        if (point2.IsVisible(nextPoint, new Point(point1.X, point1.Y), 3))
                        {
                            this.pointType = RadShapeEditorControl.PointTypes.Line;
                            this.point     = (ShapePointBase)point2;
                            break;
                        }
                    }
                }
                if (this.propertyGrid != null)
                {
                    this.propertyGrid.SelectedObject = this.point == null ? (object)null : (object)this.point;
                }
                this.Refresh();
                if (e.Button == MouseButtons.Left && (this.point == null || !this.point.Selected))
                {
                    foreach (ShapePoint point2 in this.points)
                    {
                        point2.Selected = false;
                        point2.ControlPoint1.Selected = false;
                        point2.ControlPoint2.Selected = false;
                    }
                }
                if (this.point != null)
                {
                    this.mouseDown = false;
                }
                if (e.Button != MouseButtons.Right || this.point == null)
                {
                    return;
                }
                if (this.pointType == RadShapeEditorControl.PointTypes.Point && this.point is ShapePoint)
                {
                    this.menuItemAnchorLeft.Checked   = (this.point.Anchor & AnchorStyles.Left) != AnchorStyles.None;
                    this.menuItemAnchorRight.Checked  = (this.point.Anchor & AnchorStyles.Right) != AnchorStyles.None;
                    this.menuItemAnchorTop.Checked    = (this.point.Anchor & AnchorStyles.Top) != AnchorStyles.None;
                    this.menuItemAnchorBottom.Checked = (this.point.Anchor & AnchorStyles.Bottom) != AnchorStyles.None;
                    if (this.points.Count <= 2)
                    {
                        this.menuItemRemoveLine.Enabled  = false;
                        this.menuItemRemovePoint.Enabled = false;
                    }
                    this.menuItemLocked.Checked = this.point.Locked;
                    if ((this.point as ShapePoint).Bezier)
                    {
                        this.contextMenuPoint.Items[1].Text = "Convert to Line";
                    }
                    else
                    {
                        this.contextMenuPoint.Items[1].Text = "Convert to Bezier Curve";
                    }
                    this.contextMenuPoint.Show(this.PointToScreen(new Point(e.X, e.Y)));
                }
                else
                {
                    if (this.pointType != RadShapeEditorControl.PointTypes.Line)
                    {
                        return;
                    }
                    if ((this.point as ShapePoint).Bezier)
                    {
                        this.contextMenuLine.Items[1].Text = "Convert to Line";
                    }
                    else
                    {
                        this.contextMenuLine.Items[1].Text = "Convert to Bezier Curve";
                    }
                    this.contextMenuLine.Show(this.PointToScreen(new Point(e.X, e.Y)));
                }
            }
        }
Exemple #13
0
        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.FillRectangle(Brushes.White, this.ClientRectangle);
            Rectangle clientRectangle = this.ClientRectangle;

            --clientRectangle.Width;
            --clientRectangle.Height;
            e.Graphics.DrawRectangle(SystemPens.ControlDark, clientRectangle);
            Matrix matrix = new Matrix(1f, 0.0f, 0.0f, 1f, (float)(this.xOverflowOffset - this.hScrollBar1.Value), (float)(this.yOverflowOffset - this.vScrollBar1.Value));

            matrix.Scale(this.zoomFactor, this.zoomFactor);
            e.Graphics.Transform = matrix;
            e.Graphics.FillRectangle(Brushes.LightGray, this.GetRealFromVirtualRect(this.Dimension));
            this.DrawGridLines(e.Graphics, new Rectangle(0, 0, (int)Math.Round((double)this.ClientRectangle.Width * 1.5), (int)Math.Round((double)this.ClientRectangle.Height * 1.5)), Color.Black);
            Rectangle dimension = this.dimension;
            int       num1      = dimension.Left + dimension.Width / 2;
            int       num2      = dimension.Top + dimension.Height / 2;

            e.Graphics.DrawRectangle(Pens.Black, this.GetRealFromVirtualRect(dimension));
            e.Graphics.FillRectangle(Brushes.Black, this.GetRealFromVirtualRect(new Rectangle(num1 - 4, dimension.Y - 4, 8, 4)));
            e.Graphics.FillRectangle(Brushes.Black, this.GetRealFromVirtualRect(new Rectangle(num1 - 4, dimension.Bottom, 8, 4)));
            e.Graphics.FillRectangle(Brushes.Black, this.GetRealFromVirtualRect(new Rectangle(dimension.X - 4, num2 - 4, 4, 8)));
            e.Graphics.FillRectangle(Brushes.Black, this.GetRealFromVirtualRect(new Rectangle(dimension.Right, num2 - 4, 4, 8)));
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            this.minWidth            = this.minHeight = 0;
            this.maxWidth            = this.ClientRectangle.Width;
            this.maxHeight           = this.ClientRectangle.Height;
            using (Brush brush1 = (Brush) new SolidBrush(Color.Red))
            {
                using (Pen pen1 = new Pen(Color.Black, 2f))
                {
                    using (Pen pen2 = new Pen(Color.Blue, 2f))
                    {
                        using (Brush brush2 = (Brush) new SolidBrush(Color.Blue))
                        {
                            using (Pen pen3 = new Pen(Color.Green))
                            {
                                using (Brush brush3 = (Brush) new SolidBrush(Color.Green))
                                {
                                    for (int index = 0; index < this.points.Count; ++index)
                                    {
                                        ShapePoint point      = this.points[index];
                                        ShapePoint shapePoint = index < this.points.Count - 1 ? this.points[index + 1] : this.points[0];
                                        this.UpdateMaxSize((ShapePointBase)point);
                                        this.UpdateMaxSize((ShapePointBase)shapePoint);
                                        Pen pen4 = this.point == point ? pen2 : pen1;
                                        if (point.Bezier)
                                        {
                                            e.Graphics.DrawBezier(pen4, this.GetRealFromVirtualPoint((ShapePointBase)point), this.GetRealFromVirtualPoint(point.ControlPoint1), this.GetRealFromVirtualPoint(point.ControlPoint2), this.GetRealFromVirtualPoint((ShapePointBase)shapePoint));
                                            e.Graphics.DrawLine(pen3, this.GetRealFromVirtualPoint((ShapePointBase)point), this.GetRealFromVirtualPoint(point.ControlPoint1));
                                            e.Graphics.DrawLine(pen3, this.GetRealFromVirtualPoint((ShapePointBase)shapePoint), this.GetRealFromVirtualPoint(point.ControlPoint2));
                                            e.Graphics.FillEllipse(point.ControlPoint1 == this.point || point.ControlPoint1.Selected ? brush2 : brush3, this.GetRealFromVirtualRect(point.ControlPoint1.GetBounds(8)));
                                            e.Graphics.FillEllipse(point.ControlPoint2 == this.point || point.ControlPoint2.Selected ? brush2 : brush3, this.GetRealFromVirtualRect(point.ControlPoint2.GetBounds(8)));
                                            this.UpdateMaxSize(point.ControlPoint1);
                                            this.UpdateMaxSize(point.ControlPoint2);
                                        }
                                        else
                                        {
                                            e.Graphics.DrawLine(point == this.point ? pen2 : pen1, this.GetRealFromVirtualPoint((ShapePointBase)point), this.GetRealFromVirtualPoint((ShapePointBase)shapePoint));
                                        }
                                        e.Graphics.FillEllipse(point == this.point || point.Selected ? brush2 : brush1, this.GetRealFromVirtualRect(point.GetBounds(8)));
                                        e.Graphics.FillEllipse(shapePoint == this.point || shapePoint.Selected ? brush2 : brush1, this.GetRealFromVirtualRect(shapePoint.GetBounds(8)));
                                    }
                                    if (this.mouseDown)
                                    {
                                        Rectangle rect = new Rectangle(this.downPoint.X < this.curPoint.X ? this.downPoint.X : this.curPoint.X, this.downPoint.Y < this.curPoint.Y ? this.downPoint.Y : this.curPoint.Y, Math.Abs(this.downPoint.X - this.curPoint.X), Math.Abs(this.downPoint.Y - this.curPoint.Y));
                                        rect.X      = (int)Math.Round((double)rect.X / Math.Pow((double)this.zoomFactor, 1.0));
                                        rect.Y      = (int)Math.Round((double)rect.Y / Math.Pow((double)this.zoomFactor, 1.0));
                                        rect.Width  = (int)Math.Round((double)rect.Width / Math.Pow((double)this.zoomFactor, 1.0));
                                        rect.Height = (int)Math.Round((double)rect.Height / Math.Pow((double)this.zoomFactor, 1.0));
                                        pen2.Width  = 1f;
                                        e.Graphics.DrawRectangle(pen2, rect);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            this.vScrollBar1.Minimum = this.minHeight;
            this.hScrollBar1.Minimum = this.minWidth;
            this.vScrollBar1.Maximum = this.maxHeight;
            this.hScrollBar1.Maximum = this.maxWidth;
            this.SizeScrollBars();
            if (!this.snapToGrid.IsLastSnapped)
            {
                return;
            }
            e.Graphics.FillEllipse((Brush) new SolidBrush(Color.Red), this.GetRealFromVirtualRect(new Rectangle((int)this.snapToGrid.SnappedPoint.X - 2, (int)this.snapToGrid.SnappedPoint.Y - 2, 4, 4)));
        }
        void RadShapeEditorControl_MouseDown(object sender, MouseEventArgs e)
        {
            this.Cursor = Cursors.Cross;
            mouseDown   = true;
            downPoint   = new Point(e.X, e.Y);
            Point scaledTranslatedDownPoint = new Point(
                (int)Math.Round((downPoint.X) / Math.Pow(zoomFactor, 2)) + xOverflowOffset,
                (int)Math.Round((downPoint.Y) / Math.Pow(zoomFactor, 2)) + yOverflowOffset);

            curPoint = downPoint;
            point    = null;
            //find the point underneath the mouse
            foreach (ShapePoint pos1 in points)
            {
                if (pos1.IsVisible(scaledTranslatedDownPoint.X, scaledTranslatedDownPoint.Y, (int)Math.Round(8 * zoomFactor)))
                {
                    pointType = PointTypes.Point;
                    point     = pos1;
                    break;
                }
                else if (pos1.Bezier)
                {
                    if (pos1.ControlPoint1.IsVisible(scaledTranslatedDownPoint.X, scaledTranslatedDownPoint.Y, (int)Math.Round(8 * zoomFactor)))
                    {
                        pointType = PointTypes.ControlPoint;
                        point     = pos1.ControlPoint1;
                        break;
                    }
                    else if (pos1.ControlPoint2.IsVisible(scaledTranslatedDownPoint.X, scaledTranslatedDownPoint.Y, (int)Math.Round(8 * zoomFactor)))
                    {
                        pointType = PointTypes.ControlPoint;
                        point     = pos1.ControlPoint2;
                        break;
                    }
                }
            }

            if (isSymmetricPointMode)
            {
                if (point == null)
                {
                    isSymmetricPointMode = false;
                    return;
                }
                //use the currently selected node as a reference point to make the previously selected node symmetric to it
                referencePoint = point;
                //get the size of the drawable area and compute the coordinates of the new point
                Rectangle r    = dimension;
                int       midy = r.Top + r.Height / 2;
                int       midx = r.Left + r.Width / 2;

                if (isVerticalSymmetry)
                {
                    newSymmetricPoint.Y = referencePoint.Y + 2 * (midy - point.Y);
                }
                else
                {
                    newSymmetricPoint.X = referencePoint.X + 2 * (midx - point.X);
                }

                isSymmetricPointMode = false;
                Refresh();
                return;
            }

            if (point == null)
            {
                for (int i = 0; i < points.Count; i++)
                {
                    ShapePoint pos1 = points[i];
                    ShapePoint pos2 = i < points.Count - 1 ? points[i + 1] : points[0];

                    if (pos1.IsVisible(pos2, new Point(scaledTranslatedDownPoint.X, scaledTranslatedDownPoint.Y), 3))
                    {
                        pointType = PointTypes.Line;
                        point     = pos1;
                        break;
                    }
                }
            }

            if (point != null)
            {
                propertyGrid.SelectedObject = point;
            }
            else
            {
                propertyGrid.SelectedObject = null;
            }

            Refresh();
            //in case the mouse was clicked outside of any point, unselect all points (and their control points)
            if (e.Button == MouseButtons.Left)
            {
                if (point == null || !point.Selected)
                {
                    foreach (ShapePoint pos in points)
                    {
                        pos.Selected = false;
                        pos.ControlPoint1.Selected = false;
                        pos.ControlPoint2.Selected = false;
                    }
                }
            }

            if (point != null)
            {
                mouseDown = false;
            }

            if (e.Button == MouseButtons.Right && point != null)
            {
                if (pointType == PointTypes.Point && point is ShapePoint)
                {
                    menuItemAnchorLeft.Checked   = (point.Anchor & AnchorStyles.Left) != 0;
                    menuItemAnchorRight.Checked  = (point.Anchor & AnchorStyles.Right) != 0;
                    menuItemAnchorTop.Checked    = (point.Anchor & AnchorStyles.Top) != 0;
                    menuItemAnchorBottom.Checked = (point.Anchor & AnchorStyles.Bottom) != 0;

                    if (this.points.Count <= 2)
                    {
                        menuItemRemoveLine.Enabled  = false;
                        menuItemRemovePoint.Enabled = false;
                    }

                    menuItemLocked.Checked = point.Locked;

                    if ((point as ShapePoint).Bezier)
                    {
                        contextMenuPoint.Items[1].Text = "Convert to Line";
                    }
                    else
                    {
                        contextMenuPoint.Items[1].Text = "Convert to Bezier Curve";
                    }

                    contextMenuPoint.Show(PointToScreen(new Point(e.X, e.Y)));
                }
                else if (pointType == PointTypes.Line)
                {
                    if ((point as ShapePoint).Bezier)
                    {
                        contextMenuLine.Items[1].Text = "Convert to Line";
                    }
                    else
                    {
                        contextMenuLine.Items[1].Text = "Convert to Bezier Curve";
                    }

                    contextMenuLine.Show(PointToScreen(new Point(e.X, e.Y)));
                }
            }
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            //fill the entire area with white
            e.Graphics.FillRectangle(Brushes.White, ClientRectangle);

            Rectangle rect = ClientRectangle; rect.Width--; rect.Height--;

            //draw a non-movable rectangle encompassing the drawable area
            e.Graphics.DrawRectangle(SystemPens.ControlDark, rect);

            //initialize the matrix to be used when transforming the coordinate system
            //does scaling the translation in accordance with the positions of the scrollbars
            Matrix transformationMatrix = new Matrix(1, 0, 0, 1, xOverflowOffset - hScrollBar1.Value, yOverflowOffset - vScrollBar1.Value);

            transformationMatrix.Scale(zoomFactor, zoomFactor);

            e.Graphics.Transform = transformationMatrix;

            //fill the control area
            e.Graphics.FillRectangle(Brushes.LightGray, GetRealFromVirtualRect(Dimension));

            //draw the guides in the entire area
            DrawGridLines(e.Graphics,
                          new Rectangle(0, 0,
                                        (int)Math.Round((ClientRectangle.Width * 1.5)),        //+ ClientRectangle.Width
                                        (int)Math.Round((ClientRectangle.Height * 1.5)))       //+ ClientRectangle.Height
                          , Color.Black);

            Rectangle r    = dimension;
            int       midx = r.Left + r.Width / 2;
            int       midy = r.Top + r.Height / 2;

            //draw the black rectangle denoting the clipping rectangle of the control area
            e.Graphics.DrawRectangle(Pens.Black, GetRealFromVirtualRect(r));
            e.Graphics.FillRectangle(Brushes.Black, GetRealFromVirtualRect(new Rectangle(midx - 4, r.Y - 4, 8, 4)));
            e.Graphics.FillRectangle(Brushes.Black, GetRealFromVirtualRect(new Rectangle(midx - 4, r.Bottom, 8, 4)));
            e.Graphics.FillRectangle(Brushes.Black, GetRealFromVirtualRect(new Rectangle(r.X - 4, midy - 4, 4, 8)));
            e.Graphics.FillRectangle(Brushes.Black, GetRealFromVirtualRect(new Rectangle(r.Right, midy - 4, 4, 8)));

            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

            minWidth  = minHeight = 0;
            maxWidth  = this.ClientRectangle.Width;
            maxHeight = this.ClientRectangle.Height;

            using (Brush dot = new SolidBrush(Color.Red))
                using (Pen line = new Pen(Color.Black, 2))
                    using (Pen activeLine = new Pen(Color.Blue, 2))
                        using (Brush activeDot = new SolidBrush(Color.Blue))
                            using (Pen controlLine = new Pen(Color.Green))
                                using (Brush controlDot = new SolidBrush(Color.Green))
                                {
                                    //draw the points and the lines connecting them
                                    for (int i = 0; i < points.Count; i++)
                                    {
                                        ShapePoint pos1 = points[i];
                                        ShapePoint pos2 = i < points.Count - 1 ? points[i + 1] : points[0];

                                        UpdateMaxSize(pos1);
                                        UpdateMaxSize(pos2);

                                        Pen pen = point == pos1 ? activeLine : line;
                                        //if the line at the point is a bezier curve, draw it together with the tangents and the control points
                                        if (pos1.Bezier)
                                        {
                                            //draw the bezier curve
                                            e.Graphics.DrawBezier(pen,
                                                                  GetRealFromVirtualPoint(pos1),
                                                                  GetRealFromVirtualPoint(pos1.ControlPoint1),
                                                                  GetRealFromVirtualPoint(pos1.ControlPoint2),
                                                                  GetRealFromVirtualPoint(pos2));

                                            //draw the tangents to the control points
                                            e.Graphics.DrawLine(controlLine, GetRealFromVirtualPoint(pos1), GetRealFromVirtualPoint(pos1.ControlPoint1));
                                            e.Graphics.DrawLine(controlLine, GetRealFromVirtualPoint(pos2), GetRealFromVirtualPoint(pos1.ControlPoint2));

                                            //draw the control points
                                            e.Graphics.FillEllipse((pos1.ControlPoint1 == point || pos1.ControlPoint1.Selected) ? activeDot : controlDot,
                                                                   GetRealFromVirtualRect(pos1.ControlPoint1.GetBounds(8)));
                                            e.Graphics.FillEllipse((pos1.ControlPoint2 == point || pos1.ControlPoint2.Selected) ? activeDot : controlDot,
                                                                   GetRealFromVirtualRect(pos1.ControlPoint2.GetBounds(8)));

                                            //update the maximum size in response to points outside of the drawable area
                                            UpdateMaxSize(pos1.ControlPoint1);
                                            UpdateMaxSize(pos1.ControlPoint2);
                                        }
                                        //draws a straight line
                                        else
                                        {
                                            e.Graphics.DrawLine(pos1 == point ? activeLine : line, GetRealFromVirtualPoint(pos1), GetRealFromVirtualPoint(pos2));
                                        }

                                        //draws the two points at the ends of the line
                                        e.Graphics.FillEllipse((pos1 == point || pos1.Selected) ? activeDot : dot, GetRealFromVirtualRect(pos1.GetBounds(8)));
                                        e.Graphics.FillEllipse((pos2 == point || pos2.Selected) ? activeDot : dot, GetRealFromVirtualRect(pos2.GetBounds(8)));
                                    }
                                    //draw multiple point selection rectangle
                                    if (mouseDown)
                                    {
                                        r = new Rectangle(
                                            downPoint.X < curPoint.X ? downPoint.X : curPoint.X,
                                            downPoint.Y < curPoint.Y ? downPoint.Y : curPoint.Y,
                                            Math.Abs(downPoint.X - curPoint.X),
                                            Math.Abs(downPoint.Y - curPoint.Y));
                                        //convert the rectangle location and size from virtual to real
                                        r.X = (int)Math.Round((r.X) / Math.Pow(zoomFactor, 1));
                                        r.Y = (int)Math.Round((r.Y) / Math.Pow(zoomFactor, 1));

                                        r.Width  = (int)Math.Round(r.Width / Math.Pow(zoomFactor, 1));
                                        r.Height = (int)Math.Round(r.Height / Math.Pow(zoomFactor, 1));

                                        activeLine.Width = 1;
                                        e.Graphics.DrawRectangle(activeLine, r);
                                    }
                                }
            //set the bounds of the scrollbars to contain all points
            vScrollBar1.Minimum = minHeight;
            hScrollBar1.Minimum = minWidth;

            vScrollBar1.Maximum = maxHeight;
            hScrollBar1.Maximum = maxWidth;
            SizeScrollBars();

            //draw little red point indicating the line of snap at a given point
            if (snapToGrid.IsLastSnapped)
            {
                e.Graphics.FillEllipse(new SolidBrush(Color.Red), GetRealFromVirtualRect(new Rectangle((int)snapToGrid.SnappedPoint.X - 2, (int)snapToGrid.SnappedPoint.Y - 2, 4, 4)));
            }
        }