| 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 |