Home | History | Annotate | Download | only in pathops
      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;
     19     double fY;
     20 
     21     void set(const SkVector& pt) {
     22         fX = pt.fX;
     23         fY = pt.fY;
     24     }
     25 
     26     // only used by testing
     27     void operator+=(const SkDVector& v) {
     28         fX += v.fX;
     29         fY += v.fY;
     30     }
     31 
     32     // only called by nearestT, which is currently only used by testing
     33     void operator-=(const SkDVector& v) {
     34         fX -= v.fX;
     35         fY -= v.fY;
     36     }
     37 
     38     // only used by testing
     39     void operator/=(const double s) {
     40         fX /= s;
     41         fY /= s;
     42     }
     43 
     44     // only used by testing
     45     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 
     55     // only used by testing
     56     double cross(const SkDVector& a) const {
     57         return fX * a.fY - fY * a.fX;
     58     }
     59 
     60     // 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 
     67     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 
     80 struct 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 
    104     // only used by testing
    105     void operator+=(const SkDVector& v) {
    106         fX += v.fX;
    107         fY += v.fY;
    108     }
    109 
    110     // only used by testing
    111     void operator-=(const SkDVector& v) {
    112         fX -= v.fX;
    113         fY -= v.fY;
    114     }
    115 
    116     // 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 
    130     // note: this can not be implemented with
    131     // return approximately_equal(a.fY, fY) && approximately_equal(a.fX, fX);
    132     // because that will not take the magnitude of the values into account
    133     bool approximatelyEqual(const SkDPoint& a) const {
    134         if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
    135             return true;
    136         }
    137         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);
    144         return AlmostPequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
    145     }
    146 
    147     bool approximatelyEqual(const SkPoint& a) const {
    148         SkDPoint dA;
    149         dA.set(a);
    150         return approximatelyEqual(dA);
    151     }
    152 
    153     static bool ApproximatelyEqual(const SkPoint& a, const SkPoint& b) {
    154         if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) {
    155             return true;
    156         }
    157         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);
    167         return AlmostPequalUlps((double) largest, largest + dist); // is dist within ULPS tolerance?
    168     }
    169 
    170     // only used by testing
    171     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 
    190     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 
    197     bool roughlyEqual(const SkDPoint& a) const {
    198         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?
    206     }
    207 
    208     static bool RoughlyEqual(const SkPoint& a, const SkPoint& b) {
    209         if (!RoughlyEqualUlps(a.fX, b.fX) && !RoughlyEqualUlps(a.fY, b.fY)) {
    210             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 
    222     // 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);
    225     static void DumpHex(const SkPoint& pt);
    226 };
    227 
    228 #endif
    229