From 6614cab8a74dcc5da424f0a7e2cfedbd7b8d5b7b Mon Sep 17 00:00:00 2001 From: maxluli Date: Wed, 1 Jun 2022 11:53:27 +0200 Subject: [PATCH] WIP! added a cubic bezier curve generator --- Paint_2/BezierPencil.cs | 218 ++++++++++++++++++++++++++++++++++++++++ Paint_2/DotPencil.cs | 8 +- Paint_2/Form1.cs | 1 + Paint_2/Paint_2.csproj | 1 + Paint_2/Pencil.cs | 7 +- 5 files changed, 225 insertions(+), 10 deletions(-) create mode 100644 Paint_2/BezierPencil.cs diff --git a/Paint_2/BezierPencil.cs b/Paint_2/BezierPencil.cs new file mode 100644 index 0000000..2cb74b9 --- /dev/null +++ b/Paint_2/BezierPencil.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +//[DEBUG] +using System.Windows.Forms; + +namespace Paint_2 +{ + internal class BezierPencil : PaintTool + { + private List> _drawings; + private List> _drawingsRedo; + private List _colors; + private List _colorsRedo; + private List _widths; + private List _widthsRedo; + private Color _color; + private string _name; + private int _width; + + public List> Drawings { get => _drawings; set => _drawings = value; } + public List> DrawingsRedo { get => _drawingsRedo; set => _drawingsRedo = value; } + public List Colors { get => _colors; set => _colors = value; } + public List ColorsRedo { get => _colorsRedo; set => _colorsRedo = value; } + public List Widths { get => _widths; set => _widths = value; } + public List WidthsRedo { get => _widthsRedo; set => _widthsRedo = value; } + public Color Color { get => _color; set => _color = value; } + public string Name { get => _name; set => _name = value; } + public int Width { get => _width; set => _width = value; } + + public BezierPencil(string name) + { + Drawings = new List>(); + DrawingsRedo = new List>(); + Colors = new List(); + ColorsRedo = new List(); + Widths = new List(); + WidthsRedo = new List(); + Name = name; + } + public void Add(Point point) + { + if (Drawings[Drawings.Count - 1].Count == 0) + { + Drawings[Drawings.Count - 1].Add(point); + } + } + + public void Clear() + { + Drawings = new List>(); + DrawingsRedo = new List>(); + Colors = new List(); + ColorsRedo = new List(); + Widths = new List(); + WidthsRedo = new List(); + } + + public List GetLastColors(int colorNumber) + { + List result = new List(); + if (Colors.Count <= colorNumber) + { + //We need to fill with black color + for (int i = Colors.Count; i > 0; i--) + { + result.Add(Colors[(Colors.Count) - i]); + } + for (int i = colorNumber - Colors.Count; i > 0; i--) + { + result.Add(Color.FromArgb(0x00, 0x00, 0x00)); + } + } + else + { + for (int i = colorNumber; i > 0; i--) + { + result.Add(Colors[(Colors.Count) - i]); + } + } + return result; + } + private Point LerpY(Point start,Point end,int x) + { + int newY = start.Y + (x - start.X) * ((end.Y - start.Y) / (end.X - start.X)); + return new Point(x,newY); + } + private Point LerpX(Point start,Point end,int y) + { + int newX = start.X + (y - start.Y) * ((end.Y - start.Y) / (end.X - start.X)); + return new Point(newX,y); + } + public void Paint(Bitmap canvas) + { + Graphics gr = Graphics.FromImage(canvas); + int drawingCounter = 0; + Size pointSize; + + List points = new List(); + foreach (List drawing in Drawings) + { + if (drawing.Count > 0) + { + points.Add(drawing[0]); + } + } + if (points.Count > 0) + { + + for (int i = 1; i <= points.Count; i++) + { + pointSize = new Size(Widths[i - 1], Widths[i - 1]); + gr.FillEllipse(new SolidBrush(Colors[i - 1]), new Rectangle(new Point(points[i - 1].X - pointSize.Width / 2, points[i - 1].Y - pointSize.Height / 2), pointSize)); + + if (i % 4 == 0) + { + //Drawing the first level of curve + Point p1 = points[i - 4]; + Point p2 = points[i - 3]; + Point p3 = points[i - 2]; + Point p4 = points[i - 1]; + + /* + // Calculate the lowest x change + int range = Math.Min(Math.Abs(p4.X - p3.X), Math.Min(Math.Abs(p2.X -p1.X), Math.Abs(p3.X - p2.X))); + float firstOffset = Math.Abs(p2.X - p1.X) / range; + float SecondOffset = Math.Abs(p3.X - p2.X) / range; + float thirdOffset = Math.Abs(p4.X - p3.X) / range; + */ + + //[DEBUG] MessageBox.Show("X Diff \n1: " + Math.Abs(p2.X - p1.X) + " \n2: " + Math.Abs(p3.X - p2.X) + " \n3: " + Math.Abs(p4.X - p3.X) + " \nLowest: " + range); + + gr.DrawLine(new Pen(Colors[i - 4], Widths[i - 4]), p1, p2); + gr.DrawLine(new Pen(Colors[i - 3], Widths[i - 3]), p2, p3); + gr.DrawLine(new Pen(Colors[i - 2], Widths[i - 2]), p3, p4); + + //Drawing the second level of curve + Point p1_2 = new Point((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2); + Point p2_2 = new Point((p2.X + p3.X) / 2, (p2.Y + p3.Y) / 2); + Point p3_2 = new Point((p3.X + p4.X) / 2, (p3.Y + p4.Y) / 2); + + gr.DrawLine(new Pen(Colors[i - 1], Widths[i - 1]), p1_2, p2_2); + gr.DrawLine(new Pen(Colors[i - 1], Widths[i - 1]), p2_2, p3_2); + + //Drawing the thirs level of curve + Point p1_3 = new Point((p1_2.X + p2_2.X) / 2, (p1_2.Y + p2_2.Y) / 2); + Point p2_3 = new Point((p2_2.X + p3_2.X) / 2, (p2_2.Y + p3_2.Y) / 2); + + gr.DrawLine(new Pen(Color.Pink, 5), p1_3, p2_3); + + //Drawing the Bezier point + Point p1_4 = new Point((p1_3.X + p2_3.X) / 2, (p1_3.Y + p2_3.Y) / 2); + gr.FillEllipse(new SolidBrush(Color.AliceBlue), new Rectangle(new Point(p1_4.X - pointSize.Width / 2, p1_4.Y - pointSize.Height / 2), pointSize)); + } + } + } + } + public void Start(Color color, int width) + { + Color = color; + Width = width; + List points = new List(); + Drawings.Add(points); + Colors.Add(Color); + Widths.Add(Width); + } + + public void Stop() + { + //Implement the bezier curve algorythm (if there are enough points) + + } + + public override string ToString() + { + return Name; + } + + public void Undo() + { + int last = Drawings.Count - 1; + if (Drawings.Count > 1) + { + DrawingsRedo.Add(Drawings[last]); + Drawings.RemoveAt(Drawings.Count - 1); + ColorsRedo.Add(Colors[last]); + Colors.RemoveAt(Colors.Count - 1); + WidthsRedo.Add(Widths[last]); + Widths.RemoveAt(Widths.Count - 1); + } + else + { + DrawingsRedo.Add(Drawings[0]); + Drawings.Clear(); + ColorsRedo.Add(Colors[0]); + Colors.Clear(); + WidthsRedo.Add(Widths[0]); + Widths.Clear(); + } + } + + public void Redo() + { + if (DrawingsRedo.Count > 0 && WidthsRedo.Count > 0 && ColorsRedo.Count > 0) + { + Drawings.Add(DrawingsRedo[DrawingsRedo.Count - 1]); + DrawingsRedo.RemoveAt(DrawingsRedo.Count - 1); + Colors.Add(ColorsRedo[ColorsRedo.Count - 1]); + ColorsRedo.RemoveAt(ColorsRedo.Count - 1); + Widths.Add(WidthsRedo[WidthsRedo.Count - 1]); + WidthsRedo.RemoveAt(WidthsRedo.Count - 1); + } + } + } +} diff --git a/Paint_2/DotPencil.cs b/Paint_2/DotPencil.cs index fa92d14..46aff74 100644 --- a/Paint_2/DotPencil.cs +++ b/Paint_2/DotPencil.cs @@ -61,12 +61,8 @@ namespace Paint_2 int pointCounter = 0; foreach (Point p in drawing) { - if (pointCounter > 0) - { - pointSize = new Size(Widths[drawingCounter], Widths[drawingCounter]); - gr.FillEllipse(new SolidBrush(Colors[drawingCounter]), new Rectangle(new Point(p.X - pointSize.Width / 2, p.Y - pointSize.Height / 2), pointSize)); - } - + pointSize = new Size(Widths[drawingCounter], Widths[drawingCounter]); + gr.FillEllipse(new SolidBrush(Colors[drawingCounter]), new Rectangle(new Point(p.X - pointSize.Width / 2, p.Y - pointSize.Height / 2), pointSize)); pointCounter += 1; } drawingCounter += 1; diff --git a/Paint_2/Form1.cs b/Paint_2/Form1.cs index 0c7456b..ee1b53b 100644 --- a/Paint_2/Form1.cs +++ b/Paint_2/Form1.cs @@ -34,6 +34,7 @@ namespace Paint_2 toolList = new List(); toolList.Add(new Pencil("Default Pencil")); toolList.Add(new DotPencil("Dotted Line")); + toolList.Add(new BezierPencil("Bezier Generator")); sketch = new Sketch(new Size(canvas.Width, canvas.Height), toolList); tmrRefresh.Enabled = true; diff --git a/Paint_2/Paint_2.csproj b/Paint_2/Paint_2.csproj index dad7e1d..ab0ed0c 100644 --- a/Paint_2/Paint_2.csproj +++ b/Paint_2/Paint_2.csproj @@ -46,6 +46,7 @@ + Form diff --git a/Paint_2/Pencil.cs b/Paint_2/Pencil.cs index 6b8a346..a2c12dd 100644 --- a/Paint_2/Pencil.cs +++ b/Paint_2/Pencil.cs @@ -61,13 +61,12 @@ namespace Paint_2 int pointCounter = 0; foreach (Point p in drawing) { + pointSize = new Size(Widths[drawingCounter], Widths[drawingCounter]); + gr.FillEllipse(new SolidBrush(Colors[drawingCounter]), new Rectangle(new Point(p.X - pointSize.Width / 2, p.Y - pointSize.Height / 2), pointSize)); if (pointCounter > 0) { - pointSize = new Size(Widths[drawingCounter], Widths[drawingCounter]); - gr.FillEllipse(new SolidBrush(Colors[drawingCounter]), new Rectangle(new Point(p.X - pointSize.Width / 2, p.Y - pointSize.Height / 2), pointSize)); - gr.DrawLine(new Pen(Colors[drawingCounter], Widths[drawingCounter]), drawing[pointCounter - 1], p); + gr.DrawLine(new Pen(Colors[drawingCounter], Widths[drawingCounter]), drawing[pointCounter -1], p); } - pointCounter += 1; } drawingCounter += 1;