PathOpsLineIntersectionTest.cpp revision 570863f2e22b8ea7d7c504bd15e4f766af097df2
1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7#include "PathOpsTestCommon.h"
8#include "SkIntersections.h"
9#include "SkPathOpsLine.h"
10#include "Test.h"
11
12// FIXME: add tests for intersecting, non-intersecting, degenerate, coincident
13static const SkDLine tests[][2] = {
14    {{{{90,230}, {160,60}}}, {{{60,120}, {260,120}}}},
15    {{{{90,230}, {160,60}}}, {{{181.176468,120}, {135.294128,120}}}},
16    {{{{181.1764678955078125f, 120}, {186.3661956787109375f, 134.7042236328125f}}},
17     {{{175.8309783935546875f, 141.5211334228515625f}, {187.8782806396484375f, 133.7258148193359375f}}}},
18#if 0  // FIXME: these fail because one line is too short and appears quasi-coincident
19    {{{{158.000000, 926.000000}, {1108.00000, 926.000000}}},
20            {{{1108.00000, 926.000000}, {1108.00000, 925.999634}}}},
21    {{{{1108,926}, {1108,925.9996337890625}}}, {{{158,926}, {1108,926}}}},
22#endif
23    {{{{192, 4}, {243, 4}}}, {{{246, 4}, {189, 4}}}},
24    {{{{246, 4}, {189, 4}}}, {{{192, 4}, {243, 4}}}},
25    {{{{5, 0}, {0, 5}}}, {{{5, 4}, {1, 4}}}},
26    {{{{0, 0}, {1, 0}}}, {{{1, 0}, {0, 0}}}},
27    {{{{0, 0}, {0, 0}}}, {{{0, 0}, {1, 0}}}},
28    {{{{0, 1}, {0, 1}}}, {{{0, 0}, {0, 2}}}},
29    {{{{0, 0}, {1, 0}}}, {{{0, 0}, {2, 0}}}},
30    {{{{1, 1}, {2, 2}}}, {{{0, 0}, {3, 3}}}},
31    {{{{166.86950047022856, 112.69654129527828}, {166.86948801592692, 112.69655741235339}}},
32     {{{166.86960700313026, 112.6965477747386}, {166.86925794355412, 112.69656471103423}}}}
33};
34
35static const size_t tests_count = SK_ARRAY_COUNT(tests);
36
37static const SkDLine noIntersect[][2] = {
38   {{{{(double) (2 - 1e-6f),2}, {(double) (2 - 1e-6f),4}}},
39    {{{2,1}, {2,3}}}},
40
41    {{{{0, 0}, {1, 0}}}, {{{3, 0}, {2, 0}}}},
42    {{{{0, 0}, {0, 0}}}, {{{1, 0}, {2, 0}}}},
43    {{{{0, 1}, {0, 1}}}, {{{0, 3}, {0, 2}}}},
44    {{{{0, 0}, {1, 0}}}, {{{2, 0}, {3, 0}}}},
45    {{{{1, 1}, {2, 2}}}, {{{4, 4}, {3, 3}}}},
46};
47
48static const size_t noIntersect_count = SK_ARRAY_COUNT(noIntersect);
49
50static const SkDLine coincidentTests[][2] = {
51   {{{{979.304871, 561}, {1036.69507, 291}}},
52    {{{985.681519, 531}, {982.159790, 547.568542}}}},
53
54   {{{{232.159805, 547.568542}, {235.681549, 531}}},
55    {{{286.695129,291}, {229.304855,561}}}},
56
57    {{{{186.3661956787109375f, 134.7042236328125f}, {187.8782806396484375f, 133.7258148193359375f}}},
58     {{{175.8309783935546875f, 141.5211334228515625f}, {187.8782806396484375f, 133.7258148193359375f}}}},
59
60    {{{{235.681549, 531.000000}, {280.318420, 321.000000}}},
61     {{{286.695129, 291.000000}, {229.304855, 561.000000}}}},
62};
63
64static const size_t coincidentTests_count = SK_ARRAY_COUNT(coincidentTests);
65
66static void check_results(skiatest::Reporter* reporter, const SkDLine& line1, const SkDLine& line2,
67                          const SkIntersections& ts) {
68    for (int i = 0; i < ts.used(); ++i) {
69        SkDPoint result1 = line1.ptAtT(ts[0][i]);
70        SkDPoint result2 = line2.ptAtT(ts[1][i]);
71        if (!result1.approximatelyEqual(result2)) {
72            REPORTER_ASSERT(reporter, ts.used() != 1);
73            result2 = line2.ptAtT(ts[1][i ^ 1]);
74            REPORTER_ASSERT(reporter, result1.approximatelyEqual(result2));
75            REPORTER_ASSERT(reporter, result1.approximatelyEqual(ts.pt(i).asSkPoint()));
76        }
77    }
78}
79
80static void testOne(skiatest::Reporter* reporter, const SkDLine& line1, const SkDLine& line2) {
81    SkASSERT(ValidLine(line1));
82    SkASSERT(ValidLine(line2));
83    SkIntersections i;
84    int pts = i.intersect(line1, line2);
85    REPORTER_ASSERT(reporter, pts);
86    REPORTER_ASSERT(reporter, pts == i.used());
87    check_results(reporter, line1, line2, i);
88    if (line1[0] == line1[1] || line2[0] == line2[1]) {
89        return;
90    }
91    if (line1[0].fY == line1[1].fY) {
92        double left = SkTMin(line1[0].fX, line1[1].fX);
93        double right = SkTMax(line1[0].fX, line1[1].fX);
94        SkIntersections ts;
95        ts.horizontal(line2, left, right, line1[0].fY, line1[0].fX != left);
96        check_results(reporter, line2, line1, ts);
97    }
98    if (line2[0].fY == line2[1].fY) {
99        double left = SkTMin(line2[0].fX, line2[1].fX);
100        double right = SkTMax(line2[0].fX, line2[1].fX);
101        SkIntersections ts;
102        ts.horizontal(line1, left, right, line2[0].fY, line2[0].fX != left);
103        check_results(reporter, line1, line2, ts);
104    }
105    if (line1[0].fX == line1[1].fX) {
106        double top = SkTMin(line1[0].fY, line1[1].fY);
107        double bottom = SkTMax(line1[0].fY, line1[1].fY);
108        SkIntersections ts;
109        ts.vertical(line2, top, bottom, line1[0].fX, line1[0].fY != top);
110        check_results(reporter, line2, line1, ts);
111    }
112    if (line2[0].fX == line2[1].fX) {
113        double top = SkTMin(line2[0].fY, line2[1].fY);
114        double bottom = SkTMax(line2[0].fY, line2[1].fY);
115        SkIntersections ts;
116        ts.vertical(line1, top, bottom, line2[0].fX, line2[0].fY != top);
117        check_results(reporter, line1, line2, ts);
118    }
119}
120
121static void testOneCoincident(skiatest::Reporter* reporter, const SkDLine& line1,
122                              const SkDLine& line2) {
123    SkASSERT(ValidLine(line1));
124    SkASSERT(ValidLine(line2));
125    SkIntersections ts;
126    int pts = ts.intersect(line1, line2);
127    REPORTER_ASSERT(reporter, pts == 2);
128    REPORTER_ASSERT(reporter, pts == ts.used());
129    check_results(reporter, line1, line2, ts);
130}
131
132static void PathOpsLineIntersectionTest(skiatest::Reporter* reporter) {
133    size_t index;
134    for (index = 0; index < coincidentTests_count; ++index) {
135        const SkDLine& line1 = coincidentTests[index][0];
136        const SkDLine& line2 = coincidentTests[index][1];
137        testOneCoincident(reporter, line1, line2);
138        reporter->bumpTestCount();
139    }
140    for (index = 0; index < tests_count; ++index) {
141        const SkDLine& line1 = tests[index][0];
142        const SkDLine& line2 = tests[index][1];
143        testOne(reporter, line1, line2);
144        reporter->bumpTestCount();
145    }
146    for (index = 0; index < noIntersect_count; ++index) {
147        const SkDLine& line1 = noIntersect[index][0];
148        const SkDLine& line2 = noIntersect[index][1];
149        SkIntersections ts;
150        int pts = ts.intersect(line1, line2);
151        REPORTER_ASSERT(reporter, !pts);
152        REPORTER_ASSERT(reporter, pts == ts.used());
153        reporter->bumpTestCount();
154    }
155}
156
157static void PathOpsLineIntersectionOneOffTest(skiatest::Reporter* reporter) {
158    int index = 0;
159    SkASSERT(index < (int) tests_count);
160    testOne(reporter, tests[index][0], tests[index][1]);
161    testOne(reporter, tests[1][0], tests[1][1]);
162}
163
164static void PathOpsLineIntersectionOneCoincidentTest(skiatest::Reporter* reporter) {
165    int index = 0;
166    SkASSERT(index < (int) coincidentTests_count);
167    const SkDLine& line1 = coincidentTests[index][0];
168    const SkDLine& line2 = coincidentTests[index][1];
169    testOneCoincident(reporter, line1, line2);
170}
171
172#include "TestClassDef.h"
173DEFINE_TESTCLASS_SHORT(PathOpsLineIntersectionTest)
174
175DEFINE_TESTCLASS_SHORT(PathOpsLineIntersectionOneOffTest)
176
177DEFINE_TESTCLASS_SHORT(PathOpsLineIntersectionOneCoincidentTest)
178