OLD | NEW |
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 | 9 |
10 /* Determine the intersection point of two lines. This assumes the lines are not
parallel, | 10 /* Determine the intersection point of two lines. This assumes the lines are not
parallel, |
11 and that that the lines are infinite. | 11 and that that the lines are infinite. |
12 From http://en.wikipedia.org/wiki/Line-line_intersection | 12 From http://en.wikipedia.org/wiki/Line-line_intersection |
13 */ | 13 */ |
14 SkDPoint SkIntersections::Line(const SkDLine& a, const SkDLine& b) { | 14 SkDPoint SkIntersections::Line(const SkDLine& a, const SkDLine& b) { |
15 double axLen = a[1].fX - a[0].fX; | 15 double axLen = a[1].fX - a[0].fX; |
16 double ayLen = a[1].fY - a[0].fY; | 16 double ayLen = a[1].fY - a[0].fY; |
17 double bxLen = b[1].fX - b[0].fX; | 17 double bxLen = b[1].fX - b[0].fX; |
18 double byLen = b[1].fY - b[0].fY; | 18 double byLen = b[1].fY - b[0].fY; |
19 double denom = byLen * axLen - ayLen * bxLen; | 19 double denom = byLen * axLen - ayLen * bxLen; |
20 SkASSERT(denom); | 20 SkASSERT(denom); |
21 double term1 = a[1].fX * a[0].fY - a[1].fY * a[0].fX; | 21 double term1 = a[1].fX * a[0].fY - a[1].fY * a[0].fX; |
22 double term2 = b[1].fX * b[0].fY - b[1].fY * b[0].fX; | 22 double term2 = b[1].fX * b[0].fY - b[1].fY * b[0].fX; |
23 SkDPoint p; | 23 SkDPoint p; |
24 p.fX = (term1 * bxLen - axLen * term2) / denom; | 24 p.fX = (term1 * bxLen - axLen * term2) / denom; |
25 p.fY = (term1 * byLen - ayLen * term2) / denom; | 25 p.fY = (term1 * byLen - ayLen * term2) / denom; |
26 return p; | 26 return p; |
27 } | 27 } |
28 | 28 |
29 int SkIntersections::computePoints(const SkDLine& line, int used) { | 29 void SkIntersections::cleanUpCoincidence() { |
| 30 SkASSERT(fUsed == 2); |
| 31 // both t values are good |
| 32 bool startMatch = fT[0][0] == 0 && (fT[1][0] == 0 || fT[1][0] == 1); |
| 33 bool endMatch = fT[0][1] == 1 && (fT[1][1] == 0 || fT[1][1] == 1); |
| 34 if (startMatch || endMatch) { |
| 35 removeOne(startMatch); |
| 36 return; |
| 37 } |
| 38 // either t value is good |
| 39 bool pStartMatch = fT[0][0] == 0 || fT[1][0] == 0 || fT[1][0] == 1; |
| 40 bool pEndMatch = fT[0][1] == 1 || fT[1][1] == 0 || fT[1][1] == 1; |
| 41 removeOne(pStartMatch || !pEndMatch); |
| 42 } |
| 43 |
| 44 void SkIntersections::cleanUpParallelLines(bool parallel) { |
| 45 while (fUsed > 2) { |
| 46 removeOne(1); |
| 47 } |
| 48 if (fUsed == 2 && !parallel) { |
| 49 bool startMatch = fT[0][0] == 0 || fT[1][0] == 0 || fT[1][0] == 1; |
| 50 bool endMatch = fT[0][1] == 1 || fT[1][1] == 0 || fT[1][1] == 1; |
| 51 if ((!startMatch && !endMatch) || approximately_equal(fT[0][0], fT[0][1]
)) { |
| 52 SkASSERT(startMatch || endMatch); |
| 53 removeOne(endMatch); |
| 54 } |
| 55 } |
| 56 } |
| 57 |
| 58 void SkIntersections::computePoints(const SkDLine& line, int used) { |
30 fPt[0] = line.ptAtT(fT[0][0]); | 59 fPt[0] = line.ptAtT(fT[0][0]); |
31 if ((fUsed = used) == 2) { | 60 if ((fUsed = used) == 2) { |
32 fPt[1] = line.ptAtT(fT[0][1]); | 61 fPt[1] = line.ptAtT(fT[0][1]); |
33 } | 62 } |
34 return fUsed; | |
35 } | 63 } |
36 | 64 |
37 int SkIntersections::intersectRay(const SkDLine& a, const SkDLine& b) { | 65 int SkIntersections::intersectRay(const SkDLine& a, const SkDLine& b) { |
| 66 fMax = 2; |
38 SkDVector aLen = a[1] - a[0]; | 67 SkDVector aLen = a[1] - a[0]; |
39 SkDVector bLen = b[1] - b[0]; | 68 SkDVector bLen = b[1] - b[0]; |
40 /* Slopes match when denom goes to zero: | 69 /* Slopes match when denom goes to zero: |
41 axLen / ayLen == bxLen / byLen | 70 axLen / ayLen == bxLen / byLen |
42 (ayLen * byLen) * axLen / ayLen == (ayLen * byLen) * bxLen / byLen | 71 (ayLen * byLen) * axLen / ayLen == (ayLen * byLen) * bxLen / byLen |
43 byLen * axLen == ayLen * bxLen | 72 byLen * axLen == ayLen * bxLen |
44 byLen * axLen - ayLen * bxLen == 0 ( == denom ) | 73 byLen * axLen - ayLen * bxLen == 0 ( == denom ) |
45 */ | 74 */ |
46 double denom = bLen.fY * aLen.fX - aLen.fY * bLen.fX; | 75 double denom = bLen.fY * aLen.fX - aLen.fY * bLen.fX; |
47 SkDVector ab0 = a[0] - b[0]; | 76 SkDVector ab0 = a[0] - b[0]; |
(...skipping 14 matching lines...) Expand all Loading... |
62 */ | 91 */ |
63 if (!AlmostEqualUlps(aLen.fX * a[0].fY - aLen.fY * a[0].fX, | 92 if (!AlmostEqualUlps(aLen.fX * a[0].fY - aLen.fY * a[0].fX, |
64 aLen.fX * b[0].fY - aLen.fY * b[0].fX)) { | 93 aLen.fX * b[0].fY - aLen.fY * b[0].fX)) { |
65 return fUsed = 0; | 94 return fUsed = 0; |
66 } | 95 } |
67 // there's no great answer for intersection points for coincident rays,
but return something | 96 // there's no great answer for intersection points for coincident rays,
but return something |
68 fT[0][0] = fT[1][0] = 0; | 97 fT[0][0] = fT[1][0] = 0; |
69 fT[1][0] = fT[1][1] = 1; | 98 fT[1][0] = fT[1][1] = 1; |
70 used = 2; | 99 used = 2; |
71 } | 100 } |
72 return computePoints(a, used); | 101 computePoints(a, used); |
| 102 return fUsed; |
73 } | 103 } |
74 | 104 |
75 // note that this only works if both lines are neither horizontal nor vertical | 105 // note that this only works if both lines are neither horizontal nor vertical |
76 int SkIntersections::intersect(const SkDLine& a, const SkDLine& b) { | 106 int SkIntersections::intersect(const SkDLine& a, const SkDLine& b) { |
| 107 fMax = 3; // note that we clean up so that there is no more than two in the
end |
77 // see if end points intersect the opposite line | 108 // see if end points intersect the opposite line |
78 double t; | 109 double t; |
79 for (int iA = 0; iA < 2; ++iA) { | 110 for (int iA = 0; iA < 2; ++iA) { |
80 if ((t = b.exactPoint(a[iA])) >= 0) { | 111 if ((t = b.exactPoint(a[iA])) >= 0) { |
81 insert(iA, t, a[iA]); | 112 insert(iA, t, a[iA]); |
82 } | 113 } |
83 } | 114 } |
84 for (int iB = 0; iB < 2; ++iB) { | 115 for (int iB = 0; iB < 2; ++iB) { |
85 if ((t = a.exactPoint(b[iB])) >= 0) { | 116 if ((t = a.exactPoint(b[iB])) >= 0) { |
86 insert(t, iB, b[iB]); | 117 insert(t, iB, b[iB]); |
87 } | 118 } |
88 } | 119 } |
89 /* Determine the intersection point of two line segments | 120 /* Determine the intersection point of two line segments |
90 Return FALSE if the lines don't intersect | 121 Return FALSE if the lines don't intersect |
91 from: http://paulbourke.net/geometry/lineline2d/ */ | 122 from: http://paulbourke.net/geometry/lineline2d/ */ |
92 double axLen = a[1].fX - a[0].fX; | 123 double axLen = a[1].fX - a[0].fX; |
93 double ayLen = a[1].fY - a[0].fY; | 124 double ayLen = a[1].fY - a[0].fY; |
94 double bxLen = b[1].fX - b[0].fX; | 125 double bxLen = b[1].fX - b[0].fX; |
95 double byLen = b[1].fY - b[0].fY; | 126 double byLen = b[1].fY - b[0].fY; |
96 /* Slopes match when denom goes to zero: | 127 /* Slopes match when denom goes to zero: |
97 axLen / ayLen == bxLen / byLen | 128 axLen / ayLen == bxLen / byLen |
98 (ayLen * byLen) * axLen / ayLen == (ayLen * byLen) * bxLen / byLen | 129 (ayLen * byLen) * axLen / ayLen == (ayLen * byLen) * bxLen / byLen |
99 byLen * axLen == ayLen * bxLen | 130 byLen * axLen == ayLen * bxLen |
100 byLen * axLen - ayLen * bxLen == 0 ( == denom ) | 131 byLen * axLen - ayLen * bxLen == 0 ( == denom ) |
101 */ | 132 */ |
102 double axByLen = axLen * byLen; | 133 double axByLen = axLen * byLen; |
103 double ayBxLen = ayLen * bxLen; | 134 double ayBxLen = ayLen * bxLen; |
104 // detect parallel lines the same way here and in SkOpAngle operator < | 135 // detect parallel lines the same way here and in SkOpAngle operator < |
105 // so that non-parallel means they are also sortable | 136 // so that non-parallel means they are also sortable |
106 bool unparallel = NotAlmostEqualUlps(axByLen, ayBxLen); | 137 bool unparallel = fAllowNear ? NotAlmostEqualUlps(axByLen, ayBxLen) |
107 if (unparallel) { | 138 : NotAlmostDequalUlps(axByLen, ayBxLen); |
| 139 if (unparallel && fUsed == 0) { |
108 double ab0y = a[0].fY - b[0].fY; | 140 double ab0y = a[0].fY - b[0].fY; |
109 double ab0x = a[0].fX - b[0].fX; | 141 double ab0x = a[0].fX - b[0].fX; |
110 double numerA = ab0y * bxLen - byLen * ab0x; | 142 double numerA = ab0y * bxLen - byLen * ab0x; |
111 double numerB = ab0y * axLen - ayLen * ab0x; | 143 double numerB = ab0y * axLen - ayLen * ab0x; |
112 double denom = axByLen - ayBxLen; | 144 double denom = axByLen - ayBxLen; |
113 if (between(0, numerA, denom) && between(0, numerB, denom)) { | 145 if (between(0, numerA, denom) && between(0, numerB, denom)) { |
114 fT[0][0] = numerA / denom; | 146 fT[0][0] = numerA / denom; |
115 fT[1][0] = numerB / denom; | 147 fT[1][0] = numerB / denom; |
116 computePoints(a, 1); | 148 computePoints(a, 1); |
117 } | 149 } |
118 } | 150 } |
119 if (fAllowNear || !unparallel) { | 151 if (fAllowNear || !unparallel) { |
120 for (int iA = 0; iA < 2; ++iA) { | 152 for (int iA = 0; iA < 2; ++iA) { |
121 if ((t = b.nearPoint(a[iA])) >= 0) { | 153 if ((t = b.nearPoint(a[iA])) >= 0) { |
122 insert(iA, t, a[iA]); | 154 insert(iA, t, a[iA]); |
123 } | 155 } |
124 } | 156 } |
125 for (int iB = 0; iB < 2; ++iB) { | 157 for (int iB = 0; iB < 2; ++iB) { |
126 if ((t = a.nearPoint(b[iB])) >= 0) { | 158 if ((t = a.nearPoint(b[iB])) >= 0) { |
127 insert(t, iB, b[iB]); | 159 insert(t, iB, b[iB]); |
128 } | 160 } |
129 } | 161 } |
130 } | 162 } |
131 while (fUsed > 2) { | 163 cleanUpParallelLines(!unparallel); |
132 removeOne(1); | 164 SkASSERT(fUsed <= 2); |
133 } | |
134 if (fUsed == 2 && unparallel) { | |
135 bool startMatch = fT[0][0] == 0 || fT[1][0] == 0 || fT[1][0] == 1; | |
136 bool endMatch = fT[0][1] == 1 || fT[1][1] == 0 || fT[1][1] == 1; | |
137 if (!startMatch && !endMatch) { | |
138 SkASSERT(startMatch || endMatch); | |
139 removeOne(endMatch); | |
140 } | |
141 } | |
142 return fUsed; | 165 return fUsed; |
143 } | 166 } |
144 | 167 |
145 static int horizontal_coincident(const SkDLine& line, double y) { | 168 static int horizontal_coincident(const SkDLine& line, double y) { |
146 double min = line[0].fY; | 169 double min = line[0].fY; |
147 double max = line[1].fY; | 170 double max = line[1].fY; |
148 if (min > max) { | 171 if (min > max) { |
149 SkTSwap(min, max); | 172 SkTSwap(min, max); |
150 } | 173 } |
151 if (min > y || max < y) { | 174 if (min > y || max < y) { |
152 return 0; | 175 return 0; |
153 } | 176 } |
154 if (AlmostEqualUlps(min, max) && max - min < fabs(line[0].fX - line[1].fX))
{ | 177 if (AlmostEqualUlps(min, max) && max - min < fabs(line[0].fX - line[1].fX))
{ |
155 return 2; | 178 return 2; |
156 } | 179 } |
157 return 1; | 180 return 1; |
158 } | 181 } |
159 | 182 |
160 static double horizontal_intercept(const SkDLine& line, double y) { | 183 static double horizontal_intercept(const SkDLine& line, double y) { |
161 return (y - line[0].fY) / (line[1].fY - line[0].fY); | 184 return (y - line[0].fY) / (line[1].fY - line[0].fY); |
162 } | 185 } |
163 | 186 |
164 int SkIntersections::horizontal(const SkDLine& line, double y) { | 187 int SkIntersections::horizontal(const SkDLine& line, double y) { |
| 188 fMax = 2; |
165 int horizontalType = horizontal_coincident(line, y); | 189 int horizontalType = horizontal_coincident(line, y); |
166 if (horizontalType == 1) { | 190 if (horizontalType == 1) { |
167 fT[0][0] = horizontal_intercept(line, y); | 191 fT[0][0] = horizontal_intercept(line, y); |
168 } else if (horizontalType == 2) { | 192 } else if (horizontalType == 2) { |
169 fT[0][0] = 0; | 193 fT[0][0] = 0; |
170 fT[0][1] = 1; | 194 fT[0][1] = 1; |
171 } | 195 } |
172 return fUsed = horizontalType; | 196 return fUsed = horizontalType; |
173 } | 197 } |
174 | 198 |
175 int SkIntersections::horizontal(const SkDLine& line, double left, double right, | 199 int SkIntersections::horizontal(const SkDLine& line, double left, double right, |
176 double y, bool flipped) { | 200 double y, bool flipped) { |
| 201 fMax = 2; |
177 // see if end points intersect the opposite line | 202 // see if end points intersect the opposite line |
178 double t; | 203 double t; |
179 const SkDPoint leftPt = { left, y }; | 204 const SkDPoint leftPt = { left, y }; |
180 if ((t = line.exactPoint(leftPt)) >= 0) { | 205 if ((t = line.exactPoint(leftPt)) >= 0) { |
181 insert(t, (double) flipped, leftPt); | 206 insert(t, (double) flipped, leftPt); |
182 } | 207 } |
183 if (left != right) { | 208 if (left != right) { |
184 const SkDPoint rightPt = { right, y }; | 209 const SkDPoint rightPt = { right, y }; |
185 if ((t = line.exactPoint(rightPt)) >= 0) { | 210 if ((t = line.exactPoint(rightPt)) >= 0) { |
186 insert(t, (double) !flipped, rightPt); | 211 insert(t, (double) !flipped, rightPt); |
187 } | 212 } |
188 for (int index = 0; index < 2; ++index) { | 213 for (int index = 0; index < 2; ++index) { |
189 if ((t = SkDLine::ExactPointH(line[index], left, right, y)) >= 0) { | 214 if ((t = SkDLine::ExactPointH(line[index], left, right, y)) >= 0) { |
190 insert((double) index, flipped ? 1 - t : t, line[index]); | 215 insert((double) index, flipped ? 1 - t : t, line[index]); |
191 } | 216 } |
192 } | 217 } |
193 } | 218 } |
194 int result = horizontal_coincident(line, y); | 219 int result = horizontal_coincident(line, y); |
195 if (result == 1 && fUsed == 0) { | 220 if (result == 1 && fUsed == 0) { |
196 fT[0][0] = horizontal_intercept(line, y); | 221 fT[0][0] = horizontal_intercept(line, y); |
197 double xIntercept = line[0].fX + fT[0][0] * (line[1].fX - line[0].fX); | 222 double xIntercept = line[0].fX + fT[0][0] * (line[1].fX - line[0].fX); |
198 if (between(left, xIntercept, right)) { | 223 if (between(left, xIntercept, right)) { |
199 fT[1][0] = (xIntercept - left) / (right - left); | 224 fT[1][0] = (xIntercept - left) / (right - left); |
200 if (flipped) { | 225 if (flipped) { |
201 // OPTIMIZATION: ? instead of swapping, pass original line, use
[1].fX - [0].fX | 226 // OPTIMIZATION: ? instead of swapping, pass original line, use
[1].fX - [0].fX |
202 for (int index = 0; index < result; ++index) { | 227 for (int index = 0; index < result; ++index) { |
203 fT[1][index] = 1 - fT[1][index]; | 228 fT[1][index] = 1 - fT[1][index]; |
204 } | 229 } |
205 } | 230 } |
206 return computePoints(line, result); | 231 computePoints(line, result); |
207 } | 232 } |
208 } | 233 } |
209 if (!fAllowNear && result != 2) { | 234 if (fAllowNear || result == 2) { |
210 return fUsed; | 235 if ((t = line.nearPoint(leftPt)) >= 0) { |
211 } | 236 insert(t, (double) flipped, leftPt); |
212 if ((t = line.nearPoint(leftPt)) >= 0) { | |
213 insert(t, (double) flipped, leftPt); | |
214 } | |
215 if (left != right) { | |
216 const SkDPoint rightPt = { right, y }; | |
217 if ((t = line.nearPoint(rightPt)) >= 0) { | |
218 insert(t, (double) !flipped, rightPt); | |
219 } | 237 } |
220 for (int index = 0; index < 2; ++index) { | 238 if (left != right) { |
221 if ((t = SkDLine::NearPointH(line[index], left, right, y)) >= 0) { | 239 const SkDPoint rightPt = { right, y }; |
222 insert((double) index, flipped ? 1 - t : t, line[index]); | 240 if ((t = line.nearPoint(rightPt)) >= 0) { |
| 241 insert(t, (double) !flipped, rightPt); |
| 242 } |
| 243 for (int index = 0; index < 2; ++index) { |
| 244 if ((t = SkDLine::NearPointH(line[index], left, right, y)) >= 0)
{ |
| 245 insert((double) index, flipped ? 1 - t : t, line[index]); |
| 246 } |
223 } | 247 } |
224 } | 248 } |
225 } | 249 } |
| 250 cleanUpParallelLines(result == 2); |
226 return fUsed; | 251 return fUsed; |
227 } | 252 } |
228 | 253 |
229 static int vertical_coincident(const SkDLine& line, double x) { | 254 static int vertical_coincident(const SkDLine& line, double x) { |
230 double min = line[0].fX; | 255 double min = line[0].fX; |
231 double max = line[1].fX; | 256 double max = line[1].fX; |
232 if (min > max) { | 257 if (min > max) { |
233 SkTSwap(min, max); | 258 SkTSwap(min, max); |
234 } | 259 } |
235 if (!precisely_between(min, x, max)) { | 260 if (!precisely_between(min, x, max)) { |
236 return 0; | 261 return 0; |
237 } | 262 } |
238 if (AlmostEqualUlps(min, max)) { | 263 if (AlmostEqualUlps(min, max)) { |
239 return 2; | 264 return 2; |
240 } | 265 } |
241 return 1; | 266 return 1; |
242 } | 267 } |
243 | 268 |
244 static double vertical_intercept(const SkDLine& line, double x) { | 269 static double vertical_intercept(const SkDLine& line, double x) { |
245 return (x - line[0].fX) / (line[1].fX - line[0].fX); | 270 return (x - line[0].fX) / (line[1].fX - line[0].fX); |
246 } | 271 } |
247 | 272 |
248 int SkIntersections::vertical(const SkDLine& line, double x) { | 273 int SkIntersections::vertical(const SkDLine& line, double x) { |
| 274 fMax = 2; |
249 int verticalType = vertical_coincident(line, x); | 275 int verticalType = vertical_coincident(line, x); |
250 if (verticalType == 1) { | 276 if (verticalType == 1) { |
251 fT[0][0] = vertical_intercept(line, x); | 277 fT[0][0] = vertical_intercept(line, x); |
252 } else if (verticalType == 2) { | 278 } else if (verticalType == 2) { |
253 fT[0][0] = 0; | 279 fT[0][0] = 0; |
254 fT[0][1] = 1; | 280 fT[0][1] = 1; |
255 } | 281 } |
256 return fUsed = verticalType; | 282 return fUsed = verticalType; |
257 } | 283 } |
258 | 284 |
259 int SkIntersections::vertical(const SkDLine& line, double top, double bottom, | 285 int SkIntersections::vertical(const SkDLine& line, double top, double bottom, |
260 double x, bool flipped) { | 286 double x, bool flipped) { |
| 287 fMax = 2; |
261 // see if end points intersect the opposite line | 288 // see if end points intersect the opposite line |
262 double t; | 289 double t; |
263 SkDPoint topPt = { x, top }; | 290 SkDPoint topPt = { x, top }; |
264 if ((t = line.exactPoint(topPt)) >= 0) { | 291 if ((t = line.exactPoint(topPt)) >= 0) { |
265 insert(t, (double) flipped, topPt); | 292 insert(t, (double) flipped, topPt); |
266 } | 293 } |
267 if (top != bottom) { | 294 if (top != bottom) { |
268 SkDPoint bottomPt = { x, bottom }; | 295 SkDPoint bottomPt = { x, bottom }; |
269 if ((t = line.exactPoint(bottomPt)) >= 0) { | 296 if ((t = line.exactPoint(bottomPt)) >= 0) { |
270 insert(t, (double) !flipped, bottomPt); | 297 insert(t, (double) !flipped, bottomPt); |
271 } | 298 } |
272 for (int index = 0; index < 2; ++index) { | 299 for (int index = 0; index < 2; ++index) { |
273 if ((t = SkDLine::ExactPointV(line[index], top, bottom, x)) >= 0) { | 300 if ((t = SkDLine::ExactPointV(line[index], top, bottom, x)) >= 0) { |
274 insert((double) index, flipped ? 1 - t : t, line[index]); | 301 insert((double) index, flipped ? 1 - t : t, line[index]); |
275 } | 302 } |
276 } | 303 } |
277 } | 304 } |
278 int result = vertical_coincident(line, x); | 305 int result = vertical_coincident(line, x); |
279 if (result == 1 && fUsed == 0) { | 306 if (result == 1 && fUsed == 0) { |
280 fT[0][0] = vertical_intercept(line, x); | 307 fT[0][0] = vertical_intercept(line, x); |
281 double yIntercept = line[0].fY + fT[0][0] * (line[1].fY - line[0].fY); | 308 double yIntercept = line[0].fY + fT[0][0] * (line[1].fY - line[0].fY); |
282 if (between(top, yIntercept, bottom)) { | 309 if (between(top, yIntercept, bottom)) { |
283 fT[1][0] = (yIntercept - top) / (bottom - top); | 310 fT[1][0] = (yIntercept - top) / (bottom - top); |
284 if (flipped) { | 311 if (flipped) { |
285 // OPTIMIZATION: instead of swapping, pass original line, use [1
].fY - [0].fY | 312 // OPTIMIZATION: instead of swapping, pass original line, use [1
].fY - [0].fY |
286 for (int index = 0; index < result; ++index) { | 313 for (int index = 0; index < result; ++index) { |
287 fT[1][index] = 1 - fT[1][index]; | 314 fT[1][index] = 1 - fT[1][index]; |
288 } | 315 } |
289 } | 316 } |
290 return computePoints(line, result); | 317 computePoints(line, result); |
291 } | 318 } |
292 } | 319 } |
293 if (!fAllowNear && result != 2) { | 320 if (fAllowNear || result == 2) { |
294 return fUsed; | 321 if ((t = line.nearPoint(topPt)) >= 0) { |
295 } | 322 insert(t, (double) flipped, topPt); |
296 if ((t = line.nearPoint(topPt)) >= 0) { | |
297 insert(t, (double) flipped, topPt); | |
298 } | |
299 if (top != bottom) { | |
300 SkDPoint bottomPt = { x, bottom }; | |
301 if ((t = line.nearPoint(bottomPt)) >= 0) { | |
302 insert(t, (double) !flipped, bottomPt); | |
303 } | 323 } |
304 for (int index = 0; index < 2; ++index) { | 324 if (top != bottom) { |
305 if ((t = SkDLine::NearPointV(line[index], top, bottom, x)) >= 0) { | 325 SkDPoint bottomPt = { x, bottom }; |
306 insert((double) index, flipped ? 1 - t : t, line[index]); | 326 if ((t = line.nearPoint(bottomPt)) >= 0) { |
| 327 insert(t, (double) !flipped, bottomPt); |
| 328 } |
| 329 for (int index = 0; index < 2; ++index) { |
| 330 if ((t = SkDLine::NearPointV(line[index], top, bottom, x)) >= 0)
{ |
| 331 insert((double) index, flipped ? 1 - t : t, line[index]); |
| 332 } |
307 } | 333 } |
308 } | 334 } |
309 } | 335 } |
| 336 cleanUpParallelLines(result == 2); |
310 return fUsed; | 337 return fUsed; |
311 } | 338 } |
312 | 339 |
313 // from http://www.bryceboe.com/wordpress/wp-content/uploads/2006/10/intersect.p
y | 340 // from http://www.bryceboe.com/wordpress/wp-content/uploads/2006/10/intersect.p
y |
314 // 4 subs, 2 muls, 1 cmp | 341 // 4 subs, 2 muls, 1 cmp |
315 static bool ccw(const SkDPoint& A, const SkDPoint& B, const SkDPoint& C) { | 342 static bool ccw(const SkDPoint& A, const SkDPoint& B, const SkDPoint& C) { |
316 return (C.fY - A.fY) * (B.fX - A.fX) > (B.fY - A.fY) * (C.fX - A.fX); | 343 return (C.fY - A.fY) * (B.fX - A.fX) > (B.fY - A.fY) * (C.fX - A.fX); |
317 } | 344 } |
318 | 345 |
319 // 16 subs, 8 muls, 6 cmps | 346 // 16 subs, 8 muls, 6 cmps |
320 bool SkIntersections::Test(const SkDLine& a, const SkDLine& b) { | 347 bool SkIntersections::Test(const SkDLine& a, const SkDLine& b) { |
321 return ccw(a[0], b[0], b[1]) != ccw(a[1], b[0], b[1]) | 348 return ccw(a[0], b[0], b[1]) != ccw(a[1], b[0], b[1]) |
322 && ccw(a[0], a[1], b[0]) != ccw(a[0], a[1], b[1]); | 349 && ccw(a[0], a[1], b[0]) != ccw(a[0], a[1], b[1]); |
323 } | 350 } |
OLD | NEW |