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

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

Issue 1111333002: compute initial winding from projected rays (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: add missing test reference Created 5 years, 7 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/SkDLineIntersection.cpp ('k') | src/pathops/SkIntersections.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 #include "SkPathOpsQuad.h" 9 #include "SkPathOpsQuad.h"
10 10
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 88
89 class LineQuadraticIntersections { 89 class LineQuadraticIntersections {
90 public: 90 public:
91 enum PinTPoint { 91 enum PinTPoint {
92 kPointUninitialized, 92 kPointUninitialized,
93 kPointInitialized 93 kPointInitialized
94 }; 94 };
95 95
96 LineQuadraticIntersections(const SkDQuad& q, const SkDLine& l, SkIntersectio ns* i) 96 LineQuadraticIntersections(const SkDQuad& q, const SkDLine& l, SkIntersectio ns* i)
97 : fQuad(q) 97 : fQuad(q)
98 , fLine(l) 98 , fLine(&l)
99 , fIntersections(i) 99 , fIntersections(i)
100 , fAllowNear(true) { 100 , fAllowNear(true) {
101 i->setMax(3); // allow short partial coincidence plus discrete intersec tion 101 i->setMax(3); // allow short partial coincidence plus discrete intersec tion
102 } 102 }
103 103
104 LineQuadraticIntersections(const SkDQuad& q)
105 : fQuad(q)
106 SkDEBUGPARAMS(fLine(NULL))
107 SkDEBUGPARAMS(fIntersections(NULL))
108 SkDEBUGPARAMS(fAllowNear(false)) {
109 }
110
104 void allowNear(bool allow) { 111 void allowNear(bool allow) {
105 fAllowNear = allow; 112 fAllowNear = allow;
106 } 113 }
107 114
108 void checkCoincident() { 115 void checkCoincident() {
109 int last = fIntersections->used() - 1; 116 int last = fIntersections->used() - 1;
110 for (int index = 0; index < last; ) { 117 for (int index = 0; index < last; ) {
111 double quadMidT = ((*fIntersections)[0][index] + (*fIntersections)[0 ][index + 1]) / 2; 118 double quadMidT = ((*fIntersections)[0][index] + (*fIntersections)[0 ][index + 1]) / 2;
112 SkDPoint quadMidPt = fQuad.ptAtT(quadMidT); 119 SkDPoint quadMidPt = fQuad.ptAtT(quadMidT);
113 double t = fLine.nearPoint(quadMidPt, NULL); 120 double t = fLine->nearPoint(quadMidPt, NULL);
114 if (t < 0) { 121 if (t < 0) {
115 ++index; 122 ++index;
116 continue; 123 continue;
117 } 124 }
118 if (fIntersections->isCoincident(index)) { 125 if (fIntersections->isCoincident(index)) {
119 fIntersections->removeOne(index); 126 fIntersections->removeOne(index);
120 --last; 127 --last;
121 } else if (fIntersections->isCoincident(index + 1)) { 128 } else if (fIntersections->isCoincident(index + 1)) {
122 fIntersections->removeOne(index + 1); 129 fIntersections->removeOne(index + 1);
123 --last; 130 --last;
(...skipping 13 matching lines...) Expand all
137 note that cos(a) = A(djacent) / Hypoteneuse 144 note that cos(a) = A(djacent) / Hypoteneuse
138 sin(a) = O(pposite) / Hypoteneuse 145 sin(a) = O(pposite) / Hypoteneuse
139 since we are computing Ts, we can ignore hypoteneuse, the scale factor: 146 since we are computing Ts, we can ignore hypoteneuse, the scale factor:
140 | A -O | 147 | A -O |
141 | O A | 148 | O A |
142 A = line[1].fX - line[0].fX (adjacent side of the right triangle) 149 A = line[1].fX - line[0].fX (adjacent side of the right triangle)
143 O = line[1].fY - line[0].fY (opposite side of the right triangle) 150 O = line[1].fY - line[0].fY (opposite side of the right triangle)
144 for each of the three points (e.g. n = 0 to 2) 151 for each of the three points (e.g. n = 0 to 2)
145 quad[n].fY' = (quad[n].fY - line[0].fY) * A - (quad[n].fX - line[0].fX) * O 152 quad[n].fY' = (quad[n].fY - line[0].fY) * A - (quad[n].fX - line[0].fX) * O
146 */ 153 */
147 double adj = fLine[1].fX - fLine[0].fX; 154 double adj = (*fLine)[1].fX - (*fLine)[0].fX;
148 double opp = fLine[1].fY - fLine[0].fY; 155 double opp = (*fLine)[1].fY - (*fLine)[0].fY;
149 double r[3]; 156 double r[3];
150 for (int n = 0; n < 3; ++n) { 157 for (int n = 0; n < 3; ++n) {
151 r[n] = (fQuad[n].fY - fLine[0].fY) * adj - (fQuad[n].fX - fLine[0].f X) * opp; 158 r[n] = (fQuad[n].fY - (*fLine)[0].fY) * adj - (fQuad[n].fX - (*fLine )[0].fX) * opp;
152 } 159 }
153 double A = r[2]; 160 double A = r[2];
154 double B = r[1]; 161 double B = r[1];
155 double C = r[0]; 162 double C = r[0];
156 A += C - 2 * B; // A = a - 2*b + c 163 A += C - 2 * B; // A = a - 2*b + c
157 B -= C; // B = -(b - c) 164 B -= C; // B = -(b - c)
158 return SkDQuad::RootsValidT(A, 2 * B, C, roots); 165 return SkDQuad::RootsValidT(A, 2 * B, C, roots);
159 } 166 }
160 167
161 int intersect() { 168 int intersect() {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 fIntersections->flip(); 269 fIntersections->flip();
263 } 270 }
264 checkCoincident(); 271 checkCoincident();
265 return fIntersections->used(); 272 return fIntersections->used();
266 } 273 }
267 274
268 protected: 275 protected:
269 // add endpoints first to get zero and one t values exactly 276 // add endpoints first to get zero and one t values exactly
270 void addExactEndPoints() { 277 void addExactEndPoints() {
271 for (int qIndex = 0; qIndex < 3; qIndex += 2) { 278 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
272 double lineT = fLine.exactPoint(fQuad[qIndex]); 279 double lineT = fLine->exactPoint(fQuad[qIndex]);
273 if (lineT < 0) { 280 if (lineT < 0) {
274 continue; 281 continue;
275 } 282 }
276 double quadT = (double) (qIndex >> 1); 283 double quadT = (double) (qIndex >> 1);
277 fIntersections->insert(quadT, lineT, fQuad[qIndex]); 284 fIntersections->insert(quadT, lineT, fQuad[qIndex]);
278 } 285 }
279 } 286 }
280 287
281 void addNearEndPoints() { 288 void addNearEndPoints() {
282 for (int qIndex = 0; qIndex < 3; qIndex += 2) { 289 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
283 double quadT = (double) (qIndex >> 1); 290 double quadT = (double) (qIndex >> 1);
284 if (fIntersections->hasT(quadT)) { 291 if (fIntersections->hasT(quadT)) {
285 continue; 292 continue;
286 } 293 }
287 double lineT = fLine.nearPoint(fQuad[qIndex], NULL); 294 double lineT = fLine->nearPoint(fQuad[qIndex], NULL);
288 if (lineT < 0) { 295 if (lineT < 0) {
289 continue; 296 continue;
290 } 297 }
291 fIntersections->insert(quadT, lineT, fQuad[qIndex]); 298 fIntersections->insert(quadT, lineT, fQuad[qIndex]);
292 } 299 }
293 // FIXME: see if line end is nearly on quad 300 // FIXME: see if line end is nearly on quad
294 } 301 }
295 302
296 void addExactHorizontalEndPoints(double left, double right, double y) { 303 void addExactHorizontalEndPoints(double left, double right, double y) {
297 for (int qIndex = 0; qIndex < 3; qIndex += 2) { 304 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 if (lineT < 0) { 347 if (lineT < 0) {
341 continue; 348 continue;
342 } 349 }
343 fIntersections->insert(quadT, lineT, fQuad[qIndex]); 350 fIntersections->insert(quadT, lineT, fQuad[qIndex]);
344 } 351 }
345 // FIXME: see if line end is nearly on quad 352 // FIXME: see if line end is nearly on quad
346 } 353 }
347 354
348 double findLineT(double t) { 355 double findLineT(double t) {
349 SkDPoint xy = fQuad.ptAtT(t); 356 SkDPoint xy = fQuad.ptAtT(t);
350 double dx = fLine[1].fX - fLine[0].fX; 357 double dx = (*fLine)[1].fX - (*fLine)[0].fX;
351 double dy = fLine[1].fY - fLine[0].fY; 358 double dy = (*fLine)[1].fY - (*fLine)[0].fY;
352 if (fabs(dx) > fabs(dy)) { 359 if (fabs(dx) > fabs(dy)) {
353 return (xy.fX - fLine[0].fX) / dx; 360 return (xy.fX - (*fLine)[0].fX) / dx;
354 } 361 }
355 return (xy.fY - fLine[0].fY) / dy; 362 return (xy.fY - (*fLine)[0].fY) / dy;
356 } 363 }
357 364
358 bool pinTs(double* quadT, double* lineT, SkDPoint* pt, PinTPoint ptSet) { 365 bool pinTs(double* quadT, double* lineT, SkDPoint* pt, PinTPoint ptSet) {
359 if (!approximately_one_or_less_double(*lineT)) { 366 if (!approximately_one_or_less_double(*lineT)) {
360 return false; 367 return false;
361 } 368 }
362 if (!approximately_zero_or_more_double(*lineT)) { 369 if (!approximately_zero_or_more_double(*lineT)) {
363 return false; 370 return false;
364 } 371 }
365 double qT = *quadT = SkPinT(*quadT); 372 double qT = *quadT = SkPinT(*quadT);
366 double lT = *lineT = SkPinT(*lineT); 373 double lT = *lineT = SkPinT(*lineT);
367 if (lT == 0 || lT == 1 || (ptSet == kPointUninitialized && qT != 0 && qT != 1)) { 374 if (lT == 0 || lT == 1 || (ptSet == kPointUninitialized && qT != 0 && qT != 1)) {
368 *pt = fLine.ptAtT(lT); 375 *pt = (*fLine).ptAtT(lT);
369 } else if (ptSet == kPointUninitialized) { 376 } else if (ptSet == kPointUninitialized) {
370 *pt = fQuad.ptAtT(qT); 377 *pt = fQuad.ptAtT(qT);
371 } 378 }
372 SkPoint gridPt = pt->asSkPoint(); 379 SkPoint gridPt = pt->asSkPoint();
373 if (SkDPoint::ApproximatelyEqual(gridPt, fLine[0].asSkPoint())) { 380 if (SkDPoint::ApproximatelyEqual(gridPt, (*fLine)[0].asSkPoint())) {
374 *pt = fLine[0]; 381 *pt = (*fLine)[0];
375 *lineT = 0; 382 *lineT = 0;
376 } else if (SkDPoint::ApproximatelyEqual(gridPt, fLine[1].asSkPoint())) { 383 } else if (SkDPoint::ApproximatelyEqual(gridPt, (*fLine)[1].asSkPoint()) ) {
377 *pt = fLine[1]; 384 *pt = (*fLine)[1];
378 *lineT = 1; 385 *lineT = 1;
379 } 386 }
380 if (fIntersections->used() > 0 && approximately_equal((*fIntersections)[ 1][0], *lineT)) { 387 if (fIntersections->used() > 0 && approximately_equal((*fIntersections)[ 1][0], *lineT)) {
381 return false; 388 return false;
382 } 389 }
383 if (gridPt == fQuad[0].asSkPoint()) { 390 if (gridPt == fQuad[0].asSkPoint()) {
384 *pt = fQuad[0]; 391 *pt = fQuad[0];
385 *quadT = 0; 392 *quadT = 0;
386 } else if (gridPt == fQuad[2].asSkPoint()) { 393 } else if (gridPt == fQuad[2].asSkPoint()) {
387 *pt = fQuad[2]; 394 *pt = fQuad[2];
388 *quadT = 1; 395 *quadT = 1;
389 } 396 }
390 return true; 397 return true;
391 } 398 }
392 399
393 private: 400 private:
394 const SkDQuad& fQuad; 401 const SkDQuad& fQuad;
395 const SkDLine& fLine; 402 const SkDLine* fLine;
396 SkIntersections* fIntersections; 403 SkIntersections* fIntersections;
397 bool fAllowNear; 404 bool fAllowNear;
398 }; 405 };
399 406
400 int SkIntersections::horizontal(const SkDQuad& quad, double left, double right, double y, 407 int SkIntersections::horizontal(const SkDQuad& quad, double left, double right, double y,
401 bool flipped) { 408 bool flipped) {
402 SkDLine line = {{{ left, y }, { right, y }}}; 409 SkDLine line = {{{ left, y }, { right, y }}};
403 LineQuadraticIntersections q(quad, line, this); 410 LineQuadraticIntersections q(quad, line, this);
404 return q.horizontalIntersect(y, left, right, flipped); 411 return q.horizontalIntersect(y, left, right, flipped);
405 } 412 }
(...skipping 12 matching lines...) Expand all
418 } 425 }
419 426
420 int SkIntersections::intersectRay(const SkDQuad& quad, const SkDLine& line) { 427 int SkIntersections::intersectRay(const SkDQuad& quad, const SkDLine& line) {
421 LineQuadraticIntersections q(quad, line, this); 428 LineQuadraticIntersections q(quad, line, this);
422 fUsed = q.intersectRay(fT[0]); 429 fUsed = q.intersectRay(fT[0]);
423 for (int index = 0; index < fUsed; ++index) { 430 for (int index = 0; index < fUsed; ++index) {
424 fPt[index] = quad.ptAtT(fT[0][index]); 431 fPt[index] = quad.ptAtT(fT[0][index]);
425 } 432 }
426 return fUsed; 433 return fUsed;
427 } 434 }
435
436 int SkIntersections::HorizontalIntercept(const SkDQuad& quad, SkScalar y, double * roots) {
437 LineQuadraticIntersections q(quad);
438 return q.horizontalIntersect(y, roots);
439 }
440
441 int SkIntersections::VerticalIntercept(const SkDQuad& quad, SkScalar x, double* roots) {
442 LineQuadraticIntersections q(quad);
443 return q.verticalIntersect(x, roots);
444 }
OLDNEW
« no previous file with comments | « src/pathops/SkDLineIntersection.cpp ('k') | src/pathops/SkIntersections.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698