blob: e3f722bede18219384532a11c1975064304d730d [file] [log] [blame]
caryclark@google.com07393ca2013-04-08 11:47:37 +00001/*
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
caryclark@google.coma5e55922013-05-07 18:51:31 +000013inline bool AlmostEqualUlps(const SkPoint& pt1, const SkPoint& pt2) {
14 return AlmostEqualUlps(pt1.fX, pt2.fX) && AlmostEqualUlps(pt1.fY, pt2.fY);
15}
16
caryclark@google.com07393ca2013-04-08 11:47:37 +000017struct SkDVector {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000018 double fX;
19 double fY;
20
21 void set(const SkVector& pt) {
22 fX = pt.fX;
23 fY = pt.fY;
24 }
caryclark@google.com07393ca2013-04-08 11:47:37 +000025
caryclark54359292015-03-26 07:52:43 -070026 // only used by testing
caryclark@google.com07393ca2013-04-08 11:47:37 +000027 void operator+=(const SkDVector& v) {
28 fX += v.fX;
29 fY += v.fY;
30 }
31
caryclark54359292015-03-26 07:52:43 -070032 // only called by nearestT, which is currently only used by testing
caryclark@google.com07393ca2013-04-08 11:47:37 +000033 void operator-=(const SkDVector& v) {
34 fX -= v.fX;
35 fY -= v.fY;
36 }
37
caryclark54359292015-03-26 07:52:43 -070038 // only used by testing
caryclark@google.com07393ca2013-04-08 11:47:37 +000039 void operator/=(const double s) {
40 fX /= s;
41 fY /= s;
42 }
43
caryclark54359292015-03-26 07:52:43 -070044 // only used by testing
caryclark@google.com07393ca2013-04-08 11:47:37 +000045 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
caryclark54359292015-03-26 07:52:43 -070055 // only used by testing
caryclark@google.com07393ca2013-04-08 11:47:37 +000056 double cross(const SkDVector& a) const {
57 return fX * a.fY - fY * a.fX;
58 }
59
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000060 // 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
caryclark@google.com07393ca2013-04-08 11:47:37 +000067 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
80struct 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
caryclark54359292015-03-26 07:52:43 -0700104 // only used by testing
caryclark@google.com07393ca2013-04-08 11:47:37 +0000105 void operator+=(const SkDVector& v) {
106 fX += v.fX;
107 fY += v.fY;
108 }
109
caryclark54359292015-03-26 07:52:43 -0700110 // only used by testing
caryclark@google.com07393ca2013-04-08 11:47:37 +0000111 void operator-=(const SkDVector& v) {
112 fX -= v.fX;
113 fY -= v.fY;
114 }
115
caryclark03b03ca2015-04-23 09:13:37 -0700116 // 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
caryclark@google.com07393ca2013-04-08 11:47:37 +0000130 // note: this can not be implemented with
131 // return approximately_equal(a.fY, fY) && approximately_equal(a.fX, fX);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000132 // because that will not take the magnitude of the values into account
caryclark@google.com07393ca2013-04-08 11:47:37 +0000133 bool approximatelyEqual(const SkDPoint& a) const {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000134 if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000135 return true;
136 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000137 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);
caryclark54359292015-03-26 07:52:43 -0700144 return AlmostPequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
caryclark@google.com07393ca2013-04-08 11:47:37 +0000145 }
146
147 bool approximatelyEqual(const SkPoint& a) const {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000148 SkDPoint dA;
149 dA.set(a);
150 return approximatelyEqual(dA);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000151 }
152
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000153 static bool ApproximatelyEqual(const SkPoint& a, const SkPoint& b) {
154 if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000155 return true;
156 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000157 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);
caryclark54359292015-03-26 07:52:43 -0700167 return AlmostPequalUlps((double) largest, largest + dist); // is dist within ULPS tolerance?
caryclark@google.com07393ca2013-04-08 11:47:37 +0000168 }
169
caryclark54359292015-03-26 07:52:43 -0700170 // only used by testing
caryclark@google.com07393ca2013-04-08 11:47:37 +0000171 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
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000190 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
caryclark54359292015-03-26 07:52:43 -0700197 bool roughlyEqual(const SkDPoint& a) const {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000198 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?
caryclark@google.com07393ca2013-04-08 11:47:37 +0000206 }
207
caryclark1049f122015-04-20 08:31:59 -0700208 static bool RoughlyEqual(const SkPoint& a, const SkPoint& b) {
caryclark624637c2015-05-11 07:21:27 -0700209 if (!RoughlyEqualUlps(a.fX, b.fX) && !RoughlyEqualUlps(a.fY, b.fY)) {
caryclark1049f122015-04-20 08:31:59 -0700210 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
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000222 // 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);
caryclark65f55312014-11-13 06:58:52 -0800225 static void DumpHex(const SkPoint& pt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000226};
227
228#endif