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