Browse Source

A lot of improvements

flabbet 8 months ago
parent
commit
69b2028951

+ 1 - 1
src/PixiEditor/Views/Overlays/PathOverlay/EditableVectorPath.cs

@@ -294,7 +294,7 @@ public class EditableVectorPath
                 break;
             }
         }
-
+        
         targetSubShape?.AddPointAt((VecF)point, verb);
     }
 }

+ 14 - 3
src/PixiEditor/Views/Overlays/PathOverlay/ShapePoint.cs

@@ -38,11 +38,22 @@ public class ShapePoint
         {
             VecF mid1 = Verb.ControlPoint1 ?? Verb.From;
             
-            float factor = 2 * Verb.ConicWeight / (1 + Verb.ConicWeight);
+            float fixedConic = 1 - Verb.ConicWeight;
 
-            VecF control1 = mid1;// + new VecF((mid1.X - Verb.From.X) * factor, (mid1.Y - Verb.From.Y) * factor);
-            VecF control2 = Verb.To + new VecF((mid1.X - Verb.To.X) * factor, (mid1.Y - Verb.To.Y) * factor);
+            // TODO: Make sure it is adjusted/works for other cases
+            // 0.77 works for oval case, it probably will need to be adjusted for other cases
+            // we don't have a case for any other shape than oval so right now it's hardcoded like so.
+            float factor = 2 * fixedConic / (0.77f + fixedConic);
+
+            VecF from1 = (mid1 - Verb.From);
+            from1 = new VecF(from1.X * factor, from1.Y * factor);
             
+            VecF from2 = (mid1 - Verb.To);
+            from2 = new VecF(from2.X * factor, from2.Y * factor);
+
+            VecF control1 = Verb.From + from1;
+            VecF control2 = Verb.To + from2;
+
             return [Verb.From, control1, control2, Verb.To];
         }
         

+ 18 - 10
src/PixiEditor/Views/Overlays/PathOverlay/SubShape.cs

@@ -70,14 +70,22 @@ public class SubShape
         }
     }
 
-    public void AddPointAt(VecF point, Verb onVerb)
+    public void AddPointAt(VecF point, Verb pointVerb)
     {
-        int indexOfVerb = this.points.FirstOrDefault(x => x.Verb == onVerb)?.Index ?? -1;
+        int indexOfVerb = this.points.FirstOrDefault(x => x.Verb == pointVerb)?.Index ?? -1;
         if (indexOfVerb == -1)
         {
             throw new ArgumentException("Verb not found in points list");
         }
 
+        Verb onVerb = pointVerb;
+        
+        if (onVerb.VerbType is PathVerb.Quad or PathVerb.Conic)
+        {
+            this.points[indexOfVerb].ConvertVerbToCubic();
+            onVerb = this.points[indexOfVerb].Verb;
+        }
+
         var oldTo = onVerb.To;
         VecF[] data = new VecF[4];
         VecF insertPoint = point;
@@ -92,25 +100,25 @@ public class SubShape
             float t = VectorMath.GetNormalizedSegmentPosition(onVerb, point);
             VecD oldControlPoint1 = (VecD)onVerb.ControlPoint1.Value;
             VecD oldControlPoint2 = (VecD)onVerb.ControlPoint2.Value;
-            
+
             // de Casteljau's algorithm
-            
+
             var q0 = ((VecD)onVerb.From).Lerp(oldControlPoint1, t);
             var q1 = oldControlPoint1.Lerp(oldControlPoint2, t);
             var q2 = oldControlPoint2.Lerp((VecD)oldTo, t);
-            
+
             var r0 = q0.Lerp(q1, t);
             var r1 = q1.Lerp(q2, t);
-            
+
             var s0 = r0.Lerp(r1, t);
-            
+
             onVerb.ControlPoint1 = (VecF)q0;
             onVerb.ControlPoint2 = (VecF)r0;
-            
+
             onVerb.To = (VecF)s0;
-            
+
             data = [(VecF)s0, (VecF)r1, (VecF)q2, oldTo];
-            
+
             insertPoint = (VecF)s0;
         }
 

+ 9 - 3
src/PixiEditor/Views/Overlays/PathOverlay/VectorMath.cs

@@ -222,8 +222,14 @@ internal static class VectorMath
 
     private static VecD ConicBezier(VecD start, VecD control, VecD end, float weight, double t)
     {
-        double x = Math.Pow(1 - t, 2) * start.X + 2 * (1 - t) * t * control.X + Math.Pow(t, 2) * end.X;
-        double y = Math.Pow(1 - t, 2) * start.Y + 2 * (1 - t) * t * control.Y + Math.Pow(t, 2) * end.Y;
-        return new VecD(x, y);
+        double b0 = (1 - t) * (1 - t);
+        double b1 = 2 * t * (1 - t);
+        double b2 = t * t;
+
+        VecD numerator = (start * b0) + (control * b1 * weight) + (end * b2);
+
+        double denominator = b0 + (b1 * weight) + b2;
+
+        return numerator / denominator;
     }
 }

