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 #ifndef SkPathOpsPoint_DEFINED 8 #define SkPathOpsPoint_DEFINED 9 10 #include "SkPathOpsTypes.h" 11 #include "SkPoint.h" 12 13 inline bool AlmostEqualUlps(const SkPoint& pt1, const SkPoint& pt2) { 14 return AlmostEqualUlps(pt1.fX, pt2.fX) && AlmostEqualUlps(pt1.fY, pt2.fY); 15 } 16 17 struct SkDVector { 18 double fX; 19 double fY; 20 21 void set(const SkVector& pt) { 22 fX = pt.fX; 23 fY = pt.fY; 24 } 25 26 // only used by testing 27 void operator+=(const SkDVector& v) { 28 fX += v.fX; 29 fY += v.fY; 30 } 31 32 // only called by nearestT, which is currently only used by testing 33 void operator-=(const SkDVector& v) { 34 fX -= v.fX; 35 fY -= v.fY; 36 } 37 38 // only used by testing 39 void operator/=(const double s) { 40 fX /= s; 41 fY /= s; 42 } 43 44 // only used by testing 45 void operator*=(const double s) { 46 fX *= s; 47 fY *= s; 48 } 49 50 SkVector asSkVector() const { 51 SkVector v = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)}; 52 return v; 53 } 54 55 // only used by testing 56 double cross(const SkDVector& a) const { 57 return fX * a.fY - fY * a.fX; 58 } 59 60 // similar to cross, this bastardization considers nearly coincident to be zero 61 double crossCheck(const SkDVector& a) const { 62 double xy = fX * a.fY; 63 double yx = fY * a.fX; 64 return AlmostEqualUlps(xy, yx) ? 0 : xy - yx; 65 } 66 67 double dot(const SkDVector& a) const { 68 return fX * a.fX + fY * a.fY; 69 } 70 71 double length() const { 72 return sqrt(lengthSquared()); 73 } 74 75 double lengthSquared() const { 76 return fX * fX + fY * fY; 77 } 78 }; 79 80 struct SkDPoint { 81 double fX; 82 double fY; 83 84 void set(const SkPoint& pt) { 85 fX = pt.fX; 86 fY = pt.fY; 87 } 88 89 friend SkDVector operator-(const SkDPoint& a, const SkDPoint& b); 90 91 friend bool operator==(const SkDPoint& a, const SkDPoint& b) { 92 return a.fX == b.fX && a.fY == b.fY; 93 } 94 95 friend bool operator!=(const SkDPoint& a, const SkDPoint& b) { 96 return a.fX != b.fX || a.fY != b.fY; 97 } 98 99 void operator=(const SkPoint& pt) { 100 fX = pt.fX; 101 fY = pt.fY; 102 } 103 104 // only used by testing 105 void operator+=(const SkDVector& v) { 106 fX += v.fX; 107 fY += v.fY; 108 } 109 110 // only used by testing 111 void operator-=(const SkDVector& v) { 112 fX -= v.fX; 113 fY -= v.fY; 114 } 115 116 // only used by testing 117 SkDPoint operator+(const SkDVector& v) { 118 SkDPoint result = *this; 119 result += v; 120 return result; 121 } 122 123 // only used by testing 124 SkDPoint operator-(const SkDVector& v) { 125 SkDPoint result = *this; 126 result -= v; 127 return result; 128 } 129 130 // note: this can not be implemented with 131 // return approximately_equal(a.fY, fY) && approximately_equal(a.fX, fX); 132 // because that will not take the magnitude of the values into account 133 bool approximatelyEqual(const SkDPoint& a) const { 134 if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) { 135 return true; 136 } 137 if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) { 138 return false; 139 } 140 double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ? 141 double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY); 142 double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY); 143 largest = SkTMax(largest, -tiniest); 144 return AlmostPequalUlps(largest, largest + dist); // is the dist within ULPS tolerance? 145 } 146 147 bool approximatelyEqual(const SkPoint& a) const { 148 SkDPoint dA; 149 dA.set(a); 150 return approximatelyEqual(dA); 151 } 152 153 static bool ApproximatelyEqual(const SkPoint& a, const SkPoint& b) { 154 if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) { 155 return true; 156 } 157 if (!RoughlyEqualUlps(a.fX, b.fX) || !RoughlyEqualUlps(a.fY, b.fY)) { 158 return false; 159 } 160 SkDPoint dA, dB; 161 dA.set(a); 162 dB.set(b); 163 double dist = dA.distance(dB); // OPTIMIZATION: can we compare against distSq instead ? 164 float tiniest = SkTMin(SkTMin(SkTMin(a.fX, b.fX), a.fY), b.fY); 165 float largest = SkTMax(SkTMax(SkTMax(a.fX, b.fX), a.fY), b.fY); 166 largest = SkTMax(largest, -tiniest); 167 return AlmostPequalUlps((double) largest, largest + dist); // is dist within ULPS tolerance? 168 } 169 170 // only used by testing 171 bool approximatelyZero() const { 172 return approximately_zero(fX) && approximately_zero(fY); 173 } 174 175 SkPoint asSkPoint() const { 176 SkPoint pt = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)}; 177 return pt; 178 } 179 180 double distance(const SkDPoint& a) const { 181 SkDVector temp = *this - a; 182 return temp.length(); 183 } 184 185 double distanceSquared(const SkDPoint& a) const { 186 SkDVector temp = *this - a; 187 return temp.lengthSquared(); 188 } 189 190 static SkDPoint Mid(const SkDPoint& a, const SkDPoint& b) { 191 SkDPoint result; 192 result.fX = (a.fX + b.fX) / 2; 193 result.fY = (a.fY + b.fY) / 2; 194 return result; 195 } 196 197 bool roughlyEqual(const SkDPoint& a) const { 198 if (roughly_equal(fX, a.fX) && roughly_equal(fY, a.fY)) { 199 return true; 200 } 201 double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ? 202 double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY); 203 double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY); 204 largest = SkTMax(largest, -tiniest); 205 return RoughlyEqualUlps(largest, largest + dist); // is the dist within ULPS tolerance? 206 } 207 208 static bool RoughlyEqual(const SkPoint& a, const SkPoint& b) { 209 if (!RoughlyEqualUlps(a.fX, b.fX) && !RoughlyEqualUlps(a.fY, b.fY)) { 210 return false; 211 } 212 SkDPoint dA, dB; 213 dA.set(a); 214 dB.set(b); 215 double dist = dA.distance(dB); // OPTIMIZATION: can we compare against distSq instead ? 216 float tiniest = SkTMin(SkTMin(SkTMin(a.fX, b.fX), a.fY), b.fY); 217 float largest = SkTMax(SkTMax(SkTMax(a.fX, b.fX), a.fY), b.fY); 218 largest = SkTMax(largest, -tiniest); 219 return RoughlyEqualUlps((double) largest, largest + dist); // is dist within ULPS tolerance? 220 } 221 222 // utilities callable by the user from the debugger when the implementation code is linked in 223 void dump() const; 224 static void Dump(const SkPoint& pt); 225 static void DumpHex(const SkPoint& pt); 226 }; 227 228 #endif 229