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
AlmostEqualUlps(const SkPoint & pt1,const SkPoint & pt2)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, fY;
19
20 friend SkDPoint operator+(const SkDPoint& a, const SkDVector& b);
21
22 void operator+=(const SkDVector& v) {
23 fX += v.fX;
24 fY += v.fY;
25 }
26
27 void operator-=(const SkDVector& v) {
28 fX -= v.fX;
29 fY -= v.fY;
30 }
31
32 void operator/=(const double s) {
33 fX /= s;
34 fY /= s;
35 }
36
37 void operator*=(const double s) {
38 fX *= s;
39 fY *= s;
40 }
41
asSkVectorSkDVector42 SkVector asSkVector() const {
43 SkVector v = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)};
44 return v;
45 }
46
crossSkDVector47 double cross(const SkDVector& a) const {
48 return fX * a.fY - fY * a.fX;
49 }
50
dotSkDVector51 double dot(const SkDVector& a) const {
52 return fX * a.fX + fY * a.fY;
53 }
54
lengthSkDVector55 double length() const {
56 return sqrt(lengthSquared());
57 }
58
lengthSquaredSkDVector59 double lengthSquared() const {
60 return fX * fX + fY * fY;
61 }
62 };
63
64 struct SkDPoint {
65 double fX;
66 double fY;
67
setSkDPoint68 void set(const SkPoint& pt) {
69 fX = pt.fX;
70 fY = pt.fY;
71 }
72
73 friend SkDVector operator-(const SkDPoint& a, const SkDPoint& b);
74
75 friend bool operator==(const SkDPoint& a, const SkDPoint& b) {
76 return a.fX == b.fX && a.fY == b.fY;
77 }
78
79 friend bool operator!=(const SkDPoint& a, const SkDPoint& b) {
80 return a.fX != b.fX || a.fY != b.fY;
81 }
82
83 void operator=(const SkPoint& pt) {
84 fX = pt.fX;
85 fY = pt.fY;
86 }
87
88
89 void operator+=(const SkDVector& v) {
90 fX += v.fX;
91 fY += v.fY;
92 }
93
94 void operator-=(const SkDVector& v) {
95 fX -= v.fX;
96 fY -= v.fY;
97 }
98
99 // note: this can not be implemented with
100 // return approximately_equal(a.fY, fY) && approximately_equal(a.fX, fX);
101 // because that will not take the magnitude of the values into account
approximatelyEqualSkDPoint102 bool approximatelyEqual(const SkDPoint& a) const {
103 if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
104 return true;
105 }
106 if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) {
107 return false;
108 }
109 double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ?
110 double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
111 double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
112 largest = SkTMax(largest, -tiniest);
113 return AlmostBequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
114 }
115
approximatelyEqualSkDPoint116 bool approximatelyEqual(const SkPoint& a) const {
117 SkDPoint dA;
118 dA.set(a);
119 return approximatelyEqual(dA);
120 }
121
ApproximatelyEqualSkDPoint122 static bool ApproximatelyEqual(const SkPoint& a, const SkPoint& b) {
123 if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) {
124 return true;
125 }
126 if (!RoughlyEqualUlps(a.fX, b.fX) || !RoughlyEqualUlps(a.fY, b.fY)) {
127 return false;
128 }
129 SkDPoint dA, dB;
130 dA.set(a);
131 dB.set(b);
132 double dist = dA.distance(dB); // OPTIMIZATION: can we compare against distSq instead ?
133 float tiniest = SkTMin(SkTMin(SkTMin(a.fX, b.fX), a.fY), b.fY);
134 float largest = SkTMax(SkTMax(SkTMax(a.fX, b.fX), a.fY), b.fY);
135 largest = SkTMax(largest, -tiniest);
136 return AlmostBequalUlps((double) largest, largest + dist); // is dist within ULPS tolerance?
137 }
138
approximatelyPEqualSkDPoint139 bool approximatelyPEqual(const SkDPoint& a) const {
140 if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
141 return true;
142 }
143 if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) {
144 return false;
145 }
146 double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ?
147 double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
148 double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
149 largest = SkTMax(largest, -tiniest);
150 return AlmostPequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
151 }
152
approximatelyZeroSkDPoint153 bool approximatelyZero() const {
154 return approximately_zero(fX) && approximately_zero(fY);
155 }
156
asSkPointSkDPoint157 SkPoint asSkPoint() const {
158 SkPoint pt = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)};
159 return pt;
160 }
161
distanceSkDPoint162 double distance(const SkDPoint& a) const {
163 SkDVector temp = *this - a;
164 return temp.length();
165 }
166
distanceSquaredSkDPoint167 double distanceSquared(const SkDPoint& a) const {
168 SkDVector temp = *this - a;
169 return temp.lengthSquared();
170 }
171
MidSkDPoint172 static SkDPoint Mid(const SkDPoint& a, const SkDPoint& b) {
173 SkDPoint result;
174 result.fX = (a.fX + b.fX) / 2;
175 result.fY = (a.fY + b.fY) / 2;
176 return result;
177 }
178
moreRoughlyEqualSkDPoint179 bool moreRoughlyEqual(const SkDPoint& a) const {
180 if (roughly_equal(fX, a.fX) && roughly_equal(fY, a.fY)) {
181 return true;
182 }
183 double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ?
184 double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
185 double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
186 largest = SkTMax(largest, -tiniest);
187 return RoughlyEqualUlps(largest, largest + dist); // is the dist within ULPS tolerance?
188 }
189
roughlyEqualSkDPoint190 bool roughlyEqual(const SkDPoint& a) const {
191 return roughly_equal(a.fY, fY) && roughly_equal(a.fX, fX);
192 }
193
194 #ifdef SK_DEBUG
dumpSkDPoint195 void dump() {
196 SkDebugf("{");
197 DebugDumpDouble(fX);
198 SkDebugf(", ");
199 DebugDumpDouble(fY);
200 SkDebugf("}");
201 }
202
dumpSkDPoint203 static void dump(const SkPoint& pt) {
204 SkDebugf("{");
205 DebugDumpFloat(pt.fX);
206 SkDebugf(", ");
207 DebugDumpFloat(pt.fY);
208 SkDebugf("}");
209 }
210 #endif
211 };
212
213 #endif
214