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

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

Issue 12880016: Add intersections for path ops (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/pathops/SkDCubicLineIntersection.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkIntersections.h"
9 #include "SkPathOpsCubic.h"
10 #include "SkPathOpsLine.h"
11 #include "SkPathOpsPoint.h"
12 #include "SkPathOpsQuad.h"
13 #include "SkPathOpsRect.h"
14 #include "SkReduceOrder.h"
15 #include "SkTDArray.h"
16 #include "TSearch.h"
17
18 #if ONE_OFF_DEBUG
19 static const double tLimits1[2][2] = {{0.36, 0.37}, {0.63, 0.64}};
20 static const double tLimits2[2][2] = {{-0.865211397, -0.865215212}, {-0.86520769 6, -0.865208078}};
21 #endif
22
23 #define DEBUG_QUAD_PART 0
24 #define SWAP_TOP_DEBUG 0
25
26 static int quadPart(const SkDCubic& cubic, double tStart, double tEnd, SkReduceO rder* reducer) {
27 SkDCubic part = cubic.subDivide(tStart, tEnd);
28 SkDQuad quad = part.toQuad();
29 // FIXME: should reduceOrder be looser in this use case if quartic is going to blow up on an
30 // extremely shallow quadratic?
31 int order = reducer->reduce(quad, SkReduceOrder::kFill_Style);
32 #if DEBUG_QUAD_PART
33 SkDebugf("%s cubic=(%1.17g,%1.17g %1.17g,%1.17g %1.17g,%1.17g %1.17g,%1.17g) "
34 " t=(%1.17g,%1.17g)\n", __FUNCTION__, cubic[0].fX, cubic[0].fY,
35 cubic[1].fX, cubic[1].fY, cubic[2].fX, cubic[2].fY,
36 cubic[3].fX, cubic[3].fY, tStart, tEnd);
37 SkDebugf("%s part=(%1.17g,%1.17g %1.17g,%1.17g %1.17g,%1.17g %1.17g,%1.17g)"
38 " quad=(%1.17g,%1.17g %1.17g,%1.17g %1.17g,%1.17g)\n", __FUNCTION__,
39 part[0].fX, part[0].fY, part[1].fX, part[1].fY, part[2].fX, part[2]. fY,
40 part[3].fX, part[3].fY, quad[0].fX, quad[0].fY,
41 quad[1].fX, quad[1].fY, quad[2].fX, quad[2].fY);
42 SkDebugf("%s simple=(%1.17g,%1.17g", __FUNCTION__, reducer->fQuad[0].fX, red ucer->fQuad[0].fY);
43 if (order > 1) {
44 SkDebugf(" %1.17g,%1.17g", reducer->fQuad[1].fX, reducer->fQuad[1].fY);
45 }
46 if (order > 2) {
47 SkDebugf(" %1.17g,%1.17g", reducer->fQuad[2].fX, reducer->fQuad[2].fY);
48 }
49 SkDebugf(")\n");
50 SkASSERT(order < 4 && order > 0);
51 #endif
52 return order;
53 }
54
55 static void intersectWithOrder(const SkDQuad& simple1, int order1, const SkDQuad & simple2,
56 int order2, SkIntersections& i) {
57 if (order1 == 3 && order2 == 3) {
58 i.intersect(simple1, simple2);
59 } else if (order1 <= 2 && order2 <= 2) {
60 i.intersect((const SkDLine&) simple1, (const SkDLine&) simple2);
61 } else if (order1 == 3 && order2 <= 2) {
62 i.intersect(simple1, (const SkDLine&) simple2);
63 } else {
64 SkASSERT(order1 <= 2 && order2 == 3);
65 i.intersect(simple2, (const SkDLine&) simple1);
66 i.swapPts();
67 }
68 }
69
70 // this flavor centers potential intersections recursively. In contrast, '2' may inadvertently
71 // chase intersections near quadratic ends, requiring odd hacks to find them.
72 static void intersect(const SkDCubic& cubic1, double t1s, double t1e, const SkDC ubic& cubic2,
73 double t2s, double t2e, double precisionScale, SkIntersections& i) {
74 i.upDepth();
75 SkDCubic c1 = cubic1.subDivide(t1s, t1e);
76 SkDCubic c2 = cubic2.subDivide(t2s, t2e);
77 SkTDArray<double> ts1;
78 // OPTIMIZE: if c1 == c2, call once (happens when detecting self-intersectio n)
79 c1.toQuadraticTs(c1.calcPrecision() * precisionScale, &ts1);
80 SkTDArray<double> ts2;
81 c2.toQuadraticTs(c2.calcPrecision() * precisionScale, &ts2);
82 double t1Start = t1s;
83 int ts1Count = ts1.count();
84 for (int i1 = 0; i1 <= ts1Count; ++i1) {
85 const double tEnd1 = i1 < ts1Count ? ts1[i1] : 1;
86 const double t1 = t1s + (t1e - t1s) * tEnd1;
87 SkReduceOrder s1;
88 int o1 = quadPart(cubic1, t1Start, t1, &s1);
89 double t2Start = t2s;
90 int ts2Count = ts2.count();
91 for (int i2 = 0; i2 <= ts2Count; ++i2) {
92 const double tEnd2 = i2 < ts2Count ? ts2[i2] : 1;
93 const double t2 = t2s + (t2e - t2s) * tEnd2;
94 if (&cubic1 == &cubic2 && t1Start >= t2Start) {
95 t2Start = t2;
96 continue;
97 }
98 SkReduceOrder s2;
99 int o2 = quadPart(cubic2, t2Start, t2, &s2);
100 #if ONE_OFF_DEBUG
101 char tab[] = " ";
102 if (tLimits1[0][0] >= t1Start && tLimits1[0][1] <= t1
103 && tLimits1[1][0] >= t2Start && tLimits1[1][1] <= t2) {
104 SkDCubic cSub1 = cubic1.subDivide(t1Start, t1);
105 SkDCubic cSub2 = cubic2.subDivide(t2Start, t2);
106 SkDebugf("%.*s %s t1=(%1.9g,%1.9g) t2=(%1.9g,%1.9g)", i.depth()* 2, tab,
107 __FUNCTION__, t1Start, t1, t2Start, t2);
108 SkIntersections xlocals;
109 intersectWithOrder(s1.fQuad, o1, s2.fQuad, o2, xlocals);
110 SkDebugf(" xlocals.fUsed=%d\n", xlocals.used());
111 }
112 #endif
113 SkIntersections locals;
114 intersectWithOrder(s1.fQuad, o1, s2.fQuad, o2, locals);
115 double coStart[2] = { -1 };
116 SkDPoint coPoint;
117 int tCount = locals.used();
118 for (int tIdx = 0; tIdx < tCount; ++tIdx) {
119 double to1 = t1Start + (t1 - t1Start) * locals[0][tIdx];
120 double to2 = t2Start + (t2 - t2Start) * locals[1][tIdx];
121 // if the computed t is not sufficiently precise, iterate
122 SkDPoint p1 = cubic1.xyAtT(to1);
123 SkDPoint p2 = cubic2.xyAtT(to2);
124 if (p1.approximatelyEqual(p2)) {
125 if (locals.isCoincident(tIdx)) {
126 if (coStart[0] < 0) {
127 coStart[0] = to1;
128 coStart[1] = to2;
129 coPoint = p1;
130 } else {
131 i.insertCoincidentPair(coStart[0], to1, coStart[1], to2, coPoint, p1);
132 coStart[0] = -1;
133 }
134 } else if (&cubic1 != &cubic2 || !approximately_equal(to1, t o2)) {
135 if (i.swapped()) { // FIXME: insert should respect swap
136 i.insert(to2, to1, p1);
137 } else {
138 i.insert(to1, to2, p1);
139 }
140 }
141 } else {
142 double offset = precisionScale / 16; // FIME: const is arbi trary: test, refine
143 #if 1
144 double c1Bottom = tIdx == 0 ? 0 :
145 (t1Start + (t1 - t1Start) * locals[0][tIdx - 1] + to 1) / 2;
146 double c1Min = SkTMax(c1Bottom, to1 - offset);
147 double c1Top = tIdx == tCount - 1 ? 1 :
148 (t1Start + (t1 - t1Start) * locals[0][tIdx + 1] + to 1) / 2;
149 double c1Max = SkTMin(c1Top, to1 + offset);
150 double c2Min = SkTMax(0., to2 - offset);
151 double c2Max = SkTMin(1., to2 + offset);
152 #if ONE_OFF_DEBUG
153 SkDebugf("%.*s %s 1 contains1=%d/%d contains2=%d/%d\n", i.de pth()*2, tab,
154 __FUNCTION__,
155 c1Min <= tLimits1[0][1] && tLimits1[0][0] <= c1Max
156 && c2Min <= tLimits1[1][1] && tLimits1[1][0] <= c2Max,
157 to1 - offset <= tLimits1[0][1] && tLimits1[0][0] <= to1 + offset
158 && to2 - offset <= tLimits1[1][1] && tLimits1[1][0] <= to2 + offset,
159 c1Min <= tLimits2[0][1] && tLimits2[0][0] <= c1Max
160 && c2Min <= tLimits2[1][1] && tLimits2[1][0] <= c2Max,
161 to1 - offset <= tLimits2[0][1] && tLimits2[0][0] <= to1 + offset
162 && to2 - offset <= tLimits2[1][1] && tLimits2[1][0] <= to2 + offset);
163 SkDebugf("%.*s %s 1 c1Bottom=%1.9g c1Top=%1.9g c2Bottom=%1.9 g c2Top=%1.9g"
164 " 1-o=%1.9g 1+o=%1.9g 2-o=%1.9g 2+o=%1.9g offset=%1. 9g\n",
165 i.depth()*2, tab, __FUNCTION__, c1Bottom, c1Top, 0., 1.,
166 to1 - offset, to1 + offset, to2 - offset, to2 + offs et, offset);
167 SkDebugf("%.*s %s 1 to1=%1.9g to2=%1.9g c1Min=%1.9g c1Max=%1 .9g c2Min=%1.9g"
168 " c2Max=%1.9g\n", i.depth()*2, tab, __FUNCTION__, to 1, to2, c1Min,
169 c1Max, c2Min, c2Max);
170 #endif
171 intersect(cubic1, c1Min, c1Max, cubic2, c2Min, c2Max, offset , i);
172 #if ONE_OFF_DEBUG
173 SkDebugf("%.*s %s 1 i.used=%d t=%1.9g\n", i.depth()*2, tab, __FUNCTION__,
174 i.used(), i.used() > 0 ? i[0][i.used() - 1] : -1);
175 #endif
176 if (tCount > 1) {
177 c1Min = SkTMax(0., to1 - offset);
178 c1Max = SkTMin(1., to1 + offset);
179 double c2Bottom = tIdx == 0 ? to2 :
180 (t2Start + (t2 - t2Start) * locals[1][tIdx - 1] + to2) / 2;
181 double c2Top = tIdx == tCount - 1 ? to2 :
182 (t2Start + (t2 - t2Start) * locals[1][tIdx + 1] + to2) / 2;
183 if (c2Bottom > c2Top) {
184 SkTSwap(c2Bottom, c2Top);
185 }
186 if (c2Bottom == to2) {
187 c2Bottom = 0;
188 }
189 if (c2Top == to2) {
190 c2Top = 1;
191 }
192 c2Min = SkTMax(c2Bottom, to2 - offset);
193 c2Max = SkTMin(c2Top, to2 + offset);
194 #if ONE_OFF_DEBUG
195 SkDebugf("%.*s %s 2 contains1=%d/%d contains2=%d/%d\n", i.depth()*2, tab,
196 __FUNCTION__,
197 c1Min <= tLimits1[0][1] && tLimits1[0][0] <= c1Max
198 && c2Min <= tLimits1[1][1] && tLimits1[1][0] <= c2Max,
199 to1 - offset <= tLimits1[0][1] && tLimits1[0][0] <= to1 + offset
200 && to2 - offset <= tLimits1[1][1] && tLimits1[1][0] <= to2 + offset,
201 c1Min <= tLimits2[0][1] && tLimits2[0][0] <= c1Max
202 && c2Min <= tLimits2[1][1] && tLimits2[1][0] <= c2Max,
203 to1 - offset <= tLimits2[0][1] && tLimits2[0][0] <= to1 + offset
204 && to2 - offset <= tLimits2[1][1] && tLimits2[1][0] <= to2 + offset);
205 SkDebugf("%.*s %s 2 c1Bottom=%1.9g c1Top=%1.9g c2Bottom= %1.9g c2Top=%1.9g"
206 " 1-o=%1.9g 1+o=%1.9g 2-o=%1.9g 2+o=%1.9g offset =%1.9g\n",
207 i.depth()*2, tab, __FUNCTION__, 0., 1., c2Bottom , c2Top,
208 to1 - offset, to1 + offset, to2 - offset, to2 + offset, offset);
209 SkDebugf("%.*s %s 2 to1=%1.9g to2=%1.9g c1Min=%1.9g c1Ma x=%1.9g c2Min=%1.9g"
210 " c2Max=%1.9g\n", i.depth()*2, tab, __FUNCTION__ , to1, to2, c1Min,
211 c1Max, c2Min, c2Max);
212 #endif
213 intersect(cubic1, c1Min, c1Max, cubic2, c2Min, c2Max, of fset, i);
214 #if ONE_OFF_DEBUG
215 SkDebugf("%.*s %s 2 i.used=%d t=%1.9g\n", i.depth()*2, tab, __FUNCTION__,
216 i.used(), i.used() > 0 ? i[0][i.used() - 1] : -1);
217 #endif
218 c1Min = SkTMax(c1Bottom, to1 - offset);
219 c1Max = SkTMin(c1Top, to1 + offset);
220 #if ONE_OFF_DEBUG
221 SkDebugf("%.*s %s 3 contains1=%d/%d contains2=%d/%d\n", i.depth()*2, tab,
222 __FUNCTION__,
223 c1Min <= tLimits1[0][1] && tLimits1[0][0] <= c1Max
224 && c2Min <= tLimits1[1][1] && tLimits1[1][0] <= c2Max,
225 to1 - offset <= tLimits1[0][1] && tLimits1[0][0] <= to1 + offset
226 && to2 - offset <= tLimits1[1][1] && tLimits1[1][0] <= to2 + offset,
227 c1Min <= tLimits2[0][1] && tLimits2[0][0] <= c1Max
228 && c2Min <= tLimits2[1][1] && tLimits2[1][0] <= c2Max,
229 to1 - offset <= tLimits2[0][1] && tLimits2[0][0] <= to1 + offset
230 && to2 - offset <= tLimits2[1][1] && tLimits2[1][0] <= to2 + offset);
231 SkDebugf("%.*s %s 3 c1Bottom=%1.9g c1Top=%1.9g c2Bottom= %1.9g c2Top=%1.9g"
232 " 1-o=%1.9g 1+o=%1.9g 2-o=%1.9g 2+o=%1.9g offset =%1.9g\n",
233 i.depth()*2, tab, __FUNCTION__, 0., 1., c2Bottom , c2Top,
234 to1 - offset, to1 + offset, to2 - offset, to2 + offset, offset);
235 SkDebugf("%.*s %s 3 to1=%1.9g to2=%1.9g c1Min=%1.9g c1Ma x=%1.9g c2Min=%1.9g"
236 " c2Max=%1.9g\n", i.depth()*2, tab, __FUNCTION__ , to1, to2, c1Min,
237 c1Max, c2Min, c2Max);
238 #endif
239 intersect(cubic1, c1Min, c1Max, cubic2, c2Min, c2Max, of fset, i);
240 #if ONE_OFF_DEBUG
241 SkDebugf("%.*s %s 3 i.used=%d t=%1.9g\n", i.depth()*2, tab, __FUNCTION__,
242 i.used(), i.used() > 0 ? i[0][i.used() - 1] : -1);
243 #endif
244 }
245 #else
246 double c1Bottom = tIdx == 0 ? 0 :
247 (t1Start + (t1 - t1Start) * locals.fT[0][tIdx - 1] + to1) / 2;
248 double c1Min = SkTMax(c1Bottom, to1 - offset);
249 double c1Top = tIdx == tCount - 1 ? 1 :
250 (t1Start + (t1 - t1Start) * locals.fT[0][tIdx + 1] + to1) / 2;
251 double c1Max = SkTMin(c1Top, to1 + offset);
252 double c2Bottom = tIdx == 0 ? to2 :
253 (t2Start + (t2 - t2Start) * locals.fT[1][tIdx - 1] + to2) / 2;
254 double c2Top = tIdx == tCount - 1 ? to2 :
255 (t2Start + (t2 - t2Start) * locals.fT[1][tIdx + 1] + to2) / 2;
256 if (c2Bottom > c2Top) {
257 SkTSwap(c2Bottom, c2Top);
258 }
259 if (c2Bottom == to2) {
260 c2Bottom = 0;
261 }
262 if (c2Top == to2) {
263 c2Top = 1;
264 }
265 double c2Min = SkTMax(c2Bottom, to2 - offset);
266 double c2Max = SkTMin(c2Top, to2 + offset);
267 #if ONE_OFF_DEBUG
268 SkDebugf("%s contains1=%d/%d contains2=%d/%d\n", __FUNCTION_ _,
269 c1Min <= 0.210357794 && 0.210357794 <= c1Max
270 && c2Min <= 0.223476406 && 0.223476406 <= c2Max,
271 to1 - offset <= 0.210357794 && 0.210357794 <= to1 + offset
272 && to2 - offset <= 0.223476406 && 0.223476406 <= to2 + offset,
273 c1Min <= 0.211324707 && 0.211324707 <= c1Max
274 && c2Min <= 0.211327209 && 0.211327209 <= c2Max,
275 to1 - offset <= 0.211324707 && 0.211324707 <= to1 + offset
276 && to2 - offset <= 0.211327209 && 0.211327209 <= to2 + offset);
277 SkDebugf("%s c1Bottom=%1.9g c1Top=%1.9g c2Bottom=%1.9g c2Top =%1.9g"
278 " 1-o=%1.9g 1+o=%1.9g 2-o=%1.9g 2+o=%1.9g offset=%1. 9g\n",
279 __FUNCTION__, c1Bottom, c1Top, c2Bottom, c2Top,
280 to1 - offset, to1 + offset, to2 - offset, to2 + offs et, offset);
281 SkDebugf("%s to1=%1.9g to2=%1.9g c1Min=%1.9g c1Max=%1.9g c2M in=%1.9g"
282 " c2Max=%1.9g\n", __FUNCTION__, to1, to2, c1Min, c1M ax, c2Min, c2Max);
283 #endif
284 #endif
285 intersect(cubic1, c1Min, c1Max, cubic2, c2Min, c2Max, offset , i);
286 // FIXME: if no intersection is found, either quadratics int ersected where
287 // cubics did not, or the intersection was missed. In the fo rmer case, expect
288 // the quadratics to be nearly parallel at the point of inte rsection, and check
289 // for that.
290 }
291 }
292 SkASSERT(coStart[0] == -1);
293 t2Start = t2;
294 }
295 t1Start = t1;
296 }
297 i.downDepth();
298 }
299
300 #define LINE_FRACTION 0.1
301
302 // intersect the end of the cubic with the other. Try lines from the end to cont rol and opposite
303 // end to determine range of t on opposite cubic.
304 static void intersectEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cub ic2,
305 const SkDRect& bounds2, SkIntersections& i) {
306 SkDLine line;
307 int t1Index = start ? 0 : 3;
308 line[0] = cubic1[t1Index];
309 // don't bother if the two cubics are connnected
310 SkTDArray<double> tVals; // OPTIMIZE: replace with hard-sized array
311 for (int index = 0; index < 4; ++index) {
312 if (index == t1Index) {
313 continue;
314 }
315 SkDVector dxy1 = cubic1[index] - line[0];
316 dxy1 /= SkDCubic::gPrecisionUnit;
317 line[1] = line[0] + dxy1;
318 SkDRect lineBounds;
319 lineBounds.setBounds(line);
320 if (!bounds2.intersects(&lineBounds)) {
321 continue;
322 }
323 SkIntersections local;
324 if (!local.intersect(cubic2, line)) {
325 continue;
326 }
327 for (int idx2 = 0; idx2 < local.used(); ++idx2) {
328 double foundT = local[0][idx2];
329 if (approximately_less_than_zero(foundT)
330 || approximately_greater_than_one(foundT)) {
331 continue;
332 }
333 if (local.pt(idx2).approximatelyEqual(line[0])) {
334 if (i.swapped()) { // FIXME: insert should respect swap
335 i.insert(foundT, start ? 0 : 1, line[0]);
336 } else {
337 i.insert(start ? 0 : 1, foundT, line[0]);
338 }
339 } else {
340 *tVals.append() = local[0][idx2];
341 }
342 }
343 }
344 if (tVals.count() == 0) {
345 return;
346 }
347 QSort<double>(tVals.begin(), tVals.end() - 1);
348 double tMin1 = start ? 0 : 1 - LINE_FRACTION;
349 double tMax1 = start ? LINE_FRACTION : 1;
350 int tIdx = 0;
351 do {
352 int tLast = tIdx;
353 while (tLast + 1 < tVals.count() && roughly_equal(tVals[tLast + 1], tVal s[tIdx])) {
354 ++tLast;
355 }
356 double tMin2 = SkTMax(tVals[tIdx] - LINE_FRACTION, 0.0);
357 double tMax2 = SkTMin(tVals[tLast] + LINE_FRACTION, 1.0);
358 int lastUsed = i.used();
359 intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i);
360 if (lastUsed == i.used()) {
361 tMin2 = SkTMax(tVals[tIdx] - (1.0 / SkDCubic::gPrecisionUnit), 0.0);
362 tMax2 = SkTMin(tVals[tLast] + (1.0 / SkDCubic::gPrecisionUnit), 1.0) ;
363 intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i);
364 }
365 tIdx = tLast + 1;
366 } while (tIdx < tVals.count());
367 return;
368 }
369
370 const double CLOSE_ENOUGH = 0.001;
371
372 static bool closeStart(const SkDCubic& cubic, int cubicIndex, SkIntersections& i , SkDPoint& pt) {
373 if (i[cubicIndex][0] != 0 || i[cubicIndex][1] > CLOSE_ENOUGH) {
374 return false;
375 }
376 pt = cubic.xyAtT((i[cubicIndex][0] + i[cubicIndex][1]) / 2);
377 return true;
378 }
379
380 static bool closeEnd(const SkDCubic& cubic, int cubicIndex, SkIntersections& i, SkDPoint& pt) {
381 int last = i.used() - 1;
382 if (i[cubicIndex][last] != 1 || i[cubicIndex][last - 1] < 1 - CLOSE_ENOUGH) {
383 return false;
384 }
385 pt = cubic.xyAtT((i[cubicIndex][last] + i[cubicIndex][last - 1]) / 2);
386 return true;
387 }
388
389 int SkIntersections::intersect(const SkDCubic& c1, const SkDCubic& c2) {
390 ::intersect(c1, 0, 1, c2, 0, 1, 1, *this);
391 // FIXME: pass in cached bounds from caller
392 SkDRect c1Bounds, c2Bounds;
393 c1Bounds.setBounds(c1); // OPTIMIZE use setRawBounds ?
394 c2Bounds.setBounds(c2);
395 intersectEnd(c1, false, c2, c2Bounds, *this);
396 intersectEnd(c1, true, c2, c2Bounds, *this);
397 bool selfIntersect = &c1 == &c2;
398 if (!selfIntersect) {
399 swap();
400 intersectEnd(c2, false, c1, c1Bounds, *this);
401 intersectEnd(c2, true, c1, c1Bounds, *this);
402 swap();
403 }
404 // If an end point and a second point very close to the end is returned, the second
405 // point may have been detected because the approximate quads
406 // intersected at the end and close to it. Verify that the second point is v alid.
407 if (fUsed <= 1 || coincidentUsed()) {
408 return fUsed;
409 }
410 SkDPoint pt[2];
411 if (closeStart(c1, 0, *this, pt[0]) && closeStart(c2, 1, *this, pt[1])
412 && pt[0].approximatelyEqual(pt[1])) {
413 removeOne(1);
414 }
415 if (closeEnd(c1, 0, *this, pt[0]) && closeEnd(c2, 1, *this, pt[1])
416 && pt[0].approximatelyEqual(pt[1])) {
417 removeOne(used() - 2);
418 }
419 return fUsed;
420 }
421
422 // Up promote the quad to a cubic.
423 // OPTIMIZATION If this is a common use case, optimize by duplicating
424 // the intersect 3 loop to avoid the promotion / demotion code
425 int SkIntersections::intersect(const SkDCubic& cubic, const SkDQuad& quad) {
426 SkDCubic up = quad.toCubic();
427 (void) intersect(cubic, up);
428 return used();
429 }
430
431 /* http://www.ag.jku.at/compass/compasssample.pdf
432 ( Self-Intersection Problems and Approximate Implicitization by Jan B. Thomassen
433 Centre of Mathematics for Applications, University of Oslo http://www.cma.uio.no janbth@math.uio.no
434 SINTEF Applied Mathematics http://www.sintef.no )
435 describes a method to find the self intersection of a cubic by taking the gradie nt of the implicit
436 form dotted with the normal, and solving for the roots. My math foo is too poor to implement this.*/
437
438 int SkIntersections::intersect(const SkDCubic& c) {
439 // check to see if x or y end points are the extrema. Are other quick reject s possible?
440 if (c.endsAreExtremaInXOrY()) {
441 return false;
442 }
443 (void) intersect(c, c);
444 if (used() > 0) {
445 SkASSERT(used() == 1);
446 if (fT[0][0] > fT[1][0]) {
447 swapPts();
448 }
449 }
450 return used();
451 }
OLDNEW
« no previous file with comments | « no previous file | src/pathops/SkDCubicLineIntersection.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698