/* * Copyright 2012 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkPathOpsPoint_DEFINED #define SkPathOpsPoint_DEFINED #include "SkPathOpsTypes.h" #include "SkPoint.h" inline bool AlmostEqualUlps(const SkPoint& pt1, const SkPoint& pt2) { return AlmostEqualUlps(pt1.fX, pt2.fX) && AlmostEqualUlps(pt1.fY, pt2.fY); } struct SkDVector { double fX, fY; friend SkDPoint operator+(const SkDPoint& a, const SkDVector& b); void operator+=(const SkDVector& v) { fX += v.fX; fY += v.fY; } void operator-=(const SkDVector& v) { fX -= v.fX; fY -= v.fY; } void operator/=(const double s) { fX /= s; fY /= s; } void operator*=(const double s) { fX *= s; fY *= s; } SkVector asSkVector() const { SkVector v = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)}; return v; } double cross(const SkDVector& a) const { return fX * a.fY - fY * a.fX; } double dot(const SkDVector& a) const { return fX * a.fX + fY * a.fY; } double length() const { return sqrt(lengthSquared()); } double lengthSquared() const { return fX * fX + fY * fY; } }; struct SkDPoint { double fX; double fY; void set(const SkPoint& pt) { fX = pt.fX; fY = pt.fY; } friend SkDVector operator-(const SkDPoint& a, const SkDPoint& b); friend bool operator==(const SkDPoint& a, const SkDPoint& b) { return a.fX == b.fX && a.fY == b.fY; } friend bool operator!=(const SkDPoint& a, const SkDPoint& b) { return a.fX != b.fX || a.fY != b.fY; } void operator=(const SkPoint& pt) { fX = pt.fX; fY = pt.fY; } void operator+=(const SkDVector& v) { fX += v.fX; fY += v.fY; } void operator-=(const SkDVector& v) { fX -= v.fX; fY -= v.fY; } // note: this can not be implemented with // return approximately_equal(a.fY, fY) && approximately_equal(a.fX, fX); // because that will not take the magnitude of the values bool approximatelyEqual(const SkDPoint& a) const { if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) { return true; } if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) { return false; } double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ? double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY); double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY); largest = SkTMax(largest, -tiniest); return AlmostBequalUlps(largest, largest + dist); // is the dist within ULPS tolerance? } bool approximatelyEqual(const SkPoint& a) const { SkDPoint dA; dA.set(a); return approximatelyEqual(dA); } static bool ApproximatelyEqual(const SkPoint& a, const SkPoint& b) { if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) { return true; } if (!RoughlyEqualUlps(a.fX, b.fX) || !RoughlyEqualUlps(a.fY, b.fY)) { return false; } SkDPoint dA, dB; dA.set(a); dB.set(b); double dist = dA.distance(dB); // OPTIMIZATION: can we compare against distSq instead ? float tiniest = SkTMin(SkTMin(SkTMin(a.fX, b.fX), a.fY), b.fY); float largest = SkTMax(SkTMax(SkTMax(a.fX, b.fX), a.fY), b.fY); largest = SkTMax(largest, -tiniest); return AlmostBequalUlps((double) largest, largest + dist); // is dist within ULPS tolerance? } bool approximatelyZero() const { return approximately_zero(fX) && approximately_zero(fY); } SkPoint asSkPoint() const { SkPoint pt = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)}; return pt; } double distance(const SkDPoint& a) const { SkDVector temp = *this - a; return temp.length(); } double distanceSquared(const SkDPoint& a) const { SkDVector temp = *this - a; return temp.lengthSquared(); } static SkDPoint Mid(const SkDPoint& a, const SkDPoint& b) { SkDPoint result; result.fX = (a.fX + b.fX) / 2; result.fY = (a.fY + b.fY) / 2; return result; } bool moreRoughlyEqual(const SkDPoint& a) const { if (roughly_equal(fX, a.fX) && roughly_equal(fY, a.fY)) { return true; } double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ? double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY); double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY); largest = SkTMax(largest, -tiniest); return RoughlyEqualUlps(largest, largest + dist); // is the dist within ULPS tolerance? } bool roughlyEqual(const SkDPoint& a) const { return roughly_equal(a.fY, fY) && roughly_equal(a.fX, fX); } #ifdef SK_DEBUG void dump() { SkDebugf("{"); DebugDumpDouble(fX); SkDebugf(", "); DebugDumpDouble(fY); SkDebugf("}"); } static void DumpSkPoint(const SkPoint& pt) { SkDebugf("{"); DebugDumpFloat(pt.fX); SkDebugf(", "); DebugDumpFloat(pt.fY); SkDebugf("}"); } #endif }; #endif