Browse Source

Added Circle Select

CPKreuz 4 years ago
parent
commit
2777388675

+ 1 - 1
PixiEditor/Helpers/SelectionHelpers.cs

@@ -27,7 +27,7 @@ namespace PixiEditor.Helpers
             {
                 document.UndoManager.AddUndoChange(
                     new Change(
-                        SetSelectionProcess, new object[] { document, new List<Coordinates>(oldPoints) },
+                        SetSelectionProcess, new object[] { document, oldPoints is null ? new List<Coordinates>() : new List<Coordinates>(oldPoints) },
                         SetSelectionProcess, new object[] { document, new List<Coordinates>(document.ActiveSelection.SelectedPoints) }));
 #pragma warning restore SA1117 // Parameters should be on same line or separate lines
             }

+ 5 - 0
PixiEditor/Models/DataHolders/BitmapPixelChanges.cs

@@ -35,6 +35,11 @@ namespace PixiEditor.Models.DataHolders
             Dictionary<Coordinates, Color> dict = new Dictionary<Coordinates, Color>();
             foreach (Coordinates coordinate in coordinates)
             {
+                if (dict.ContainsKey(coordinate))
+                {
+                    continue;
+                }
+
                 dict.Add(coordinate, color);
             }
 

+ 14 - 0
PixiEditor/Models/Enums/SelectionShape.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PixiEditor.Models.Enums
+{
+    public enum SelectionShape
+    {
+        Rectangle,
+        Circle
+    }
+}

+ 18 - 18
PixiEditor/Models/Tools/ShapeTool.cs

@@ -16,25 +16,9 @@ namespace PixiEditor.Models.Tools
             RequiresPreviewLayer = true;
             Cursor = Cursors.Cross;
             Toolbar = new BasicShapeToolbar();
-        }
-
-        // TODO: Add cache for lines 31, 32 (hopefully it would speed up calculation)
-        public abstract override LayerChange[] Use(Layer layer, Coordinates[] coordinates, Color color);
-
-        protected IEnumerable<Coordinates> GetThickShape(IEnumerable<Coordinates> shape, int thickness)
-        {
-            List<Coordinates> output = new List<Coordinates>();
-            foreach (Coordinates item in shape)
-            {
-                output.AddRange(
-                    CoordinatesCalculator.RectangleToCoordinates(
-                        CoordinatesCalculator.CalculateThicknessCenter(item, thickness)));
-            }
-
-            return output.Distinct();
-        }
+        }
 
-        protected DoubleCords CalculateCoordinatesForShapeRotation(
+        public static DoubleCords CalculateCoordinatesForShapeRotation(
             Coordinates startingCords,
             Coordinates secondCoordinates)
         {
@@ -70,5 +54,21 @@ namespace PixiEditor.Models.Tools
 
             return new DoubleCords(startingCords, secondCoordinates);
         }
+
+        // TODO: Add cache for lines 31, 32 (hopefully it would speed up calculation)
+        public abstract override LayerChange[] Use(Layer layer, Coordinates[] coordinates, Color color);
+
+        protected IEnumerable<Coordinates> GetThickShape(IEnumerable<Coordinates> shape, int thickness)
+        {
+            List<Coordinates> output = new List<Coordinates>();
+            foreach (Coordinates item in shape)
+            {
+                output.AddRange(
+                    CoordinatesCalculator.RectangleToCoordinates(
+                        CoordinatesCalculator.CalculateThicknessCenter(item, thickness)));
+            }
+
+            return output.Distinct();
+        }
     }
 }

+ 1 - 0
PixiEditor/Models/Tools/ToolSettings/Toolbars/SelectToolToolbar.cs

@@ -8,6 +8,7 @@ namespace PixiEditor.Models.Tools.ToolSettings.Toolbars
         public SelectToolToolbar()
         {
             Settings.Add(new EnumSetting<SelectionType>("SelectMode", "Selection type"));
+            Settings.Add(new EnumSetting<SelectionShape>("SelectShape", "Selection shape"));
         }
     }
 }

+ 22 - 16
PixiEditor/Models/Tools/Tools/CircleTool.cs

@@ -158,27 +158,15 @@ namespace PixiEditor.Models.Tools.Tools
             return outputCoordinates;
         }
 
