blob: 8fc673f2fb80e36558df1ae889a82863e6e05975 [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
caryclark65f55312014-11-13 06:58:52 -080029int SkIntersections::cleanUpCoincidence() {
30 do {
31 int last = fUsed - 1;
32 for (int index = 0; index < last; ++index) {
33 if (fT[0][index] == fT[0][index + 1]) {
34 removeOne(index + (int) (fT[1][index] == 0 || fT[1][index] == 1));
35 goto tryAgain;
36 }
37 }
38 for (int index = 0; index < last; ++index) {
39 if (fT[1][index] == fT[1][index + 1]) {
40 removeOne(index + (int) (fT[0][index] == 0 || fT[0][index] == 1));
41 goto tryAgain;
42 }
43 }
44 return fUsed;
45tryAgain: ;
46 } while (true);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000047}
48
49void SkIntersections::cleanUpParallelLines(bool parallel) {
50 while (fUsed > 2) {
51 removeOne(1);
52 }
53 if (fUsed == 2 && !parallel) {
54 bool startMatch = fT[0][0] == 0 || fT[1][0] == 0 || fT[1][0] == 1;
55 bool endMatch = fT[0][1] == 1 || fT[1][1] == 0 || fT[1][1] == 1;
56 if ((!startMatch && !endMatch) || approximately_equal(fT[0][0], fT[0][1])) {
57 SkASSERT(startMatch || endMatch);
58 removeOne(endMatch);
59 }
60 }
61}
62
63void SkIntersections::computePoints(const SkDLine& line, int used) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +000064 fPt[0] = line.ptAtT(fT[0][0]);
caryclark@google.com07393ca2013-04-08 11:47:37 +000065 if ((fUsed = used) == 2) {
caryclark@google.com4fdbb222013-07-23 15:27:41 +000066 fPt[1] = line.ptAtT(fT[0][1]);
caryclark@google.com07393ca2013-04-08 11:47:37 +000067 }
caryclark@google.com07393ca2013-04-08 11:47:37 +000068}
69
caryclark@google.comcffbcc32013-06-04 17:59:42 +000070int SkIntersections::intersectRay(const SkDLine& a, const SkDLine& b) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000071 fMax = 2;
caryclark@google.com570863f2013-09-16 15:55:01 +000072 SkDVector aLen = a[1] - a[0];
73 SkDVector bLen = b[1] - b[0];
caryclark@google.comcffbcc32013-06-04 17:59:42 +000074 /* Slopes match when denom goes to zero:
75 axLen / ayLen == bxLen / byLen
76 (ayLen * byLen) * axLen / ayLen == (ayLen * byLen) * bxLen / byLen
77 byLen * axLen == ayLen * bxLen
78 byLen * axLen - ayLen * bxLen == 0 ( == denom )
79 */
caryclark@google.com570863f2013-09-16 15:55:01 +000080 double denom = bLen.fY * aLen.fX - aLen.fY * bLen.fX;
81 SkDVector ab0 = a[0] - b[0];
82 double numerA = ab0.fY * bLen.fX - bLen.fY * ab0.fX;
83 double numerB = ab0.fY * aLen.fX - aLen.fY * ab0.fX;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000084#if 0
85 if (!between(0, numerA, denom) || !between(0, numerB, denom)) {
86 fUsed = 0;
87 return 0;
88 }
89#endif
caryclark@google.comcffbcc32013-06-04 17:59:42 +000090 numerA /= denom;
91 numerB /= denom;
92 int used;
93 if (!approximately_zero(denom)) {
94 fT[0][0] = numerA;
95 fT[1][0] = numerB;
96 used = 1;
97 } else {
98 /* See if the axis intercepts match:
99 ay - ax * ayLen / axLen == by - bx * ayLen / axLen
100 axLen * (ay - ax * ayLen / axLen) == axLen * (by - bx * ayLen / axLen)
101 axLen * ay - ax * ayLen == axLen * by - bx * ayLen
102 */
caryclark@google.com570863f2013-09-16 15:55:01 +0000103 if (!AlmostEqualUlps(aLen.fX * a[0].fY - aLen.fY * a[0].fX,
104 aLen.fX * b[0].fY - aLen.fY * b[0].fX)) {
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000105 return fUsed = 0;
106 }
107 // there's no great answer for intersection points for coincident rays, but return something
108 fT[0][0] = fT[1][0] = 0;
109 fT[1][0] = fT[1][1] = 1;
110 used = 2;
111 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000112 computePoints(a, used);
113 return fUsed;
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000114}
115
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000116// note that this only works if both lines are neither horizontal nor vertical
caryclark@google.com07393ca2013-04-08 11:47:37 +0000117int SkIntersections::intersect(const SkDLine& a, const SkDLine& b) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000118 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 +0000119 // see if end points intersect the opposite line
120 double t;
121 for (int iA = 0; iA < 2; ++iA) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000122 if ((t = b.exactPoint(a[iA])) >= 0) {
123 insert(iA, t, a[iA]);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000124 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000125 }
126 for (int iB = 0; iB < 2; ++iB) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000127 if ((t = a.exactPoint(b[iB])) >= 0) {
128 insert(t, iB, b[iB]);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000129 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000130 }
131 /* Determine the intersection point of two line segments
132 Return FALSE if the lines don't intersect
133 from: http://paulbourke.net/geometry/lineline2d/ */
caryclark@google.com07393ca2013-04-08 11:47:37 +0000134 double axLen = a[1].fX - a[0].fX;
135 double ayLen = a[1].fY - a[0].fY;
136 double bxLen = b[1].fX - b[0].fX;
137 double byLen = b[1].fY - b[0].fY;
138 /* Slopes match when denom goes to zero:
139 axLen / ayLen == bxLen / byLen
140 (ayLen * byLen) * axLen / ayLen == (ayLen * byLen) * bxLen / byLen
141 byLen * axLen == ayLen * bxLen
142 byLen * axLen - ayLen * bxLen == 0 ( == denom )
143 */
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000144 double axByLen = axLen * byLen;
145 double ayBxLen = ayLen * bxLen;
146 // detect parallel lines the same way here and in SkOpAngle operator <
147 // so that non-parallel means they are also sortable
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000148 bool unparallel = fAllowNear ? NotAlmostEqualUlps(axByLen, ayBxLen)
149 : NotAlmostDequalUlps(axByLen, ayBxLen);
150 if (unparallel && fUsed == 0) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000151 double ab0y = a[0].fY - b[0].fY;
152 double ab0x = a[0].fX - b[0].fX;
153 double numerA = ab0y * bxLen - byLen * ab0x;
154 double numerB = ab0y * axLen - ayLen * ab0x;
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000155 double denom = axByLen - ayBxLen;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000156 if (between(0, numerA, denom) && between(0, numerB, denom)) {
157 fT[0][0] = numerA / denom;
158 fT[1][0] = numerB / denom;
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000159 computePoints(a, 1);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000160 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000161 }
caryclarkdac1d172014-06-17 05:15:38 -0700162/* Allow tracking that both sets of end points are near each other -- the lines are entirely
163 coincident -- even when the end points are not exactly the same.
164 Mark this as a 'wild card' for the end points, so that either point is considered totally
165 coincident. Then, avoid folding the lines over each other, but allow either end to mate
166 to the next set of lines.
167 */
caryclark@google.com570863f2013-09-16 15:55:01 +0000168 if (fAllowNear || !unparallel) {
caryclarkdac1d172014-06-17 05:15:38 -0700169 double aNearB[2];
170 double bNearA[2];
171 bool aNotB[2] = {false, false};
172 bool bNotA[2] = {false, false};
173 int nearCount = 0;
174 for (int index = 0; index < 2; ++index) {
175 aNearB[index] = t = b.nearPoint(a[index], &aNotB[index]);
176 nearCount += t >= 0;
177 bNearA[index] = t = a.nearPoint(b[index], &bNotA[index]);
178 nearCount += t >= 0;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000179 }
caryclarkdac1d172014-06-17 05:15:38 -0700180 if (nearCount > 0) {
caryclark19eb3b22014-07-18 05:08:14 -0700181 // Skip if each segment contributes to one end point.
182 if (nearCount != 2 || aNotB[0] == aNotB[1]) {
183 for (int iA = 0; iA < 2; ++iA) {
184 if (!aNotB[iA]) {
185 continue;
186 }
187 int nearer = aNearB[iA] > 0.5;
188 if (!bNotA[nearer]) {
189 continue;
190 }
191 SkASSERT(a[iA] != b[nearer]);
192 SkASSERT(iA == (bNearA[nearer] > 0.5));
193 fNearlySame[iA] = true;
194 insertNear(iA, nearer, a[iA], b[nearer]);
195 aNearB[iA] = -1;
196 bNearA[nearer] = -1;
197 nearCount -= 2;
caryclarkdac1d172014-06-17 05:15:38 -0700198 }
caryclarkdac1d172014-06-17 05:15:38 -0700199 }
200 if (nearCount > 0) {
201 for (int iA = 0; iA < 2; ++iA) {
202 if (aNearB[iA] >= 0) {
203 insert(iA, aNearB[iA], a[iA]);
204 }
205 }
206 for (int iB = 0; iB < 2; ++iB) {
207 if (bNearA[iB] >= 0) {
208 insert(bNearA[iB], iB, b[iB]);
209 }
210 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000211 }
212 }
213 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000214 cleanUpParallelLines(!unparallel);
215 SkASSERT(fUsed <= 2);
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000216 return fUsed;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000217}
218
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000219static int horizontal_coincident(const SkDLine& line, double y) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000220 double min = line[0].fY;
221 double max = line[1].fY;
222 if (min > max) {
223 SkTSwap(min, max);
224 }
225 if (min > y || max < y) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000226 return 0;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000227 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000228 if (AlmostEqualUlps(min, max) && max - min < fabs(line[0].fX - line[1].fX)) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000229 return 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000230 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000231 return 1;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000232}
233
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000234static double horizontal_intercept(const SkDLine& line, double y) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000235 return SkPinT((y - line[0].fY) / (line[1].fY - line[0].fY));
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000236}
237
238int SkIntersections::horizontal(const SkDLine& line, double y) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000239 fMax = 2;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000240 int horizontalType = horizontal_coincident(line, y);
241 if (horizontalType == 1) {
242 fT[0][0] = horizontal_intercept(line, y);
243 } else if (horizontalType == 2) {
244 fT[0][0] = 0;
245 fT[0][1] = 1;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000246 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000247 return fUsed = horizontalType;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000248}
249
caryclark@google.com07393ca2013-04-08 11:47:37 +0000250int SkIntersections::horizontal(const SkDLine& line, double left, double right,
251 double y, bool flipped) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000252 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 +0000253 // see if end points intersect the opposite line
254 double t;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000255 const SkDPoint leftPt = { left, y };
256 if ((t = line.exactPoint(leftPt)) >= 0) {
257 insert(t, (double) flipped, leftPt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000258 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000259 if (left != right) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000260 const SkDPoint rightPt = { right, y };
261 if ((t = line.exactPoint(rightPt)) >= 0) {
262 insert(t, (double) !flipped, rightPt);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000263 }
264 for (int index = 0; index < 2; ++index) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000265 if ((t = SkDLine::ExactPointH(line[index], left, right, y)) >= 0) {
266 insert((double) index, flipped ? 1 - t : t, line[index]);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000267 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000268 }
269 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000270 int result = horizontal_coincident(line, y);
271 if (result == 1 && fUsed == 0) {
272 fT[0][0] = horizontal_intercept(line, y);
273 double xIntercept = line[0].fX + fT[0][0] * (line[1].fX - line[0].fX);
274 if (between(left, xIntercept, right)) {
275 fT[1][0] = (xIntercept - left) / (right - left);
276 if (flipped) {
277 // OPTIMIZATION: ? instead of swapping, pass original line, use [1].fX - [0].fX
278 for (int index = 0; index < result; ++index) {
279 fT[1][index] = 1 - fT[1][index];
280 }
281 }
caryclark@google.com15107262013-11-08 18:00:01 +0000282 fPt[0].fX = xIntercept;
283 fPt[0].fY = y;
284 fUsed = 1;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000285 }
286 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000287 if (fAllowNear || result == 2) {
caryclarkdac1d172014-06-17 05:15:38 -0700288 if ((t = line.nearPoint(leftPt, NULL)) >= 0) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000289 insert(t, (double) flipped, leftPt);
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000290 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000291 if (left != right) {
292 const SkDPoint rightPt = { right, y };
caryclarkdac1d172014-06-17 05:15:38 -0700293 if ((t = line.nearPoint(rightPt, NULL)) >= 0) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000294 insert(t, (double) !flipped, rightPt);
295 }
296 for (int index = 0; index < 2; ++index) {
297 if ((t = SkDLine::NearPointH(line[index], left, right, y)) >= 0) {
298 insert((double) index, flipped ? 1 - t : t, line[index]);
299 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000300 }
301 }
302 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000303 cleanUpParallelLines(result == 2);
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000304 return fUsed;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000305}
306
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000307static int vertical_coincident(const SkDLine& line, double x) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000308 double min = line[0].fX;
309 double max = line[1].fX;
310 if (min > max) {
311 SkTSwap(min, max);
312 }
caryclark@google.com03610322013-04-18 15:58:21 +0000313 if (!precisely_between(min, x, max)) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000314 return 0;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000315 }
316 if (AlmostEqualUlps(min, max)) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000317 return 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000318 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000319 return 1;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000320}
321
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000322static double vertical_intercept(const SkDLine& line, double x) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000323 return SkPinT((x - line[0].fX) / (line[1].fX - line[0].fX));
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000324}
325
326int SkIntersections::vertical(const SkDLine& line, double x) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000327 fMax = 2;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000328 int verticalType = vertical_coincident(line, x);
329 if (verticalType == 1) {
330 fT[0][0] = vertical_intercept(line, x);
331 } else if (verticalType == 2) {
332 fT[0][0] = 0;
333 fT[0][1] = 1;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000334 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000335 return fUsed = verticalType;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000336}
337
338int SkIntersections::vertical(const SkDLine& line, double top, double bottom,
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000339 double x, bool flipped) {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000340 fMax = 3; // cleanup parallel lines will bring this back line
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000341 // see if end points intersect the opposite line
342 double t;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000343 SkDPoint topPt = { x, top };
344 if ((t = line.exactPoint(topPt)) >= 0) {
345 insert(t, (double) flipped, topPt);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000346 }
347 if (top != bottom) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000348 SkDPoint bottomPt = { x, bottom };
349 if ((t = line.exactPoint(bottomPt)) >= 0) {
350 insert(t, (double) !flipped, bottomPt);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000351 }
352 for (int index = 0; index < 2; ++index) {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000353 if ((t = SkDLine::ExactPointV(line[index], top, bottom, x)) >= 0) {
354 insert((double) index, flipped ? 1 - t : t, line[index]);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000355 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000356 }
357 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000358 int result = vertical_coincident(line, x);
359 if (result == 1 && fUsed == 0) {
360 fT[0][0] = vertical_intercept(line, x);
361 double yIntercept = line[0].fY + fT[0][0] * (line[1].fY - line[0].fY);
362 if (between(top, yIntercept, bottom)) {
363 fT[1][0] = (yIntercept - top) / (bottom - top);
364 if (flipped) {
365 // OPTIMIZATION: instead of swapping, pass original line, use [1].fY - [0].fY
366 for (int index = 0; index < result; ++index) {
367 fT[1][index] = 1 - fT[1][index];
368 }
369 }
caryclark@google.com15107262013-11-08 18:00:01 +0000370 fPt[0].fX = x;
371 fPt[0].fY = yIntercept;
372 fUsed = 1;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000373 }
374 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000375 if (fAllowNear || result == 2) {
caryclarkdac1d172014-06-17 05:15:38 -0700376 if ((t = line.nearPoint(topPt, NULL)) >= 0) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000377 insert(t, (double) flipped, topPt);
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000378 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000379 if (top != bottom) {
380 SkDPoint bottomPt = { x, bottom };
caryclarkdac1d172014-06-17 05:15:38 -0700381 if ((t = line.nearPoint(bottomPt, NULL)) >= 0) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000382 insert(t, (double) !flipped, bottomPt);
383 }
384 for (int index = 0; index < 2; ++index) {
385 if ((t = SkDLine::NearPointV(line[index], top, bottom, x)) >= 0) {
386 insert((double) index, flipped ? 1 - t : t, line[index]);
387 }
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000388 }
389 }
390 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000391 cleanUpParallelLines(result == 2);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000392 SkASSERT(fUsed <= 2);
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000393 return fUsed;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000394}
395
396// from http://www.bryceboe.com/wordpress/wp-content/uploads/2006/10/intersect.py
397// 4 subs, 2 muls, 1 cmp
398static bool ccw(const SkDPoint& A, const SkDPoint& B, const SkDPoint& C) {
399 return (C.fY - A.fY) * (B.fX - A.fX) > (B.fY - A.fY) * (C.fX - A.fX);
400}
401
402// 16 subs, 8 muls, 6 cmps
403bool SkIntersections::Test(const SkDLine& a, const SkDLine& b) {
404 return ccw(a[0], b[0], b[1]) != ccw(a[1], b[0], b[1])
405 && ccw(a[0], a[1], b[0]) != ccw(a[0], a[1], b[1]);
406}