17#include <initializer_list>
40 "Invalid test case. Should have 4 input points.");
42 "Invalid test case. t %f should be in [0, 1]", t);
47 "X wrong %1.16f != %1.16f", expectedXY.
x,
x);
49 "Y wrong %1.16f != %1.16f", expectedXY.
y,
y);
54 {{ 0, 0 }, { 0, 0 }, { 10, 10 }, { 10, 10 }},
56 { 0.4192451819200000, 0.4192451819200000 });
59 {{ 0, 0 }, { 5, 5 }, { 5, 5 }, { 10, 10 }},
61 { 2.8215983862500000, 2.8215983862500000 });
64 {{ -10, -20 }, { -7, 5 }, { 14, -2 }, { 3, 13 }},
69 {{ -10, -20 }, { -7, 5 }, { 14, -2 }, { 3, 13 }},
71 { -2.503786700800000, -3.31715344793600 });
74 {{ -10, -20 }, { -7, 5 }, { 14, -2 }, { 3, 13 }},
79 {{ -10, -20 }, { -7, 5 }, { 14, -2 }, { 3, 13 }},
81 { 6.158763291450000, 5.938550084434000 });
84 {{ -10, -20 }, { -7, 5 }, { 14, -2 }, { 3, 13 }},
91 double expectedA,
double expectedB,
92 double expectedC,
double expectedD) {
95 "Invalid test case. Need 4 points (start, control, control, end)");
98 const double* input = &curveInputs[0].x;
110 {{1, 2}, {-3, 4}, {5, -6}, {7, 8}},
false,
114 {{1, 2}, {-3, 4}, {5, -6}, {7, 8}},
true,
123 const double interestingRoots[] =
124 {-1000, -10, -1, -0.1, -0.0001, 0, 0.0001, 0.1, 0.9, 0.9999, 1, 1.0001, 1.1, 10, 1000};
127 const double interestingScales[] =
128 {-1000, -10, -1, -0.1, -0.0001, 0.0001, 0.1, 1, 10, 1000};
130 auto outsideTRange = [](
double r) {
131 return r < 0 || 1 < r;
134 auto insideTRange = [&] (
double r) {
135 return !outsideTRange(r);
140 auto equalAsFloat = [] (
double a,
double b) {
146 for (
double r1 : interestingRoots) {
147 for (
double r0 : interestingRoots) {
148 for (
double s : interestingScales) {
153 const double B =
s * 0.5 * (r0 + r1);
154 const double C =
s*r0*r1;
161 if (intersections.empty()) {
165 || (outsideTRange(r0) && outsideTRange(r1)));
166 }
else if (intersections.size() == 1) {
169 const double insideRoot = insideTRange(r0) ? r0 : r1;
174 auto [smaller, bigger] = std::minmax(intersections[0], intersections[1]);
175 auto [smallerRoot, biggerRoot] = std::minmax(r0, r1);
203 const double interestingRoots[] =
204 {-10, -5, -2, -1, 0, 0.5, 1, 2, 5, 10};
207 const double interestingScales[] =
208 {-1000, -10, -1, -0.1, -0.0001, 0.0001, 0.1, 1, 10, 1000};
210 auto outsideTRange = [](
double r) {
211 return r < 0 || 1 < r;
214 auto insideTRange = [&] (
double r) {
215 return !outsideTRange(r);
218 auto specialEqual = [] (
double actual,
double test) {
220 const double errorFactor = std::numeric_limits<float>::epsilon();
224 for (
double r2 : interestingRoots) {
225 for (
double r1 : interestingRoots) {
226 for (
double r0 : interestingRoots) {
227 for (
double s : interestingScales) {
232 C =
s * (r0*r1 + r1*r2 + r0*r2),
233 D = -
s * r0 * r1 * r2;
236 std::set<double> inRangeRoots;
237 for (
auto r : {r0, r1, r2}) {
238 if (insideTRange(r)) {
239 inRangeRoots.insert(r);
251 for (
auto candidate : intersections) {
252 for (
auto answer : inRangeRoots) {
253 if (specialEqual(candidate, answer)) {
static void testCubicConvertToPolynomial(skiatest::Reporter *reporter, const std::string &name, SkSpan< const DoublePoint > curveInputs, bool yValues, double expectedA, double expectedB, double expectedC, double expectedD)
DEF_TEST(BezierCubicEvalAt, reporter)
static void testCubicEvalAtT(skiatest::Reporter *reporter, const std::string &name, SkSpan< const DoublePoint > curveInputs, double t, const DoublePoint &expectedXY)
static bool nearly_equal(double expected, double actual)
bool sk_double_nearly_zero(double a)
static constexpr float sk_double_to_float(double x)
bool sk_doubles_nearly_equal_ulps(double a, double b, uint8_t maxUlpsDiff=16)
#define REPORTER_ASSERT(r, cond,...)
static std::array< double, 4 > ConvertToPolynomial(const double curve[8], bool yValues)
static std::array< double, 2 > EvalAt(const double curve[8], double t)
static SkSpan< const float > Intersect(double AX, double BX, double CX, double DX, double AY, double BY, double CY, double DY, float toIntersect, float intersectionsStorage[3])
static SkSpan< const float > Intersect(double AX, double BX, double CX, double AY, double BY, double CY, double yIntercept, float intersectionStorage[2])
static double Discriminant(double A, double B, double C)
constexpr T * data() const
constexpr size_t size() const
static float max(float r, float g, float b)
DEF_SWITCHES_START aot vmservice shared library name
SIN Vec< N, float > abs(const Vec< N, float > &x)