@@ -96,47 +96,40 @@ static bool IsBetween(double a, double b, double c, double d)
96
96
return true ;
97
97
}
98
98
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
+
99
113
/// <summary>
100
114
/// Gets a value indicating whether all of the control points are on the same line.
101
115
/// </summary>
102
116
bool IsColinear
103
117
{
104
118
get
105
119
{
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 ) ;
135
123
}
136
124
}
137
125
138
126
/// <inheritdoc/>
139
127
// (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.
140
133
protected override Vector2 Simplify ( )
141
134
{
142
135
var oneMinusT = 1 - _t ;
0 commit comments