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

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

Issue 19183003: path ops near exact (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: remove unused static function Created 7 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « src/pathops/SkDQuadIntersection.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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 B = 2*(-(a - b ) + g'*(d - e ) ) 85 B = 2*(-(a - b ) + g'*(d - e ) )
86 C = ( (a ) - g'*(d ) - h' ) 86 C = ( (a ) - g'*(d ) - h' )
87 */ 87 */
88 88
89 89
90 class LineQuadraticIntersections { 90 class LineQuadraticIntersections {
91 public: 91 public:
92 LineQuadraticIntersections(const SkDQuad& q, const SkDLine& l, SkIntersectio ns* i) 92 LineQuadraticIntersections(const SkDQuad& q, const SkDLine& l, SkIntersectio ns* i)
93 : quad(q) 93 : quad(q)
94 , line(l) 94 , line(l)
95 , intersections(i) { 95 , intersections(i)
96 , fAllowNear(true) {
97 }
98
99 void allowNear(bool allow) {
100 fAllowNear = allow;
96 } 101 }
97 102
98 int intersectRay(double roots[2]) { 103 int intersectRay(double roots[2]) {
99 /* 104 /*
100 solve by rotating line+quad so line is horizontal, then finding the root s 105 solve by rotating line+quad so line is horizontal, then finding the root s
101 set up matrix to rotate quad to x-axis 106 set up matrix to rotate quad to x-axis
102 |cos(a) -sin(a)| 107 |cos(a) -sin(a)|
103 |sin(a) cos(a)| 108 |sin(a) cos(a)|
104 note that cos(a) = A(djacent) / Hypoteneuse 109 note that cos(a) = A(djacent) / Hypoteneuse
105 sin(a) = O(pposite) / Hypoteneuse 110 sin(a) = O(pposite) / Hypoteneuse
(...skipping 13 matching lines...) Expand all
119 } 124 }
120 double A = r[2]; 125 double A = r[2];
121 double B = r[1]; 126 double B = r[1];
122 double C = r[0]; 127 double C = r[0];
123 A += C - 2 * B; // A = a - 2*b + c 128 A += C - 2 * B; // A = a - 2*b + c
124 B -= C; // B = -(b - c) 129 B -= C; // B = -(b - c)
125 return SkDQuad::RootsValidT(A, 2 * B, C, roots); 130 return SkDQuad::RootsValidT(A, 2 * B, C, roots);
126 } 131 }
127 132
128 int intersect() { 133 int intersect() {
129 addEndPoints(); 134 addExactEndPoints();
130 double rootVals[2]; 135 double rootVals[2];
131 int roots = intersectRay(rootVals); 136 int roots = intersectRay(rootVals);
132 for (int index = 0; index < roots; ++index) { 137 for (int index = 0; index < roots; ++index) {
133 double quadT = rootVals[index]; 138 double quadT = rootVals[index];
134 double lineT = findLineT(quadT); 139 double lineT = findLineT(quadT);
135 if (PinTs(&quadT, &lineT)) { 140 if (PinTs(&quadT, &lineT)) {
136 SkDPoint pt = line.xyAtT(lineT); 141 SkDPoint pt = line.xyAtT(lineT);
137 intersections->insert(quadT, lineT, pt); 142 intersections->insert(quadT, lineT, pt);
138 } 143 }
139 } 144 }
145 if (fAllowNear) {
146 addNearEndPoints();
147 }
140 return intersections->used(); 148 return intersections->used();
141 } 149 }
142 150
143 int horizontalIntersect(double axisIntercept, double roots[2]) { 151 int horizontalIntersect(double axisIntercept, double roots[2]) {
144 double D = quad[2].fY; // f 152 double D = quad[2].fY; // f
145 double E = quad[1].fY; // e 153 double E = quad[1].fY; // e
146 double F = quad[0].fY; // d 154 double F = quad[0].fY; // d
147 D += F - 2 * E; // D = d - 2*e + f 155 D += F - 2 * E; // D = d - 2*e + f
148 E -= F; // E = -(d - e) 156 E -= F; // E = -(d - e)
149 F -= axisIntercept; 157 F -= axisIntercept;
150 return SkDQuad::RootsValidT(D, 2 * E, F, roots); 158 return SkDQuad::RootsValidT(D, 2 * E, F, roots);
151 } 159 }
152 160
153 int horizontalIntersect(double axisIntercept, double left, double right, boo l flipped) { 161 int horizontalIntersect(double axisIntercept, double left, double right, boo l flipped) {
154 addHorizontalEndPoints(left, right, axisIntercept); 162 addExactHorizontalEndPoints(left, right, axisIntercept);
155 double rootVals[2]; 163 double rootVals[2];
156 int roots = horizontalIntersect(axisIntercept, rootVals); 164 int roots = horizontalIntersect(axisIntercept, rootVals);
157 for (int index = 0; index < roots; ++index) { 165 for (int index = 0; index < roots; ++index) {
158 double quadT = rootVals[index]; 166 double quadT = rootVals[index];
159 SkDPoint pt = quad.xyAtT(quadT); 167 SkDPoint pt = quad.xyAtT(quadT);
160 double lineT = (pt.fX - left) / (right - left); 168 double lineT = (pt.fX - left) / (right - left);
161 if (PinTs(&quadT, &lineT)) { 169 if (PinTs(&quadT, &lineT)) {
162 intersections->insert(quadT, lineT, pt); 170 intersections->insert(quadT, lineT, pt);
163 } 171 }
164 } 172 }
173 if (fAllowNear) {
174 addNearHorizontalEndPoints(left, right, axisIntercept);
175 }
165 if (flipped) { 176 if (flipped) {
166 intersections->flip(); 177 intersections->flip();
167 } 178 }
168 return intersections->used(); 179 return intersections->used();
169 } 180 }
170 181
171 int verticalIntersect(double axisIntercept, double roots[2]) { 182 int verticalIntersect(double axisIntercept, double roots[2]) {
172 double D = quad[2].fX; // f 183 double D = quad[2].fX; // f
173 double E = quad[1].fX; // e 184 double E = quad[1].fX; // e
174 double F = quad[0].fX; // d 185 double F = quad[0].fX; // d
175 D += F - 2 * E; // D = d - 2*e + f 186 D += F - 2 * E; // D = d - 2*e + f
176 E -= F; // E = -(d - e) 187 E -= F; // E = -(d - e)
177 F -= axisIntercept; 188 F -= axisIntercept;
178 return SkDQuad::RootsValidT(D, 2 * E, F, roots); 189 return SkDQuad::RootsValidT(D, 2 * E, F, roots);
179 } 190 }
180 191
181 int verticalIntersect(double axisIntercept, double top, double bottom, bool flipped) { 192 int verticalIntersect(double axisIntercept, double top, double bottom, bool flipped) {
182 addVerticalEndPoints(top, bottom, axisIntercept); 193 addExactVerticalEndPoints(top, bottom, axisIntercept);
183 double rootVals[2]; 194 double rootVals[2];
184 int roots = verticalIntersect(axisIntercept, rootVals); 195 int roots = verticalIntersect(axisIntercept, rootVals);
185 for (int index = 0; index < roots; ++index) { 196 for (int index = 0; index < roots; ++index) {
186 double quadT = rootVals[index]; 197 double quadT = rootVals[index];
187 SkDPoint pt = quad.xyAtT(quadT); 198 SkDPoint pt = quad.xyAtT(quadT);
188 double lineT = (pt.fY - top) / (bottom - top); 199 double lineT = (pt.fY - top) / (bottom - top);
189 if (PinTs(&quadT, &lineT)) { 200 if (PinTs(&quadT, &lineT)) {
190 intersections->insert(quadT, lineT, pt); 201 intersections->insert(quadT, lineT, pt);
191 } 202 }
192 } 203 }
204 if (fAllowNear) {
205 addNearVerticalEndPoints(top, bottom, axisIntercept);
206 }
193 if (flipped) { 207 if (flipped) {
194 intersections->flip(); 208 intersections->flip();
195 } 209 }
196 return intersections->used(); 210 return intersections->used();
197 } 211 }
198 212
199 protected: 213 protected:
200 // add endpoints first to get zero and one t values exactly 214 // add endpoints first to get zero and one t values exactly
201 void addEndPoints() { 215 void addExactEndPoints() {
202 for (int qIndex = 0; qIndex < 3; qIndex += 2) { 216 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
203 bool foundEnd = false; 217 double lineT = line.exactPoint(quad[qIndex]);
204 for (int lIndex = 0; lIndex < 2; lIndex++) { 218 if (lineT < 0) {
205 if (quad[qIndex] == line[lIndex]) {
206 intersections->insert(qIndex >> 1, lIndex, line[lIndex]);
207 foundEnd = true;
208 }
209 }
210 if (foundEnd) {
211 continue; 219 continue;
212 } 220 }
213 // See if the quad end touches the line. 221 double quadT = (double) (qIndex >> 1);
214 double dist = line.isLeft(quad[qIndex]); // this distance isn't cart esian 222 intersections->insert(quadT, lineT, quad[qIndex]);
215 SkDVector lineLen = line[1] - line[0]; // the x/y magnitudes of the line
216 // compute the ULPS of the larger of the x/y deltas
217 double larger = SkTMax(SkTAbs(lineLen.fX), SkTAbs(lineLen.fY));
218 if (!RoughlyEqualUlps(larger, larger + dist)) { // is the dist withi n ULPS tolerance?
219 continue;
220 }
221 double lineT = findLineT(qIndex >> 1);
222 if (!between(0, lineT, 1)) {
223 continue;
224 }
225 SkDPoint linePt = line.xyAtT(lineT);
226 if (linePt.approximatelyEqual(quad[qIndex])) {
227 intersections->insert(qIndex >> 1, lineT, quad[qIndex]);
228 }
229 } 223 }
230 } 224 }
231 225
232 void addHorizontalEndPoints(double left, double right, double y) { 226 void addNearEndPoints() {
233 for (int qIndex = 0; qIndex < 3; qIndex += 2) { 227 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
234 if (!AlmostEqualUlps(quad[qIndex].fY, y)) { 228 double quadT = (double) (qIndex >> 1);
229 if (intersections->hasT(quadT)) {
235 continue; 230 continue;
236 } 231 }
237 double x = quad[qIndex].fX; 232 double lineT = line.nearPoint(quad[qIndex]);
238 if (between(left, x, right)) { 233 if (lineT < 0) {
239 double t = (x - left) / (right - left); 234 continue;
240 intersections->insert(qIndex >> 1, t, quad[qIndex]);
241 } 235 }
236 intersections->insert(quadT, lineT, quad[qIndex]);
237 }
238 // FIXME: see if line end is nearly on quad
239 }
240
241 void addExactHorizontalEndPoints(double left, double right, double y) {
242 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
243 double lineT = SkDLine::ExactPointH(quad[qIndex], left, right, y);
244 if (lineT < 0) {
245 continue;
246 }
247 double quadT = (double) (qIndex >> 1);
248 intersections->insert(quadT, lineT, quad[qIndex]);
242 } 249 }
243 } 250 }
244 251
245 void addVerticalEndPoints(double top, double bottom, double x) { 252 void addNearHorizontalEndPoints(double left, double right, double y) {
246 for (int qIndex = 0; qIndex < 3; qIndex += 2) { 253 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
247 if (!AlmostEqualUlps(quad[qIndex].fX, x)) { 254 double quadT = (double) (qIndex >> 1);
255 if (intersections->hasT(quadT)) {
248 continue; 256 continue;
249 } 257 }
250 double y = quad[qIndex].fY; 258 double lineT = SkDLine::NearPointH(quad[qIndex], left, right, y);
251 if (between(top, y, bottom)) { 259 if (lineT < 0) {
252 double t = (y - top) / (bottom - top); 260 continue;
253 intersections->insert(qIndex >> 1, t, quad[qIndex]);
254 } 261 }
262 intersections->insert(quadT, lineT, quad[qIndex]);
255 } 263 }
264 // FIXME: see if line end is nearly on quad
265 }
266
267 void addExactVerticalEndPoints(double top, double bottom, double x) {
268 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
269 double lineT = SkDLine::ExactPointV(quad[qIndex], top, bottom, x);
270 if (lineT < 0) {
271 continue;
272 }
273 double quadT = (double) (qIndex >> 1);
274 intersections->insert(quadT, lineT, quad[qIndex]);
275 }
276 }
277
278 void addNearVerticalEndPoints(double top, double bottom, double x) {
279 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
280 double quadT = (double) (qIndex >> 1);
281 if (intersections->hasT(quadT)) {
282 continue;
283 }
284 double lineT = SkDLine::NearPointV(quad[qIndex], top, bottom, x);
285 if (lineT < 0) {
286 continue;
287 }
288 intersections->insert(quadT, lineT, quad[qIndex]);
289 }
290 // FIXME: see if line end is nearly on quad
256 } 291 }
257 292
258 double findLineT(double t) { 293 double findLineT(double t) {
259 SkDPoint xy = quad.xyAtT(t); 294 SkDPoint xy = quad.xyAtT(t);
260 double dx = line[1].fX - line[0].fX; 295 double dx = line[1].fX - line[0].fX;
261 double dy = line[1].fY - line[0].fY; 296 double dy = line[1].fY - line[0].fY;
262 #if 0
263 if (fabs(dx) > fabs(dy)) {
264 return (xy.fX - line[0].fX) / dx;
265 }
266 return (xy.fY - line[0].fY) / dy;
267 #else
268 double dxT = (xy.fX - line[0].fX) / dx; 297 double dxT = (xy.fX - line[0].fX) / dx;
269 double dyT = (xy.fY - line[0].fY) / dy; 298 double dyT = (xy.fY - line[0].fY) / dy;
270 if (!between(FLT_EPSILON, dxT, 1 - FLT_EPSILON) && between(0, dyT, 1)) { 299 if (!between(FLT_EPSILON, dxT, 1 - FLT_EPSILON) && between(0, dyT, 1)) {
271 return dyT; 300 return dyT;
272 } 301 }
273 if (!between(FLT_EPSILON, dyT, 1 - FLT_EPSILON) && between(0, dxT, 1)) { 302 if (!between(FLT_EPSILON, dyT, 1 - FLT_EPSILON) && between(0, dxT, 1)) {
274 return dxT; 303 return dxT;
275 } 304 }
276 return fabs(dx) > fabs(dy) ? dxT : dyT; 305 return fabs(dx) > fabs(dy) ? dxT : dyT;
277 #endif
278 } 306 }
279 307
280 static bool PinTs(double* quadT, double* lineT) { 308 static bool PinTs(double* quadT, double* lineT) {
281 if (!approximately_one_or_less(*lineT)) { 309 if (!approximately_one_or_less(*lineT)) {
282 return false; 310 return false;
283 } 311 }
284 if (!approximately_zero_or_more(*lineT)) { 312 if (!approximately_zero_or_more(*lineT)) {
285 return false; 313 return false;
286 } 314 }
287 if (precisely_less_than_zero(*quadT)) { 315 *quadT = SkPinT(*quadT);
288 *quadT = 0; 316 *lineT = SkPinT(*lineT);
289 } else if (precisely_greater_than_one(*quadT)) {
290 *quadT = 1;
291 }
292 if (precisely_less_than_zero(*lineT)) {
293 *lineT = 0;
294 } else if (precisely_greater_than_one(*lineT)) {
295 *lineT = 1;
296 }
297 return true; 317 return true;
298 } 318 }
299 319
300 private: 320 private:
301 const SkDQuad& quad; 321 const SkDQuad& quad;
302 const SkDLine& line; 322 const SkDLine& line;
303 SkIntersections* intersections; 323 SkIntersections* intersections;
324 bool fAllowNear;
304 }; 325 };
305 326
306 // utility for pairs of coincident quads 327 // utility for pairs of coincident quads
307 static double horizontalIntersect(const SkDQuad& quad, const SkDPoint& pt) { 328 static double horizontalIntersect(const SkDQuad& quad, const SkDPoint& pt) {
308 LineQuadraticIntersections q(quad, *(static_cast<SkDLine*>(0)), 329 LineQuadraticIntersections q(quad, *(static_cast<SkDLine*>(0)),
309 static_cast<SkIntersections*>(0)); 330 static_cast<SkIntersections*>(0));
310 double rootVals[2]; 331 double rootVals[2];
311 int roots = q.horizontalIntersect(pt.fY, rootVals); 332 int roots = q.horizontalIntersect(pt.fY, rootVals);
312 for (int index = 0; index < roots; ++index) { 333 for (int index = 0; index < roots; ++index) {
313 double t = rootVals[index]; 334 double t = rootVals[index];
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 } 369 }
349 370
350 int SkIntersections::vertical(const SkDQuad& quad, double top, double bottom, do uble x, 371 int SkIntersections::vertical(const SkDQuad& quad, double top, double bottom, do uble x,
351 bool flipped) { 372 bool flipped) {
352 LineQuadraticIntersections q(quad, *(static_cast<SkDLine*>(0)), this); 373 LineQuadraticIntersections q(quad, *(static_cast<SkDLine*>(0)), this);
353 return q.verticalIntersect(x, top, bottom, flipped); 374 return q.verticalIntersect(x, top, bottom, flipped);
354 } 375 }
355 376
356 int SkIntersections::intersect(const SkDQuad& quad, const SkDLine& line) { 377 int SkIntersections::intersect(const SkDQuad& quad, const SkDLine& line) {
357 LineQuadraticIntersections q(quad, line, this); 378 LineQuadraticIntersections q(quad, line, this);
379 q.allowNear(fAllowNear);
358 return q.intersect(); 380 return q.intersect();
359 } 381 }
360 382
361 int SkIntersections::intersectRay(const SkDQuad& quad, const SkDLine& line) { 383 int SkIntersections::intersectRay(const SkDQuad& quad, const SkDLine& line) {
362 LineQuadraticIntersections q(quad, line, this); 384 LineQuadraticIntersections q(quad, line, this);
363 fUsed = q.intersectRay(fT[0]); 385 fUsed = q.intersectRay(fT[0]);
364 for (int index = 0; index < fUsed; ++index) { 386 for (int index = 0; index < fUsed; ++index) {
365 fPt[index] = quad.xyAtT(fT[0][index]); 387 fPt[index] = quad.xyAtT(fT[0][index]);
366 } 388 }
367 return fUsed; 389 return fUsed;
368 } 390 }
OLDNEW
« no previous file with comments | « src/pathops/SkDQuadIntersection.cpp ('k') | src/pathops/SkIntersections.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698