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