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