blob: 7ddfbfb5d15bce28b46643e2cd7b46122e22fcfc [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
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
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000057 // 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
caryclark@google.com07393ca2013-04-08 11:47:37 +000064 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
caryclark@google.com07393ca2013-04-08 11:47:37 +0000101 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);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000113 // because that will not take the magnitude of the values into account
caryclark@google.com07393ca2013-04-08 11:47:37 +0000114 bool approximatelyEqual(const SkDPoint& a) const {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000115 if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000116 return true;
117 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000118 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?
caryclark@google.com07393ca2013-04-08 11:47:37 +0000126 }
127
128 bool approximatelyEqual(const SkPoint& a) const {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000129 SkDPoint dA;
130 dA.set(a);
131 return approximatelyEqual(dA);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000132 }
133
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000134 static bool ApproximatelyEqual(const SkPoint& a, const SkPoint& b) {
135 if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000136 return true;
137 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000138 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?
caryclark@google.com07393ca2013-04-08 11:47:37 +0000149 }
150
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000151 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 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000157
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000158 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
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000172 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
caryclark@google.com07393ca2013-04-08 11:47:37 +0000186 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
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000205 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
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000212 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?
caryclark@google.com07393ca2013-04-08 11:47:37 +0000221 }
222
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000223 bool roughlyEqual(const SkDPoint& a) const {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000224 return roughly_equal(a.fY, fY) && roughly_equal(a.fX, fX);
225 }
caryclark@google.com570863f2013-09-16 15:55:01 +0000226
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000227 // 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);
caryclark65f55312014-11-13 06:58:52 -0800230 static void DumpHex(const SkPoint& pt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000231};
232
233#endif