/// <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; }
/// <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); }
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)); }
/// <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(); }
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(); }
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); } } }
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(); }
/// <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); } } }
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))); } } }
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))); } }