コード例 #1
0
static void oneOffTest() {
    for (size_t outer = 0; outer < testSetCount - 1; ++outer) {
        for (size_t inner = outer + 1; inner < testSetCount; ++inner) {
            const Quadratic& quad1 = testSet[outer];
            const Quadratic& quad2 = testSet[inner];
            double tt1, tt2;
            Intersections intersections2;
            intersect2(quad1, quad2, intersections2);
            for (int pt = 0; pt < intersections2.used(); ++pt) {
                tt1 = intersections2.fT[0][pt];
                double tx1, ty1;
                xy_at_t(quad1, tt1, tx1, ty1);
                int pt2 = intersections2.fFlip ? intersections2.used() - pt - 1 : pt;
                tt2 = intersections2.fT[1][pt2];
                double tx2, ty2;
                xy_at_t(quad2, tt2, tx2, ty2);
                if (!approximately_equal(tx1, tx2)) {
                    SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
                        __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
                    SkASSERT(0);
                }
                if (!approximately_equal(ty1, ty2)) {
                    SkDebugf("%s [%d,%d] y!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
                        __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
                    SkASSERT(0);
                }
                SkDebugf("%s [%d][%d] t1=%1.9g (%1.9g, %1.9g) t2=%1.9g\n", __FUNCTION__,
                    outer, inner, tt1, tx1, tx2, tt2);
            }
        }
    }
}
コード例 #2
0
ファイル: SkPathOpsCubic.cpp プロジェクト: aseprite/skia
// from SkGeometry.cpp (and Numeric Solutions, 5.6)
int SkDCubic::RootsValidT(double A, double B, double C, double D, double t[3]) {
    double s[3];
    int realRoots = RootsReal(A, B, C, D, s);
    int foundRoots = SkDQuad::AddValidTs(s, realRoots, t);
    for (int index = 0; index < realRoots; ++index) {
        double tValue = s[index];
        if (!approximately_one_or_less(tValue) && between(1, tValue, 1.00005)) {
            for (int idx2 = 0; idx2 < foundRoots; ++idx2) {
                if (approximately_equal(t[idx2], 1)) {
                    goto nextRoot;
                }
            }
            SkASSERT(foundRoots < 3);
            t[foundRoots++] = 1;
        } else if (!approximately_zero_or_more(tValue) && between(-0.00005, tValue, 0)) {
            for (int idx2 = 0; idx2 < foundRoots; ++idx2) {
                if (approximately_equal(t[idx2], 0)) {
                    goto nextRoot;
                }
            }
            SkASSERT(foundRoots < 3);
            t[foundRoots++] = 0;
        }
nextRoot:
        ;
    }
    return foundRoots;
}
コード例 #3
0
// check to see if it is a quadratic or a line
static int check_quadratic(const SkDCubic& cubic, SkDCubic& reduction) {
    double dx10 = cubic[1].fX - cubic[0].fX;
    double dx23 = cubic[2].fX - cubic[3].fX;
    double midX = cubic[0].fX + dx10 * 3 / 2;
    double sideAx = midX - cubic[3].fX;
    double sideBx = dx23 * 3 / 2;
    if (approximately_zero(sideAx) ? !approximately_equal(sideAx, sideBx)
            : !AlmostEqualUlps(sideAx, sideBx)) {
        return 0;
    }
    double dy10 = cubic[1].fY - cubic[0].fY;
    double dy23 = cubic[2].fY - cubic[3].fY;
    double midY = cubic[0].fY + dy10 * 3 / 2;
    double sideAy = midY - cubic[3].fY;
    double sideBy = dy23 * 3 / 2;
    if (approximately_zero(sideAy) ? !approximately_equal(sideAy, sideBy)
            : !AlmostEqualUlps(sideAy, sideBy)) {
        return 0;
    }
    reduction[0] = cubic[0];
    reduction[1].fX = midX;
    reduction[1].fY = midY;
    reduction[2] = cubic[3];
    return 3;
}
コード例 #4
0
ファイル: QuarticRoot_Test.cpp プロジェクト: bunhere/skia
static void quadraticTest() {
    // (x - a)(x - b) == x^2 - (a + b)x + ab
    for (size_t aIndex = 0; aIndex < mulACount; ++aIndex) {
        for (size_t bIndex = 0; bIndex < rootBCount; ++bIndex) {
            for (size_t cIndex = 0; cIndex < rootCCount; ++cIndex) {
                const double A = mulA[aIndex];
                const double B = rootB[bIndex];
                const double C = rootC[cIndex];
                const double b = A * (B + C);
                const double c = A * B * C;
                double roots[2];
                const int rootCount = QuarticRootTest::quadraticRootsX(A, b, c, roots);
                const int expected = 1 + (B != C);
                assert(rootCount == expected);
                assert(approximately_equal(roots[0], -B)
                        || approximately_equal(roots[0], -C));
                if (B != C) {
                    assert(!approximately_equal(roots[0], roots[1]));
                    assert(approximately_equal(roots[1], -B)
                            || approximately_equal(roots[1], -C));
                }
            }
        }
    }
}
コード例 #5
0
ファイル: matrix4x4_tests.cpp プロジェクト: hershal/hrt
void check_identity(float m[4][4]) {
    for (int i=0; i<4; ++i) {
        for (int j=0; j<4; ++j) {
            if (i==j) {
                BOOST_REQUIRE(approximately_equal(m[i][j], 1.f));
            } else {
                BOOST_REQUIRE(approximately_equal(m[i][j], 0.f));
            }
        }
    }
}
コード例 #6
0
static void coincidentTest() {
    for (size_t testIndex = 0; testIndex < coincidentTestSetCount - 1; testIndex += 2) {
        const Quadratic& quad1 = coincidentTestSet[testIndex];
        const Quadratic& quad2 = coincidentTestSet[testIndex + 1];
        Intersections intersections2;
        intersect2(quad1, quad2, intersections2);
        SkASSERT(intersections2.coincidentUsed() == 2);
        for (int pt = 0; pt < intersections2.coincidentUsed(); ++pt) {
            double tt1 = intersections2.fT[0][pt];
            double tt2 = intersections2.fT[1][pt];
            SkASSERT(approximately_equal(1, tt1) || approximately_zero(tt1));
            SkASSERT(approximately_equal(1, tt2) || approximately_zero(tt2));
        }
    }
}
コード例 #7
0
ファイル: CubicIntersection_Test.cpp プロジェクト: Cue/skia
// FIXME: this test no longer valid -- does not take minimum scale contribution into account
void CubicIntersection_ComputeDeltaTest() {
    SkASSERT(deltaTestSetLen == deltaTestSetTLen);
    SkASSERT(expectedTLen == deltaTestSetTLen);
    for (size_t index = 0; index < deltaTestSetLen; index += 2) {
        const Cubic& c1 = deltaTestSet[index];
        const Cubic& c2 = deltaTestSet[index + 1];
        double t1 = deltaTestSetT[index];
        double t2 = deltaTestSetT[index + 1];
        double d1, d2;
        computeDelta(c1, t1, 1, c2, t2, 1, d1, d2);
        SkASSERT(approximately_equal(t1 + d1, expectedT[index])
            || approximately_equal(t1 - d1, expectedT[index]));
        SkASSERT(approximately_equal(t2 + d2, expectedT[index + 1])
            || approximately_equal(t2 - d2, expectedT[index + 1]));
    }
}
コード例 #8
0
static void selfOneOff(skiatest::Reporter* reporter, int index) {
    const SkDCubic& cubic = selfSet[index];
#if ONE_OFF_DEBUG
    int idx2;
    double max[3];
    int ts = cubic.findMaxCurvature(max);
    for (idx2 = 0; idx2 < ts; ++idx2) {
        SkDebugf("%s max[%d]=%1.9g (%1.9g, %1.9g)\n", __FUNCTION__, idx2,
                max[idx2], cubic.ptAtT(max[idx2]).fX, cubic.ptAtT(max[idx2]).fY);
    }
    SkTArray<double, true> ts1;
    SkTArray<SkDQuad, true> quads1;
    cubic.toQuadraticTs(cubic.calcPrecision(), &ts1);
    for (idx2 = 0; idx2 < ts1.count(); ++idx2) {
        SkDebugf("%s t[%d]=%1.9g\n", __FUNCTION__, idx2, ts1[idx2]);
    }
    CubicToQuads(cubic, cubic.calcPrecision(), quads1);
    for (idx2 = 0; idx2 < quads1.count(); ++idx2) {
        const SkDQuad& q = quads1[idx2];
        SkDebugf("  {{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}},\n",
                q[0].fX, q[0].fY,  q[1].fX, q[1].fY,  q[2].fX, q[2].fY);
    }
    SkDebugf("\n");
#endif
    SkIntersections i;
    int result = i.intersect(cubic);
    REPORTER_ASSERT(reporter, result == 1);
    REPORTER_ASSERT(reporter, i.used() == 1);
    REPORTER_ASSERT(reporter, !approximately_equal(i[0][0], i[1][0]));
    SkDPoint pt1 = cubic.ptAtT(i[0][0]);
    SkDPoint pt2 = cubic.ptAtT(i[1][0]);
    REPORTER_ASSERT(reporter, pt1.approximatelyEqual(pt2));
    reporter->bumpTestCount();
}
コード例 #9
0
static bool orderTRange(skiatest::Reporter* reporter, const SkDQuad& quad1, const SkDQuad& quad2,
        double r, TRange* result) {
    SkTArray<double, false> t1Array, t2Array;
    orderQuads(reporter, quad1, r, &t1Array);
    orderQuads(reporter,quad2, r, &t2Array);
    if (!t1Array.count() || !t2Array.count()) {
        return false;
    }
    SkTQSort<double>(t1Array.begin(), t1Array.end() - 1);
    SkTQSort<double>(t2Array.begin(), t2Array.end() - 1);
    double t1 = result->tMin1 = t1Array[0];
    double t2 = result->tMin2 = t2Array[0];
    double a1 = quadAngle(reporter,quad1, t1);
    double a2 = quadAngle(reporter,quad2, t2);
    if (approximately_equal(a1, a2)) {
        return false;
    }
    bool refCCW = angleDirection(a1, a2);
    result->t1 = t1;
    result->t2 = t2;
    result->tMin = SkTMin(t1, t2);
    result->a1 = a1;
    result->a2 = a2;
    result->ccw = refCCW;
    return true;
}
コード例 #10
0
ファイル: LineUtilities.cpp プロジェクト: jiezh/h5vcc
void x_at(const _Point& p1, const _Point& p2, double top, double bottom,
        int flags, double& minX, double& maxX) {
    if (approximately_equal(p1.y, p2.y)) {
        // It should be OK to bail early in this case. There's another edge
        // which shares this end point which can intersect without failing to
        // have a slope ... maybe
        return;
    }

    // p2.x is always greater than p1.x -- the part of points (p1, p2) are
    // moving from the start of the cubic towards its end.
    // if p1.y < p2.y, minX can be affected
    // if p1.y > p2.y, maxX can be affected
    double slope = (p2.x - p1.x) / (p2.y - p1.y);
    int topFlags = flags & (kFindTopMin | kFindTopMax);
    if (topFlags && ((top <= p1.y && top >= p2.y)
            || (top >= p1.y && top <= p2.y))) {
        double x = p1.x + (top - p1.y) * slope;
        setMinMax(x, topFlags, minX, maxX);
    }
    int bottomFlags = flags & (kFindBottomMin | kFindBottomMax);
    if (bottomFlags && ((bottom <= p1.y && bottom >= p2.y)
            || (bottom >= p1.y && bottom <= p2.y))) {
        double x = p1.x + (bottom - p1.y) * slope;
        setMinMax(x, bottomFlags, minX, maxX);
    }
}
コード例 #11
0
static void PathOpsDVectorTest(skiatest::Reporter* reporter) {
    for (size_t index = 0; index < tests_count - 1; ++index) {
        SkDVector v1 = tests[index + 1] - tests[index];
        SkDVector v2 = tests[index] - tests[index + 1];
        v1 += v2;
        REPORTER_ASSERT(reporter, v1.fX == 0 && v1.fY == 0);
        SkDPoint p = tests[index + 1] + v2;
        REPORTER_ASSERT(reporter, p == tests[index]);
        v2 -= v2;
        REPORTER_ASSERT(reporter, v2.fX == 0 && v2.fY == 0);
        v1 = tests[index + 1] - tests[index];
        v1 /= 2;
        v1 *= 2;
        v1 -= tests[index + 1] - tests[index];
        REPORTER_ASSERT(reporter, v1.fX == 0 && v1.fY == 0);
        SkVector sv = v1.asSkVector();
        REPORTER_ASSERT(reporter, sv.fX == 0 && sv.fY == 0);
        v1 = tests[index + 1] - tests[index];
        double lenSq = v1.lengthSquared();
        double v1Dot = v1.dot(v1);
        REPORTER_ASSERT(reporter, lenSq == v1Dot);
        REPORTER_ASSERT(reporter, approximately_equal(sqrt(lenSq), v1.length()));
        double v1Cross = v1.cross(v1);
        REPORTER_ASSERT(reporter, v1Cross == 0);
    }
}
コード例 #12
0
ファイル: matrix4x4_tests.cpp プロジェクト: hershal/hrt
/* check if \m is approximately equal to \r */
void check_matrix(float m[4][4], float r[4][4]) {
    for (int i=0; i<4; ++i) {
        for (int j=0; j<4; ++j) {
            BOOST_REQUIRE(approximately_equal(m[i][j], r[i][j]));
        }
    }
}
コード例 #13
0
ファイル: matrix4x4_tests.cpp プロジェクト: hershal/hrt
void check_zero(float m[4][4]) {
    for (int i=0; i<4; ++i) {
        for (int j=0; j<4; ++j) {
            BOOST_REQUIRE(approximately_equal(m[i][j], 0.f));
        }
    }
}
コード例 #14
0
ファイル: PathOpsDPointTest.cpp プロジェクト: ROM-PacMe/skia
DEF_TEST(PathOpsDPoint, reporter) {
    for (size_t index = 0; index < tests_count; ++index) {
        const SkDPoint& pt = tests[index];
        SkASSERT(ValidPoint(pt));
        SkDPoint p = pt;
        REPORTER_ASSERT(reporter, p == pt);
        REPORTER_ASSERT(reporter, !(pt != pt));
        SkDVector v = p - pt;
        p += v;
        REPORTER_ASSERT(reporter, p == pt);
        p -= v;
        REPORTER_ASSERT(reporter, p == pt);
        REPORTER_ASSERT(reporter, p.approximatelyEqual(pt));
        SkPoint sPt = pt.asSkPoint();
        p.set(sPt);
        REPORTER_ASSERT(reporter, p == pt);
        REPORTER_ASSERT(reporter, p.approximatelyEqual(sPt));
        REPORTER_ASSERT(reporter, p.roughlyEqual(pt));
        p.fX = p.fY = 0;
        REPORTER_ASSERT(reporter, p.fX == 0 && p.fY == 0);
        REPORTER_ASSERT(reporter, p.approximatelyZero());
        REPORTER_ASSERT(reporter, pt.distanceSquared(p) == pt.fX * pt.fX + pt.fY * pt.fY);
        REPORTER_ASSERT(reporter, approximately_equal(pt.distance(p),
                        sqrt(pt.fX * pt.fX + pt.fY * pt.fY)));
    }
}
コード例 #15
0
static void orderQuads(skiatest::Reporter* reporter, const SkDQuad& quad, double radius,
        SkTArray<double, false>* tArray) {
    double r = radius;
    double s = r * SK_ScalarTanPIOver8;
    double m = r * SK_ScalarRoot2Over2;
    // construct circle from quads
    const SkDQuad circle[8] = {{{{ r,  0}, { r, -s}, { m, -m}}},
                                {{{ m, -m}, { s, -r}, { 0, -r}}},
                                {{{ 0, -r}, {-s, -r}, {-m, -m}}},
                                {{{-m, -m}, {-r, -s}, {-r,  0}}},
                                {{{-r,  0}, {-r,  s}, {-m,  m}}},
                                {{{-m,  m}, {-s,  r}, { 0,  r}}},
                                {{{ 0,  r}, { s,  r}, { m,  m}}},
                                {{{ m,  m}, { r,  s}, { r,  0}}}};
    for (int octant = 0; octant < 8; ++octant) {
        double t = testArc(reporter, quad, circle[octant], octant);
        if (t < 0) {
            continue;
        }
        for (int index = 0; index < tArray->count(); ++index) {
            double matchT = (*tArray)[index];
            if (approximately_equal(t, matchT)) {
                goto next;
            }
        }
        tArray->push_back(t);
next:   ;
    }
}
コード例 #16
0
ファイル: CubicReduceOrder.cpp プロジェクト: bunhere/skia
// reduce to a quadratic or smaller
// look for identical points
// look for all four points in a line
    // note that three points in a line doesn't simplify a cubic
// look for approximation with single quadratic
    // save approximation with multiple quadratics for later
int reduceOrder(const Cubic& cubic, Cubic& reduction, ReduceOrder_Flags allowQuadratics) {
    int index, minX, maxX, minY, maxY;
    int minXSet, minYSet;
    minX = maxX = minY = maxY = 0;
    minXSet = minYSet = 0;
    for (index = 1; index < 4; ++index) {
        if (cubic[minX].x > cubic[index].x) {
            minX = index;
        }
        if (cubic[minY].y > cubic[index].y) {
            minY = index;
        }
        if (cubic[maxX].x < cubic[index].x) {
            maxX = index;
        }
        if (cubic[maxY].y < cubic[index].y) {
            maxY = index;
        }
    }
    for (index = 0; index < 4; ++index) {
        if (approximately_equal(cubic[index].x, cubic[minX].x)) {
            minXSet |= 1 << index;
        }
        if (approximately_equal(cubic[index].y, cubic[minY].y)) {
            minYSet |= 1 << index;
        }
    }
    if (minXSet == 0xF) { // test for vertical line
        if (minYSet == 0xF) { // return 1 if all four are coincident
            return coincident_line(cubic, reduction);
        }
        return vertical_line(cubic, reduction);
    }
    if (minYSet == 0xF) { // test for horizontal line
        return horizontal_line(cubic, reduction);
    }
    int result = check_linear(cubic, reduction, minX, maxX, minY, maxY);
    if (result) {
        return result;
    }
    if (allowQuadratics && (result = check_quadratic(cubic, reduction))) {
        return result;
    }
    memcpy(reduction, cubic, sizeof(Cubic));
    return 4;
}
コード例 #17
0
static void standardTestCases() {
    for (size_t index = firstQuadIntersectionTest; index < quadraticTests_count; ++index) {
        const Quadratic& quad1 = quadraticTests[index][0];
        const Quadratic& quad2 = quadraticTests[index][1];
        Quadratic reduce1, reduce2;
        int order1 = reduceOrder(quad1, reduce1);
        int order2 = reduceOrder(quad2, reduce2);
        if (order1 < 3) {
            printf("[%d] quad1 order=%d\n", (int) index, order1);
        }
        if (order2 < 3) {
            printf("[%d] quad2 order=%d\n", (int) index, order2);
        }
        if (order1 == 3 && order2 == 3) {
            Intersections intersections, intersections2;
            intersect(reduce1, reduce2, intersections);
            intersect2(reduce1, reduce2, intersections2);
            SkASSERT(intersections.used() == intersections2.used());
            if (intersections.intersected()) {
                for (int pt = 0; pt < intersections.used(); ++pt) {
                    double tt1 = intersections.fT[0][pt];
                    double tx1, ty1;
                    xy_at_t(quad1, tt1, tx1, ty1);
                    double tt2 = intersections.fT[1][pt];
                    double tx2, ty2;
                    xy_at_t(quad2, tt2, tx2, ty2);
                    if (!approximately_equal(tx1, tx2)) {
                        printf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
                            __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
                    }
                    if (!approximately_equal(ty1, ty2)) {
                        printf("%s [%d,%d] y!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
                            __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
                    }
                    tt1 = intersections2.fT[0][pt];
                    SkASSERT(approximately_equal(intersections.fT[0][pt], tt1));
                    tt2 = intersections2.fT[1][pt];
                    SkASSERT(approximately_equal(intersections.fT[1][pt], tt2));
                }
            }
        }
    }
}
コード例 #18
0
ファイル: CubicReduceOrder.cpp プロジェクト: bunhere/skia
// check to see if it is a quadratic or a line
static int check_quadratic(const Cubic& cubic, Cubic& reduction) {
    double dx10 = cubic[1].x - cubic[0].x;
    double dx23 = cubic[2].x - cubic[3].x;
    double midX = cubic[0].x + dx10 * 3 / 2;
    if (!approximately_equal(midX - cubic[3].x, dx23 * 3 / 2)) {
        return 0;
    }
    double dy10 = cubic[1].y - cubic[0].y;
    double dy23 = cubic[2].y - cubic[3].y;
    double midY = cubic[0].y + dy10 * 3 / 2;
    if (!approximately_equal(midY - cubic[3].y, dy23 * 3 / 2)) {
        return 0;
    }
    reduction[0] = cubic[0];
    reduction[1].x = midX;
    reduction[1].y = midY;
    reduction[2] = cubic[3];
    return 3;
}
コード例 #19
0
ファイル: QuadraticReduceOrder.cpp プロジェクト: bunhere/skia
// reduce to a quadratic or smaller
// look for identical points
// look for all four points in a line
    // note that three points in a line doesn't simplify a cubic
// look for approximation with single quadratic
    // save approximation with multiple quadratics for later
int reduceOrder(const Quadratic& quad, Quadratic& reduction) {
    int index, minX, maxX, minY, maxY;
    int minXSet, minYSet;
    minX = maxX = minY = maxY = 0;
    minXSet = minYSet = 0;
    for (index = 1; index < 3; ++index) {
        if (quad[minX].x > quad[index].x) {
            minX = index;
        }
        if (quad[minY].y > quad[index].y) {
            minY = index;
        }
        if (quad[maxX].x < quad[index].x) {
            maxX = index;
        }
        if (quad[maxY].y < quad[index].y) {
            maxY = index;
        }
    }
    for (index = 0; index < 3; ++index) {
        if (approximately_equal(quad[index].x, quad[minX].x)) {
            minXSet |= 1 << index;
        }
        if (approximately_equal(quad[index].y, quad[minY].y)) {
            minYSet |= 1 << index;
        }
    }
    if (minXSet == 0x7) { // test for vertical line
        if (minYSet == 0x7) { // return 1 if all four are coincident
            return coincident_line(quad, reduction);
        }
        return vertical_line(quad, reduction);
    }
    if (minYSet == 0xF) { // test for horizontal line
        return horizontal_line(quad, reduction);
    }
    int result = check_linear(quad, reduction, minX, maxX, minY, maxY);
    if (result) {
        return result;
    }
    memcpy(reduction, quad, sizeof(Quadratic));
    return 3;
}
コード例 #20
0
int SkReducedQuarticRoots(const double t4, const double t3, const double t2, const double t1,
        const double t0, const bool oneHint, double roots[4]) {
#ifdef SK_DEBUG
    // create a string mathematica understands
    // GDB set print repe 15 # if repeated digits is a bother
    //     set print elements 400 # if line doesn't fit
    char str[1024];
    sk_bzero(str, sizeof(str));
    SK_SNPRINTF(str, sizeof(str),
            "Solve[%1.19g x^4 + %1.19g x^3 + %1.19g x^2 + %1.19g x + %1.19g == 0, x]",
            t4, t3, t2, t1, t0);
    SkPathOpsDebug::MathematicaIze(str, sizeof(str));
#if ONE_OFF_DEBUG && ONE_OFF_DEBUG_MATHEMATICA
    SkDebugf("%s\n", str);
#endif
#endif
    if (approximately_zero_when_compared_to(t4, t0)  // 0 is one root
            && approximately_zero_when_compared_to(t4, t1)
            && approximately_zero_when_compared_to(t4, t2)) {
        if (approximately_zero_when_compared_to(t3, t0)
            && approximately_zero_when_compared_to(t3, t1)
            && approximately_zero_when_compared_to(t3, t2)) {
            return SkDQuad::RootsReal(t2, t1, t0, roots);
        }
        if (approximately_zero_when_compared_to(t4, t3)) {
            return SkDCubic::RootsReal(t3, t2, t1, t0, roots);
        }
    }
    if ((approximately_zero_when_compared_to(t0, t1) || approximately_zero(t1))  // 0 is one root
      //      && approximately_zero_when_compared_to(t0, t2)
            && approximately_zero_when_compared_to(t0, t3)
            && approximately_zero_when_compared_to(t0, t4)) {
        int num = SkDCubic::RootsReal(t4, t3, t2, t1, roots);
        for (int i = 0; i < num; ++i) {
            if (approximately_zero(roots[i])) {
                return num;
            }
        }
        roots[num++] = 0;
        return num;
    }
    if (oneHint) {
        SkASSERT(approximately_zero_double(t4 + t3 + t2 + t1 + t0));  // 1 is one root
        // note that -C == A + B + D + E
        int num = SkDCubic::RootsReal(t4, t4 + t3, -(t1 + t0), -t0, roots);
        for (int i = 0; i < num; ++i) {
            if (approximately_equal(roots[i], 1)) {
                return num;
            }
        }
        roots[num++] = 1;
        return num;
    }
    return -1;
}
コード例 #21
0
ファイル: TestUtilities.cpp プロジェクト: ghub/NVprSDK
static bool tiny(const Cubic& cubic) {
    int index, minX, maxX, minY, maxY;
    minX = maxX = minY = maxY = 0;
    for (index = 1; index < 4; ++index) {
        if (cubic[minX].x > cubic[index].x) {
            minX = index;
        }
        if (cubic[minY].y > cubic[index].y) {
            minY = index;
        }
        if (cubic[maxX].x < cubic[index].x) {
            maxX = index;
        }
        if (cubic[maxY].y < cubic[index].y) {
            maxY = index;
        }
    }
    return     approximately_equal(cubic[maxX].x, cubic[minX].x)
            && approximately_equal(cubic[maxY].y, cubic[minY].y);
}
コード例 #22
0
ファイル: SkDWriteGeometrySink.cpp プロジェクト: Just-D/skia
static bool check_quadratic(const Cubic& cubic, Quadratic& reduction) {
    float dx10 = cubic[1].x - cubic[0].x;
    float dx23 = cubic[2].x - cubic[3].x;
    float midX = cubic[0].x + dx10 * 3 / 2;
    //NOTE: !approximately_equal(midX - cubic[3].x, dx23 * 3 / 2)
    //does not work as subnormals get in between the left side and 0.
    if (!approximately_equal(midX, (dx23 * 3 / 2) + cubic[3].x)) {
        return false;
    }
    float dy10 = cubic[1].y - cubic[0].y;
    float dy23 = cubic[2].y - cubic[3].y;
    float midY = cubic[0].y + dy10 * 3 / 2;
    if (!approximately_equal(midY, (dy23 * 3 / 2) + cubic[3].y)) {
        return false;
    }
    reduction[0] = cubic[0];
    reduction[1].x = midX;
    reduction[1].y = midY;
    reduction[2] = cubic[3];
    return true;
}
コード例 #23
0
ファイル: QuarticRoot_Test.cpp プロジェクト: Adenilson/skia
static void quadraticTest(bool limit) {
    // (x - a)(x - b) == x^2 - (a + b)x + ab
    for (size_t aIndex = 0; aIndex < mulACount; ++aIndex) {
        for (size_t bIndex = 0; bIndex < rootBCount; ++bIndex) {
            for (size_t cIndex = 0; cIndex < rootCCount; ++cIndex) {
                const double A = mulA[aIndex];
                double B = rootB[bIndex];
                double C = rootC[cIndex];
                if (limit) {
                    B = (B - 6) / 12;
                    C = (C - 6) / 12;
                }
                const double b = A * (B + C);
                const double c = A * B * C;
                double roots[2];
                const int rootCount = limit ? quadraticRootsValidT(A, b, c, roots)
                    : quadraticRootsReal(A, b, c, roots);
                int expected;
                if (limit) {
                    expected = B <= 0 && B >= -1;
                    expected += B != C && C <= 0 && C >= -1;
                } else {
                    expected = 1 + (B != C);
                }
                SkASSERT(rootCount == expected);
                if (!rootCount) {
                    continue;
                }
                SkASSERT(approximately_equal(roots[0], -B)
                        || approximately_equal(roots[0], -C));
                if (expected > 1) {
                    SkASSERT(!approximately_equal(roots[0], roots[1]));
                    SkASSERT(approximately_equal(roots[1], -B)
                            || approximately_equal(roots[1], -C));
                }
            }
        }
    }
}
コード例 #24
0
ファイル: SkDLineIntersection.cpp プロジェクト: 3rdexp/soui
void SkIntersections::cleanUpParallelLines(bool parallel) {
    while (fUsed > 2) {
        removeOne(1);
    }
    if (fUsed == 2 && !parallel) {
        bool startMatch = fT[0][0] == 0 || fT[1][0] == 0 || fT[1][0] == 1;
        bool endMatch = fT[0][1] == 1 || fT[1][1] == 0 || fT[1][1] == 1;
        if ((!startMatch && !endMatch) || approximately_equal(fT[0][0], fT[0][1])) {
            SkASSERT(startMatch || endMatch);
            removeOne(endMatch);
        }
    }
}
コード例 #25
0
void LineParameter_Test() {
    for (size_t index = firstLineParameterTest; index < tests_count; ++index) {
        LineParameters lineParameters;
        const Cubic& cubic = tests[index];
        lineParameters.cubicEndPoints(cubic);
        double denormalizedDistance[2];
        lineParameters.controlPtDistance(cubic, denormalizedDistance);
        double normalSquared = lineParameters.normalSquared();
        size_t inner;
        for (inner = 0; inner < 2; ++inner) {
            double distSq = denormalizedDistance[inner];
            distSq *= distSq;
            double answersSq = answers[index][inner];
            answersSq *= answersSq;
            if (approximately_equal(distSq, normalSquared * answersSq)) {
                continue;
            }
            printf("%s [%d,%d] denormalizedDistance:%g != answer:%g"
                    " distSq:%g answerSq:%g normalSquared:%g\n",
                    __FUNCTION__, (int)index, (int)inner,
                    denormalizedDistance[inner], answers[index][inner],
                    distSq, answersSq, normalSquared);
        }
        lineParameters.normalize();
        double normalizedDistance[2];
        lineParameters.controlPtDistance(cubic, normalizedDistance);
        for (inner = 0; inner < 2; ++inner) {
            if (approximately_equal(fabs(normalizedDistance[inner]), 
                    answers[index][inner])) {
                continue;
            }
            printf("%s [%d,%d] normalizedDistance:%1.10g != answer:%g\n",
                    __FUNCTION__, (int)index, (int)inner,
                    normalizedDistance[inner], answers[index][inner]);
        }
    }
}
コード例 #26
0
void LineCubicIntersection_Test() {
    for (size_t index = firstLineCubicIntersectionTest; index < lineCubicTests_count; ++index) {
        const Cubic& cubic = lineCubicTests[index].cubic;
        const _Line& line = lineCubicTests[index].line;
        Cubic reduce1;
        _Line reduce2;
        int order1 = reduceOrder(cubic, reduce1, kReduceOrder_NoQuadraticsAllowed);
        int order2 = reduceOrder(line, reduce2);
        if (order1 < 4) {
            printf("[%d] cubic order=%d\n", (int) index, order1);
        }
        if (order2 < 2) {
            printf("[%d] line order=%d\n", (int) index, order2);
        }
        if (order1 == 4 && order2 == 2) {
            double range1[2], range2[2];
            int roots = intersect(reduce1, reduce2, range1, range2);
            for (int pt = 0; pt < roots; ++pt) {
                double tt1 = range1[pt];
                double tx1, ty1;
                xy_at_t(cubic, tt1, tx1, ty1);
                double tt2 = range2[pt];
                double tx2, ty2;
                xy_at_t(line, tt2, tx2, ty2);
                if (!approximately_equal(tx1, tx2)) {
                    printf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
                        __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
                }
                if (!approximately_equal(ty1, ty2)) {
                    printf("%s [%d,%d] y!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
                        __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
                }
            }
        }
    }
}
コード例 #27
0
static double verticalIntersect(const Quadratic& quad, const _Point& pt) {
    Intersections intersections;
    LineQuadraticIntersections q(quad, *((_Line*) 0), intersections);
    int result = q.horizontalIntersect(pt.x);
    if (result == 0) {
        return -1;
    }
    assert(result == 1);
    double x, y;
    xy_at_t(quad, intersections.fT[0][0], x, y);
    if (approximately_equal(y, pt.y)) {
        return intersections.fT[0][0];
    }
    return -1;
}
コード例 #28
0
 static int VerticalIntersect(const SkDCubic& c, double axisIntercept, double roots[3]) {
     double A, B, C, D;
     SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D);
     D -= axisIntercept;
     int count = SkDCubic::RootsValidT(A, B, C, D, roots);
     for (int index = 0; index < count; ++index) {
         SkDPoint calcPt = c.ptAtT(roots[index]);
         if (!approximately_equal(calcPt.fX, axisIntercept)) {
             double extremeTs[6];
             int extrema = SkDCubic::FindExtrema(&c[0].fX, extremeTs);
             count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kXAxis, roots);
             break;
         }
     }
     return count;
 }
コード例 #29
0
ファイル: SkPathOpsCubic.cpp プロジェクト: aseprite/skia
// give up when changing t no longer moves point
// also, copy point rather than recompute it when it does change
double SkDCubic::binarySearch(double min, double max, double axisIntercept,
        SearchAxis xAxis) const {
    double t = (min + max) / 2;
    double step = (t - min) / 2;
    SkDPoint cubicAtT = ptAtT(t);
    double calcPos = (&cubicAtT.fX)[xAxis];
    double calcDist = calcPos - axisIntercept;
    do {
        double priorT = t - step;
        SkOPASSERT(priorT >= min);
        SkDPoint lessPt = ptAtT(priorT);
        if (approximately_equal_half(lessPt.fX, cubicAtT.fX)
                && approximately_equal_half(lessPt.fY, cubicAtT.fY)) {
            return -1;  // binary search found no point at this axis intercept
        }
        double lessDist = (&lessPt.fX)[xAxis] - axisIntercept;
#if DEBUG_CUBIC_BINARY_SEARCH
        SkDebugf("t=%1.9g calc=%1.9g dist=%1.9g step=%1.9g less=%1.9g\n", t, calcPos, calcDist,
                step, lessDist);
#endif
        double lastStep = step;
        step /= 2;
        if (calcDist > 0 ? calcDist > lessDist : calcDist < lessDist) {
            t = priorT;
        } else {
            double nextT = t + lastStep;
            if (nextT > max) {
                return -1;
            }
            SkDPoint morePt = ptAtT(nextT);
            if (approximately_equal_half(morePt.fX, cubicAtT.fX)
                    && approximately_equal_half(morePt.fY, cubicAtT.fY)) {
                return -1;  // binary search found no point at this axis intercept
            }
            double moreDist = (&morePt.fX)[xAxis] - axisIntercept;
            if (calcDist > 0 ? calcDist <= moreDist : calcDist >= moreDist) {
                continue;
            }
            t = nextT;
        }
        SkDPoint testAtT = ptAtT(t);
        cubicAtT = testAtT;
        calcPos = (&cubicAtT.fX)[xAxis];
        calcDist = calcPos - axisIntercept;
    } while (!approximately_equal(calcPos, axisIntercept));
    return t;
}
コード例 #30
0
ファイル: SkOpAngle.cpp プロジェクト: venkatarajasekhar/Qt
// the original angle is too short to get meaningful sector information
// lengthen it until it is long enough to be meaningful or leave it unset if lengthening it
// would cause it to intersect one of the adjacent angles
bool SkOpAngle::computeSector() {
    if (fComputedSector) {
        // FIXME: logically, this should return !fUnorderable, but doing so breaks testQuadratic51
        // -- but in general, this code may not work so this may be the least of problems
        // adding the bang fixes testQuads46x in release, however
        return !fUnorderable;
    }
    SkASSERT(fSegment->verb() != SkPath::kLine_Verb && small());
    fComputedSector = true;
    int step = fStart < fEnd ? 1 : -1;
    int limit = step > 0 ? fSegment->count() : -1;
    int checkEnd = fEnd;
    do {
// advance end
        const SkOpSpan& span = fSegment->span(checkEnd);
        const SkOpSegment* other = span.fOther;
        int oCount = other->count();
        for (int oIndex = 0; oIndex < oCount; ++oIndex) {
            const SkOpSpan& oSpan = other->span(oIndex);
            if (oSpan.fOther != fSegment) {
                continue;
            }
            if (oSpan.fOtherIndex == checkEnd) {
                continue;
            }
            if (!approximately_equal(oSpan.fOtherT, span.fT)) {
                continue;
            }
            goto recomputeSector;
        }
        checkEnd += step;
    } while (checkEnd != limit);
recomputeSector:
    if (checkEnd == fEnd || checkEnd - step == fEnd) {
        fUnorderable = true;
        return false;
    }
    int saveEnd = fEnd;
    fComputedEnd = fEnd = checkEnd - step;
    setSpans();
    setSector();
    fEnd = saveEnd;
    return !fUnorderable;
}