Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1379)

Side by Side Diff: src/pathops/SkDLineIntersection.cpp

Issue 1037573004: cumulative pathops patch (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix pathopsinverse gm Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pathops/SkDCubicToQuads.cpp ('k') | src/pathops/SkDQuadImplicit.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 #include "SkIntersections.h" 7 #include "SkIntersections.h"
8 #include "SkPathOpsLine.h" 8 #include "SkPathOpsLine.h"
9 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 */
14 SkDPoint 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
29 int 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;
45 tryAgain: ;
46 } while (true);
47 }
48
49 void SkIntersections::cleanUpParallelLines(bool parallel) { 10 void SkIntersections::cleanUpParallelLines(bool parallel) {
50 while (fUsed > 2) { 11 while (fUsed > 2) {
51 removeOne(1); 12 removeOne(1);
52 } 13 }
53 if (fUsed == 2 && !parallel) { 14 if (fUsed == 2 && !parallel) {
54 bool startMatch = fT[0][0] == 0 || fT[1][0] == 0 || fT[1][0] == 1; 15 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; 16 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] )) { 17 if ((!startMatch && !endMatch) || approximately_equal(fT[0][0], fT[0][1] )) {
57 SkASSERT(startMatch || endMatch); 18 SkASSERT(startMatch || endMatch);
58 removeOne(endMatch); 19 removeOne(endMatch);
59 } 20 }
60 } 21 }
22 if (fUsed == 2) {
23 fIsCoincident[0] = fIsCoincident[1] = 0x03;
24 }
61 } 25 }
62 26
63 void SkIntersections::computePoints(const SkDLine& line, int used) { 27 void SkIntersections::computePoints(const SkDLine& line, int used) {
64 fPt[0] = line.ptAtT(fT[0][0]); 28 fPt[0] = line.ptAtT(fT[0][0]);
65 if ((fUsed = used) == 2) { 29 if ((fUsed = used) == 2) {
66 fPt[1] = line.ptAtT(fT[0][1]); 30 fPt[1] = line.ptAtT(fT[0][1]);
67 } 31 }
68 } 32 }
69 33
70 int SkIntersections::intersectRay(const SkDLine& a, const SkDLine& b) { 34 int SkIntersections::intersectRay(const SkDLine& a, const SkDLine& b) {
71 fMax = 2; 35 fMax = 2;
72 SkDVector aLen = a[1] - a[0]; 36 SkDVector aLen = a[1] - a[0];
73 SkDVector bLen = b[1] - b[0]; 37 SkDVector bLen = b[1] - b[0];
74 /* Slopes match when denom goes to zero: 38 /* Slopes match when denom goes to zero:
75 axLen / ayLen == bxLen / byLen 39 axLen / ayLen == bxLen / byLen
76 (ayLen * byLen) * axLen / ayLen == (ayLen * byLen) * bxLen / byLen 40 (ayLen * byLen) * axLen / ayLen == (ayLen * byLen) * bxLen / byLen
77 byLen * axLen == ayLen * bxLen 41 byLen * axLen == ayLen * bxLen
78 byLen * axLen - ayLen * bxLen == 0 ( == denom ) 42 byLen * axLen - ayLen * bxLen == 0 ( == denom )
79 */ 43 */
80 double denom = bLen.fY * aLen.fX - aLen.fY * bLen.fX; 44 double denom = bLen.fY * aLen.fX - aLen.fY * bLen.fX;
81 SkDVector ab0 = a[0] - b[0]; 45 SkDVector ab0 = a[0] - b[0];
82 double numerA = ab0.fY * bLen.fX - bLen.fY * ab0.fX; 46 double numerA = ab0.fY * bLen.fX - bLen.fY * ab0.fX;
83 double numerB = ab0.fY * aLen.fX - aLen.fY * ab0.fX; 47 double numerB = ab0.fY * aLen.fX - aLen.fY * ab0.fX;
84 #if 0
85 if (!between(0, numerA, denom) || !between(0, numerB, denom)) {
86 fUsed = 0;
87 return 0;
88 }
89 #endif
90 numerA /= denom; 48 numerA /= denom;
91 numerB /= denom; 49 numerB /= denom;
92 int used; 50 int used;
93 if (!approximately_zero(denom)) { 51 if (!approximately_zero(denom)) {
94 fT[0][0] = numerA; 52 fT[0][0] = numerA;
95 fT[1][0] = numerB; 53 fT[1][0] = numerB;
96 used = 1; 54 used = 1;
97 } else { 55 } else {
98 /* See if the axis intercepts match: 56 /* See if the axis intercepts match:
99 ay - ax * ayLen / axLen == by - bx * ayLen / axLen 57 ay - ax * ayLen / axLen == by - bx * ayLen / axLen
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 for (int iA = 0; iA < 2; ++iA) { 141 for (int iA = 0; iA < 2; ++iA) {
184 if (!aNotB[iA]) { 142 if (!aNotB[iA]) {
185 continue; 143 continue;
186 } 144 }
187 int nearer = aNearB[iA] > 0.5; 145 int nearer = aNearB[iA] > 0.5;
188 if (!bNotA[nearer]) { 146 if (!bNotA[nearer]) {
189 continue; 147 continue;
190 } 148 }
191 SkASSERT(a[iA] != b[nearer]); 149 SkASSERT(a[iA] != b[nearer]);
192 SkASSERT(iA == (bNearA[nearer] > 0.5)); 150 SkASSERT(iA == (bNearA[nearer] > 0.5));
193 fNearlySame[iA] = true;
194 insertNear(iA, nearer, a[iA], b[nearer]); 151 insertNear(iA, nearer, a[iA], b[nearer]);
195 aNearB[iA] = -1; 152 aNearB[iA] = -1;
196 bNearA[nearer] = -1; 153 bNearA[nearer] = -1;
197 nearCount -= 2; 154 nearCount -= 2;
198 } 155 }
199 } 156 }
200 if (nearCount > 0) { 157 if (nearCount > 0) {
201 for (int iA = 0; iA < 2; ++iA) { 158 for (int iA = 0; iA < 2; ++iA) {
202 if (aNearB[iA] >= 0) { 159 if (aNearB[iA] >= 0) {
203 insert(iA, aNearB[iA], a[iA]); 160 insert(iA, aNearB[iA], a[iA]);
(...skipping 24 matching lines...) Expand all
228 if (AlmostEqualUlps(min, max) && max - min < fabs(line[0].fX - line[1].fX)) { 185 if (AlmostEqualUlps(min, max) && max - min < fabs(line[0].fX - line[1].fX)) {
229 return 2; 186 return 2;
230 } 187 }
231 return 1; 188 return 1;
232 } 189 }
233 190
234 static double horizontal_intercept(const SkDLine& line, double y) { 191 static double horizontal_intercept(const SkDLine& line, double y) {
235 return SkPinT((y - line[0].fY) / (line[1].fY - line[0].fY)); 192 return SkPinT((y - line[0].fY) / (line[1].fY - line[0].fY));
236 } 193 }
237 194
238 int SkIntersections::horizontal(const SkDLine& line, double y) {
239 fMax = 2;
240 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;
246 }
247 return fUsed = horizontalType;
248 }
249
250 int SkIntersections::horizontal(const SkDLine& line, double left, double right, 195 int SkIntersections::horizontal(const SkDLine& line, double left, double right,
251 double y, bool flipped) { 196 double y, bool flipped) {
252 fMax = 3; // clean up parallel at the end will limit the result to 2 at the most 197 fMax = 3; // clean up parallel at the end will limit the result to 2 at the most
253 // see if end points intersect the opposite line 198 // see if end points intersect the opposite line
254 double t; 199 double t;
255 const SkDPoint leftPt = { left, y }; 200 const SkDPoint leftPt = { left, y };
256 if ((t = line.exactPoint(leftPt)) >= 0) { 201 if ((t = line.exactPoint(leftPt)) >= 0) {
257 insert(t, (double) flipped, leftPt); 202 insert(t, (double) flipped, leftPt);
258 } 203 }
259 if (left != right) { 204 if (left != right) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 if (AlmostEqualUlps(min, max)) { 261 if (AlmostEqualUlps(min, max)) {
317 return 2; 262 return 2;
318 } 263 }
319 return 1; 264 return 1;
320 } 265 }
321 266
322 static double vertical_intercept(const SkDLine& line, double x) { 267 static double vertical_intercept(const SkDLine& line, double x) {
323 return SkPinT((x - line[0].fX) / (line[1].fX - line[0].fX)); 268 return SkPinT((x - line[0].fX) / (line[1].fX - line[0].fX));
324 } 269 }
325 270
326 int SkIntersections::vertical(const SkDLine& line, double x) {
327 fMax = 2;
328 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;
334 }
335 return fUsed = verticalType;
336 }
337
338 int SkIntersections::vertical(const SkDLine& line, double top, double bottom, 271 int SkIntersections::vertical(const SkDLine& line, double top, double bottom,
339 double x, bool flipped) { 272 double x, bool flipped) {
340 fMax = 3; // cleanup parallel lines will bring this back line 273 fMax = 3; // cleanup parallel lines will bring this back line
341 // see if end points intersect the opposite line 274 // see if end points intersect the opposite line
342 double t; 275 double t;
343 SkDPoint topPt = { x, top }; 276 SkDPoint topPt = { x, top };
344 if ((t = line.exactPoint(topPt)) >= 0) { 277 if ((t = line.exactPoint(topPt)) >= 0) {
345 insert(t, (double) flipped, topPt); 278 insert(t, (double) flipped, topPt);
346 } 279 }
347 if (top != bottom) { 280 if (top != bottom) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 insert((double) index, flipped ? 1 - t : t, line[index]); 319 insert((double) index, flipped ? 1 - t : t, line[index]);
387 } 320 }
388 } 321 }
389 } 322 }
390 } 323 }
391 cleanUpParallelLines(result == 2); 324 cleanUpParallelLines(result == 2);
392 SkASSERT(fUsed <= 2); 325 SkASSERT(fUsed <= 2);
393 return fUsed; 326 return fUsed;
394 } 327 }
395 328
396 // from http://www.bryceboe.com/wordpress/wp-content/uploads/2006/10/intersect.p y
397 // 4 subs, 2 muls, 1 cmp
398 static 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
403 bool 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 }
OLDNEW
« no previous file with comments | « src/pathops/SkDCubicToQuads.cpp ('k') | src/pathops/SkDQuadImplicit.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698