@@ -96,47 +96,40 @@ static bool IsBetween(double a, double b, double c, double d)
9696 return true ;
9797 }
9898
99+ static float CrossProduct ( SnVector2 v1 , SnVector2 v2 )
100+ {
101+ return ( v1 . X * v2 . Y ) - ( v1 . Y * v2 . X ) ;
102+ }
103+
104+ // Checks if two vectors are colinear.
105+ static bool AlmostColinear ( SnVector2 v1 , SnVector2 v2 )
106+ {
107+ // Epsilon is chosen so that vectors that are very close to being
108+ // colinear are also considered as colinear, since sometimes After Effects
109+ // outputs bezier curves with small precision, which may result in slight deviation.
110+ return Math . Abs ( CrossProduct ( v1 , v2 ) / ( 1 + v1 . Length ( ) + v2 . Length ( ) ) ) < 1e-2 ;
111+ }
112+
99113 /// <summary>
100114 /// Gets a value indicating whether all of the control points are on the same line.
101115 /// </summary>
102116 bool IsColinear
103117 {
104118 get
105119 {
106- var p01X = _p0 . X - _p1 . X ;
107- var p01Y = _p0 . Y - _p1 . Y ;
108-
109- var p02X = _p0 . X - _p2 . X ;
110- var p02Y = _p0 . Y - _p2 . Y ;
111-
112- var p03X = _p0 . X - _p3 . X ;
113- var p03Y = _p0 . Y - _p3 . Y ;
114-
115- if ( p01Y == 0 || p02Y == 0 || p03Y == 0 )
116- {
117- // Can't divide by Y because it's 0 in at least one case. (i.e. horizontal line)
118- if ( p01X == 0 || p02X == 0 || p03X == 0 )
119- {
120- // Can't divide by X because it's 0 in at least one case (i.e. vertical line)
121- // The points can only be colinear if they're all equal.
122- return p01X == p02X && p02X == p03X && p03X == p01X ;
123- }
124- else
125- {
126- return ( p01Y / p01X ) == ( p02Y / p02X ) &&
127- ( p01Y / p01X ) == ( p03Y / p03X ) ;
128- }
129- }
130- else
131- {
132- return ( p01X / p01Y ) == ( p02X / p02Y ) &&
133- ( p01X / p01Y ) == ( p03X / p03Y ) ;
134- }
120+ // In order for 4 points to be colinear, any two pairs of directions
121+ // between them should be colinear.
122+ return AlmostColinear ( _p1 - _p0 , _p3 - _p0 ) && AlmostColinear ( _p2 - _p3 , _p0 - _p3 ) ;
135123 }
136124 }
137125
138126 /// <inheritdoc/>
139127 // (1-t)^3P0 + 3(1-t)^2tP1 + 3(1-t)t^2P2 + t^3P3
128+ //
129+ // TODO: This also needs some kind of "arc-length parametrization" (https://pomax.github.io/bezierinfo/#tracing)
130+ // because currently point does not move along the curve with a uniform speed.
131+ // This is probably impossible to achieve because translation approach limits us to Windown Composition API
132+ // which does not support this feature, and probably won't, because it is very expensive to compute.
140133 protected override Vector2 Simplify ( )
141134 {
142135 var oneMinusT = 1 - _t ;
0 commit comments