blob: b209474066bde4865da3e2fa27e1c6a004c265c2 [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 "SkPathOpsLine.h"
9
10/* Determine the intersection point of two lines. This assumes the lines are not parallel,
11 and that that the lines are infinite.
12 From http://en.wikipedia.org/wiki/Line-line_intersection
13 */
14SkDPoint SkIntersections::Line(const SkDLine& a, const SkDLine& b) {
15 double axLen = a[1].fX - a[0].fX;
16 double ayLen = a[1].fY - a[0].fY;
17 double bxLen = b[1].fX - b[0].fX;
18 double byLen = b[1].fY - b[0].fY;
19 double denom = byLen * axLen - ayLen * bxLen;
20 SkASSERT(denom);
21 double term1 = a[1].fX * a[0].fY - a[1].fY * a[0].fX;
22 double term2 = b[1].fX * b[0].fY - b[1].fY * b[0].fX;
23 SkDPoint p;
24 p.fX = (term1 * bxLen - axLen * term2) / denom;
25 p.fY = (term1 * byLen - ayLen * term2) / denom;
26 return p;
27}
28
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000029void SkIntersections::cleanUpCoincidence() {
30 SkASSERT(fUsed == 2);
31 // both t values are good
32 bool startMatch = fT[0][0] == 0 && (fT[1][0] == 0 || fT[1][0] == 1);
33 bool endMatch = fT[0][1] == 1 && (fT[1][1] == 0 || fT[1][1] == 1);
34 if (startMatch || endMatch) {
35 removeOne(startMatch);
36 return;
37 }
38 // either t value is good
39 bool pStartMatch = fT[0][0] == 0 || fT[1][0] == 0 || fT[1][0] == 1;
40 bool pEndMatch = fT[0][1] == 1 || fT[1][1] == 0 || fT[1][1] == 1;
41 removeOne(pStartMatch || !pEndMatch);
42}
43
44void SkIntersections::cleanUpParallelLines(bool parallel) {
45 while (fUsed > 2) {
46 removeOne(1);
47 }
48 if (fUsed == 2 && !parallel) {
49 bool startMatch = fT[0][0] == 0 || fT[1][0] == 0 || fT[1][0] == 1;
50 bool endMatch = fT[0][1] == 1 || fT[1][1] == 0 || fT[1][1] == 1;
51 if ((!startMatch && !endMatch) || approximately_equal(fT[0][0], fT[0][1])) {
52 SkASSERT(startMatch || endMatch);
53 removeOne(endMatch);
54 }
55 }
56}
57
58void SkIntersections::computePoints(const SkDLine& line, int used) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +000059 fPt[0] = line.ptAtT(fT[0][0]);
caryclark@google.com07393ca2013-04-08 11:47:37 +000060 if ((fUsed = used) == 2) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +000061 fPt[1] = line.ptAtT(fT[0][1]);
caryclark@google.com07393ca2013-04-08 11:47:37 +000062 }
caryclark@google.com07393ca2013-04-08 11:47:37 +000063}
64
caryclark@google.comcffbcc32013-06-04 17:59:42 +000065int SkIntersections::intersectRay(const SkDLine& a, const SkDLine& b) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000066 fMax = 2;
caryclark@google.com570863f2013-09-16 15:55:01 +000067 SkDVector aLen = a[1] - a[0];
68 SkDVector bLen = b[1] - b[0];
caryclark@google.comcffbcc32013-06-04 17:59:42 +000069 /* Slopes match when denom goes to zero:
70 axLen / ayLen == bxLen / byLen
71 (ayLen * byLen) * axLen / ayLen == (ayLen * byLen) * bxLen / byLen
72 byLen * axLen == ayLen * bxLen
73 byLen * axLen - ayLen * bxLen == 0 ( == denom )
74 */
caryclark@google.com570863f2013-09-16 15:55:01 +000075 double denom = bLen.fY * aLen.fX - aLen.fY * bLen.fX;
76 SkDVector ab0 = a[0] - b[0];
77 double numerA = ab0.fY * bLen.fX - bLen.fY * ab0.fX;
78 double numerB = ab0.fY * aLen.fX - aLen.fY * ab0.fX;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000079#if 0
80 if (!between(0, numerA, denom) || !between(0, numerB, denom)) {
81 fUsed = 0;
82 return 0;
83 }
84#endif
caryclark@google.comcffbcc32013-06-04 17:59:42 +000085 numerA /= denom;
86 numerB /= denom;
87 int used;
88 if (!approximately_zero(denom)) {
89 fT[0][0] = numerA;
90 fT[1][0] = numerB;
91 used = 1;
92 } else {
93 /* See if the axis intercepts match:
94 ay - ax * ayLen / axLen == by - bx * ayLen / axLen
95 axLen * (ay - ax * ayLen / axLen) == axLen * (by - bx * ayLen / axLen)
96 axLen * ay - ax * ayLen == axLen * by - bx * ayLen
97 */
caryclark@google.com570863f2013-09-16 15:55:01 +000098 if (!AlmostEqualUlps(aLen.fX * a[0].fY - aLen.fY * a[0].fX,
99 aLen.fX * b[0].fY - aLen.fY * b[0].fX)) {
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000100 return fUsed = 0;
101 }
102 // there's no great answer for intersection points for coincident rays, but return something
103 fT[0][0] = fT[1][0] = 0;
104 fT[1][0] = fT[1][1] = 1;
105 used = 2;
106 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000107 computePoints(a, used);
108 return fUsed;
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000109}
110
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000111// note that this only works if both lines are neither horizontal nor vertical
caryclark@google.com07393ca2013-04-08 11:47:37 +0000112int SkIntersections::intersect(const SkDLine& a, const SkDLine& b) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000113 fMax = 3; // note that we clean up so that there is no more than two in the end
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000114 // see if end points intersect the opposite line
115 double t;
116 for (int iA = 0; iA < 2; ++iA) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000117 if ((t = b.exactPoint(a[iA])) >= 0) {
118 insert(iA, t, a[iA]);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000119 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000120 }
121 for (int iB = 0; iB < 2; ++iB) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000122 if ((t = a.exactPoint(b[iB])) >= 0) {
123 insert(t, iB, b[iB]);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000124 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000125 }
126 /* Determine the intersection point of two line segments
127 Return FALSE if the lines don't intersect
128 from: http://paulbourke.net/geometry/lineline2d/ */
caryclark@google.com07393ca2013-04-08 11:47:37 +0000129 double axLen = a[1].fX - a[0].fX;
130 double ayLen = a[1].fY - a[0].fY;
131 double bxLen = b[1].fX - b[0].fX;
132 double byLen = b[1].fY - b[0].fY;
133 /* Slopes match when denom goes to zero:
134 axLen / ayLen == bxLen / byLen
135 (ayLen * byLen) * axLen / ayLen == (ayLen * byLen) * bxLen / byLen
136 byLen * axLen == ayLen * bxLen
137 byLen * axLen - ayLen * bxLen == 0 ( == denom )
138 */
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000139 double axByLen = axLen * byLen;
140 double ayBxLen = ayLen * bxLen;
141 // detect parallel lines the same way here and in SkOpAngle operator <
142 // so that non-parallel means they are also sortable
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000143 bool unparallel = fAllowNear ? NotAlmostEqualUlps(axByLen, ayBxLen)
144 : NotAlmostDequalUlps(axByLen, ayBxLen);
145 if (unparallel && fUsed == 0) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000146 double ab0y = a[0].fY - b[0].fY;
147 double ab0x = a[0].fX - b[0].fX;
148 double numerA = ab0y * bxLen - byLen * ab0x;
149 double numerB = ab0y * axLen - ayLen * ab0x;
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000150 double denom = axByLen - ayBxLen;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000151 if (between(0, numerA, denom) && between(0, numerB, denom)) {
152 fT[0][0] = numerA / denom;
153 fT[1][0] = numerB / denom;
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000154 computePoints(a, 1);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000155 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000156 }
caryclarkdac1d172014-06-17 05:15:38 -0700157/* Allow tracking that both sets of end points are near each other -- the lines are entirely
158 coincident -- even when the end points are not exactly the same.
159 Mark this as a 'wild card' for the end points, so that either point is considered totally
160 coincident. Then, avoid folding the lines over each other, but allow either end to mate
161 to the next set of lines.
162 */
caryclark@google.com570863f2013-09-16 15:55:01 +0000163 if (fAllowNear || !unparallel) {
caryclarkdac1d172014-06-17 05:15:38 -0700164 double aNearB[2];
165 double bNearA[2];
166 bool aNotB[2] = {false, false};
167 bool bNotA[2] = {false, false};
168 int nearCount = 0;
169 for (int index = 0; index < 2; ++index) {
170 aNearB[index] = t = b.nearPoint(a[index], &aNotB[index]);
171 nearCount += t >= 0;
172 bNearA[index] = t = a.nearPoint(b[index], &bNotA[index]);
173 nearCount += t >= 0;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000174 }
caryclarkdac1d172014-06-17 05:15:38 -0700175 if (nearCount > 0) {
caryclark19eb3b22014-07-18 05:08:14 -0700176 // Skip if each segment contributes to one end point.
177 if (nearCount != 2 || aNotB[0] == aNotB[1]) {
178 for (int iA = 0; iA < 2; ++iA) {
179 if (!aNotB[iA]) {
180 continue;
181 }
182 int nearer = aNearB[iA] > 0.5;
183 if (!bNotA[nearer]) {
184 continue;
185 }
186 SkASSERT(a[iA] != b[nearer]);
187 SkASSERT(iA == (bNearA[nearer] > 0.5));
188 fNearlySame[iA] = true;
189 insertNear(iA, nearer, a[iA], b[nearer]);
190 aNearB[iA] = -1;
191 bNearA[nearer] = -1;
192 nearCount -= 2;
caryclarkdac1d172014-06-17 05:15:38 -0700193 }
caryclarkdac1d172014-06-17 05:15:38 -0700194 }
195 if (nearCount > 0) {
196 for (int iA = 0; iA < 2; ++iA) {
197 if (aNearB[iA] >= 0) {
198 insert(iA, aNearB[iA], a[iA]);
199 }
200 }
201 for (int iB = 0; iB < 2; ++iB) {
202 if (bNearA[iB] >= 0) {
203 insert(bNearA[iB], iB, b[iB]);
204 }
205 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000206 }
207 }
208 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000209 cleanUpParallelLines(!unparallel);
210 SkASSERT(fUsed <= 2);
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000211 return fUsed;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000212}
213
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000214static int horizontal_coincident(const SkDLine& line, double y) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000215 double min = line[0].fY;
216 double max = line[1].fY;
217 if (min > max) {
218 SkTSwap(min, max);
219 }
220 if (min > y || max < y) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000221 return 0;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000222 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000223 if (AlmostEqualUlps(min, max) && max - min < fabs(line[0].fX - line[1].fX)) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000224 return 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000225 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000226 return 1;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000227}
228
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000229static double horizontal_intercept(const SkDLine& line, double y) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000230 return SkPinT((y - line[0].fY) / (line[1].fY - line[0].fY));
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000231}
232
233int SkIntersections::horizontal(const SkDLine& line, double y) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000234 fMax = 2;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000235 int horizontalType = horizontal_coincident(line, y);
236 if (horizontalType == 1) {
237 fT[0][0] = horizontal_intercept(line, y);
238 } else if (horizontalType == 2) {
239 fT[0][0] = 0;
240 fT[0][1] = 1;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000241 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000242 return fUsed = horizontalType;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000243}
244
caryclark@google.com07393ca2013-04-08 11:47:37 +0000245int SkIntersections::horizontal(const SkDLine& line, double left, double right,
246 double y, bool flipped) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000247 fMax = 3; // clean up parallel at the end will limit the result to 2 at the most
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000248 // see if end points intersect the opposite line
249 double t;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000250 const SkDPoint leftPt = { left, y };
251 if ((t = line.exactPoint(leftPt)) >= 0) {
252 insert(t, (double) flipped, leftPt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000253 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000254 if (left != right) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000255 const SkDPoint rightPt = { right, y };
256 if ((t = line.exactPoint(rightPt)) >= 0) {
257 insert(t, (double) !flipped, rightPt);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000258 }
259 for (int index = 0; index < 2; ++index) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000260 if ((t = SkDLine::ExactPointH(line[index], left, right, y)) >= 0) {
261 insert((double) index, flipped ? 1 - t : t, line[index]);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000262 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000263 }
264 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000265 int result = horizontal_coincident(line, y);
266 if (result == 1 && fUsed == 0) {
267 fT[0][0] = horizontal_intercept(line, y);
268 double xIntercept = line[0].fX + fT[0][0] * (line[1].fX - line[0].fX);
269 if (between(left, xIntercept, right)) {
270 fT[1][0] = (xIntercept - left) / (right - left);
271 if (flipped) {
272 // OPTIMIZATION: ? instead of swapping, pass original line, use [1].fX - [0].fX
273 for (int index = 0; index < result; ++index) {
274 fT[1][index] = 1 - fT[1][index];
275 }
276 }
caryclark@google.com15107262013-11-08 18:00:01 +0000277 fPt[0].fX = xIntercept;
278 fPt[0].fY = y;
279 fUsed = 1;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000280 }
281 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000282 if (fAllowNear || result == 2) {
caryclarkdac1d172014-06-17 05:15:38 -0700283 if ((t = line.nearPoint(leftPt, NULL)) >= 0) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000284 insert(t, (double) flipped, leftPt);
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000285 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000286 if (left != right) {
287 const SkDPoint rightPt = { right, y };
caryclarkdac1d172014-06-17 05:15:38 -0700288 if ((t = line.nearPoint(rightPt, NULL)) >= 0) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000289 insert(t, (double) !flipped, rightPt);
290 }
291 for (int index = 0; index < 2; ++index) {
292 if ((t = SkDLine::NearPointH(line[index], left, right, y)) >= 0) {
293 insert((double) index, flipped ? 1 - t : t, line[index]);
294 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000295 }
296 }
297 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000298 cleanUpParallelLines(result == 2);
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000299 return fUsed;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000300}
301
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000302static int vertical_coincident(const SkDLine& line, double x) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000303 double min = line[0].fX;
304 double max = line[1].fX;
305 if (min > max) {
306 SkTSwap(min, max);
307 }
caryclark@google.com03610322013-04-18 15:58:21 +0000308 if (!precisely_between(min, x, max)) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000309 return 0;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000310 }
311 if (AlmostEqualUlps(min, max)) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000312 return 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000313 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000314 return 1;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000315}
316
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000317static double vertical_intercept(const SkDLine& line, double x) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000318 return SkPinT((x - line[0].fX) / (line[1].fX - line[0].fX));
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000319}
320
321int SkIntersections::vertical(const SkDLine& line, double x) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000322 fMax = 2;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000323 int verticalType = vertical_coincident(line, x);
324 if (verticalType == 1) {
325 fT[0][0] = vertical_intercept(line, x);
326 } else if (verticalType == 2) {
327 fT[0][0] = 0;
328 fT[0][1] = 1;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000329 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000330 return fUsed = verticalType;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000331}
332
333int SkIntersections::vertical(const SkDLine& line, double top, double bottom,
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000334 double x, bool flipped) {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000335 fMax = 3; // cleanup parallel lines will bring this back line
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000336 // see if end points intersect the opposite line
337 double t;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000338 SkDPoint topPt = { x, top };
339 if ((t = line.exactPoint(topPt)) >= 0) {
340 insert(t, (double) flipped, topPt);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000341 }
342 if (top != bottom) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000343 SkDPoint bottomPt = { x, bottom };
344 if ((t = line.exactPoint(bottomPt)) >= 0) {
345 insert(t, (double) !flipped, bottomPt);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000346 }
347 for (int index = 0; index < 2; ++index) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000348 if ((t = SkDLine::ExactPointV(line[index], top, bottom, x)) >= 0) {
349 insert((double) index, flipped ? 1 - t : t, line[index]);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000350 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000351 }
352 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000353 int result = vertical_coincident(line, x);
354 if (result == 1 && fUsed == 0) {
355 fT[0][0] = vertical_intercept(line, x);
356 double yIntercept = line[0].fY + fT[0][0] * (line[1].fY - line[0].fY);
357 if (between(top, yIntercept, bottom)) {
358 fT[1][0] = (yIntercept - top) / (bottom - top);
359 if (flipped) {
360 // OPTIMIZATION: instead of swapping, pass original line, use [1].fY - [0].fY
361 for (int index = 0; index < result; ++index) {
362 fT[1][index] = 1 - fT[1][index];
363 }
364 }
caryclark@google.com15107262013-11-08 18:00:01 +0000365 fPt[0].fX = x;
366 fPt[0].fY = yIntercept;
367 fUsed = 1;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000368 }
369 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000370 if (fAllowNear || result == 2) {
caryclarkdac1d172014-06-17 05:15:38 -0700371 if ((t = line.nearPoint(topPt, NULL)) >= 0) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000372 insert(t, (double) flipped, topPt);
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000373 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000374 if (top != bottom) {
375 SkDPoint bottomPt = { x, bottom };
caryclarkdac1d172014-06-17 05:15:38 -0700376 if ((t = line.nearPoint(bottomPt, NULL)) >= 0) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000377 insert(t, (double) !flipped, bottomPt);
378 }
379 for (int index = 0; index < 2; ++index) {
380 if ((t = SkDLine::NearPointV(line[index], top, bottom, x)) >= 0) {
381 insert((double) index, flipped ? 1 - t : t, line[index]);
382 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000383 }
384 }
385 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000386 cleanUpParallelLines(result == 2);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000387 SkASSERT(fUsed <= 2);
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000388 return fUsed;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000389}
390
391// from http://www.bryceboe.com/wordpress/wp-content/uploads/2006/10/intersect.py
392// 4 subs, 2 muls, 1 cmp
393static bool ccw(const SkDPoint& A, const SkDPoint& B, const SkDPoint& C) {
394 return (C.fY - A.fY) * (B.fX - A.fX) > (B.fY - A.fY) * (C.fX - A.fX);
395}
396
397// 16 subs, 8 muls, 6 cmps
398bool SkIntersections::Test(const SkDLine& a, const SkDLine& b) {
399 return ccw(a[0], b[0], b[1]) != ccw(a[1], b[0], b[1])
400 && ccw(a[0], a[1], b[0]) != ccw(a[0], a[1], b[1]);
401}