|
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, 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 |
|
42 SkVector asSkVector() const { |
|
43 SkVector v = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)}; |
|
44 return v; |
|
45 } |
|
46 |
|
47 double cross(const SkDVector& a) const { |
|
48 return fX * a.fY - fY * a.fX; |
|
49 } |
|
50 |
|
51 double dot(const SkDVector& a) const { |
|
52 return fX * a.fX + fY * a.fY; |
|
53 } |
|
54 |
|
55 double length() const { |
|
56 return sqrt(lengthSquared()); |
|
57 } |
|
58 |
|
59 double lengthSquared() const { |
|
60 return fX * fX + fY * fY; |
|
61 } |
|
62 }; |
|
63 |
|
64 struct SkDPoint { |
|
65 double fX; |
|
66 double fY; |
|
67 |
|
68 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 |
|
102 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 |
|
116 bool approximatelyEqual(const SkPoint& a) const { |
|
117 SkDPoint dA; |
|
118 dA.set(a); |
|
119 return approximatelyEqual(dA); |
|
120 } |
|
121 |
|
122 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 |
|
139 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 |
|
153 bool approximatelyZero() const { |
|
154 return approximately_zero(fX) && approximately_zero(fY); |
|
155 } |
|
156 |
|
157 SkPoint asSkPoint() const { |
|
158 SkPoint pt = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)}; |
|
159 return pt; |
|
160 } |
|
161 |
|
162 double distance(const SkDPoint& a) const { |
|
163 SkDVector temp = *this - a; |
|
164 return temp.length(); |
|
165 } |
|
166 |
|
167 double distanceSquared(const SkDPoint& a) const { |
|
168 SkDVector temp = *this - a; |
|
169 return temp.lengthSquared(); |
|
170 } |
|
171 |
|
172 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 |
|
179 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 |
|
190 bool roughlyEqual(const SkDPoint& a) const { |
|
191 return roughly_equal(a.fY, fY) && roughly_equal(a.fX, fX); |
|
192 } |
|
193 |
|
194 #ifdef SK_DEBUG |
|
195 void dump() { |
|
196 SkDebugf("{"); |
|
197 DebugDumpDouble(fX); |
|
198 SkDebugf(", "); |
|
199 DebugDumpDouble(fY); |
|
200 SkDebugf("}"); |
|
201 } |
|
202 |
|
203 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 |