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

Side by Side Diff: src/pathops/SkDCubicLineIntersection.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/SkDCubicIntersection.cpp ('k') | src/pathops/SkDLineIntersection.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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 3 e t^2 - 6 f t^2 + 3 g t^2 - 73 3 e t^2 - 6 f t^2 + 3 g t^2 -
74 e t^3 + 3 f t^3 - 3 g t^3 + h t^3 74 e t^3 + 3 f t^3 - 3 g t^3 + h t^3
75 */ 75 */
76 76
77 class LineCubicIntersections { 77 class LineCubicIntersections {
78 public: 78 public:
79 79
80 LineCubicIntersections(const SkDCubic& c, const SkDLine& l, SkIntersections& i) 80 LineCubicIntersections(const SkDCubic& c, const SkDLine& l, SkIntersections& i)
81 : cubic(c) 81 : cubic(c)
82 , line(l) 82 , line(l)
83 , intersections(i) { 83 , intersections(i)
84 , fAllowNear(true) {
85 }
86
87 void allowNear(bool allow) {
88 fAllowNear = allow;
84 } 89 }
85 90
86 // see parallel routine in line quadratic intersections 91 // see parallel routine in line quadratic intersections
87 int intersectRay(double roots[3]) { 92 int intersectRay(double roots[3]) {
88 double adj = line[1].fX - line[0].fX; 93 double adj = line[1].fX - line[0].fX;
89 double opp = line[1].fY - line[0].fY; 94 double opp = line[1].fY - line[0].fY;
90 SkDCubic r; 95 SkDCubic r;
91 for (int n = 0; n < 4; ++n) { 96 for (int n = 0; n < 4; ++n) {
92 r[n].fX = (cubic[n].fY - line[0].fY) * adj - (cubic[n].fX - line[0].fX) * opp; 97 r[n].fX = (cubic[n].fY - line[0].fY) * adj - (cubic[n].fX - line[0].fX) * opp;
93 } 98 }
94 double A, B, C, D; 99 double A, B, C, D;
95 SkDCubic::Coefficients(&r[0].fX, &A, &B, &C, &D); 100 SkDCubic::Coefficients(&r[0].fX, &A, &B, &C, &D);
96 return SkDCubic::RootsValidT(A, B, C, D, roots); 101 return SkDCubic::RootsValidT(A, B, C, D, roots);
97 } 102 }
98 103
99 int intersect() { 104 int intersect() {
100 addEndPoints(); 105 addExactEndPoints();
101 double rootVals[3]; 106 double rootVals[3];
102 int roots = intersectRay(rootVals); 107 int roots = intersectRay(rootVals);
103 for (int index = 0; index < roots; ++index) { 108 for (int index = 0; index < roots; ++index) {
104 double cubicT = rootVals[index]; 109 double cubicT = rootVals[index];
105 double lineT = findLineT(cubicT); 110 double lineT = findLineT(cubicT);
106 if (pinTs(&cubicT, &lineT)) { 111 if (pinTs(&cubicT, &lineT)) {
107 SkDPoint pt = line.xyAtT(lineT); 112 SkDPoint pt = line.xyAtT(lineT);
108 #if ONE_OFF_DEBUG 113 #if ONE_OFF_DEBUG
109 SkDPoint cPt = cubic.xyAtT(cubicT); 114 SkDPoint cPt = cubic.xyAtT(cubicT);
110 SkDebugf("%s pt=(%1.9g,%1.9g) cPt=(%1.9g,%1.9g)\n", __FUNCTION__, pt .fX, pt.fY, 115 SkDebugf("%s pt=(%1.9g,%1.9g) cPt=(%1.9g,%1.9g)\n", __FUNCTION__, pt .fX, pt.fY,
111 cPt.fX, cPt.fY); 116 cPt.fX, cPt.fY);
112 #endif 117 #endif
113 intersections.insert(cubicT, lineT, pt); 118 intersections.insert(cubicT, lineT, pt);
114 } 119 }
115 } 120 }
121 if (fAllowNear) {
122 addNearEndPoints();
123 }
116 return intersections.used(); 124 return intersections.used();
117 } 125 }
118 126
119 int horizontalIntersect(double axisIntercept, double roots[3]) { 127 int horizontalIntersect(double axisIntercept, double roots[3]) {
120 double A, B, C, D; 128 double A, B, C, D;
121 SkDCubic::Coefficients(&cubic[0].fY, &A, &B, &C, &D); 129 SkDCubic::Coefficients(&cubic[0].fY, &A, &B, &C, &D);
122 D -= axisIntercept; 130 D -= axisIntercept;
123 return SkDCubic::RootsValidT(A, B, C, D, roots); 131 return SkDCubic::RootsValidT(A, B, C, D, roots);
124 } 132 }
125 133
126 int horizontalIntersect(double axisIntercept, double left, double right, bool fl ipped) { 134 int horizontalIntersect(double axisIntercept, double left, double right, bool fl ipped) {
127 addHorizontalEndPoints(left, right, axisIntercept); 135 addExactHorizontalEndPoints(left, right, axisIntercept);
128 double rootVals[3]; 136 double rootVals[3];
129 int roots = horizontalIntersect(axisIntercept, rootVals); 137 int roots = horizontalIntersect(axisIntercept, rootVals);
130 for (int index = 0; index < roots; ++index) { 138 for (int index = 0; index < roots; ++index) {
131 double cubicT = rootVals[index]; 139 double cubicT = rootVals[index];
132 SkDPoint pt = cubic.xyAtT(cubicT); 140 SkDPoint pt = cubic.xyAtT(cubicT);
133 double lineT = (pt.fX - left) / (right - left); 141 double lineT = (pt.fX - left) / (right - left);
134 if (pinTs(&cubicT, &lineT)) { 142 if (pinTs(&cubicT, &lineT)) {
135 intersections.insert(cubicT, lineT, pt); 143 intersections.insert(cubicT, lineT, pt);
136 } 144 }
137 } 145 }
146 if (fAllowNear) {
147 addNearHorizontalEndPoints(left, right, axisIntercept);
148 }
138 if (flipped) { 149 if (flipped) {
139 intersections.flip(); 150 intersections.flip();
140 } 151 }
141 return intersections.used(); 152 return intersections.used();
142 } 153 }
143 154
144 int verticalIntersect(double axisIntercept, double roots[3]) { 155 int verticalIntersect(double axisIntercept, double roots[3]) {
145 double A, B, C, D; 156 double A, B, C, D;
146 SkDCubic::Coefficients(&cubic[0].fX, &A, &B, &C, &D); 157 SkDCubic::Coefficients(&cubic[0].fX, &A, &B, &C, &D);
147 D -= axisIntercept; 158 D -= axisIntercept;
148 return SkDCubic::RootsValidT(A, B, C, D, roots); 159 return SkDCubic::RootsValidT(A, B, C, D, roots);
149 } 160 }
150 161
151 int verticalIntersect(double axisIntercept, double top, double bottom, bool flip ped) { 162 int verticalIntersect(double axisIntercept, double top, double bottom, bool flip ped) {
152 addVerticalEndPoints(top, bottom, axisIntercept); 163 addExactVerticalEndPoints(top, bottom, axisIntercept);
153 double rootVals[3]; 164 double rootVals[3];
154 int roots = verticalIntersect(axisIntercept, rootVals); 165 int roots = verticalIntersect(axisIntercept, rootVals);
155 for (int index = 0; index < roots; ++index) { 166 for (int index = 0; index < roots; ++index) {
156 double cubicT = rootVals[index]; 167 double cubicT = rootVals[index];
157 SkDPoint pt = cubic.xyAtT(cubicT); 168 SkDPoint pt = cubic.xyAtT(cubicT);
158 double lineT = (pt.fY - top) / (bottom - top); 169 double lineT = (pt.fY - top) / (bottom - top);
159 if (pinTs(&cubicT, &lineT)) { 170 if (pinTs(&cubicT, &lineT)) {
160 intersections.insert(cubicT, lineT, pt); 171 intersections.insert(cubicT, lineT, pt);
161 } 172 }
162 } 173 }
174 if (fAllowNear) {
175 addNearVerticalEndPoints(top, bottom, axisIntercept);
176 }
163 if (flipped) { 177 if (flipped) {
164 intersections.flip(); 178 intersections.flip();
165 } 179 }
166 return intersections.used(); 180 return intersections.used();
167 } 181 }
168 182
169 protected: 183 protected:
170 184
171 void addEndPoints() { 185 void addExactEndPoints() {
172 for (int cIndex = 0; cIndex < 4; cIndex += 3) { 186 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
173 bool foundEnd = false; 187 double lineT = line.exactPoint(cubic[cIndex]);
174 for (int lIndex = 0; lIndex < 2; lIndex++) { 188 if (lineT < 0) {
175 if (cubic[cIndex] == line[lIndex]) {
176 intersections.insert(cIndex >> 1, lIndex, line[lIndex]);
177 foundEnd = true;
178 }
179 }
180 // for the test case this was written for, the dist / error ratio was 17 0.6667
181 // it looks like the cubic stops short of touching the line, but this fi xed it.
182 if (foundEnd) {
183 continue; 189 continue;
184 } 190 }
185 // See if the cubic end touches the line. 191 double cubicT = (double) (cIndex >> 1);
186 double dist = line.isLeft(cubic[cIndex]); // this distance isn't cartesi an 192 intersections.insert(cubicT, lineT, cubic[cIndex]);
187 SkDVector lineLen = line[1] - line[0]; // the x/y magnitudes of the line
188 // compute the ULPS of the larger of the x/y deltas
189 double larger = SkTMax(SkTAbs(lineLen.fX), SkTAbs(lineLen.fY));
190 if (!RoughlyEqualUlps(larger, larger + dist)) { // is the dist within UL PS tolerance?
191 continue;
192 }
193 double lineT = findLineT(cIndex >> 1);
194 if (!between(0, lineT, 1)) {
195 continue;
196 }
197 SkDPoint linePt = line.xyAtT(lineT);
198 if (linePt.approximatelyEqual(cubic[cIndex])) {
199 intersections.insert(cIndex >> 1, lineT, cubic[cIndex]);
200 }
201 } 193 }
202 } 194 }
203 195
204 void addHorizontalEndPoints(double left, double right, double y) { 196 void addNearEndPoints() {
205 for (int cIndex = 0; cIndex < 4; cIndex += 3) { 197 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
206 if (cubic[cIndex].fY != y) { 198 double cubicT = (double) (cIndex >> 1);
199 if (intersections.hasT(cubicT)) {
207 continue; 200 continue;
208 } 201 }
209 if (cubic[cIndex].fX == left) { 202 double lineT = line.nearPoint(cubic[cIndex]);
210 intersections.insert(cIndex >> 1, 0, cubic[cIndex]); 203 if (lineT < 0) {
204 continue;
211 } 205 }
212 if (cubic[cIndex].fX == right) { 206 intersections.insert(cubicT, lineT, cubic[cIndex]);
213 intersections.insert(cIndex >> 1, 1, cubic[cIndex]);
214 }
215 } 207 }
216 } 208 }
217 209
218 void addVerticalEndPoints(double top, double bottom, double x) { 210 void addExactHorizontalEndPoints(double left, double right, double y) {
219 for (int cIndex = 0; cIndex < 4; cIndex += 3) { 211 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
220 if (cubic[cIndex].fX != x) { 212 double lineT = SkDLine::ExactPointH(cubic[cIndex], left, right, y);
213 if (lineT < 0) {
221 continue; 214 continue;
222 } 215 }
223 if (cubic[cIndex].fY == top) { 216 double cubicT = (double) (cIndex >> 1);
224 intersections.insert(cIndex >> 1, 0, cubic[cIndex]); 217 intersections.insert(cubicT, lineT, cubic[cIndex]);
225 }
226 if (cubic[cIndex].fY == bottom) {
227 intersections.insert(cIndex >> 1, 1, cubic[cIndex]);
228 }
229 } 218 }
230 } 219 }
231 220
221 void addNearHorizontalEndPoints(double left, double right, double y) {
222 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
223 double cubicT = (double) (cIndex >> 1);
224 if (intersections.hasT(cubicT)) {
225 continue;
226 }
227 double lineT = SkDLine::NearPointH(cubic[cIndex], left, right, y);
228 if (lineT < 0) {
229 continue;
230 }
231 intersections.insert(cubicT, lineT, cubic[cIndex]);
232 }
233 // FIXME: see if line end is nearly on cubic
234 }
235
236 void addExactVerticalEndPoints(double top, double bottom, double x) {
237 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
238 double lineT = SkDLine::ExactPointV(cubic[cIndex], top, bottom, x);
239 if (lineT < 0) {
240 continue;
241 }
242 double cubicT = (double) (cIndex >> 1);
243 intersections.insert(cubicT, lineT, cubic[cIndex]);
244 }
245 }
246
247 void addNearVerticalEndPoints(double top, double bottom, double x) {
248 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
249 double cubicT = (double) (cIndex >> 1);
250 if (intersections.hasT(cubicT)) {
251 continue;
252 }
253 double lineT = SkDLine::NearPointV(cubic[cIndex], top, bottom, x);
254 if (lineT < 0) {
255 continue;
256 }
257 intersections.insert(cubicT, lineT, cubic[cIndex]);
258 }
259 // FIXME: see if line end is nearly on cubic
260 }
261
232 double findLineT(double t) { 262 double findLineT(double t) {
233 SkDPoint xy = cubic.xyAtT(t); 263 SkDPoint xy = cubic.xyAtT(t);
234 double dx = line[1].fX - line[0].fX; 264 double dx = line[1].fX - line[0].fX;
235 double dy = line[1].fY - line[0].fY; 265 double dy = line[1].fY - line[0].fY;
236 if (fabs(dx) > fabs(dy)) { 266 if (fabs(dx) > fabs(dy)) {
237 return (xy.fX - line[0].fX) / dx; 267 return (xy.fX - line[0].fX) / dx;
238 } 268 }
239 return (xy.fY - line[0].fY) / dy; 269 return (xy.fY - line[0].fY) / dy;
240 } 270 }
241 271
(...skipping 15 matching lines...) Expand all
257 *lineT = 1; 287 *lineT = 1;
258 } 288 }
259 return true; 289 return true;
260 } 290 }
261 291
262 private: 292 private:
263 293
264 const SkDCubic& cubic; 294 const SkDCubic& cubic;
265 const SkDLine& line; 295 const SkDLine& line;
266 SkIntersections& intersections; 296 SkIntersections& intersections;
297 bool fAllowNear;
267 }; 298 };
268 299
269 int SkIntersections::horizontal(const SkDCubic& cubic, double left, double right , double y, 300 int SkIntersections::horizontal(const SkDCubic& cubic, double left, double right , double y,
270 bool flipped) { 301 bool flipped) {
271 LineCubicIntersections c(cubic, *(static_cast<SkDLine*>(0)), *this); 302 LineCubicIntersections c(cubic, *(static_cast<SkDLine*>(0)), *this);
272 return c.horizontalIntersect(y, left, right, flipped); 303 return c.horizontalIntersect(y, left, right, flipped);
273 } 304 }
274 305
275 int SkIntersections::vertical(const SkDCubic& cubic, double top, double bottom, double x, 306 int SkIntersections::vertical(const SkDCubic& cubic, double top, double bottom, double x,
276 bool flipped) { 307 bool flipped) {
277 LineCubicIntersections c(cubic, *(static_cast<SkDLine*>(0)), *this); 308 LineCubicIntersections c(cubic, *(static_cast<SkDLine*>(0)), *this);
278 return c.verticalIntersect(x, top, bottom, flipped); 309 return c.verticalIntersect(x, top, bottom, flipped);
279 } 310 }
280 311
281 int SkIntersections::intersect(const SkDCubic& cubic, const SkDLine& line) { 312 int SkIntersections::intersect(const SkDCubic& cubic, const SkDLine& line) {
282 LineCubicIntersections c(cubic, line, *this); 313 LineCubicIntersections c(cubic, line, *this);
314 c.allowNear(fAllowNear);
283 return c.intersect(); 315 return c.intersect();
284 } 316 }
285 317
286 int SkIntersections::intersectRay(const SkDCubic& cubic, const SkDLine& line) { 318 int SkIntersections::intersectRay(const SkDCubic& cubic, const SkDLine& line) {
287 LineCubicIntersections c(cubic, line, *this); 319 LineCubicIntersections c(cubic, line, *this);
288 fUsed = c.intersectRay(fT[0]); 320 fUsed = c.intersectRay(fT[0]);
289 for (int index = 0; index < fUsed; ++index) { 321 for (int index = 0; index < fUsed; ++index) {
290 fPt[index] = cubic.xyAtT(fT[0][index]); 322 fPt[index] = cubic.xyAtT(fT[0][index]);
291 } 323 }
292 return fUsed; 324 return fUsed;
293 } 325 }
OLDNEW
« no previous file with comments | « src/pathops/SkDCubicIntersection.cpp ('k') | src/pathops/SkDLineIntersection.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698