-        private Coordinates[] FallbackRectangle(double halfWidth, double halfHeight, double centerX, double centerY)
+        public IEnumerable<Coordinates> CalculateFillForEllipse(IEnumerable<Coordinates> outlineCoordinates)
         {
-            List<Coordinates> coordinates = new List<Coordinates>();
-            for (double x = centerX - halfWidth; x <= centerX + halfWidth; x++)
-            {
-                coordinates.Add(new Coordinates((int)x, (int)(centerY - halfHeight)));
-                coordinates.Add(new Coordinates((int)x, (int)(centerY + halfHeight)));
-            }
+            List<Coordinates> finalCoordinates = new List<Coordinates>();
 
-            for (double y = centerY - halfHeight + 1; y <= centerY + halfHeight - 1; y++)
+            if (!outlineCoordinates.Any())
             {
-                coordinates.Add(new Coordinates((int)(centerX - halfWidth), (int)y));
-                coordinates.Add(new Coordinates((int)(centerX + halfWidth), (int)y));
+                return finalCoordinates;
             }
 
-            return coordinates.ToArray();
-        }
-
-        private IEnumerable<Coordinates> CalculateFillForEllipse(IEnumerable<Coordinates> outlineCoordinates)
-        {
-            List<Coordinates> finalCoordinates = new List<Coordinates>();
             int bottom = outlineCoordinates.Max(x => x.Y);
             int top = outlineCoordinates.Min(x => x.Y);
             for (int i = top + 1; i < bottom; i++)
@@ -195,6 +183,24 @@ namespace PixiEditor.Models.Tools.Tools
             return finalCoordinates;
         }
 
+        private Coordinates[] FallbackRectangle(double halfWidth, double halfHeight, double centerX, double centerY)
+        {
+            List<Coordinates> coordinates = new List<Coordinates>();
+            for (double x = centerX - halfWidth; x <= centerX + halfWidth; x++)
+            {
+                coordinates.Add(new Coordinates((int)x, (int)(centerY - halfHeight)));
+                coordinates.Add(new Coordinates((int)x, (int)(centerY + halfHeight)));
+            }
+
+            for (double y = centerY - halfHeight + 1; y <= centerY + halfHeight - 1; y++)
+            {
+                coordinates.Add(new Coordinates((int)(centerX - halfWidth), (int)y));
+                coordinates.Add(new Coordinates((int)(centerX + halfWidth), (int)y));
+            }
+
+            return coordinates.ToArray();
+        }
+
         private Coordinates[] GetRegionPoints(double x, double xc, double y, double yc)
         {
             Coordinates[] outputCoordinates = new Coordinates[4];

+ 27 - 4
PixiEditor/Models/Tools/Tools/SelectTool.cs

@@ -19,8 +19,9 @@ namespace PixiEditor.Models.Tools.Tools
 {
     public class SelectTool : ReadonlyTool
     {
+        private readonly RectangleTool rectangleTool = new RectangleTool();
+        private readonly CircleTool circleTool = new CircleTool();
         private IEnumerable<Coordinates> oldSelectedPoints;
-        private RectangleTool rectangleTool = new RectangleTool();
 
         private static Selection ActiveSelection { get => ViewModelMain.Current.BitmapManager.ActiveDocument.ActiveSelection; }
 
@@ -53,7 +54,7 @@ namespace PixiEditor.Models.Tools.Tools
 
         public override void Use(Coordinates[] pixels)
         {
-            Select(pixels);
+            Select(pixels, Toolbar.GetEnumSetting<SelectionShape>("SelectShape").Value);
         }
 
         public IEnumerable<Coordinates> GetRectangleSelectionForPoints(Coordinates start, Coordinates end)
@@ -63,6 +64,14 @@ namespace PixiEditor.Models.Tools.Tools
             return selection;
         }
 
+        public IEnumerable<Coordinates> GetCircleSelectionForPoints(Coordinates start, Coordinates end)
+        {
+            DoubleCords fixedCoordinates = ShapeTool.CalculateCoordinatesForShapeRotation(start, end);
+            List<Coordinates> selection = circleTool.CreateEllipse(fixedCoordinates.Coords1, fixedCoordinates.Coords2, 1).ToList();
+            selection.AddRange(circleTool.CalculateFillForEllipse(selection));
+            return selection;
+        }
+
         /// <summary>
         ///     Gets coordinates of every pixel in root layer.
         /// </summary>
@@ -81,9 +90,23 @@ namespace PixiEditor.Models.Tools.Tools
             return GetRectangleSelectionForPoints(new Coordinates(0, 0), new Coordinates(document.Width - 1, document.Height - 1));
         }
 
-        private void Select(Coordinates[] pixels)
+        private void Select(Coordinates[] pixels, SelectionShape shape)
         {
-            IEnumerable<Coordinates> selection = GetRectangleSelectionForPoints(pixels[^1], pixels[0]);
+            IEnumerable<Coordinates> selection;
+
+            if (shape == SelectionShape.Circle)
+            {
+                selection = GetCircleSelectionForPoints(pixels[^1], pixels[0]);
+            }
+            else if (shape == SelectionShape.Rectangle)
+            {
+                selection = GetRectangleSelectionForPoints(pixels[^1], pixels[0]);
+            }
+            else
+            {
+                throw new NotImplementedException($"Selection shape '{shape}' has not been implemented");
+            }
+
             ViewModelMain.Current.BitmapManager.ActiveDocument.ActiveSelection.SetSelection(selection, SelectionType);
         }
     }