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

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

Issue 1002693002: pathops version two (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix arm 64 inspired coincident handling Created 5 years, 9 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/SkDCubicIntersection.cpp ('k') | src/pathops/SkDCubicToQuads.cpp » ('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 "SkPathOpsCubic.h" 8 #include "SkPathOpsCubic.h"
9 #include "SkPathOpsLine.h" 9 #include "SkPathOpsLine.h"
10 10
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 , fLine(l) 86 , fLine(l)
87 , fIntersections(i) 87 , fIntersections(i)
88 , fAllowNear(true) { 88 , fAllowNear(true) {
89 i->setMax(3); 89 i->setMax(3);
90 } 90 }
91 91
92 void allowNear(bool allow) { 92 void allowNear(bool allow) {
93 fAllowNear = allow; 93 fAllowNear = allow;
94 } 94 }
95 95
96 void checkCoincident() {
97 int last = fIntersections->used() - 1;
98 for (int index = 0; index < last; ) {
99 double cubicMidT = ((*fIntersections)[0][index] + (*fIntersections)[ 0][index + 1]) / 2;
100 SkDPoint cubicMidPt = fCubic.ptAtT(cubicMidT);
101 double t = fLine.nearPoint(cubicMidPt, NULL);
102 if (t < 0) {
103 ++index;
104 continue;
105 }
106 if (fIntersections->isCoincident(index)) {
107 fIntersections->removeOne(index);
108 --last;
109 } else if (fIntersections->isCoincident(index + 1)) {
110 fIntersections->removeOne(index + 1);
111 --last;
112 } else {
113 fIntersections->setCoincident(index++);
114 }
115 fIntersections->setCoincident(index);
116 }
117 }
118
96 // see parallel routine in line quadratic intersections 119 // see parallel routine in line quadratic intersections
97 int intersectRay(double roots[3]) { 120 int intersectRay(double roots[3]) {
98 double adj = fLine[1].fX - fLine[0].fX; 121 double adj = fLine[1].fX - fLine[0].fX;
99 double opp = fLine[1].fY - fLine[0].fY; 122 double opp = fLine[1].fY - fLine[0].fY;
100 SkDCubic c; 123 SkDCubic c;
101 for (int n = 0; n < 4; ++n) { 124 for (int n = 0; n < 4; ++n) {
102 c[n].fX = (fCubic[n].fY - fLine[0].fY) * adj - (fCubic[n].fX - fLine [0].fX) * opp; 125 c[n].fX = (fCubic[n].fY - fLine[0].fY) * adj - (fCubic[n].fX - fLine [0].fX) * opp;
103 } 126 }
104 double A, B, C, D; 127 double A, B, C, D;
105 SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D); 128 SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D);
(...skipping 18 matching lines...) Expand all
124 addExactEndPoints(); 147 addExactEndPoints();
125 if (fAllowNear) { 148 if (fAllowNear) {
126 addNearEndPoints(); 149 addNearEndPoints();
127 } 150 }
128 double rootVals[3]; 151 double rootVals[3];
129 int roots = intersectRay(rootVals); 152 int roots = intersectRay(rootVals);
130 for (int index = 0; index < roots; ++index) { 153 for (int index = 0; index < roots; ++index) {
131 double cubicT = rootVals[index]; 154 double cubicT = rootVals[index];
132 double lineT = findLineT(cubicT); 155 double lineT = findLineT(cubicT);
133 SkDPoint pt; 156 SkDPoint pt;
134 if (pinTs(&cubicT, &lineT, &pt, kPointUninitialized)) { 157 if (pinTs(&cubicT, &lineT, &pt, kPointUninitialized) && uniqueAnswer (cubicT, pt)) {
135 #if ONE_OFF_DEBUG
136 SkDPoint cPt = fCubic.ptAtT(cubicT);
137 SkDebugf("%s pt=(%1.9g,%1.9g) cPt=(%1.9g,%1.9g)\n", __FUNCTION__ , pt.fX, pt.fY,
138 cPt.fX, cPt.fY);
139 #endif
140 for (int inner = 0; inner < fIntersections->used(); ++inner) {
141 if (fIntersections->pt(inner) != pt) {
142 continue;
143 }
144 double existingCubicT = (*fIntersections)[0][inner];
145 if (cubicT == existingCubicT) {
146 goto skipInsert;
147 }
148 // check if midway on cubic is also same point. If so, disca rd this
149 double cubicMidT = (existingCubicT + cubicT) / 2;
150 SkDPoint cubicMidPt = fCubic.ptAtT(cubicMidT);
151 if (cubicMidPt.approximatelyEqual(pt)) {
152 goto skipInsert;
153 }
154 }
155 fIntersections->insert(cubicT, lineT, pt); 158 fIntersections->insert(cubicT, lineT, pt);
156 skipInsert:
157 ;
158 } 159 }
159 } 160 }
161 checkCoincident();
160 return fIntersections->used(); 162 return fIntersections->used();
161 } 163 }
162 164
163 static int HorizontalIntersect(const SkDCubic& c, double axisIntercept, doub le roots[3]) { 165 static int HorizontalIntersect(const SkDCubic& c, double axisIntercept, doub le roots[3]) {
164 double A, B, C, D; 166 double A, B, C, D;
165 SkDCubic::Coefficients(&c[0].fY, &A, &B, &C, &D); 167 SkDCubic::Coefficients(&c[0].fY, &A, &B, &C, &D);
166 D -= axisIntercept; 168 D -= axisIntercept;
167 int count = SkDCubic::RootsValidT(A, B, C, D, roots); 169 int count = SkDCubic::RootsValidT(A, B, C, D, roots);
168 for (int index = 0; index < count; ++index) { 170 for (int index = 0; index < count; ++index) {
169 SkDPoint calcPt = c.ptAtT(roots[index]); 171 SkDPoint calcPt = c.ptAtT(roots[index]);
170 if (!approximately_equal(calcPt.fY, axisIntercept)) { 172 if (!approximately_equal(calcPt.fY, axisIntercept)) {
171 double extremeTs[6]; 173 double extremeTs[6];
172 int extrema = SkDCubic::FindExtrema(c[0].fY, c[1].fY, c[2].fY, c [3].fY, extremeTs); 174 int extrema = SkDCubic::FindExtrema(c[0].fY, c[1].fY, c[2].fY, c [3].fY, extremeTs);
173 count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubi c::kYAxis, roots); 175 count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubi c::kYAxis, roots);
174 break; 176 break;
175 } 177 }
176 } 178 }
177 return count; 179 return count;
178 } 180 }
179 181
180 int horizontalIntersect(double axisIntercept, double left, double right, boo l flipped) { 182 int horizontalIntersect(double axisIntercept, double left, double right, boo l flipped) {
181 addExactHorizontalEndPoints(left, right, axisIntercept); 183 addExactHorizontalEndPoints(left, right, axisIntercept);
182 if (fAllowNear) { 184 if (fAllowNear) {
183 addNearHorizontalEndPoints(left, right, axisIntercept); 185 addNearHorizontalEndPoints(left, right, axisIntercept);
184 } 186 }
185 double roots[3]; 187 double roots[3];
186 int count = HorizontalIntersect(fCubic, axisIntercept, roots); 188 int count = HorizontalIntersect(fCubic, axisIntercept, roots);
187 for (int index = 0; index < count; ++index) { 189 for (int index = 0; index < count; ++index) {
188 double cubicT = roots[index]; 190 double cubicT = roots[index];
189 SkDPoint pt; 191 SkDPoint pt = { fCubic.ptAtT(cubicT).fX, axisIntercept };
190 pt.fX = fCubic.ptAtT(cubicT).fX;
191 pt.fY = axisIntercept;
192 double lineT = (pt.fX - left) / (right - left); 192 double lineT = (pt.fX - left) / (right - left);
193 if (pinTs(&cubicT, &lineT, &pt, kPointInitialized)) { 193 if (pinTs(&cubicT, &lineT, &pt, kPointInitialized) && uniqueAnswer(c ubicT, pt)) {
194 fIntersections->insert(cubicT, lineT, pt); 194 fIntersections->insert(cubicT, lineT, pt);
195 } 195 }
196 } 196 }
197 if (flipped) { 197 if (flipped) {
198 fIntersections->flip(); 198 fIntersections->flip();
199 } 199 }
200 checkCoincident();
200 return fIntersections->used(); 201 return fIntersections->used();
201 } 202 }
202 203
204 bool uniqueAnswer(double cubicT, const SkDPoint& pt) {
205 for (int inner = 0; inner < fIntersections->used(); ++inner) {
206 if (fIntersections->pt(inner) != pt) {
207 continue;
208 }
209 double existingCubicT = (*fIntersections)[0][inner];
210 if (cubicT == existingCubicT) {
211 return false;
212 }
213 // check if midway on cubic is also same point. If so, discard t his
214 double cubicMidT = (existingCubicT + cubicT) / 2;
215 SkDPoint cubicMidPt = fCubic.ptAtT(cubicMidT);
216 if (cubicMidPt.approximatelyEqual(pt)) {
217 return false;
218 }
219 }
220 #if ONE_OFF_DEBUG
221 SkDPoint cPt = fCubic.ptAtT(cubicT);
222 SkDebugf("%s pt=(%1.9g,%1.9g) cPt=(%1.9g,%1.9g)\n", __FUNCTION__, pt .fX, pt.fY,
223 cPt.fX, cPt.fY);
224 #endif
225 return true;
226 }
227
203 static int VerticalIntersect(const SkDCubic& c, double axisIntercept, double roots[3]) { 228 static int VerticalIntersect(const SkDCubic& c, double axisIntercept, double roots[3]) {
204 double A, B, C, D; 229 double A, B, C, D;
205 SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D); 230 SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D);
206 D -= axisIntercept; 231 D -= axisIntercept;
207 int count = SkDCubic::RootsValidT(A, B, C, D, roots); 232 int count = SkDCubic::RootsValidT(A, B, C, D, roots);
208 for (int index = 0; index < count; ++index) { 233 for (int index = 0; index < count; ++index) {
209 SkDPoint calcPt = c.ptAtT(roots[index]); 234 SkDPoint calcPt = c.ptAtT(roots[index]);
210 if (!approximately_equal(calcPt.fX, axisIntercept)) { 235 if (!approximately_equal(calcPt.fX, axisIntercept)) {
211 double extremeTs[6]; 236 double extremeTs[6];
212 int extrema = SkDCubic::FindExtrema(c[0].fX, c[1].fX, c[2].fX, c [3].fX, extremeTs); 237 int extrema = SkDCubic::FindExtrema(c[0].fX, c[1].fX, c[2].fX, c [3].fX, extremeTs);
213 count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubi c::kXAxis, roots); 238 count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubi c::kXAxis, roots);
214 break; 239 break;
215 } 240 }
216 } 241 }
217 return count; 242 return count;
218 } 243 }
219 244
220 int verticalIntersect(double axisIntercept, double top, double bottom, bool flipped) { 245 int verticalIntersect(double axisIntercept, double top, double bottom, bool flipped) {
221 addExactVerticalEndPoints(top, bottom, axisIntercept); 246 addExactVerticalEndPoints(top, bottom, axisIntercept);
222 if (fAllowNear) { 247 if (fAllowNear) {
223 addNearVerticalEndPoints(top, bottom, axisIntercept); 248 addNearVerticalEndPoints(top, bottom, axisIntercept);
224 } 249 }
225 double roots[3]; 250 double roots[3];
226 int count = VerticalIntersect(fCubic, axisIntercept, roots); 251 int count = VerticalIntersect(fCubic, axisIntercept, roots);
227 for (int index = 0; index < count; ++index) { 252 for (int index = 0; index < count; ++index) {
228 double cubicT = roots[index]; 253 double cubicT = roots[index];
229 SkDPoint pt; 254 SkDPoint pt = { axisIntercept, fCubic.ptAtT(cubicT).fY };
230 pt.fX = axisIntercept;
231 pt.fY = fCubic.ptAtT(cubicT).fY;
232 double lineT = (pt.fY - top) / (bottom - top); 255 double lineT = (pt.fY - top) / (bottom - top);
233 if (pinTs(&cubicT, &lineT, &pt, kPointInitialized)) { 256 if (pinTs(&cubicT, &lineT, &pt, kPointInitialized) && uniqueAnswer(c ubicT, pt)) {
234 fIntersections->insert(cubicT, lineT, pt); 257 fIntersections->insert(cubicT, lineT, pt);
235 } 258 }
236 } 259 }
237 if (flipped) { 260 if (flipped) {
238 fIntersections->flip(); 261 fIntersections->flip();
239 } 262 }
263 checkCoincident();
240 return fIntersections->used(); 264 return fIntersections->used();
241 } 265 }
242 266
243 protected: 267 protected:
244 268
245 void addExactEndPoints() { 269 void addExactEndPoints() {
246 for (int cIndex = 0; cIndex < 4; cIndex += 3) { 270 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
247 double lineT = fLine.exactPoint(fCubic[cIndex]); 271 double lineT = fLine.exactPoint(fCubic[cIndex]);
248 if (lineT < 0) { 272 if (lineT < 0) {
249 continue; 273 continue;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 if (!approximately_one_or_less(*lineT)) { 359 if (!approximately_one_or_less(*lineT)) {
336 return false; 360 return false;
337 } 361 }
338 if (!approximately_zero_or_more(*lineT)) { 362 if (!approximately_zero_or_more(*lineT)) {
339 return false; 363 return false;
340 } 364 }
341 double cT = *cubicT = SkPinT(*cubicT); 365 double cT = *cubicT = SkPinT(*cubicT);
342 double lT = *lineT = SkPinT(*lineT); 366 double lT = *lineT = SkPinT(*lineT);
343 SkDPoint lPt = fLine.ptAtT(lT); 367 SkDPoint lPt = fLine.ptAtT(lT);
344 SkDPoint cPt = fCubic.ptAtT(cT); 368 SkDPoint cPt = fCubic.ptAtT(cT);
345 if (!lPt.moreRoughlyEqual(cPt)) { 369 if (!lPt.roughlyEqual(cPt)) {
346 return false; 370 return false;
347 } 371 }
348 // FIXME: if points are roughly equal but not approximately equal, need to do 372 // FIXME: if points are roughly equal but not approximately equal, need to do
349 // a binary search like quad/quad intersection to find more precise t va lues 373 // a binary search like quad/quad intersection to find more precise t va lues
350 if (lT == 0 || lT == 1 || (ptSet == kPointUninitialized && cT != 0 && cT != 1)) { 374 if (lT == 0 || lT == 1 || (ptSet == kPointUninitialized && cT != 0 && cT != 1)) {
351 *pt = lPt; 375 *pt = lPt;
352 } else if (ptSet == kPointUninitialized) { 376 } else if (ptSet == kPointUninitialized) {
353 *pt = cPt; 377 *pt = cPt;
354 } 378 }
355 SkPoint gridPt = pt->asSkPoint(); 379 SkPoint gridPt = pt->asSkPoint();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 } 418 }
395 419
396 int SkIntersections::intersectRay(const SkDCubic& cubic, const SkDLine& line) { 420 int SkIntersections::intersectRay(const SkDCubic& cubic, const SkDLine& line) {
397 LineCubicIntersections c(cubic, line, this); 421 LineCubicIntersections c(cubic, line, this);
398 fUsed = c.intersectRay(fT[0]); 422 fUsed = c.intersectRay(fT[0]);
399 for (int index = 0; index < fUsed; ++index) { 423 for (int index = 0; index < fUsed; ++index) {
400 fPt[index] = cubic.ptAtT(fT[0][index]); 424 fPt[index] = cubic.ptAtT(fT[0][index]);
401 } 425 }
402 return fUsed; 426 return fUsed;
403 } 427 }
OLDNEW
« no previous file with comments | « src/pathops/SkDCubicIntersection.cpp ('k') | src/pathops/SkDCubicToQuads.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698