blob: fd060de6468f0f709d91c588c00682bc2b649a6d [file] [log] [blame]
caryclark@google.com07393ca2013-04-08 11:47:37 +00001/*
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 "SkIntersections.h"
8#include "SkPathOpsCubic.h"
caryclark55888e42016-07-18 10:01:36 -07009#include "SkPathOpsCurve.h"
caryclark@google.com07393ca2013-04-08 11:47:37 +000010#include "SkPathOpsLine.h"
11
12/*
13Find the interection of a line and cubic by solving for valid t values.
14
15Analogous to line-quadratic intersection, solve line-cubic intersection by
16representing the cubic as:
17 x = a(1-t)^3 + 2b(1-t)^2t + c(1-t)t^2 + dt^3
18 y = e(1-t)^3 + 2f(1-t)^2t + g(1-t)t^2 + ht^3
19and the line as:
20 y = i*x + j (if the line is more horizontal)
21or:
22 x = i*y + j (if the line is more vertical)
23
24Then using Mathematica, solve for the values of t where the cubic intersects the
25line:
26
27 (in) Resultant[
28 a*(1 - t)^3 + 3*b*(1 - t)^2*t + 3*c*(1 - t)*t^2 + d*t^3 - x,
29 e*(1 - t)^3 + 3*f*(1 - t)^2*t + 3*g*(1 - t)*t^2 + h*t^3 - i*x - j, x]
30 (out) -e + j +
31 3 e t - 3 f t -
32 3 e t^2 + 6 f t^2 - 3 g t^2 +
33 e t^3 - 3 f t^3 + 3 g t^3 - h t^3 +
34 i ( a -
35 3 a t + 3 b t +
36 3 a t^2 - 6 b t^2 + 3 c t^2 -
37 a t^3 + 3 b t^3 - 3 c t^3 + d t^3 )
38
39if i goes to infinity, we can rewrite the line in terms of x. Mathematica:
40
41 (in) Resultant[
42 a*(1 - t)^3 + 3*b*(1 - t)^2*t + 3*c*(1 - t)*t^2 + d*t^3 - i*y - j,
43 e*(1 - t)^3 + 3*f*(1 - t)^2*t + 3*g*(1 - t)*t^2 + h*t^3 - y, y]
44 (out) a - j -
45 3 a t + 3 b t +
46 3 a t^2 - 6 b t^2 + 3 c t^2 -
47 a t^3 + 3 b t^3 - 3 c t^3 + d t^3 -
48 i ( e -
49 3 e t + 3 f t +
50 3 e t^2 - 6 f t^2 + 3 g t^2 -
51 e t^3 + 3 f t^3 - 3 g t^3 + h t^3 )
52
53Solving this with Mathematica produces an expression with hundreds of terms;
54instead, use Numeric Solutions recipe to solve the cubic.
55
56The near-horizontal case, in terms of: Ax^3 + Bx^2 + Cx + D == 0
57 A = (-(-e + 3*f - 3*g + h) + i*(-a + 3*b - 3*c + d) )
58 B = 3*(-( e - 2*f + g ) + i*( a - 2*b + c ) )
59 C = 3*(-(-e + f ) + i*(-a + b ) )
60 D = (-( e ) + i*( a ) + j )
61
62The near-vertical case, in terms of: Ax^3 + Bx^2 + Cx + D == 0
63 A = ( (-a + 3*b - 3*c + d) - i*(-e + 3*f - 3*g + h) )
64 B = 3*( ( a - 2*b + c ) - i*( e - 2*f + g ) )
65 C = 3*( (-a + b ) - i*(-e + f ) )
66 D = ( ( a ) - i*( e ) - j )
67
68For horizontal lines:
69(in) Resultant[
70 a*(1 - t)^3 + 3*b*(1 - t)^2*t + 3*c*(1 - t)*t^2 + d*t^3 - j,
71 e*(1 - t)^3 + 3*f*(1 - t)^2*t + 3*g*(1 - t)*t^2 + h*t^3 - y, y]
72(out) e - j -
73 3 e t + 3 f t +
74 3 e t^2 - 6 f t^2 + 3 g t^2 -
75 e t^3 + 3 f t^3 - 3 g t^3 + h t^3
76 */
77
78class LineCubicIntersections {
79public:
caryclark@google.com4fdbb222013-07-23 15:27:41 +000080 enum PinTPoint {
81 kPointUninitialized,
82 kPointInitialized
83 };
caryclark@google.com07393ca2013-04-08 11:47:37 +000084
caryclark@google.com4fdbb222013-07-23 15:27:41 +000085 LineCubicIntersections(const SkDCubic& c, const SkDLine& l, SkIntersections* i)
86 : fCubic(c)
87 , fLine(l)
88 , fIntersections(i)
89 , fAllowNear(true) {
caryclarka339bb02016-07-21 12:28:04 -070090 i->setMax(4);
caryclark@google.com07393ca2013-04-08 11:47:37 +000091 }
caryclark@google.com07393ca2013-04-08 11:47:37 +000092
caryclark@google.com4fdbb222013-07-23 15:27:41 +000093 void allowNear(bool allow) {
94 fAllowNear = allow;
95 }
96
caryclark54359292015-03-26 07:52:43 -070097 void checkCoincident() {
98 int last = fIntersections->used() - 1;
99 for (int index = 0; index < last; ) {
100 double cubicMidT = ((*fIntersections)[0][index] + (*fIntersections)[0][index + 1]) / 2;
101 SkDPoint cubicMidPt = fCubic.ptAtT(cubicMidT);
halcanary96fcdcc2015-08-27 07:41:13 -0700102 double t = fLine.nearPoint(cubicMidPt, nullptr);
caryclark54359292015-03-26 07:52:43 -0700103 if (t < 0) {
104 ++index;
105 continue;
106 }
107 if (fIntersections->isCoincident(index)) {
108 fIntersections->removeOne(index);
109 --last;
110 } else if (fIntersections->isCoincident(index + 1)) {
111 fIntersections->removeOne(index + 1);
112 --last;
113 } else {
114 fIntersections->setCoincident(index++);
115 }
116 fIntersections->setCoincident(index);
117 }
118 }
119
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000120 // see parallel routine in line quadratic intersections
121 int intersectRay(double roots[3]) {
122 double adj = fLine[1].fX - fLine[0].fX;
123 double opp = fLine[1].fY - fLine[0].fY;
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000124 SkDCubic c;
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000125 for (int n = 0; n < 4; ++n) {
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000126 c[n].fX = (fCubic[n].fY - fLine[0].fY) * adj - (fCubic[n].fX - fLine[0].fX) * opp;
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000127 }
128 double A, B, C, D;
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000129 SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D);
130 int count = SkDCubic::RootsValidT(A, B, C, D, roots);
131 for (int index = 0; index < count; ++index) {
132 SkDPoint calcPt = c.ptAtT(roots[index]);
133 if (!approximately_zero(calcPt.fX)) {
134 for (int n = 0; n < 4; ++n) {
135 c[n].fY = (fCubic[n].fY - fLine[0].fY) * opp
136 + (fCubic[n].fX - fLine[0].fX) * adj;
137 }
138 double extremeTs[6];
caryclarkaec25102015-04-29 08:28:30 -0700139 int extrema = SkDCubic::FindExtrema(&c[0].fX, extremeTs);
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000140 count = c.searchRoots(extremeTs, extrema, 0, SkDCubic::kXAxis, roots);
141 break;
142 }
143 }
144 return count;
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000145 }
146
147 int intersect() {
148 addExactEndPoints();
caryclark@google.com570863f2013-09-16 15:55:01 +0000149 if (fAllowNear) {
150 addNearEndPoints();
151 }
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000152 double rootVals[3];
153 int roots = intersectRay(rootVals);
154 for (int index = 0; index < roots; ++index) {
155 double cubicT = rootVals[index];
156 double lineT = findLineT(cubicT);
157 SkDPoint pt;
caryclark54359292015-03-26 07:52:43 -0700158 if (pinTs(&cubicT, &lineT, &pt, kPointUninitialized) && uniqueAnswer(cubicT, pt)) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000159 fIntersections->insert(cubicT, lineT, pt);
160 }
161 }
caryclark54359292015-03-26 07:52:43 -0700162 checkCoincident();
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000163 return fIntersections->used();
164 }
165
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000166 static int HorizontalIntersect(const SkDCubic& c, double axisIntercept, double roots[3]) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000167 double A, B, C, D;
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000168 SkDCubic::Coefficients(&c[0].fY, &A, &B, &C, &D);
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000169 D -= axisIntercept;
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000170 int count = SkDCubic::RootsValidT(A, B, C, D, roots);
171 for (int index = 0; index < count; ++index) {
172 SkDPoint calcPt = c.ptAtT(roots[index]);
173 if (!approximately_equal(calcPt.fY, axisIntercept)) {
174 double extremeTs[6];
caryclarkaec25102015-04-29 08:28:30 -0700175 int extrema = SkDCubic::FindExtrema(&c[0].fY, extremeTs);
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000176 count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kYAxis, roots);
177 break;
178 }
179 }
180 return count;
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000181 }
182
183 int horizontalIntersect(double axisIntercept, double left, double right, bool flipped) {
184 addExactHorizontalEndPoints(left, right, axisIntercept);
caryclark@google.com570863f2013-09-16 15:55:01 +0000185 if (fAllowNear) {
186 addNearHorizontalEndPoints(left, right, axisIntercept);
187 }
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000188 double roots[3];
189 int count = HorizontalIntersect(fCubic, axisIntercept, roots);
190 for (int index = 0; index < count; ++index) {
191 double cubicT = roots[index];
caryclark54359292015-03-26 07:52:43 -0700192 SkDPoint pt = { fCubic.ptAtT(cubicT).fX, axisIntercept };
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000193 double lineT = (pt.fX - left) / (right - left);
caryclark54359292015-03-26 07:52:43 -0700194 if (pinTs(&cubicT, &lineT, &pt, kPointInitialized) && uniqueAnswer(cubicT, pt)) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000195 fIntersections->insert(cubicT, lineT, pt);
196 }
197 }
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000198 if (flipped) {
199 fIntersections->flip();
200 }
caryclark54359292015-03-26 07:52:43 -0700201 checkCoincident();
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000202 return fIntersections->used();
203 }
204
caryclark54359292015-03-26 07:52:43 -0700205 bool uniqueAnswer(double cubicT, const SkDPoint& pt) {
206 for (int inner = 0; inner < fIntersections->used(); ++inner) {
207 if (fIntersections->pt(inner) != pt) {
208 continue;
209 }
210 double existingCubicT = (*fIntersections)[0][inner];
211 if (cubicT == existingCubicT) {
212 return false;
213 }
214 // check if midway on cubic is also same point. If so, discard this
215 double cubicMidT = (existingCubicT + cubicT) / 2;
216 SkDPoint cubicMidPt = fCubic.ptAtT(cubicMidT);
217 if (cubicMidPt.approximatelyEqual(pt)) {
218 return false;
219 }
220 }
221#if ONE_OFF_DEBUG
222 SkDPoint cPt = fCubic.ptAtT(cubicT);
223 SkDebugf("%s pt=(%1.9g,%1.9g) cPt=(%1.9g,%1.9g)\n", __FUNCTION__, pt.fX, pt.fY,
224 cPt.fX, cPt.fY);
225#endif
226 return true;
227 }
228
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000229 static int VerticalIntersect(const SkDCubic& c, double axisIntercept, double roots[3]) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000230 double A, B, C, D;
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000231 SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D);
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000232 D -= axisIntercept;
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000233 int count = SkDCubic::RootsValidT(A, B, C, D, roots);
234 for (int index = 0; index < count; ++index) {
235 SkDPoint calcPt = c.ptAtT(roots[index]);
236 if (!approximately_equal(calcPt.fX, axisIntercept)) {
237 double extremeTs[6];
caryclarkaec25102015-04-29 08:28:30 -0700238 int extrema = SkDCubic::FindExtrema(&c[0].fX, extremeTs);
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000239 count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kXAxis, roots);
240 break;
241 }
242 }
243 return count;
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000244 }
245
246 int verticalIntersect(double axisIntercept, double top, double bottom, bool flipped) {
247 addExactVerticalEndPoints(top, bottom, axisIntercept);
caryclark@google.com570863f2013-09-16 15:55:01 +0000248 if (fAllowNear) {
249 addNearVerticalEndPoints(top, bottom, axisIntercept);
250 }
commit-bot@chromium.org2db7fe72014-05-07 15:31:40 +0000251 double roots[3];
252 int count = VerticalIntersect(fCubic, axisIntercept, roots);
253 for (int index = 0; index < count; ++index) {
254 double cubicT = roots[index];
caryclark54359292015-03-26 07:52:43 -0700255 SkDPoint pt = { axisIntercept, fCubic.ptAtT(cubicT).fY };
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000256 double lineT = (pt.fY - top) / (bottom - top);
caryclark54359292015-03-26 07:52:43 -0700257 if (pinTs(&cubicT, &lineT, &pt, kPointInitialized) && uniqueAnswer(cubicT, pt)) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000258 fIntersections->insert(cubicT, lineT, pt);
259 }
260 }
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000261 if (flipped) {
262 fIntersections->flip();
263 }
caryclark54359292015-03-26 07:52:43 -0700264 checkCoincident();
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000265 return fIntersections->used();
266 }
267
268 protected:
269
270 void addExactEndPoints() {
271 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
272 double lineT = fLine.exactPoint(fCubic[cIndex]);
273 if (lineT < 0) {
274 continue;
275 }
276 double cubicT = (double) (cIndex >> 1);
277 fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000278 }
279 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000280
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000281 /* Note that this does not look for endpoints of the line that are near the cubic.
282 These points are found later when check ends looks for missing points */
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000283 void addNearEndPoints() {
284 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
285 double cubicT = (double) (cIndex >> 1);
286 if (fIntersections->hasT(cubicT)) {
287 continue;
288 }
halcanary96fcdcc2015-08-27 07:41:13 -0700289 double lineT = fLine.nearPoint(fCubic[cIndex], nullptr);
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000290 if (lineT < 0) {
291 continue;
292 }
293 fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000294 }
caryclark55888e42016-07-18 10:01:36 -0700295 this->addLineNearEndPoints();
296 }
297
298 void addLineNearEndPoints() {
299 for (int lIndex = 0; lIndex < 2; ++lIndex) {
300 double lineT = (double) lIndex;
301 if (fIntersections->hasOppT(lineT)) {
302 continue;
303 }
304 double cubicT = ((SkDCurve*) &fCubic)->nearPoint(SkPath::kCubic_Verb,
305 fLine[lIndex], fLine[!lIndex]);
306 if (cubicT < 0) {
307 continue;
308 }
309 fIntersections->insert(cubicT, lineT, fLine[lIndex]);
310 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000311 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000312
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000313 void addExactHorizontalEndPoints(double left, double right, double y) {
314 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
315 double lineT = SkDLine::ExactPointH(fCubic[cIndex], left, right, y);
316 if (lineT < 0) {
317 continue;
318 }
319 double cubicT = (double) (cIndex >> 1);
320 fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000321 }
322 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000323
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000324 void addNearHorizontalEndPoints(double left, double right, double y) {
325 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
326 double cubicT = (double) (cIndex >> 1);
327 if (fIntersections->hasT(cubicT)) {
328 continue;
329 }
330 double lineT = SkDLine::NearPointH(fCubic[cIndex], left, right, y);
331 if (lineT < 0) {
332 continue;
333 }
334 fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
335 }
caryclark55888e42016-07-18 10:01:36 -0700336 this->addLineNearEndPoints();
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000337 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000338
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000339 void addExactVerticalEndPoints(double top, double bottom, double x) {
340 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
341 double lineT = SkDLine::ExactPointV(fCubic[cIndex], top, bottom, x);
342 if (lineT < 0) {
343 continue;
344 }
345 double cubicT = (double) (cIndex >> 1);
346 fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000347 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000348 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000349
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000350 void addNearVerticalEndPoints(double top, double bottom, double x) {
351 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
352 double cubicT = (double) (cIndex >> 1);
353 if (fIntersections->hasT(cubicT)) {
354 continue;
355 }
356 double lineT = SkDLine::NearPointV(fCubic[cIndex], top, bottom, x);
357 if (lineT < 0) {
358 continue;
359 }
360 fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000361 }
caryclark55888e42016-07-18 10:01:36 -0700362 this->addLineNearEndPoints();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000363 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000364
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000365 double findLineT(double t) {
366 SkDPoint xy = fCubic.ptAtT(t);
367 double dx = fLine[1].fX - fLine[0].fX;
368 double dy = fLine[1].fY - fLine[0].fY;
369 if (fabs(dx) > fabs(dy)) {
370 return (xy.fX - fLine[0].fX) / dx;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000371 }
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000372 return (xy.fY - fLine[0].fY) / dy;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000373 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000374
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000375 bool pinTs(double* cubicT, double* lineT, SkDPoint* pt, PinTPoint ptSet) {
376 if (!approximately_one_or_less(*lineT)) {
377 return false;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000378 }
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000379 if (!approximately_zero_or_more(*lineT)) {
380 return false;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000381 }
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000382 double cT = *cubicT = SkPinT(*cubicT);
383 double lT = *lineT = SkPinT(*lineT);
commit-bot@chromium.org91fc81c2014-04-30 13:37:48 +0000384 SkDPoint lPt = fLine.ptAtT(lT);
385 SkDPoint cPt = fCubic.ptAtT(cT);
caryclark54359292015-03-26 07:52:43 -0700386 if (!lPt.roughlyEqual(cPt)) {
commit-bot@chromium.org91fc81c2014-04-30 13:37:48 +0000387 return false;
388 }
skia.committer@gmail.com24f6e292014-05-01 03:04:54 +0000389 // FIXME: if points are roughly equal but not approximately equal, need to do
commit-bot@chromium.org91fc81c2014-04-30 13:37:48 +0000390 // a binary search like quad/quad intersection to find more precise t values
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000391 if (lT == 0 || lT == 1 || (ptSet == kPointUninitialized && cT != 0 && cT != 1)) {
commit-bot@chromium.org91fc81c2014-04-30 13:37:48 +0000392 *pt = lPt;
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000393 } else if (ptSet == kPointUninitialized) {
commit-bot@chromium.org91fc81c2014-04-30 13:37:48 +0000394 *pt = cPt;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000395 }
caryclark@google.com570863f2013-09-16 15:55:01 +0000396 SkPoint gridPt = pt->asSkPoint();
397 if (gridPt == fLine[0].asSkPoint()) {
398 *lineT = 0;
399 } else if (gridPt == fLine[1].asSkPoint()) {
400 *lineT = 1;
401 }
402 if (gridPt == fCubic[0].asSkPoint() && approximately_equal(*cubicT, 0)) {
403 *cubicT = 0;
404 } else if (gridPt == fCubic[3].asSkPoint() && approximately_equal(*cubicT, 1)) {
405 *cubicT = 1;
406 }
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000407 return true;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000408 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000409
410private:
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000411 const SkDCubic& fCubic;
412 const SkDLine& fLine;
413 SkIntersections* fIntersections;
414 bool fAllowNear;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000415};
416
417int SkIntersections::horizontal(const SkDCubic& cubic, double left, double right, double y,
418 bool flipped) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000419 SkDLine line = {{{ left, y }, { right, y }}};
420 LineCubicIntersections c(cubic, line, this);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000421 return c.horizontalIntersect(y, left, right, flipped);
422}
423
424int SkIntersections::vertical(const SkDCubic& cubic, double top, double bottom, double x,
425 bool flipped) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000426 SkDLine line = {{{ x, top }, { x, bottom }}};
427 LineCubicIntersections c(cubic, line, this);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000428 return c.verticalIntersect(x, top, bottom, flipped);
429}
430
431int SkIntersections::intersect(const SkDCubic& cubic, const SkDLine& line) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000432 LineCubicIntersections c(cubic, line, this);
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000433 c.allowNear(fAllowNear);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000434 return c.intersect();
435}
436
437int SkIntersections::intersectRay(const SkDCubic& cubic, const SkDLine& line) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000438 LineCubicIntersections c(cubic, line, this);
caryclark@google.coma5e55922013-05-07 18:51:31 +0000439 fUsed = c.intersectRay(fT[0]);
440 for (int index = 0; index < fUsed; ++index) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000441 fPt[index] = cubic.ptAtT(fT[0][index]);
caryclark@google.coma5e55922013-05-07 18:51:31 +0000442 }
443 return fUsed;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000444}
reeddc308852015-04-30 07:47:13 -0700445
446// SkDCubic accessors to Intersection utilities
447
448int SkDCubic::horizontalIntersect(double yIntercept, double roots[3]) const {
449 return LineCubicIntersections::HorizontalIntersect(*this, yIntercept, roots);
450}
451
452int SkDCubic::verticalIntersect(double xIntercept, double roots[3]) const {
453 return LineCubicIntersections::VerticalIntersect(*this, xIntercept, roots);
454}