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, 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
    214