Index: src/pathops/SkPathOpsLine.cpp |
diff --git a/src/pathops/SkPathOpsLine.cpp b/src/pathops/SkPathOpsLine.cpp |
index 48c042a7facbb7ecfe525669662bdf7649e1b17a..1b548fcd30b20e4f59729808239585a37095fb2c 100644 |
--- a/src/pathops/SkPathOpsLine.cpp |
+++ b/src/pathops/SkPathOpsLine.cpp |
@@ -78,9 +78,7 @@ double SkDLine::nearPoint(const SkDPoint& xy) const { |
} |
double t = numer / denom; |
SkDPoint realPt = ptAtT(t); |
- SkDVector distU = xy - realPt; |
- double distSq = distU.fX * distU.fX + distU.fY * distU.fY; |
- double dist = sqrt(distSq); // OPTIMIZATION: can we compare against distSq instead ? |
+ double dist = realPt.distance(xy); // OPTIMIZATION: can we compare against distSq instead ? |
// find the ordinal in the original line with the largest unsigned exponent |
double tiniest = SkTMin(SkTMin(SkTMin(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY); |
double largest = SkTMax(SkTMax(SkTMax(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY); |
@@ -93,6 +91,35 @@ double SkDLine::nearPoint(const SkDPoint& xy) const { |
return t; |
} |
+bool SkDLine::nearRay(const SkDPoint& xy) const { |
+ // project a perpendicular ray from the point to the line; find the T on the line |
+ SkDVector len = fPts[1] - fPts[0]; // the x/y magnitudes of the line |
+ double denom = len.fX * len.fX + len.fY * len.fY; // see DLine intersectRay |
+ SkDVector ab0 = xy - fPts[0]; |
+ double numer = len.fX * ab0.fX + ab0.fY * len.fY; |
+ double t = numer / denom; |
+ SkDPoint realPt = ptAtT(t); |
+ double dist = realPt.distance(xy); // OPTIMIZATION: can we compare against distSq instead ? |
+ // find the ordinal in the original line with the largest unsigned exponent |
+ double tiniest = SkTMin(SkTMin(SkTMin(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY); |
+ double largest = SkTMax(SkTMax(SkTMax(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY); |
+ largest = SkTMax(largest, -tiniest); |
+ return RoughlyEqualUlps(largest, largest + dist); // is the dist within ULPS tolerance? |
+} |
+ |
+// Returns true if a ray from (0,0) to (x1,y1) is coincident with a ray (0,0) to (x2,y2) |
+// OPTIMIZE: a specialty routine could speed this up -- may not be called very often though |
+bool SkDLine::NearRay(double x1, double y1, double x2, double y2) { |
+ double denom1 = x1 * x1 + y1 * y1; |
+ double denom2 = x2 * x2 + y2 * y2; |
+ SkDLine line = {{{0, 0}, {x1, y1}}}; |
+ SkDPoint pt = {x2, y2}; |
+ if (denom2 > denom1) { |
+ SkTSwap(line[1], pt); |
+ } |
+ return line.nearRay(pt); |
+} |
+ |
double SkDLine::ExactPointH(const SkDPoint& xy, double left, double right, double y) { |
if (xy.fY == y) { |
if (xy.fX == left) { |
@@ -106,7 +133,7 @@ double SkDLine::ExactPointH(const SkDPoint& xy, double left, double right, doubl |
} |
double SkDLine::NearPointH(const SkDPoint& xy, double left, double right, double y) { |
- if (!AlmostEqualUlps(xy.fY, y)) { |
+ if (!AlmostBequalUlps(xy.fY, y)) { |
return -1; |
} |
if (!AlmostBetweenUlps(left, xy.fX, right)) { |
@@ -115,6 +142,18 @@ double SkDLine::NearPointH(const SkDPoint& xy, double left, double right, double |
double t = (xy.fX - left) / (right - left); |
t = SkPinT(t); |
SkASSERT(between(0, t, 1)); |
+ double realPtX = (1 - t) * left + t * right; |
+ SkDVector distU = {xy.fY - y, xy.fX - realPtX}; |
+ double distSq = distU.fX * distU.fX + distU.fY * distU.fY; |
+ double dist = sqrt(distSq); // OPTIMIZATION: can we compare against distSq instead ? |
+ double tiniest = SkTMin(SkTMin(y, left), right); |
+ double largest = SkTMax(SkTMax(y, left), right); |
+ largest = SkTMax(largest, -tiniest); |
+ if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS tolerance? |
+ return -1; |
+ } |
+ t = SkPinT(t); |
+ SkASSERT(between(0, t, 1)); |
return t; |
} |
@@ -131,7 +170,7 @@ double SkDLine::ExactPointV(const SkDPoint& xy, double top, double bottom, doubl |
} |
double SkDLine::NearPointV(const SkDPoint& xy, double top, double bottom, double x) { |
- if (!AlmostEqualUlps(xy.fX, x)) { |
+ if (!AlmostBequalUlps(xy.fX, x)) { |
return -1; |
} |
if (!AlmostBetweenUlps(top, xy.fY, bottom)) { |
@@ -140,5 +179,27 @@ double SkDLine::NearPointV(const SkDPoint& xy, double top, double bottom, double |
double t = (xy.fY - top) / (bottom - top); |
t = SkPinT(t); |
SkASSERT(between(0, t, 1)); |
+ double realPtY = (1 - t) * top + t * bottom; |
+ SkDVector distU = {xy.fX - x, xy.fY - realPtY}; |
+ double distSq = distU.fX * distU.fX + distU.fY * distU.fY; |
+ double dist = sqrt(distSq); // OPTIMIZATION: can we compare against distSq instead ? |
+ double tiniest = SkTMin(SkTMin(x, top), bottom); |
+ double largest = SkTMax(SkTMax(x, top), bottom); |
+ largest = SkTMax(largest, -tiniest); |
+ if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS tolerance? |
+ return -1; |
+ } |
+ t = SkPinT(t); |
+ SkASSERT(between(0, t, 1)); |
return t; |
} |
+ |
+#ifdef SK_DEBUG |
+void SkDLine::dump() { |
+ SkDebugf("{{"); |
+ fPts[0].dump(); |
+ SkDebugf(", "); |
+ fPts[1].dump(); |
+ SkDebugf("}}\n"); |
+} |
+#endif |