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 "SkPathOpsLine.h" | 7 #include "SkPathOpsLine.h" |
8 | 8 |
9 SkDLine SkDLine::subDivide(double t1, double t2) const { | 9 SkDLine SkDLine::subDivide(double t1, double t2) const { |
10 SkDVector delta = tangent(); | 10 SkDVector delta = tangent(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 // project a perpendicular ray from the point to the line; find the T on the
line | 71 // project a perpendicular ray from the point to the line; find the T on the
line |
72 SkDVector len = fPts[1] - fPts[0]; // the x/y magnitudes of the line | 72 SkDVector len = fPts[1] - fPts[0]; // the x/y magnitudes of the line |
73 double denom = len.fX * len.fX + len.fY * len.fY; // see DLine intersectRay | 73 double denom = len.fX * len.fX + len.fY * len.fY; // see DLine intersectRay |
74 SkDVector ab0 = xy - fPts[0]; | 74 SkDVector ab0 = xy - fPts[0]; |
75 double numer = len.fX * ab0.fX + ab0.fY * len.fY; | 75 double numer = len.fX * ab0.fX + ab0.fY * len.fY; |
76 if (!between(0, numer, denom)) { | 76 if (!between(0, numer, denom)) { |
77 return -1; | 77 return -1; |
78 } | 78 } |
79 double t = numer / denom; | 79 double t = numer / denom; |
80 SkDPoint realPt = ptAtT(t); | 80 SkDPoint realPt = ptAtT(t); |
81 SkDVector distU = xy - realPt; | 81 double dist = realPt.distance(xy); // OPTIMIZATION: can we compare against
distSq instead ? |
82 double distSq = distU.fX * distU.fX + distU.fY * distU.fY; | |
83 double dist = sqrt(distSq); // OPTIMIZATION: can we compare against distSq i
nstead ? | |
84 // find the ordinal in the original line with the largest unsigned exponent | 82 // find the ordinal in the original line with the largest unsigned exponent |
85 double tiniest = SkTMin(SkTMin(SkTMin(fPts[0].fX, fPts[0].fY), fPts[1].fX),
fPts[1].fY); | 83 double tiniest = SkTMin(SkTMin(SkTMin(fPts[0].fX, fPts[0].fY), fPts[1].fX),
fPts[1].fY); |
86 double largest = SkTMax(SkTMax(SkTMax(fPts[0].fX, fPts[0].fY), fPts[1].fX),
fPts[1].fY); | 84 double largest = SkTMax(SkTMax(SkTMax(fPts[0].fX, fPts[0].fY), fPts[1].fX),
fPts[1].fY); |
87 largest = SkTMax(largest, -tiniest); | 85 largest = SkTMax(largest, -tiniest); |
88 if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS
tolerance? | 86 if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS
tolerance? |
89 return -1; | 87 return -1; |
90 } | 88 } |
91 t = SkPinT(t); | 89 t = SkPinT(t); |
92 SkASSERT(between(0, t, 1)); | 90 SkASSERT(between(0, t, 1)); |
93 return t; | 91 return t; |
94 } | 92 } |
95 | 93 |
| 94 bool SkDLine::nearRay(const SkDPoint& xy) const { |
| 95 // project a perpendicular ray from the point to the line; find the T on the
line |
| 96 SkDVector len = fPts[1] - fPts[0]; // the x/y magnitudes of the line |
| 97 double denom = len.fX * len.fX + len.fY * len.fY; // see DLine intersectRay |
| 98 SkDVector ab0 = xy - fPts[0]; |
| 99 double numer = len.fX * ab0.fX + ab0.fY * len.fY; |
| 100 double t = numer / denom; |
| 101 SkDPoint realPt = ptAtT(t); |
| 102 double dist = realPt.distance(xy); // OPTIMIZATION: can we compare against
distSq instead ? |
| 103 // find the ordinal in the original line with the largest unsigned exponent |
| 104 double tiniest = SkTMin(SkTMin(SkTMin(fPts[0].fX, fPts[0].fY), fPts[1].fX),
fPts[1].fY); |
| 105 double largest = SkTMax(SkTMax(SkTMax(fPts[0].fX, fPts[0].fY), fPts[1].fX),
fPts[1].fY); |
| 106 largest = SkTMax(largest, -tiniest); |
| 107 return RoughlyEqualUlps(largest, largest + dist); // is the dist within ULPS
tolerance? |
| 108 } |
| 109 |
| 110 // Returns true if a ray from (0,0) to (x1,y1) is coincident with a ray (0,0) to
(x2,y2) |
| 111 // OPTIMIZE: a specialty routine could speed this up -- may not be called very o
ften though |
| 112 bool SkDLine::NearRay(double x1, double y1, double x2, double y2) { |
| 113 double denom1 = x1 * x1 + y1 * y1; |
| 114 double denom2 = x2 * x2 + y2 * y2; |
| 115 SkDLine line = {{{0, 0}, {x1, y1}}}; |
| 116 SkDPoint pt = {x2, y2}; |
| 117 if (denom2 > denom1) { |
| 118 SkTSwap(line[1], pt); |
| 119 } |
| 120 return line.nearRay(pt); |
| 121 } |
| 122 |
96 double SkDLine::ExactPointH(const SkDPoint& xy, double left, double right, doubl
e y) { | 123 double SkDLine::ExactPointH(const SkDPoint& xy, double left, double right, doubl
e y) { |
97 if (xy.fY == y) { | 124 if (xy.fY == y) { |
98 if (xy.fX == left) { | 125 if (xy.fX == left) { |
99 return 0; | 126 return 0; |
100 } | 127 } |
101 if (xy.fX == right) { | 128 if (xy.fX == right) { |
102 return 1; | 129 return 1; |
103 } | 130 } |
104 } | 131 } |
105 return -1; | 132 return -1; |
106 } | 133 } |
107 | 134 |
108 double SkDLine::NearPointH(const SkDPoint& xy, double left, double right, double
y) { | 135 double SkDLine::NearPointH(const SkDPoint& xy, double left, double right, double
y) { |
109 if (!AlmostEqualUlps(xy.fY, y)) { | 136 if (!AlmostBequalUlps(xy.fY, y)) { |
110 return -1; | 137 return -1; |
111 } | 138 } |
112 if (!AlmostBetweenUlps(left, xy.fX, right)) { | 139 if (!AlmostBetweenUlps(left, xy.fX, right)) { |
113 return -1; | 140 return -1; |
114 } | 141 } |
115 double t = (xy.fX - left) / (right - left); | 142 double t = (xy.fX - left) / (right - left); |
116 t = SkPinT(t); | 143 t = SkPinT(t); |
117 SkASSERT(between(0, t, 1)); | 144 SkASSERT(between(0, t, 1)); |
| 145 double realPtX = (1 - t) * left + t * right; |
| 146 SkDVector distU = {xy.fY - y, xy.fX - realPtX}; |
| 147 double distSq = distU.fX * distU.fX + distU.fY * distU.fY; |
| 148 double dist = sqrt(distSq); // OPTIMIZATION: can we compare against distSq i
nstead ? |
| 149 double tiniest = SkTMin(SkTMin(y, left), right); |
| 150 double largest = SkTMax(SkTMax(y, left), right); |
| 151 largest = SkTMax(largest, -tiniest); |
| 152 if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS
tolerance? |
| 153 return -1; |
| 154 } |
| 155 t = SkPinT(t); |
| 156 SkASSERT(between(0, t, 1)); |
118 return t; | 157 return t; |
119 } | 158 } |
120 | 159 |
121 double SkDLine::ExactPointV(const SkDPoint& xy, double top, double bottom, doubl
e x) { | 160 double SkDLine::ExactPointV(const SkDPoint& xy, double top, double bottom, doubl
e x) { |
122 if (xy.fX == x) { | 161 if (xy.fX == x) { |
123 if (xy.fY == top) { | 162 if (xy.fY == top) { |
124 return 0; | 163 return 0; |
125 } | 164 } |
126 if (xy.fY == bottom) { | 165 if (xy.fY == bottom) { |
127 return 1; | 166 return 1; |
128 } | 167 } |
129 } | 168 } |
130 return -1; | 169 return -1; |
131 } | 170 } |
132 | 171 |
133 double SkDLine::NearPointV(const SkDPoint& xy, double top, double bottom, double
x) { | 172 double SkDLine::NearPointV(const SkDPoint& xy, double top, double bottom, double
x) { |
134 if (!AlmostEqualUlps(xy.fX, x)) { | 173 if (!AlmostBequalUlps(xy.fX, x)) { |
135 return -1; | 174 return -1; |
136 } | 175 } |
137 if (!AlmostBetweenUlps(top, xy.fY, bottom)) { | 176 if (!AlmostBetweenUlps(top, xy.fY, bottom)) { |
138 return -1; | 177 return -1; |
139 } | 178 } |
140 double t = (xy.fY - top) / (bottom - top); | 179 double t = (xy.fY - top) / (bottom - top); |
141 t = SkPinT(t); | 180 t = SkPinT(t); |
142 SkASSERT(between(0, t, 1)); | 181 SkASSERT(between(0, t, 1)); |
| 182 double realPtY = (1 - t) * top + t * bottom; |
| 183 SkDVector distU = {xy.fX - x, xy.fY - realPtY}; |
| 184 double distSq = distU.fX * distU.fX + distU.fY * distU.fY; |
| 185 double dist = sqrt(distSq); // OPTIMIZATION: can we compare against distSq i
nstead ? |
| 186 double tiniest = SkTMin(SkTMin(x, top), bottom); |
| 187 double largest = SkTMax(SkTMax(x, top), bottom); |
| 188 largest = SkTMax(largest, -tiniest); |
| 189 if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS
tolerance? |
| 190 return -1; |
| 191 } |
| 192 t = SkPinT(t); |
| 193 SkASSERT(between(0, t, 1)); |
143 return t; | 194 return t; |
144 } | 195 } |
| 196 |
| 197 #ifdef SK_DEBUG |
| 198 void SkDLine::dump() { |
| 199 SkDebugf("{{"); |
| 200 fPts[0].dump(); |
| 201 SkDebugf(", "); |
| 202 fPts[1].dump(); |
| 203 SkDebugf("}}\n"); |
| 204 } |
| 205 #endif |
OLD | NEW |