Add test for quadratic Wang's formula
Just verify that the max error on any of the intervals after splitting is less than the specified tolerance. Looks like we're running into some FP precision issues with large coord values, so I'm limiting the max multiplier to 2^15 in this test. Bug: skia:10419 Change-Id: I39e76dca5f77389833ba3c94930e6b67c2b1bc97 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/340116 Reviewed-by: Chris Dalton <csmartdalton@google.com> Commit-Queue: Tyler Denniston <tdenniston@google.com>
This commit is contained in:
parent
3c161467f0
commit
4be95c541c
@ -55,10 +55,11 @@ static void for_random_matrices(SkRandom* rand, std::function<void(const SkMatri
|
||||
}
|
||||
|
||||
static void for_random_beziers(int numPoints, SkRandom* rand,
|
||||
std::function<void(const SkPoint[])> f) {
|
||||
std::function<void(const SkPoint[])> f,
|
||||
int maxExponent = 30) {
|
||||
SkASSERT(numPoints <= 4);
|
||||
SkPoint pts[4];
|
||||
for (int i = -10; i <= 30; ++i) {
|
||||
for (int i = -10; i <= maxExponent; ++i) {
|
||||
for (int j = 0; j < numPoints; ++j) {
|
||||
pts[j].set(std::ldexp(1 + rand->nextF(), i), std::ldexp(1 + rand->nextF(), i));
|
||||
}
|
||||
@ -295,3 +296,54 @@ DEF_TEST(WangsFormula_worst_case_cubic, r) {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure Wang's formula for quads produces max error within tolerance.
|
||||
DEF_TEST(WangsFormula_quad_within_tol, r) {
|
||||
// Wang's formula and the quad math starts to lose precision with very large
|
||||
// coordinate values, so limit the magnitude a bit to prevent test failures
|
||||
// due to loss of precision.
|
||||
constexpr int maxExponent = 15;
|
||||
SkRandom rand;
|
||||
for_random_beziers(3, &rand, [&r](const SkPoint pts[]) {
|
||||
const int nsegs = static_cast<int>(
|
||||
std::ceil(wangs_formula_quadratic_reference_impl(kIntolerance, pts)));
|
||||
|
||||
const float tdelta = 1.f / nsegs;
|
||||
for (int j = 0; j < nsegs; ++j) {
|
||||
const float tmin = j * tdelta, tmax = (j + 1) * tdelta;
|
||||
|
||||
// Get section of quad in [tmin,tmax]
|
||||
const SkPoint* sectionPts;
|
||||
SkPoint tmp0[5];
|
||||
SkPoint tmp1[5];
|
||||
if (tmin == 0) {
|
||||
if (tmax == 1) {
|
||||
sectionPts = pts;
|
||||
} else {
|
||||
SkChopQuadAt(pts, tmp0, tmax);
|
||||
sectionPts = tmp0;
|
||||
}
|
||||
} else {
|
||||
SkChopQuadAt(pts, tmp0, tmin);
|
||||
if (tmax == 1) {
|
||||
sectionPts = tmp0 + 2;
|
||||
} else {
|
||||
SkChopQuadAt(tmp0 + 2, tmp1, (tmax - tmin) / (1 - tmin));
|
||||
sectionPts = tmp1;
|
||||
}
|
||||
}
|
||||
|
||||
// For quads, max distance from baseline is always at t=0.5.
|
||||
SkPoint p;
|
||||
p = SkEvalQuadAt(sectionPts, 0.5f);
|
||||
|
||||
// Get distance of p to baseline
|
||||
const SkPoint n = {sectionPts[2].fY - sectionPts[0].fY,
|
||||
sectionPts[0].fX - sectionPts[2].fX};
|
||||
const float d = std::abs((p - sectionPts[0]).dot(n)) / n.length();
|
||||
|
||||
// Check distance is within specified tolerance
|
||||
REPORTER_ASSERT(r, d <= (1.f / kIntolerance) + SK_ScalarNearlyZero);
|
||||
}
|
||||
}, maxExponent);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user