+ 23 - 9
src/PixiEditor/Views/Overlays/PathOverlay/VectorPathOverlay.cs

@@ -119,6 +119,8 @@ public class VectorPathOverlay : Overlay
 
         EditableVectorPath editablePath = new EditableVectorPath(Path);
 
+        UpdatePointsPositions();
+
         int anchorIndex = 0;
         int controlPointIndex = 0;
         for (int i = 0; i < editablePath.SubShapes.Count; i++)
@@ -133,7 +135,7 @@ public class VectorPathOverlay : Overlay
             foreach (var point in subPath.Points)
             {
                 var handle = anchorHandles[anchorIndex];
-                handle.Position = (VecD)point.Position;
+                //handle.Position = (VecD)point.Position;
 
                 if (point.Verb.ControlPoint1 != null || point.Verb.ControlPoint2 != null)
                 {
@@ -221,9 +223,9 @@ public class VectorPathOverlay : Overlay
     private void UpdatePointsPositions()
     {
         int controlPointIndex = 0;
+        int anchorIndex = 0;
         foreach (var subShape in editableVectorPath.SubShapes)
         {
-            int anchorIndex = 0;
             foreach (var point in subShape.Points)
             {
                 if (point.Verb.VerbType == PathVerb.Cubic)
@@ -356,7 +358,12 @@ public class VectorPathOverlay : Overlay
             anchor.OnRelease += OnHandleRelease;
             anchor.OnTap += OnHandleTap;
             AddHandle(anchor);
-            SnappingController.AddXYAxis($"editingPath[{atIndex}]", () => anchor.Position);
+            SnappingController.AddXYAxis($"editingPath[{atIndex}]", () =>
+            {
+                var subs = editableVectorPath.GetSubShapeContainingIndex(atIndex);
+                int localIndex = editableVectorPath.GetSubShapePointIndex(atIndex, subs);
+                return (VecD)subs.Points[localIndex].Position;
+            });
         }
         else
         {
@@ -473,16 +480,21 @@ public class VectorPathOverlay : Overlay
     {
         int index = anchorHandles.IndexOf(anchorHandle);
 
+        return ConvertTouchingVerbsToCubic(index);
+    }
+
+    private EditableVectorPath ConvertTouchingVerbsToCubic(int index)
+    {
         SubShape subShapeContainingIndex = editableVectorPath.GetSubShapeContainingIndex(index);
 
         int localIndex = editableVectorPath.GetSubShapePointIndex(index, subShapeContainingIndex);
 
         var previousPoint = subShapeContainingIndex.GetPreviousPoint(localIndex);
-        var nextPoint = subShapeContainingIndex.Points[localIndex];
+        var point = subShapeContainingIndex.Points[localIndex];
 
         previousPoint?.ConvertVerbToCubic();
 
-        nextPoint.ConvertVerbToCubic();
+        point.ConvertVerbToCubic();
 
         return editableVectorPath;
     }
@@ -524,13 +536,15 @@ public class VectorPathOverlay : Overlay
         VecD symmetricPos = targetPos;
         bool canMirror = true;
 
+        var thisPoint = subShapeContainingIndex.Points[localIndex];
+
         if (constrainRatio)
         {
-            symmetricPos = GetMirroredControlPoint((VecF)targetPos, (VecF)handle.Position);
+            symmetricPos = GetMirroredControlPoint((VecF)targetPos, thisPoint.Position);
         }
         else
         {
-            VecD direction = targetPos - handle.Position;
+            VecD direction = targetPos - (VecD)thisPoint.Position;
             direction = direction.Normalize();
             var controlPos = ((VecD?)previousPoint?.Verb.ControlPoint2 ?? targetPos);
             if (swapOrder)
@@ -538,10 +552,10 @@ public class VectorPathOverlay : Overlay
                 controlPos = ((VecD?)subShapeContainingIndex.Points[localIndex]?.Verb.ControlPoint1 ?? targetPos);
             }
 
-            double length = VecD.Distance(handle.Position, controlPos);
+            double length = VecD.Distance((VecD)thisPoint.Position, controlPos);
             if (!direction.IsNaNOrInfinity())
             {
-                symmetricPos = handle.Position - direction * length;
+                symmetricPos = (VecD)thisPoint.Position - direction * length;
             }
             else
             {